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/home-api/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" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
||||
20
Cargo.toml
20
Cargo.toml
@@ -1,5 +1,21 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["packages/gotify-ws"]
|
||||
#members = ["packages/gotify-ws", "packages/home-api"]
|
||||
members = ["packages/gotify-ws", "packages/serv"]
|
||||
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"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
name = "gotify_ws"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
#diesel = { version = "2.2.12", features = ["r2d2", "serde_json", "sqlite"] }
|
||||
env_logger = "0.11.8"
|
||||
futures = "0.3.31"
|
||||
log = "0.4.27"
|
||||
#r2d2 = "0.8.10"
|
||||
#r2d2_sqlite = "0.31.0"
|
||||
#libsqlite3-sys = { version = "0.35.0", features = ["bundled"] }
|
||||
env_logger.workspace = true
|
||||
futures.workspace = true
|
||||
log.workspace = true
|
||||
# 或如果是通过 rusqlite 依赖:
|
||||
rusqlite = { version = "0.32.1", features = ["bundled"] }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.142"
|
||||
tokio = { version = "1.47.1", features = ["full"] }
|
||||
rusqlite.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
tokio-tungstenite = { version = "0.27.0", features = ["native-tls"] }
|
||||
regex = "1.11.1"
|
||||
sea-orm = { version = "1.1.14", features = ["sqlx-sqlite", "runtime-tokio-rustls", "macros"] }
|
||||
chrono = "0.4.41"
|
||||
regex.workspace = true
|
||||
sea-orm.workspace = true
|
||||
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 tests;
|
||||
mod utils;
|
||||
pub mod utils;
|
||||
|
||||
use crate::model::ssh_connection::{ActiveModel, SSHConnection};
|
||||
use crate::utils::sql::sqlite;
|
||||
@@ -12,7 +12,7 @@ use tokio_tungstenite::tungstenite::client::IntoClientRequest;
|
||||
use utils::logger;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
pub async fn main() {
|
||||
logger::init_logger();
|
||||
let addr = "wss://home.hzer.xyz/gotify/stream?token=CDIwYlYJuxWxVr5"
|
||||
.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 格式化配置
|
||||
tab_spaces = 2 # 设置缩进为2个空格
|
||||
max_width = 100 # 每行最大宽度
|
||||
max_width = 120 # 每行最大宽度
|
||||
edition = "2024" # 使用Rust 2021版本
|
||||
|
||||
Reference in New Issue
Block a user