rebuild log, and add aliyun sms server

This commit is contained in:
yanweitong 2024-01-05 17:47:20 +08:00
parent 972f378389
commit 0f9f06db53
11 changed files with 1259 additions and 46 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.idea
target
test
logs

1077
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,12 +10,13 @@ edition = "2021"
default = ["pokemmo"]
pokemmo = ["screen", "ocr", "joystick", "dep:image", "pokemon", "detector"]
pokemmo = ["screen", "ocr", "joystick", "dep:image", "pokemon", "detector","sms"]
screen = ["dep:screenshots"]
ocr = ["dep:rusty-tesseract", "dep:image"]
joystick = ["dep:enigo","dep:rand"]
pokemon = []
detector = ["dep:crossterm"]
sms = []
[lib]
@ -30,4 +31,13 @@ image = { version = "0.24.6", optional = true }
crossterm = { version = "0.27.0", optional = true }
rusty-tesseract = { version = "1.1.7", optional = true }
rand = { version = "0.8.5", optional = true }
simple-logging = {version = "2.0.2"}
log4rs = {version = "1.2.0"}
#sms = {version = "0.1.8", optional = true}
futures = "0.3"
reqwest = { version = "0.11.18", features = ["json", "blocking"]}
chrono = { version = "0.4.24"}
ring = "0.16"
urlencoding = "2.1.0"
base64 = "0.21.5"

26
src/base/logger.rs Normal file
View File

@ -0,0 +1,26 @@
pub mod logger {
use log4rs::append::file::FileAppender;
use log4rs::Config;
use log4rs::config::{Appender, Logger, Root};
use log4rs::encode::pattern::PatternEncoder;
use log::LevelFilter;
#[no_mangle]
pub extern "C" fn init_logger(log_file_name: &str, level_filter: LevelFilter) {
let file_path = format!(".\\logs\\{}.log", log_file_name);
let mut config_builder = Config::builder();
let file = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new("[{d(%Y-%m-%d %H:%M:%S%.3f)}] {(\\({tid}\\)):7.7} {({l}):5.5} {m}{n}")))
// .encoder(Box::new(PatternEncoder::new("[{d(%Y-%m-%d %H:%M:%S%.3f)}] {(\\({tid}\\)):7.7} {({l}):5.5} {t} {m}{n}")))
.build(&file_path)
.unwrap();
config_builder = config_builder.appender(Appender::builder().build("file", Box::new(file)));
let mut tag_logger = Logger::builder();
tag_logger = tag_logger.appender("file");
tag_logger = tag_logger.additive(true);
let wecode_log = tag_logger.clone().build("nezha", level_filter);
config_builder = config_builder.logger(wecode_log);
let config = config_builder.build(Root::builder().build(level_filter)).expect("build log failed");
let handle_res = log4rs::init_config(config).expect("init log config failed");
}
}

2
src/base/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub(crate) mod logger;
pub(crate) mod network;

125
src/base/network.rs Normal file
View File

