init serv file
This commit is contained in:
1
.idea/serv.iml
generated
1
.idea/serv.iml
generated
@@ -5,6 +5,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/packages/gotify-ws/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/packages/gotify-ws/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/packages/home-api/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/packages/home-api/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/packages/serv/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|||||||
22
Cargo.toml
22
Cargo.toml
@@ -1,5 +1,21 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["packages/gotify-ws"]
|
members = ["packages/gotify-ws", "packages/serv"]
|
||||||
#members = ["packages/gotify-ws", "packages/home-api"]
|
default-members = ["packages/gotify-ws"]
|
||||||
default-members = ["packages/gotify-ws"]
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
gotify-ws = { path = "./packages/gotify-ws" }
|
||||||
|
tokio = { version = "1.47.1", features = ["full"] }
|
||||||
|
rusqlite = { version = "0.32.1", features = ["bundled"] }
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.142"
|
||||||
|
regex = "1.11.1"
|
||||||
|
sea-orm = { version = "1.1.14", features = [
|
||||||
|
"sqlx-sqlite",
|
||||||
|
"runtime-tokio-rustls",
|
||||||
|
"macros",
|
||||||
|
] }
|
||||||
|
chrono = "0.4.41"
|
||||||
|
env_logger = "0.11.8"
|
||||||
|
futures = "0.3.31"
|
||||||
|
log = "0.4.27"
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ name = "gotify-ws"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "gotify_ws"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#diesel = { version = "2.2.12", features = ["r2d2", "serde_json", "sqlite"] }
|
env_logger.workspace = true
|
||||||
env_logger = "0.11.8"
|
futures.workspace = true
|
||||||
futures = "0.3.31"
|
log.workspace = true
|
||||||
log = "0.4.27"
|
|
||||||
#r2d2 = "0.8.10"
|
|
||||||
#r2d2_sqlite = "0.31.0"
|
|
||||||
#libsqlite3-sys = { version = "0.35.0", features = ["bundled"] }
|
|
||||||
# 或如果是通过 rusqlite 依赖:
|
# 或如果是通过 rusqlite 依赖:
|
||||||
rusqlite = { version = "0.32.1", features = ["bundled"] }
|
rusqlite.workspace = true
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde.workspace = true
|
||||||
serde_json = "1.0.142"
|
serde_json.workspace = true
|
||||||
tokio = { version = "1.47.1", features = ["full"] }
|
tokio.workspace = true
|
||||||
tokio-tungstenite = { version = "0.27.0", features = ["native-tls"] }
|
tokio-tungstenite = { version = "0.27.0", features = ["native-tls"] }
|
||||||
regex = "1.11.1"
|
regex.workspace = true
|
||||||
sea-orm = { version = "1.1.14", features = ["sqlx-sqlite", "runtime-tokio-rustls", "macros"] }
|
sea-orm.workspace = true
|
||||||
chrono = "0.4.41"
|
chrono.workspace = true
|
||||||
2
packages/gotify-ws/src/lib.rs
Normal file
2
packages/gotify-ws/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod model;
|
||||||
|
pub mod utils;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
mod model;
|
mod model;
|
||||||
mod tests;
|
mod tests;
|
||||||
mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
use crate::model::ssh_connection::{ActiveModel, SSHConnection};
|
use crate::model::ssh_connection::{ActiveModel, SSHConnection};
|
||||||
use crate::utils::sql::sqlite;
|
use crate::utils::sql::sqlite;
|
||||||
@@ -12,7 +12,7 @@ use tokio_tungstenite::tungstenite::client::IntoClientRequest;
|
|||||||
use utils::logger;
|
use utils::logger;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
pub async fn main() {
|
||||||
logger::init_logger();
|
logger::init_logger();
|
||||||
let addr = "wss://home.hzer.xyz/gotify/stream?token=CDIwYlYJuxWxVr5"
|
let addr = "wss://home.hzer.xyz/gotify/stream?token=CDIwYlYJuxWxVr5"
|
||||||
.into_client_request()
|
.into_client_request()
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "home-api"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
pub struct Location {
|
|
||||||
latitude: f64,
|
|
||||||
longitude: f64,
|
|
||||||
altitude: f64,
|
|
||||||
accuracy: f64,
|
|
||||||
vertical_accuracy: f64,
|
|
||||||
bearing: f64,
|
|
||||||
speed: f64,
|
|
||||||
elapsedMs: i64,
|
|
||||||
provider: String,
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pub mod location;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
use crate::utils::database::SqliteState;
|
|
||||||
use actix_web::{get, web};
|
|
||||||
use log::info;
|
|
||||||
|
|
||||||
// 上报location位置
|
|
||||||
#[get("/{user}/addr/post")]
|
|
||||||
pub async fn location(
|
|
||||||
user_id: web::Path<String>,
|
|
||||||
db: web::Data<SqliteState>,
|
|
||||||
) -> Result<String, actix_web::Error> {
|
|
||||||
info!("user_id: {}", user_id);
|
|
||||||
Ok(user_id.into_inner())
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pub mod location;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
use crate::utils::database::init_database;
|
|
||||||
use actix_web::{App, HttpServer};
|
|
||||||
|
|
||||||
mod handler;
|
|
||||||
mod utils;
|
|
||||||
mod test;
|
|
||||||
|
|
||||||
#[actix_web::main]
|
|
||||||
async fn main() -> std::io::Result<()> {
|
|
||||||
// 初始化 logger 内容
|
|
||||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
||||||
|
|
||||||
let db = init_database();
|
|
||||||
HttpServer::new(move || {
|
|
||||||
App::new()
|
|
||||||
.app_data(db.clone())
|
|
||||||
.configure(utils::router::location)
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8080")?
|
|
||||||
.run()
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
mod sqlite;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
mod sqlite {
|
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
fs::{File, read_to_string},
|
|
||||||
io::{BufRead, BufReader, Read},
|
|
||||||
};
|
|
||||||
|
|
||||||
use r2d2::Pool;
|
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn init() {
|
|
||||||
let manager = SqliteConnectionManager::file("database.mod");
|
|
||||||
let pool = r2d2::Pool::new(manager).unwrap();
|
|
||||||
|
|
||||||
let file = File::open("./resources/ID/id.txt").unwrap();
|
|
||||||
let reader = BufReader::new(file);
|
|
||||||
|
|
||||||
check_id_column_exist(&pool);
|
|
||||||
|
|
||||||
let mut id_map = HashMap::<String, String>::new();
|
|
||||||
|
|
||||||
for line in reader.lines() {
|
|
||||||
match line {
|
|
||||||
Ok(line) => {
|
|
||||||
handle_duplicate_id(&line, &mut id_map);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// println!("id_map 中共有 {} 条记录", id_map.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_id_column_exist(conn: &Pool<SqliteConnectionManager>) {
|
|
||||||
let conn: r2d2::PooledConnection<SqliteConnectionManager> = conn.get().unwrap();
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE IF NOT EXISTS id_card (
|
|
||||||
row_id INTEGER PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
id TEXT NOT NULL,
|
|
||||||
create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
update_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)",
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理重复的id
|
|
||||||
*/
|
|
||||||
fn handle_duplicate_id(lineStr: &str, id_map: &mut HashMap<String, String>) {
|
|
||||||
let line = lineStr.split("----").collect::<Vec<&str>>();
|
|
||||||
|
|
||||||
if line.len() != 2 { println!("the line {} is invalid", line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (name, id) = (line[0], line[1]);
|
|
||||||
|
|
||||||
if id_map.contains_key(id) {
|
|
||||||
println!("the id {} is duplicate, and the name is {}", id, name);
|
|
||||||
} else {
|
|
||||||
id_map.insert(id.to_string(), name.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
use actix_web::web;
|
|
||||||
use r2d2::{Pool, State};
|
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use actix_web::web::Data;
|
|
||||||
|
|
||||||
pub struct SqliteState {
|
|
||||||
pool: Pool<SqliteConnectionManager>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_database() -> Data<SqliteState> {
|
|
||||||
let db = SqliteConnectionManager::file("./database.mod");
|
|
||||||
let pool = Pool::new(db).unwrap();
|
|
||||||
Data::new(SqliteState { pool: pool.clone() })
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
pub mod router;
|
|
||||||
pub mod database;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
use actix_web::{web};
|
|
||||||
|
|
||||||
use crate::handler::location;
|
|
||||||
|
|
||||||
pub fn location(cfg: &mut web::ServiceConfig) {
|
|
||||||
cfg.service(web::scope("/location").service(location::location));
|
|
||||||
}
|
|
||||||
10
packages/serv/Cargo.toml
Normal file
10
packages/serv/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "serv"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio.workspace = true
|
||||||
|
gotify-ws.workspace = true
|
||||||
|
log = "0.4.27"
|
||||||
|
env_logger = "0.11.8"
|
||||||
3957
packages/serv/resources/ID/nation.sql
Normal file
3957
packages/serv/resources/ID/nation.sql
Normal file
File diff suppressed because it is too large
Load Diff
50
packages/serv/resources/ID/validate.md
Normal file
50
packages/serv/resources/ID/validate.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
中国身份证号码的校验涉及严格的规则,主要用于验证号码的格式合法性(是否符合国家标准),但无法验证证件真实性(需对接公安系统)。以下是完整的校验规则和实现逻辑:
|
||||||
|
|
||||||
|
身份证号码结构(18位)
|
||||||
|
`AAAAAA YYYYMMDD XXX C`
|
||||||
|
|
||||||
|
地址码(AAAAAA):前6位,代表户籍所在地(需符合最新行政区划代码)。
|
||||||
|
|
||||||
|
出生日期码(YYYYMMDD):第7-14位,必须为有效日期(如19900101)。
|
||||||
|
|
||||||
|
顺序码(XXX):第15-17位,奇数男性、偶数女性。
|
||||||
|
|
||||||
|
校验码(C):第18位,由前17位计算得出(0-9或X)。
|
||||||
|
|
||||||
|
校验码计算规则
|
||||||
|
权重分配:前17位分别乘以固定权重系数:
|
||||||
|
`[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]`
|
||||||
|
|
||||||
|
加权求和:
|
||||||
|
`S = Sum(ID[i] * W[i]) (i=0~16)`
|
||||||
|
|
||||||
|
取模11:
|
||||||
|
S_mod = S % 11
|
||||||
|
|
||||||
|
映射校验码:根据余数S_mod查表:
|
||||||
|
|
||||||
|
| 余数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|
||||||
|
|------|---|----|----|----|----|----|----|----|----|----|-----|
|
||||||
|
| 校验码 | 1 | 0 | X | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 |
|
||||||
|
|
||||||
|
校验步骤(代码实现逻辑)
|
||||||
|
基本检查:
|
||||||
|
|
||||||
|
长度必须为18位
|
||||||
|
|
||||||
|
前17位全为数字
|
||||||
|
|
||||||
|
第18位是数字或X
|
||||||
|
|
||||||
|
地址码校验:
|
||||||
|
|
||||||
|
前6位在有效行政区划列表中(需定期更新)
|
||||||
|
|
||||||
|
日期校验:
|
||||||
|
|
||||||
|
第7-14位转换为日期(如1990-01-01),检查是否为有效日期
|
||||||
|
|
||||||
|
校验码计算:
|
||||||
|
|
||||||
|
按权重计算并比对最后一位
|
||||||
|
|
||||||
11
packages/serv/src/dto/location.rs
Normal file
11
packages/serv/src/dto/location.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
pub struct Location {
|
||||||
|
latitude: f64,
|
||||||
|
longitude: f64,
|
||||||
|
altitude: f64,
|
||||||
|
accuracy: f64,
|
||||||
|
vertical_accuracy: f64,
|
||||||
|
bearing: f64,
|
||||||
|
speed: f64,
|
||||||
|
elapsedMs: i64,
|
||||||
|
provider: String,
|
||||||
|
}
|
||||||
1
packages/serv/src/dto/mod.rs
Normal file
1
packages/serv/src/dto/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod location;
|
||||||
1
packages/serv/src/handler/location.rs
Normal file
1
packages/serv/src/handler/location.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
packages/serv/src/handler/mod.rs
Normal file
1
packages/serv/src/handler/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod location;
|
||||||
4
packages/serv/src/main.rs
Normal file
4
packages/serv/src/main.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
mod test;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {}
|
||||||
9
packages/serv/src/test/base_api.rs
Normal file
9
packages/serv/src/test/base_api.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use gotify_ws::utils::logger;
|
||||||
|
use log::info;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base_api_env() {
|
||||||
|
logger::init_logger();
|
||||||
|
info!(r"current dir is {:?}", env::vars())
|
||||||
|
}
|
||||||
2
packages/serv/src/test/mod.rs
Normal file
2
packages/serv/src/test/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod base_api;
|
||||||
14
packages/serv/src/utils/database.rs
Normal file
14
packages/serv/src/utils/database.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use actix_web::web;
|
||||||
|
use actix_web::web::Data;
|
||||||
|
use r2d2::{Pool, State};
|
||||||
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
|
|
||||||
|
pub struct SqliteState {
|
||||||
|
pool: Pool<SqliteConnectionManager>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_database() -> Data<SqliteState> {
|
||||||
|
let db = SqliteConnectionManager::file("./database.mod");
|
||||||
|
let pool = Pool::new(db).unwrap();
|
||||||
|
Data::new(SqliteState { pool: pool.clone() })
|
||||||
|
}
|
||||||
2
packages/serv/src/utils/mod.rs
Normal file
2
packages/serv/src/utils/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod database;
|
||||||
|
pub mod router;
|
||||||
7
packages/serv/src/utils/router.rs
Normal file
7
packages/serv/src/utils/router.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
use actix_web::web;
|
||||||
|
|
||||||
|
use crate::handler::location;
|
||||||
|
|
||||||
|
pub fn location(cfg: &mut web::ServiceConfig) {
|
||||||
|
cfg.service(web::scope("/location").service(location::location));
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Rust 格式化配置
|
# Rust 格式化配置
|
||||||
tab_spaces = 2 # 设置缩进为2个空格
|
tab_spaces = 2 # 设置缩进为2个空格
|
||||||
max_width = 100 # 每行最大宽度
|
max_width = 120 # 每行最大宽度
|
||||||
edition = "2024" # 使用Rust 2021版本
|
edition = "2024" # 使用Rust 2021版本
|
||||||
|
|||||||
Reference in New Issue
Block a user