@ -0,0 +1,125 @@
pub(crate) mod network{
use chrono::{SecondsFormat, Utc};
use std::collections::HashMap;
use ring::hmac;
/// SMS API 版本
const SMS_VERSION: &'static str = "2017-05-25";
/// 签名算法版本。目前为固定值 `1.0`。
const SIGNATURE_VERSION: &'static str = "1.0";
/// 签名方式。目前为固定值 `HMAC-SHA1`。
const SIGNATURE_METHOD: &'static str = "HMAC-SHA1";
/// 指定接口返回数据的格式。可以选择 `JSON` 或者 `XML`。默认为 `XML`。
///
/// 这里选择 `JSON`。
const FORMAT: &'static str = "json";
pub struct Aliyun<'a> {
access_key_id: &'a str,
access_secret: &'a str,
}
impl<'a> Aliyun<'a> {
pub fn new(access_key_id: &'a str, access_secret: &'a str) -> Self {
Self {
access_key_id,
access_secret,
}
}
pub fn send_sms(
&self,
phone_numbers: &'a str,
sign_name: &'a str,
template_code: &'a str,
template_param: &'a str,
) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
let mut params = HashMap::new();
params.insert("PhoneNumbers", phone_numbers);
params.insert("SignName", sign_name);
params.insert("TemplateCode", template_code);
params.insert("RegionId", "cn-hangzhou");
params.insert("TemplateParam", template_param);
params.insert("Action", "SendSms");
params.insert("Version", SMS_VERSION);
// 构造规范化请求字符串
let canonicalize_query_string = self.canonicalize_query_string(&params);
// 构造签名字符串
let signature = self.signature(
format!(
"GET&%2F&{}",
urlencoding::encode(&canonicalize_query_string)
)
.as_bytes(),
);
let url = format!(
"https://dysmsapi.aliyuncs.com/?{}&Signature={}",
canonicalize_query_string, signature
);
let client = reqwest::blocking::Client::new();
let resp= client.get(url).send()?.json::<HashMap<String, String>>()?;
// let resp = reqwest::get(url)
// .await?
// .json::<HashMap<String, String>>()
// .await?;
Ok(resp)
}
/// 构造规范化请求字符串
///
/// 详见链接: https://help.aliyun.com/document_detail/315526.html#sectiondiv-y9b-x9s-wvp
fn canonicalize_query_string(&self, params: &HashMap<&str, &'a str>) -> String {
let now = Utc::now();
let signature_nonce = now.timestamp_nanos().to_string();
let timestamp = now.to_rfc3339_opts(SecondsFormat::Secs, true);
let mut all_params = HashMap::new();
all_params.insert("AccessKeyId", self.access_key_id);
all_params.insert("Format", FORMAT);
all_params.insert("SignatureMethod", SIGNATURE_METHOD);
all_params.insert("SignatureNonce", signature_nonce.as_str());
all_params.insert("SignatureVersion", SIGNATURE_VERSION);
all_params.insert("Timestamp", timestamp.as_str());
params.iter().for_each(|(&k, &v)| {
all_params.insert(k, v);
});
let mut vec_arams: Vec<String> = all_params
.iter()
.map(|(&k, &v)| format!("{}={}", k, urlencoding::encode(&v)))
.collect();
vec_arams.sort();
vec_arams.join("&")
}
/// 构建签名字符串
fn signature(&self, string_to_sign: &[u8]) -> String {
let key = hmac::Key::new(
hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
format!("{}&", self.access_secret).as_bytes(),
);
let sign = hmac::sign(&key, string_to_sign);
base64::encode(sign.as_ref())
}
}
}

View File

@ -3,4 +3,6 @@ pub(crate) mod joystick;
pub(crate) mod pokemmo;
pub(crate) mod pokemon;
pub(crate) mod detector;
pub(crate) mod ocr;
pub(crate) mod ocr;
pub(crate) mod sms;
pub(crate) mod base;

View File

@ -11,7 +11,6 @@ mod tests {
#[test]
fn try_meet_shiny(){
simple_logging::log_to_file("./test/log/meet_shiny2.log",LevelFilter::Info).expect("set log failed");
let key_words = vec![
"shiny".to_string(),

3
src/sms/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod sms;
mod sms_test;

23
src/sms/sms.rs Normal file
View File

@ -0,0 +1,23 @@
#[cfg(feature = "sms")]
pub mod sms {
use log::{info, trace};
use crate::base::network::network::Aliyun;
const ALIYUN_SMS_SERVER_REGION: &str = "cn-hangzhou";
const ALIYUN_SMS_ACCESS_KEY_ID: &str = "LTAI5t79FAQwjWFsrHM1F3bu";
const ALIYUN_SMS_ACCESS_KEY_SECRET: &str = "VoAm5sdLUvGMKUuxAWFABhQyEldC4A";
const ALIYUN_SMS_SIGN_NAME: &str = "";
// 模板
const TEMPLATE_TARGET: &str = "SMS_157282676"; // 目标模板
pub(crate) async fn sms_target(target_name: &str, phone: &str) -> Result<(),std::io::Error> {
trace!("sms start.");
let aliyun = Aliyun::new(ALIYUN_SMS_ACCESS_KEY_ID, ALIYUN_SMS_ACCESS_KEY_SECRET);
let resp = aliyun.send_sms("18227630764", "yanweitong", TEMPLATE_TARGET, "").expect("get sms res failed");
info!("sent resp : {:?}",&resp);
return Ok(());
}
}

29
src/sms/sms_test.rs Normal file
View File

@ -0,0 +1,29 @@
#[cfg(test)]
mod tests {
use std::thread;
use std::time::Duration;
use futures::executor::block_on;
use log::{debug, error, info, LevelFilter, trace, warn};
use crate::base::logger::logger::init_logger;
use crate::sms::sms::sms::sms_target;
#[test]
fn test_send_msg(){
init_logger("abc", LevelFilter::Trace);
let res = sms_target(&"",&"18227630764");
block_on(res);
trace!("trace!");
debug!("debug!");
info!("info!");
warn!("warn!");
error!("error!");
thread::sleep(Duration::from_secs(10));
}
}