├── .gitignore ├── src ├── server │ ├── mod.rs │ └── resend.rs ├── osint │ ├── mod.rs │ ├── dns.rs │ └── ip.rs ├── brute_force │ ├── mod.rs │ ├── sha1_cracker.rs │ └── ssh_brute.rs ├── download │ ├── mod.rs │ ├── aria2c.rs │ ├── yt_dlp.rs │ ├── yt_dlp_audio.rs │ └── y_ytdl.rs ├── shell │ ├── mod.rs │ ├── ping.rs │ ├── ls.rs │ ├── any_shell_command.rs │ ├── shell_no_output.rs │ └── command.rs ├── ai │ ├── mod.rs │ └── chatgpt.rs ├── cron.rs ├── lib.rs ├── callback_handler.rs ├── start.rs ├── util.rs ├── handler.rs └── main.rs ├── test-dev.sh ├── .github └── workflows │ ├── rust.yml │ └── deploy.yml ├── deploy.sh ├── wordlist.txt ├── Cargo.toml ├── config-template.toml ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /logs 3 | config.toml 4 | .idea -------------------------------------------------------------------------------- /src/server/mod.rs: -------------------------------------------------------------------------------- 1 | //! 此模块为第三方API服务的集合 2 | //! resend:通过调用api来发送邮件 3 | 4 | mod resend; 5 | 6 | pub use resend::resend; 7 | -------------------------------------------------------------------------------- /src/osint/mod.rs: -------------------------------------------------------------------------------- 1 | //! 信息收集相关,ip,dns 2 | 3 | mod dns; 4 | mod ip; 5 | 6 | pub use dns::{cb_dnsenum, cb_dnsrecon, dns}; 7 | pub use ip::{cb_ip123, ip}; 8 | -------------------------------------------------------------------------------- /src/brute_force/mod.rs: -------------------------------------------------------------------------------- 1 | //! 枚举相关模块:ssh 2 | 3 | mod ssh_brute; 4 | mod sha1_cracker; 5 | 6 | pub use ssh_brute::ssh_brute; 7 | pub use sha1_cracker::sha1_cracker; 8 | -------------------------------------------------------------------------------- /test-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 停止脚本执行时发生错误 4 | set -e 5 | 6 | # 停止tgbot-app服务 7 | echo "停止 tgbot-app 服务..." 8 | sudo systemctl stop tgbot-app 9 | 10 | # 命令行运行项目 11 | echo "当前命令行下运行tgbot-app" 12 | cargo run -------------------------------------------------------------------------------- /src/download/mod.rs: -------------------------------------------------------------------------------- 1 | //! 与下载有关,下载视频或音频 2 | //! aria2c yt-dlp 3 | 4 | mod aria2c; 5 | // mod y_ytdl; 6 | mod yt_dlp; 7 | mod yt_dlp_audio; 8 | 9 | pub use aria2c::aria2c; 10 | // pub use y_ytdl::yt_audio; 11 | pub use yt_dlp::ytdlp; 12 | pub use yt_dlp_audio::ytdlp_audio; 13 | -------------------------------------------------------------------------------- /src/shell/mod.rs: -------------------------------------------------------------------------------- 1 | //! 和Linux shell相关的模块,用来执行shell命令,比如:ls, ping, 机器人接收传入的任意shell命令或定制的通用命令 2 | //! any_shell_command:执行任意shell命令并返回结果,包括标准输出和标准错误 3 | //! shell_no_output:执行任意shell命令并返回是否执行成功 4 | //! ls , ping ... 5 | 6 | mod any_shell_command; 7 | mod command; 8 | mod ls; 9 | mod ping; 10 | mod shell_no_output; 11 | 12 | pub use any_shell_command::shell; 13 | pub use command::c; 14 | pub use ls::ls; 15 | pub use ping::ping; 16 | pub use shell_no_output::shell_no_output; 17 | -------------------------------------------------------------------------------- /src/ai/mod.rs: -------------------------------------------------------------------------------- 1 | //! AI相关模块 2 | //! 在不匹配其它命令的情况默认为AI问答,单次对话 3 | 4 | mod chatgpt; 5 | 6 | pub use chatgpt::chatgpt; 7 | 8 | pub const PROMPT_SHELL_OUTPUT: &str = "作为Shell命令输出分析AI助手,请对给定的任何命令输出执行以下分析: 9 | 简要说明可能的命令类型和输出主要内容。 10 | 列出输出中的关键数据类型或字段。 11 | 突出显示最重要或异常的信息。 12 | 指出任何错误信息或警告。 13 | 根据输出,简要推断系统状态或配置。 14 | 请直接提供简洁、专业的分析结果,无需额外解释或建议。请使用Markdown格式组织你的回答,包括适当的标题、列表和代码块。"; 15 | 16 | // ai分析json数据的提示词 17 | pub const PROMPT_IP_JSON: &str = r#" 18 | 请分析下面的IP信息JSON数据,并提供一个简洁的总结,包括以下要点: 19 | IP地址和所属公司/组织 20 | 地理位置(国家、城市) 21 | ASN信息 22 | 是否为代理、VPN或托管服务 23 | 任何特殊用途(如DNS服务器) 24 | 其他值得注意的重要信息 25 | 请用3-5句话概括最关键的发现。(以markdown格式回复我)"#; 26 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Clippy 20 | run: cargo clippy 21 | - name: Build 22 | run: cargo build --verbose 23 | - name: Run tests 24 | run: cargo test --verbose 25 | - name: Run cargo update 26 | run: cargo update 27 | - name: Install cargo audit 28 | run: cargo install cargo-audit 29 | - name: Audit 30 | run: cargo audit -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 停止脚本执行时发生错误 4 | set -e 5 | 6 | # 编译项目 7 | echo "构建tgbot-app项目..." 8 | cargo build -r 9 | 10 | # 停止服务 11 | echo "停止 tgbot-app 服务..." 12 | sudo systemctl stop tgbot-app 13 | 14 | # 复制构建输出文件 15 | echo "复制 tgbot-app 可执行文件到 /root/tgbot-app/..." 16 | sudo cp target/release/tgbot-app /root/tgbot-app/ 17 | 18 | # 设定可执行权限 19 | echo "设置 tgbot-app 可执行权限..." 20 | sudo chmod +x /root/tgbot-app/tgbot-app 21 | 22 | # 复制配置文件 23 | echo "复制配置文件到 /root/tgbot-app/..." 24 | sudo cp config.toml /root/tgbot-app/ 25 | 26 | # 重新加载 systemd 27 | echo "重新加载 systemd 守护进程..." 28 | sudo systemctl daemon-reload 29 | 30 | # 重启服务 31 | echo "重启 tgbot-app 服务..." 32 | sudo systemctl restart tgbot-app 33 | 34 | echo "操作完成。" 35 | -------------------------------------------------------------------------------- /src/shell/ping.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 2 | use tokio::process::Command; 3 | 4 | use ferrisgram::error::Result; 5 | 6 | pub async fn ping(bot: Bot, ctx: Context) -> Result { 7 | // Same logic as chat applies on unwrapping effective message here. 8 | let msg = ctx.effective_message.unwrap(); 9 | let chat_id = msg.chat.id; 10 | let cm = msg.text.unwrap(); 11 | let cm = &cm[7..].trim(); 12 | 13 | let output = Command::new("ping") 14 | .args(["-c", "4", cm]) 15 | .output() 16 | .await 17 | .expect("ping command failed") 18 | .stdout; 19 | 20 | bot.send_message(chat_id, String::from_utf8_lossy(&output).to_string()) 21 | .send() 22 | .await?; 23 | 24 | Ok(GroupIteration::EndGroups) 25 | } 26 | -------------------------------------------------------------------------------- /wordlist.txt: -------------------------------------------------------------------------------- 1 | root 2 | admin 3 | password 4 | 123456 5 | test_data 6 | 1 7 | 2 8 | 3 9 | 4 10 | 5 11 | 6 12 | 7 13 | 8 14 | 9 15 | 10 16 | 11 17 | 12 18 | 13 19 | 14 20 | 15 21 | 16 22 | 17 23 | 18 24 | 19 25 | 20 26 | 21 27 | 22 28 | 23 29 | 24 30 | 25 31 | 26 32 | 27 33 | 28 34 | 29 35 | 30 36 | 31 37 | 32 38 | 33 39 | 34 40 | 35 41 | 36 42 | 37 43 | 38 44 | 39 45 | 40 46 | 41 47 | 42 48 | 43 49 | 44 50 | 45 51 | 46 52 | 47 53 | 48 54 | 49 55 | 50 56 | 51 57 | 52 58 | 53 59 | 54 60 | 55 61 | 56 62 | 57 63 | 58 64 | 59 65 | 60 66 | 61 67 | 62 68 | 63 69 | 64 70 | 65 71 | 66 72 | 67 73 | 68 74 | 69 75 | 70 76 | 71 77 | 72 78 | 73 79 | 74 80 | 75 81 | 76 82 | 77 83 | 78 84 | 79 85 | 80 86 | 81 87 | 82 88 | 83 89 | 84 90 | 85 91 | 86 92 | 87 93 | 88 94 | 89 95 | 90 96 | 91 97 | 92 98 | 93 99 | 94 100 | 95 101 | 96 102 | 97 103 | 98 104 | 99 105 | 100 -------------------------------------------------------------------------------- /src/shell/ls.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 2 | use tklog::{async_error, async_info}; 3 | use tokio::process::Command; 4 | 5 | use ferrisgram::error::Result; 6 | 7 | /// 列出当前目录下的内容,不支持指定参数,默认参数为-lah 8 | /// ```txt 9 | /// /ls 10 | /// ``` 11 | pub async fn ls(bot: Bot, ctx: Context) -> Result { 12 | // Same logic as chat applies on unwrapping effective message here. 13 | let msg = ctx.effective_message.unwrap(); 14 | let chat_id = msg.chat.id; 15 | 16 | if let Ok(output) = Command::new("ls").args(["-l", "-a", "-h"]).output().await { 17 | bot.send_message(chat_id, String::from_utf8_lossy(&output.stdout).to_string()) 18 | .send() 19 | .await?; 20 | async_info!("ls命令调用成功"); 21 | } else { 22 | bot.send_message(chat_id, "ls命令调用失败".to_owned()) 23 | .send() 24 | .await?; 25 | async_error!("ls命令调用失败"); 26 | } 27 | 28 | Ok(GroupIteration::EndGroups) 29 | } 30 | -------------------------------------------------------------------------------- /src/cron.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use ferrisgram::Bot; 4 | use serde_json::Value; 5 | use tgbot_app::{util::REQWEST_CLIENT, GLOBAL_CONFIG}; 6 | 7 | pub async fn tianqi(bot: Arc) { 8 | let tianqi:Value = REQWEST_CLIENT.get("https://cn.apihz.cn/api/tianqi/tqyb.php?id=88888888&key=88888888&sheng=湖南&place=长沙") 9 | .send().await.unwrap().json().await.unwrap(); 10 | // 公共id key容易失败 11 | if tianqi["place"] == "null" { 12 | return; 13 | } 14 | let str_format = format!( 15 | " 16 | *☀️ 天气预报 ☀️* 17 | 18 | 🏙️ *地区*: {} 19 | 🌡️ *温度*: {}°C 20 | 💧 *湿度*: {}% 21 | 🌬️ *风速*: {}m/s 22 | 🍃 *风力等级*: {} 23 | ", 24 | tianqi["place"], 25 | tianqi["temperature"], 26 | tianqi["humidity"], 27 | tianqi["windSpeed"], 28 | tianqi["windScale"] 29 | ); 30 | let _ = bot 31 | .send_message(GLOBAL_CONFIG.telegram.ids[0], str_format) 32 | .parse_mode(String::from("markdown")) 33 | .send() 34 | .await; 35 | } 36 | -------------------------------------------------------------------------------- /src/ai/chatgpt.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::error::Result; 2 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 3 | 4 | use crate::util::ai_q_s; 5 | 6 | pub async fn chatgpt(bot: Bot, ctx: Context) -> Result { 7 | // Same logic as chat applies on unwrapping effective message here. 8 | let msg = ctx.effective_message.unwrap(); 9 | let chat_id = msg.chat.id; 10 | let cm = msg.text.unwrap(); 11 | // let cm = cm[9..].trim(); 12 | // 默认为AI问答,如果是从handle过来的则不去除前面的命令 13 | let cm = if cm.starts_with("/chatgpt") { 14 | cm[9..].trim() 15 | } else { 16 | cm[..].trim() 17 | }; 18 | 19 | // let _ = ai_q_s(&bot, chat_id, cm).await; 20 | let ai_result = ai_q_s(cm).await; 21 | if let Ok(ai_answer) = ai_result { 22 | let _ = bot.send_message(chat_id, ai_answer).send().await; 23 | } else { 24 | let _ = bot 25 | .send_message(chat_id, "AI请求失败".to_string()) 26 | .send() 27 | .await; 28 | } 29 | Ok(GroupIteration::EndGroups) 30 | } 31 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tgbot-app" 3 | version = "0.2.14" 4 | edition = "2021" 5 | authors = ["HZzz2", "Leslie", "hzzz2yb@gmail.com"] 6 | repository = "https://github.com/HZzz2/tgbot-app" 7 | description = "Telegram Bot助手" 8 | keywords = ["Telegram", "bot", "assistant","telegram","TGBot"] 9 | # default-run = "tgbot-app" 10 | 11 | [dependencies] 12 | # Telegram Bot API 13 | ferrisgram = "0.2.1" 14 | # log 15 | tklog = "0.2.7" 16 | serde_derive = "1.0.219" 17 | serde_json = "1.0.140" 18 | serde = { version = "1.0.219", features = ["derive"] } 19 | toml = "0.8.20" 20 | # anyhow = "1.0.86" 21 | anyhow = { version = "1.0.97", default-features = false } 22 | once_cell = "1.21.3" 23 | reqwest = { version = "0.12.15", default-features = false, features = ["json", "rustls-tls", "socks"] } 24 | tokio = { version = "1.44.1", features = ["full"] } 25 | # rusty_ytdl = "0.7.4" # 目前无法下载油管 26 | # ssh brute 27 | async-ssh2-tokio = "0.8.14" 28 | async-channel = "2.3.1" 29 | # email send 30 | resend-rs = "0.12.1" 31 | tokio-cron-scheduler = "0.13.0" 32 | chrono = "0.4.40" 33 | chrono-tz = "0.10.3" 34 | 35 | 36 | # [profile.release] 37 | # lto = true # 2024年7月27日 release size 24MB -> 19MB 38 | # panic = "abort" # size 19MB -> 16MB 39 | -------------------------------------------------------------------------------- /src/download/aria2c.rs: -------------------------------------------------------------------------------- 1 | use crate::util::chunks_msg; 2 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 3 | 4 | use ferrisgram::error::Result; 5 | 6 | pub async fn aria2c(bot: Bot, ctx: Context) -> Result { 7 | // Same logic as chat applies on unwrapping effective message here. 8 | let msg = ctx.effective_message.unwrap(); 9 | let chat_id = msg.chat.id; 10 | let cm = msg.text.unwrap(); 11 | let link = cm[8..].trim(); 12 | 13 | let com = format!("aria2c -d aria2c_download -x 16 -s 16 {}", link); 14 | let task = tokio::task::spawn_blocking(move || { 15 | std::process::Command::new("sh") 16 | .arg("-c") 17 | .arg(com) 18 | .output() 19 | .unwrap() 20 | }); 21 | 22 | let msg = bot 23 | .send_message(chat_id, "正在使用aria2c下载文件中···".to_string()) 24 | .disable_notification(true) 25 | .send() 26 | .await 27 | .unwrap(); 28 | let output = task.await; 29 | 30 | let status = output.as_ref().unwrap().status; 31 | let result = if status.success() { 32 | String::from("文件下载成功") 33 | } else { 34 | let out = output.as_ref().unwrap().stdout.clone(); 35 | let err = output.unwrap().stderr; 36 | format!( 37 | " 38 | *文件下载失败*: 39 | stdout: {:?} 40 | stderr: {:?} 41 | ", 42 | out, err 43 | ) 44 | }; 45 | 46 | // bot.send_message(chat_id, result) 47 | // .parse_mode("markdown".to_string()) 48 | // .send() 49 | // .await?; 50 | let _ = chunks_msg(&bot, chat_id, result).await; 51 | bot.delete_message(chat_id, msg.message_id).send().await?; 52 | // 修改消息不会修改消息时间,不能知晓下载所花费的时间 53 | // bot.edit_message_text(result).chat_id(chat_id).message_id(msg.message_id).send().await?; 54 | Ok(GroupIteration::EndGroups) 55 | } 56 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::HashMap, 3 | sync::Arc, 4 | }; 5 | 6 | use once_cell::sync::Lazy; 7 | 8 | use serde::Deserialize; 9 | 10 | // pub mod macros; 11 | pub mod ai; 12 | pub mod brute_force; 13 | pub mod download; 14 | pub mod osint; 15 | pub mod server; 16 | pub mod shell; 17 | pub mod util; 18 | 19 | /// 获取tgbot-app配置文件信息 20 | pub static GLOBAL_CONFIG: Lazy> = Lazy::new(|| { 21 | // let config_str = include_str!("../config.toml"); // 编译期会将内容包含在可执行程序中 22 | let config_str = std::fs::read_to_string("./config.toml").expect("未找到config.toml"); 23 | let config = toml::from_str::(&config_str).expect("Failed to parse config.toml"); 24 | Arc::new(config) 25 | }); 26 | 27 | // 反序列化配置信息 28 | #[derive(Deserialize, Debug, Clone)] 29 | pub struct Config { 30 | pub telegram: Telegram, // TG相关配置信息 31 | pub openai: Chatgpt, // AI相关配置信息 32 | pub command: Command, // 常用命令定制配置信息 33 | pub reqwest: Reqwest, 34 | pub brute_force: BruteForce, 35 | pub yt_dlp: YtDlp, 36 | pub y_ytdl: YYtdl, 37 | pub resend: ReSend, 38 | } 39 | 40 | #[derive(Deserialize, Debug, Clone)] 41 | pub struct Telegram { 42 | pub bot_token: String, 43 | // pub ids: HashSet, 44 | pub ids: Vec, 45 | } 46 | 47 | #[derive(Deserialize, Debug, Clone)] 48 | pub struct Chatgpt { 49 | pub base_url: String, 50 | pub model: String, 51 | pub api_key: String, 52 | } 53 | 54 | #[derive(Deserialize, Debug, Clone)] 55 | pub struct Command { 56 | // pub cmd: BTreeMap, 57 | pub cmd: Vec>, 58 | } 59 | 60 | #[derive(Deserialize, Debug, Clone)] 61 | pub struct Reqwest { 62 | pub user_agent: String, 63 | pub proxy: String, 64 | } 65 | 66 | #[derive(Deserialize, Debug, Clone)] 67 | pub struct BruteForce { 68 | pub ssh: HashMap, 69 | } 70 | 71 | #[derive(Deserialize, Debug, Clone)] 72 | pub struct YtDlp { 73 | pub cookie: String, 74 | pub proxy: String, 75 | pub args: String, 76 | } 77 | 78 | #[derive(Deserialize, Debug, Clone)] 79 | pub struct YYtdl { 80 | pub proxy: String, 81 | pub hight_audio_save: bool, 82 | } 83 | 84 | #[derive(Deserialize, Debug, Clone)] 85 | pub struct ReSend { 86 | pub api_key: String, 87 | pub from: String, 88 | } 89 | -------------------------------------------------------------------------------- /src/callback_handler.rs: -------------------------------------------------------------------------------- 1 | use crate::util::ai_q_s; 2 | use ferrisgram::error::Result; 3 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 4 | 5 | use crate::ai::PROMPT_SHELL_OUTPUT; 6 | use crate::osint::{cb_dnsenum, cb_dnsrecon, cb_ip123}; 7 | // use crate::{ai::chatgpt, yt_audio}; 8 | 9 | // 消息处理函数 10 | pub async fn callback_handler(bot: Bot, ctx: Context) -> Result { 11 | let msg = ctx.clone().effective_message.unwrap(); 12 | let user_id = ctx.clone().effective_user.unwrap().id; 13 | 14 | tgbot_app::verify_telegram_id!(user_id); 15 | 16 | let chat_id = msg.chat.id; 17 | //按钮的原始文本 18 | let raw_content = msg.text.unwrap(); 19 | 20 | //回调内容 21 | let content = ctx.update.callback_query.unwrap().data.unwrap(); 22 | 23 | let vec_content = content.split(' ').collect::>(); 24 | 25 | match vec_content.as_slice() { 26 | ["osint", "ip", "cb_ip123", arg] => { 27 | let _ = cb_ip123(arg, bot, chat_id).await; 28 | } 29 | ["osint", "dns", "cb_dnsrecon", arg] => { 30 | let _ = cb_dnsrecon(arg, bot, chat_id).await; 31 | } 32 | ["osint", "dns", "cb_dnsenum", arg] => { 33 | let _ = cb_dnsenum(arg, bot, chat_id).await; 34 | } 35 | ["AI分析", "PROMPT_SHELL_OUTPUT"] => { 36 | let res = ai_q_s(format!("{}:\n{}", PROMPT_SHELL_OUTPUT, raw_content)) 37 | .await 38 | .unwrap(); 39 | let _ = bot 40 | .send_message(chat_id, res) 41 | .parse_mode("markdown".to_string()) 42 | .send() 43 | .await; 44 | } 45 | ["AI分析", prompt] => { 46 | let res = ai_q_s(format!("{}:\n{}", prompt, raw_content)) 47 | .await 48 | .unwrap(); 49 | let _ = bot 50 | .send_message(chat_id, res) 51 | .parse_mode("markdown".to_string()) 52 | .send() 53 | .await; 54 | } 55 | _ => { 56 | let _ = bot 57 | .send_message(chat_id, "*未知回调匹配*".to_string()) 58 | .parse_mode("markdown".to_string()) 59 | .send() 60 | .await; 61 | } 62 | } 63 | Ok(GroupIteration::EndGroups) 64 | } 65 | -------------------------------------------------------------------------------- /src/shell/any_shell_command.rs: -------------------------------------------------------------------------------- 1 | use crate::util::{chunks_msg, send_err_msg}; 2 | use ferrisgram::error::Result; 3 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 4 | use std::process::Stdio; 5 | use std::time::Instant; 6 | use tokio::process::Command; 7 | 8 | pub async fn shell(bot: Bot, ctx: Context) -> Result { 9 | let msg = ctx.effective_message.unwrap(); 10 | let chat_id = msg.chat.id; 11 | 12 | let cm = msg.text.unwrap(); 13 | let cm = &cm[7..].trim(); // 去掉 "/shell " 前缀 14 | 15 | bot.send_message(chat_id, format!("收到命令: {}", cm)) 16 | .send() 17 | .await?; 18 | 19 | if cm.is_empty() { 20 | send_err_msg(bot, chat_id, "命令为空".to_string()).await; 21 | return Ok(GroupIteration::EndGroups); 22 | } 23 | 24 | let start_time = Instant::now(); 25 | 26 | let output = Command::new("bash") 27 | .arg("-c") 28 | .arg(cm) 29 | .stdout(Stdio::piped()) 30 | .stderr(Stdio::piped()) 31 | .output() 32 | .await; 33 | 34 | let elapsed_secs = start_time.elapsed().as_secs(); 35 | let time_format = if elapsed_secs > 60 { 36 | let minutes = elapsed_secs / 60; 37 | let seconds = elapsed_secs % 60; 38 | format!("{} 分 {} 秒", minutes, seconds) 39 | } else { 40 | format!("{} 秒", elapsed_secs) 41 | }; 42 | 43 | // bot.send_message(chat_id, format!("命令耗时: {:?}", time_format)) 44 | // .send() 45 | // .await?; 46 | match output { 47 | Ok(output) => { 48 | let stdout = String::from_utf8_lossy(&output.stdout); 49 | let stderr = String::from_utf8_lossy(&output.stderr); 50 | let status = output.status; 51 | 52 | let message = format!( 53 | "命令执行结果:\n\ 54 | 状态: {}\n\ 55 | 执行时间: {:?}\n\ 56 | 命令: {}\n\n\ 57 | 标准输出 (长度 {} 字节):\n{}\n\n\ 58 | 错误输出 (长度 {} 字节):\n{}", 59 | status, 60 | time_format, 61 | cm, 62 | stdout.len(), 63 | stdout, 64 | stderr.len(), 65 | stderr 66 | ); 67 | 68 | // 分段发送消息 69 | let _ = chunks_msg(&bot, chat_id, message).await; 70 | } 71 | Err(e) => { 72 | send_err_msg(bot, chat_id, format!("命令执行失败: {:?}", e)).await; 73 | } 74 | } 75 | 76 | Ok(GroupIteration::EndGroups) 77 | } 78 | -------------------------------------------------------------------------------- /src/server/resend.rs: -------------------------------------------------------------------------------- 1 | use crate::util::send_err_msg; 2 | use ferrisgram::error::GroupIteration; 3 | use ferrisgram::error::Result; 4 | use ferrisgram::ext::Context; 5 | use ferrisgram::Bot; 6 | use resend_rs::types::CreateEmailBaseOptions; 7 | use resend_rs::Resend; 8 | // use crate::verify_telegram_id; 9 | use crate::GLOBAL_CONFIG; 10 | 11 | pub async fn resend(bot: Bot, ctx: Context) -> Result { 12 | let msg = ctx.effective_message.unwrap(); 13 | let chat_id = msg.chat.id; 14 | 15 | let api_key = &GLOBAL_CONFIG.resend.api_key; 16 | let from = &GLOBAL_CONFIG.resend.from; 17 | if api_key.is_empty() || from.is_empty() { 18 | //todo err msg send 19 | let msg = r#" 20 | 如需使用[resend](https://resend.com)需要添加api_key和发送邮箱地址(from) 21 | 在网站上申请密钥和验证邮箱后填入配置文件中并重启程序服务,如`systemctl restart tgbot-app` 22 | 使用方式:`/resend 接收邮箱地址###邮件标题###邮件正文` 23 | 比如:`/resend abc@efg.com###全民制作人们大家好###我喜欢唱跳Rap篮球,CTRL!!!` 24 | "#; 25 | send_err_msg(bot, chat_id, msg.to_string()).await; 26 | return Ok(GroupIteration::EndGroups); 27 | } 28 | 29 | let resend = Resend::new(api_key); 30 | 31 | let all_content = msg.text.unwrap(); 32 | let use_content: Vec<&str> = all_content[8..].split("###").map(|c| c.trim()).collect(); 33 | if use_content.len() != 3 { 34 | let msg = r#" 35 | 使用方式:`/resend 接收邮箱地址###邮件标题###邮件正文` 36 | 比如:`/resend abc@efg.com###全民制作人们大家好###我喜欢唱跳Rap篮球,CTRL!!!` 37 | "#; 38 | send_err_msg(bot, chat_id, msg.to_string()).await; 39 | return Ok(GroupIteration::EndGroups); 40 | } 41 | let to = [use_content[0]]; 42 | let subject = use_content[1]; 43 | 44 | // let filename = "invoice.pdf"; 45 | // let mut f = File::open(filename).await.unwrap(); 46 | // let mut invoice = Vec::new(); 47 | // f.read_to_end(&mut invoice).await.unwrap(); 48 | 49 | let email = CreateEmailBaseOptions::new(from, to, subject).with_text(use_content[2]); 50 | // .with_attachment(Attachment::from_content(invoice).with_filename(filename)) 51 | // .with_header("X-Entity-Ref-ID", "123456789") 52 | // .with_tag(Tag::new("category", "confirm_email")); 53 | 54 | // let _email = resend.emails.send(email).await.unwrap(); 55 | match resend.emails.send(email).await { 56 | Ok(_) => { 57 | let _ = bot 58 | .send_message(chat_id, "邮件发送成功".to_string()) 59 | .send() 60 | .await; 61 | } 62 | Err(e) => { 63 | let _ = bot 64 | .send_message(chat_id, format!("邮件发送失败:{:#?}", e)) 65 | .send() 66 | .await; 67 | } 68 | } 69 | 70 | Ok(GroupIteration::EndGroups) 71 | } 72 | -------------------------------------------------------------------------------- /src/download/yt_dlp.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use crate::GLOBAL_CONFIG; 4 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 5 | 6 | use ferrisgram::error::Result; 7 | 8 | pub async fn ytdlp(bot: Bot, ctx: Context) -> Result { 9 | // Same logic as chat applies on unwrapping effective message here. 10 | let msg = ctx.effective_message.unwrap(); 11 | let chat_id = msg.chat.id; 12 | let cm = msg.text.unwrap(); 13 | let link = cm[7..].trim(); 14 | 15 | let cookie = GLOBAL_CONFIG.yt_dlp.cookie.as_str(); 16 | let proxy = GLOBAL_CONFIG.yt_dlp.proxy.as_str(); 17 | let args = GLOBAL_CONFIG.yt_dlp.args.as_str(); 18 | 19 | let mut com = Vec::new(); 20 | com.push("./yt-dlp"); 21 | 22 | if !cookie.is_empty() { 23 | com.extend_from_slice(&["--cookies", cookie]); 24 | } 25 | 26 | if !proxy.is_empty() { 27 | com.extend_from_slice(&["--proxy", proxy]); 28 | } 29 | 30 | if !args.is_empty() { 31 | com.push(args); 32 | } 33 | 34 | com.push(link); 35 | let command_string = com.join(" "); 36 | let comm_string = command_string.clone(); 37 | 38 | let task = tokio::task::spawn_blocking(move || { 39 | std::process::Command::new("sh") 40 | .arg("-c") 41 | .arg(command_string.clone()) 42 | .output() 43 | .unwrap() 44 | }); 45 | 46 | let msg = bot 47 | .send_message( 48 | chat_id, 49 | format!("正在使用yt-dlp下载视频中···{}", comm_string), 50 | ) 51 | .disable_notification(true) 52 | .send() 53 | .await 54 | .unwrap(); 55 | let output = task.await; 56 | 57 | let status = output.as_ref().unwrap().status; 58 | let result = if status.success() { 59 | String::from("视频下载成功") 60 | } else { 61 | let file_name = "yt-dlp"; 62 | let path = Path::new(file_name); 63 | if !path.exists() { 64 | let err_msg = r#" 65 | 当前工作目录没有yt-dlp程序: 66 | ```shell 67 | wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp 68 | mv ./yt-dlp /root/tgbot_app 69 | cd !$ 70 | chmod +x yt-dlp 71 | ``` 72 | "#; 73 | String::from(err_msg) 74 | } else { 75 | let out = output.as_ref().unwrap().stdout.clone(); 76 | let err = output.unwrap().stderr; 77 | format!( 78 | " 79 | *视频下载失败*: 80 | stdout: {:?} 81 | stderr: {:?} 82 | ", 83 | out, err 84 | ) 85 | } 86 | }; 87 | 88 | bot.send_message(chat_id, result) 89 | .parse_mode("markdown".to_string()) 90 | .send() 91 | .await?; 92 | bot.delete_message(chat_id, msg.message_id).send().await?; 93 | // 修改消息不会修改消息时间,不能知晓下载所花费的时间 94 | // bot.edit_message_text(result).chat_id(chat_id).message_id(msg.message_id).send().await?; 95 | Ok(GroupIteration::EndGroups) 96 | } 97 | -------------------------------------------------------------------------------- /src/brute_force/sha1_cracker.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 2 | use tklog::{async_error, async_info}; 3 | use tokio::{fs::File, io::BufReader, process::Command}; 4 | 5 | use ferrisgram::error::Result; 6 | 7 | const SHA1_HEX_STRING_LENGTH: usize = 40; 8 | 9 | /// sha1哈希爆破 10 | /// ```txt 11 | /// /sha1 hash or 12 | /// /sha1 hash 本地字典文件 or 13 | /// /sha1 hash 在线字典地址 14 | /// ``` 15 | pub async fn sha1_cracker(bot: Bot, ctx: Context) -> Result { 16 | // Same logic as chat applies on unwrapping effective message here. 17 | let msg = ctx.effective_message.unwrap(); 18 | let chat_id = msg.chat.id; 19 | 20 | let text = msg.text.unwrap(); 21 | if text.len() == 5 { 22 | let usage = r#" 23 | 使用方式: 24 | ```txt 25 | /sha1 hash // 默认本地sha1字典,config中配置 26 | /sha1 hash 本地字典文件 // 指定本地字典 27 | /sha1 hash 在线字典地址 // 在线字典地址URL 28 | ``` 29 | "#; 30 | bot.send_message(chat_id, usage.to_string()) 31 | .parse_mode("markdown".to_string()) 32 | .send() 33 | .await 34 | .unwrap(); 35 | return Ok(GroupIteration::EndGroups); 36 | } 37 | let text = text[6..].trim(); 38 | let input: Vec<&str> = text.split(' ').collect(); 39 | 40 | match input.len() { 41 | 1 => sha1_brute(input[0], bot, chat_id).await, 42 | 2 => sha1_brute_file(input[0], input[1], bot, chat_id).await, 43 | _ => { 44 | let usage = r#" 45 | 使用方式: 46 | ```txt 47 | /sha1 hash // 默认本地sha1字典,config中配置 48 | /sha1 hash 本地字典文件 // 指定本地字典 49 | /sha1 hash 在线字典地址 // 在线字典地址URL 50 | ``` 51 | "#; 52 | bot.send_message(chat_id, usage.to_string()) 53 | .parse_mode("markdown".to_string()) 54 | .send() 55 | .await 56 | .unwrap(); 57 | return Ok(GroupIteration::EndGroups); 58 | } 59 | } 60 | 61 | // bot.send_message(chat_id, input.join("-")) 62 | // .send() 63 | // .await 64 | // .unwrap(); 65 | 66 | Ok(GroupIteration::EndGroups) 67 | } 68 | 69 | async fn sha1_brute(hash: &str, bot: Bot, chat_id: i64) { 70 | if hash.len() != SHA1_HEX_STRING_LENGTH { 71 | let _ = bot 72 | .send_message(chat_id, "请输入正确的sha1哈希(40位)".to_string()) 73 | .send() 74 | .await; 75 | return; 76 | } 77 | // todo 暂且先这个字典文件,实际为配置定义的文件名 配置还没加 78 | let wordlist_file = File::open("./wordlist.txt").await.unwrap(); 79 | let reader = BufReader::new(wordlist_file); 80 | } 81 | 82 | async fn sha1_brute_file(hash: &str, file: &str, bot: Bot, chat_id: i64) { 83 | if hash.len() != SHA1_HEX_STRING_LENGTH { 84 | let _ = bot 85 | .send_message(chat_id, "请输入正确的sha1哈希(40位)".to_string()) 86 | .send() 87 | .await; 88 | return; 89 | } 90 | // todo 可以是本地文件或在线字典,如果是在线字典则下载到本地使用 91 | let wordlist_file = File::open(file).await.unwrap(); 92 | let reader = BufReader::new(wordlist_file); 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/shell/shell_no_output.rs: -------------------------------------------------------------------------------- 1 | use crate::util::send_err_msg; 2 | use ferrisgram::error::Result; 3 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 4 | use std::process::Stdio; 5 | use std::time::Instant; 6 | use tokio::process::Command; 7 | 8 | pub async fn shell_no_output(bot: Bot, ctx: Context) -> Result { 9 | let msg = ctx.effective_message.unwrap(); 10 | let chat_id = msg.chat.id; 11 | let cm = msg.text.unwrap(); 12 | let cm = &cm[17..].trim(); // 去掉 "/shell_no_output " 前缀 13 | 14 | bot.send_message(chat_id, format!("收到命令: {}\t正在执行中", cm)) 15 | .send() 16 | .await?; 17 | 18 | if cm.is_empty() { 19 | send_err_msg(bot, chat_id, "命令为空".to_string()).await; 20 | return Ok(GroupIteration::EndGroups); 21 | } 22 | 23 | let start_time = Instant::now(); 24 | 25 | let output = Command::new("bash") 26 | .arg("-c") 27 | .arg(cm) 28 | .stdout(Stdio::piped()) 29 | .stderr(Stdio::piped()) 30 | .output() 31 | .await; 32 | 33 | let elapsed_secs = start_time.elapsed().as_secs(); 34 | let time_format = if elapsed_secs > 60 { 35 | let minutes = elapsed_secs / 60; 36 | let seconds = elapsed_secs % 60; 37 | format!("{} 分 {} 秒", minutes, seconds) 38 | } else { 39 | format!("{} 秒", elapsed_secs) 40 | }; 41 | 42 | // bot.send_message(chat_id, format!("命令耗时: {:?}", time_format)) 43 | // .send() 44 | // .await?; 45 | 46 | match output { 47 | Ok(output) => { 48 | // let stdout = String::from_utf8_lossy(&output.stdout); 49 | // let stderr = String::from_utf8_lossy(&output.stderr); 50 | // let status = output.status; 51 | 52 | // let message = format!( 53 | // "命令执行结果:\n\ 54 | // 状态: {}\n\ 55 | // 执行时间: {:?}\n\ 56 | // 命令: {}\n\n\ 57 | // 标准输出 (长度 {} 字节):\n{}\n\n\ 58 | // 错误输出 (长度 {} 字节):\n{}", 59 | // status, duration, cm, stdout.len(), stdout, stderr.len(), stderr 60 | // ); 61 | 62 | // 分段发送消息 63 | // let _ = chunks_msg(&bot, chat_id, message).await; 64 | 65 | let status = output.status; 66 | if status.success() { 67 | bot.send_message( 68 | chat_id, 69 | format!("执行命令成功!耗时:{}\t命令:{}", time_format, cm), 70 | ) 71 | .send() 72 | .await?; 73 | } else { 74 | send_err_msg( 75 | bot, 76 | chat_id, 77 | format!("命令执行失败,耗时:{}\t命令:{}", time_format, cm), 78 | ) 79 | .await; 80 | } 81 | } 82 | Err(e) => { 83 | send_err_msg( 84 | bot, 85 | chat_id, 86 | format!("命令执行失败: {:?}\t失败的命令:{}", e, cm), 87 | ) 88 | .await; 89 | } 90 | } 91 | 92 | Ok(GroupIteration::EndGroups) 93 | } 94 | -------------------------------------------------------------------------------- /config-template.toml: -------------------------------------------------------------------------------- 1 | ### 使用前修改为自己的内容参数并将配置文件更名为:config.toml 2 | ### $cp config-template.toml config.toml 3 | ### 为了调用本地系统资源或程序,推荐使用系统服务的方式启动而不是docker启动 4 | 5 | [telegram] 6 | bot_token = "6763******uQ" #telegram bot token 通过BotFather申请获得:https://t.me/BotFather 7 | ids = [6111119, 6222228] # telegram user id 可使用此bot的id,可多个 获取ID:https://t.me/get_id_bot 8 | 9 | 10 | [openai] #兼容openai chatgpt请求格式的模型api调用应该都可以正常使用 11 | base_url = "https://api.openai.com/v1/chat/completions" # 请求地址 可更改 12 | model = "gpt-3.5-turbo" # 模型名,可更改"gpt-4"等受支持模型 13 | api_key = "sk-kx****57c71" # API KEY 14 | 15 | 16 | [command] # 定制常用的命令,使用方式:`/c 1` 或 `/c 跳`,输入不存在的key则显示所有已定制的命令,如/c 999 17 | cmd = [ 18 | {"1" = "curl ipinfo.io"}, 19 | {"2" = "df -h"}, 20 | {"3" = "curl ip.fm"}, 21 | {"4" = "curl wttr.in/Hunan"}, 22 | {"c" = "free -m"}, 23 | {"唱" = "id"}, 24 | {"跳" = "curl https://uapis.cn/api/say"}, 25 | {"rap" = "ip -s -s -h link ls dev eth0"}, 26 | { "查看当前所在目录" = "pwd"} 27 | ] 28 | 29 | 30 | [reqwest] #机器人在使用reqwest库发送网络请求时附带的参数 部分网站会检查UA 31 | user_agent = "tgbot-app" 32 | #user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0" 33 | proxy = "" 34 | # proxy = "http://username:password@1.2.3.4:1880" 35 | # proxy = "https://username:password@1.2.3.4:1880" 36 | # proxy = "socks5://1.2.3.4:1880" #好像不支持带账密验证的socks5,HTTP/HTTPS可带可不带 37 | 38 | 39 | [brute_force] 40 | ssh = { "username" = "root", "port" = "22", "brute_file" = "./wordlist.txt", "threads" = "16", "display_message_time_interval_seconds" = "5" } 41 | 42 | 43 | #使用此命令需下载yt-dlp程序到工作目录并添加执行权限chmod +x yt-dlp 44 | [yt_dlp] # 使用yt-dlp时是否使用cookie或代理,或一起使用 45 | cookie = "" #填入文件名,比如:"ytb-cookie.txt" 使用浏览器插件(https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)获取youtube cookie的文本文件,然后上传放到工作目录。比如我的是:/root/tgbot-app下 46 | proxy = "" # 为空则不使用代理,默认不使用代理 (由于某些IP会被油管禁止,如果无法下载可以使用cookie或代理,或同时使用) HTTP代理下载速度貌似比socks5更快,推荐 47 | #proxy = "socks5://username:password@1.2.3.4:1080" # 支持HTTP/HTTPS/SOCKS proxy yt-dlp可选身份验证 48 | args = "" #传递给yt-dlp的任意参数,可放多个。 49 | 50 | [y_ytdl] # 目前reqwest好像不支持带身份验证socks5。HTTP/HTTPS可选择带身份验证,推荐 51 | proxy = "" # 为空则不使用代理,默认不使用代理 (由于某些IP会被油管禁止(要求验证),如果无法下载可以使用代理) 52 | #proxy = "http://username:password@1.2.3.4:1880" # HTTP/HTTPS可选身份验证,暂不支持带有账号密码验证的socks5。 reqwest crate本人测试后发现无法使用带身份验证的socks5代理 如果要使用,socks5要没有身份验证的才行,不推荐,推荐HTTP 53 | hight_audio_save = false #在低品质音频发送失败时是否删除高音质音频,serv00建议开启:true 54 | 55 | 56 | 57 | # 如需使用[resend](https://resend.com)需要添加api_key和发送邮箱地址(from) 58 | # 在网站上申请密钥和验证邮箱后填入配置文件中并重启程序服务,如`systemctl restart tgbot-app` 59 | # 使用方式:/resend 接收邮箱地址###邮件标题###邮件正文 ps:使用三个连续的#来分割 60 | # 比如:/resend abc@efg.com###全民制作人们大家好###我喜欢唱跳Rap篮球,CTRL!!! 61 | [resend] #使用此方式发送不会暴露自己的真实邮箱(如:gmail),虽然也会显示代发,实际的发送地址是from,代发的地址显示为:前面随机字符@你的域名。如果使用gmail发送,代发地址会显示gmail地址 62 | api_key = "" 63 | from = "" 64 | # api_key = "re_********U" 65 | # from = "abc@efg.com" 66 | #目前resend限制每天免费发送100次 每月免费3000次 67 | 68 | 69 | 70 | # 以系统服务的方式运行此程序 71 | # vim /etc/systemd/system/tgbot-app.service 72 | # 添加一下内容 73 | # [Unit] 74 | # Description=电报机器人程序 75 | # After=network.target 76 | 77 | # [Service] 78 | # ExecStart=/root/tgbot-app/tgbot-app 79 | # WorkingDirectory=/root/tgbot-app 80 | # Restart=always 81 | 82 | # [Install] 83 | # WantedBy=default.targe 84 | -------------------------------------------------------------------------------- /src/start.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::error::Result; 2 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 3 | 4 | // use tokio::{fs::File, io::AsyncReadExt}; 5 | 6 | // This is our callable function for the command handler that we declared earlier 7 | // It will be triggered when someone send /start to the bot. 8 | pub async fn start(bot: Bot, ctx: Context) -> Result { 9 | // Same logic as chat applies on unwrapping effective message here. 10 | let msg = ctx.effective_message.unwrap(); 11 | let chat_id = msg.chat.id; 12 | 13 | let help_msg = r#" 14 | 🤖 Telegram Bot 帮助信息 15 | Rust语言编写并开源 🦀,GitHub:https://github.com/HZzz2/tgbot-app 16 | 17 | 🛠️ 可用命令: 18 | 19 | /c {key} - 执行键 key 对应的自定义命令。如果 key 不存在,则显示所有自定义命令 📜 20 | /shell {命令} - 执行任意 Shell 命令并返回标准输出和标准错误信息 🖥️ 21 | /shell_no_output {命令} - 执行任意 Shell 命令,返回命令是否执行成功而不返回相关输出 🖥️ 22 | /ip {ip地址} - 查询 IP 相关信息 🌍 23 | /dns {ip地址} - 查询 DNS 相关信息 🌐 24 | /chatgpt {消息} - 与 AI 进行对话 或直接发送{消息} 单次对话 🤖 25 | /ls - 显示当前目录下的所有文件 📂(不支持显示指定目录。如有需要,使用 /shell ls xxx) 26 | /ping {example.com} - 检测与另一主机之间的网络连接。默认发送4个数据包 🌐 27 | /aria2c {链接} - 使用aria2c下载受aria2c支持的文件到aria2c_download文件夹下 28 | /ytdlp {视频链接} - 使用yt-dlp下载最佳音视频到当前目录下 29 | /ssh_brute {ip地址} - ssh登录密码找回 30 | 发送非命令消息默认与 AI 进行单次对话 💬 例如发送:红烧鱼怎么做? 🍲 31 | 发送油管链接默认下载音频 🎵(工作目录下需要 yt-dlp ) 32 | 📌 其他信息: 33 | 34 | 您可以通过 /c 1 命令执行自定义命令,例如:/c 1 查看本机IP信息 (配置文件中可自定义)🌐 35 | 您可以使用 /shell 命令执行任何 Shell 命令,例如:/shell cd /home/user 💻 36 | 您可以使用 /chatgpt xxx 命令与 AI 进行对话,例如:/chatgpt 辣椒炒肉怎么做? 🍲 37 | 您可以使用 /ls 命令显示当前目录下的所有文件,例如:/ls 📋 38 | 您可以使用 /ping example.com 命令检测与另一主机之间的网络连接,例如:/ping google.com 🌐 39 | "#; 40 | bot.send_message(chat_id, help_msg.to_string()) 41 | .parse_mode(String::from("HTML")) 42 | .send() 43 | .await 44 | .unwrap(); 45 | 46 | // let mut link_preview_options = LinkPreviewOptions::new(); 47 | // link_preview_options.is_disabled = Some(true); 48 | // // Ferrisgram offers some custom helpers which make your work easy 49 | // // Here we have used one of those helpers known as msg.reply 50 | // msg.reply( 51 | // &bot, 52 | // "Hey! I am an echo bot built using [Ferrisgram](https://github.com/ferrisgram/ferrisgram). 53 | // I will repeat your messages.", 54 | // ) 55 | // // this method will ensure that our text will be sent with markdown formatting. 56 | // .parse_mode("markdown".to_string()) 57 | // .link_preview_options(link_preview_options) 58 | // // You must use this send() method in order to send the request to the API 59 | // .send() 60 | // .await?; 61 | 62 | // bot.send_photo(chat_id, "cat.jpg").send().await?; 63 | // bot.send_audio(chat_id, "许嵩-有何不可.mp3").send().await?; 64 | 65 | // let mut file = File::open("./许嵩-有何不可.mp3").await.unwrap(); 66 | // let metadata = file.metadata().await.unwrap(); 67 | // let file_size = metadata.len() as usize; 68 | 69 | // // 创建一个足够大的 buffer 70 | // let mut buffer = Vec::with_capacity(file_size); 71 | 72 | // // 读取整个文件内容 73 | // file.read_to_end(&mut buffer).await.unwrap(); 74 | 75 | // let namefile = NamedFile { 76 | // file_name: "许嵩-有何不可.mp3".to_string(), 77 | // file_data: buffer, 78 | // }; 79 | 80 | // bot.send_audio(chat_id, namefile).send().await?; 81 | // GroupIteration::EndGroups will end iteration of groups for an update. 82 | // This means that rest of the pending groups and their handlers won't be checked 83 | // for this particular update. 84 | Ok(GroupIteration::EndGroups) 85 | } 86 | -------------------------------------------------------------------------------- /src/shell/command.rs: -------------------------------------------------------------------------------- 1 | use crate::util::chunks_msg; 2 | use crate::{util::send_err_msg, GLOBAL_CONFIG}; 3 | use ferrisgram::error::Result; 4 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 5 | use tokio::process::Command; 6 | 7 | pub async fn c(bot: Bot, ctx: Context) -> Result { 8 | // Same logic as chat applies on unwrapping effective message here. 9 | let msg = ctx.effective_message.unwrap(); 10 | let chat_id = msg.chat.id; 11 | let cmd = &GLOBAL_CONFIG.command.cmd; 12 | let cm = msg.text.unwrap(); 13 | if cm.len() == 2 { 14 | let mut help_message = String::from("已定制的命令:\n"); 15 | for command in cmd.iter() { 16 | for (k, v) in command { 17 | help_message.push_str(format!("key:{} = {}\n", k, v).as_str()); 18 | } 19 | } 20 | bot.send_message(chat_id, help_message).send().await?; 21 | return Ok(GroupIteration::EndGroups); 22 | } 23 | 24 | let cm = cm[3..].trim(); 25 | 26 | // let li = match cmd.get(cm) { 27 | // Some(cmd_value) => cmd_value, 28 | // None => { 29 | // let mut help_message = String::new(); 30 | // for (k, v) in cmd { 31 | // help_message.push_str(format!("key:{} = {}\n", k, v).as_str()); 32 | // } 33 | // send_err_msg(bot, chat_id, help_message).await; 34 | // return Ok(GroupIteration::EndGroups); 35 | // } 36 | // }; 37 | 38 | // if cm.is_empty() { 39 | // let mut help_message = String::from("未找到命令:\n"); 40 | // for command in cmd.iter() { 41 | // for (k, v) in command { 42 | // help_message.push_str(format!("key:{} = {}\n", k, v).as_str()); 43 | // } 44 | // } 45 | // send_err_msg(bot, chat_id, help_message).await; 46 | // return Ok(GroupIteration::EndGroups); 47 | // } 48 | 49 | let mut li = "not_find_command".to_string(); 50 | for c in cmd { 51 | match c.get(cm) { 52 | Some(v) => { 53 | li.clone_from(v); 54 | break; 55 | } 56 | None => continue, 57 | } 58 | } 59 | if li == "not_find_command" { 60 | let mut help_message = String::from("未找到命令:\n"); 61 | for command in cmd.iter() { 62 | for (k, v) in command { 63 | help_message.push_str(format!("key:{} = {}\n", k, v).as_str()); 64 | } 65 | } 66 | send_err_msg(bot, chat_id, help_message).await; 67 | return Ok(GroupIteration::EndGroups); 68 | } else { 69 | bot.send_message(chat_id, format!("正在执行{}命令", li)) 70 | .send() 71 | .await?; 72 | } 73 | let Ok(output) = Command::new("sh").arg("-c").arg(li.as_str()).output().await else { 74 | send_err_msg(bot, chat_id, "执行定制常用命令执行失败".to_string()).await; 75 | return Ok(GroupIteration::EndGroups); 76 | }; 77 | if !&output.status.success() { 78 | send_err_msg(bot, chat_id, "执行定制常用命令执行失败".to_string()).await; 79 | return Ok(GroupIteration::EndGroups); 80 | } 81 | let output = output.stdout; 82 | // let output = task.await; 83 | 84 | // bot.send_message(chat_id, String::from_utf8_lossy(&output).to_string()) 85 | // .send() 86 | // .await?; 87 | if cm != "c" { 88 | chunks_msg(&bot, chat_id, String::from_utf8_lossy(&output)).await; 89 | } else { 90 | bot.send_message(chat_id, "/c c命令执行成功!".to_string()) 91 | .send() 92 | .await?; 93 | } 94 | 95 | Ok(GroupIteration::EndGroups) 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🤖 Telegram Bot - 多功能助手 2 | 3 | 这是一个用Rust语言编写的多功能Telegram机器人,提供了丰富的实用命令和功能。程序设计为以Linux服务的方式运行,并在出错时自动重启,确保稳定可靠的服务。🚀 4 | 5 | ## ✨ 功能特点 6 | 7 | - 🔧 执行自定义命令 8 | - 🖥️ 执行Shell命令 9 | - 🌐 IP和DNS查询 10 | - 🤖 与AI单次对话 11 | - 📂 文件系统操作 12 | - 🌍 网络连接测试 13 | - 📥 文件下载(调用aria2c和yt-dlp) 14 | - 🔑 SSH暴力枚举(用于密码找回) 15 | 16 | ## 🛠️ 可用命令 17 | 18 | - `/c {key}` - 执行键 *key* 对应的自定义命令。如果 *key* 不存在,则显示所有自定义命令 📜 19 | - `/shell {命令}` - 执行任意 Shell 命令并返回标准输出和标准错误信息 🖥️ 20 | - `/shell_no_output {命令}` - 执行任意 Shell 命令,返回命令是否执行成功而不返回相关输出 🔇 21 | - `/ip {ip地址}` - 查询 IP 相关信息 🌍 22 | - `/dns {ip地址}` - 查询 DNS 相关信息 🌐 23 | - `/chatgpt {消息}` - 与 AI 进行对话 或直接发送{消息} 单次对话 🤖 24 | - `/ls` - 显示当前目录下的所有文件 📂(不支持显示指定目录。如有需要,使用 `/shell ls xxx`) 25 | - `/ping {example.com}` - 检测与另一主机之间的网络连接。默认发送4个数据包 🏓 26 | - `/aria2c {链接}` - 使用aria2c下载受aria2c支持的文件到aria2c_download文件夹下 📥 27 | - `/ytdlp {视频链接}` - 使用yt-dlp下载最佳音视频到当前目录下 🎥 28 | - `/ssh_brute {ip地址}` - ssh登录密码找回 🔐 29 | 30 | 📝 **特别说明:** 31 | - 发送非命令消息默认与 AI 进行单次对话 💬 例如发送:`红烧鱼怎么做?` 🍲 32 | - 发送油管链接默认下载音频 🎵(工作目录下需要 [yt-dlp](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#release-files) ) 33 | 34 | ## 📦 安装编译步骤(提供已编译好的Debian和FreeBSD版本) 35 | 36 | 1. 确保您的系统中已安装Rust和Cargo。🦀 37 | ``` 38 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 39 | ``` 40 | ``` 41 | apt install pkg-config libssl-dev -y 42 | ``` 43 | 2. 克隆此仓库: 44 | ``` 45 | git clone https://github.com/HZzz2/tgbot-app 46 | ``` 47 | 3. 进入项目目录: 48 | ``` 49 | cd tgbot-app 50 | ``` 51 | 4. 编译项目: 52 | ``` 53 | cargo build --release 54 | ``` 55 | 56 | ## ⚙️ 配置与部署 57 | 58 | 1. 在项目根目录将`config-template.toml`更名为`config.toml`。📄 59 | ``` 60 | cp config-template.toml config.toml 61 | ``` 62 | 63 | 2. 在`config.toml`文件中添加您的Telegram Bot Token和其他必要的配置。🔑 64 | 65 | 3. 创建服务运行目录: 66 | ``` 67 | sudo mkdir -p /root/tgbot-app 68 | ``` 69 | 70 | 4. 将编译好的二进制文件和配置文件复制到服务目录: 71 | ``` 72 | sudo cp target/release/tgbot-app /root/tgbot-app/ 73 | sudo cp config.toml /root/tgbot-app/ 74 | ``` 75 | 76 | 5. 确保文件权限正确: 77 | ``` 78 | sudo chmod +x /root/tgbot-app/tgbot-app 79 | sudo chmod 644 /root/tgbot-app/config.toml 80 | ``` 81 | 82 | 83 | ## 🚀 部署为Linux服务 84 | 85 | 1. 创建一个系统服务文件,例如`/etc/systemd/system/tgbot-app.service`: 86 | 87 | ``` 88 | [Unit] 89 | Description=tgbot-app 90 | After=network.target 91 | 92 | [Service] 93 | ExecStart=/root/tgbot-app/tgbot-app 94 | WorkingDirectory=/root/tgbot-app 95 | Restart=always 96 | 97 | [Install] 98 | WantedBy=default.target 99 | ``` 100 | 101 | 2. 替换上面的路径为您系统上的实际值。📍 102 | 103 | 3. 重新加载systemd配置: 104 | ``` 105 | sudo systemctl daemon-reload 106 | ``` 107 | 108 | 4. 启动服务: 109 | ``` 110 | sudo systemctl start tgbot-app 111 | ``` 112 | 113 | 5. 设置开机自启: 114 | ``` 115 | sudo systemctl enable tgbot-app 116 | ``` 117 | 118 | ## 💡 使用示例 119 | 120 | - 执行自定义命令:`/c 1` 🔢 121 | - 执行Shell命令:`/shell ls -la` 📁 122 | - 与AI对话:`/chatgpt 你好,请介绍一下自己` 🤖 123 | - 下载YouTube视频:`/ytdlp https://www.youtube.com/watch?v=dQw4w9WgXcQ` 🎵 124 | 125 | ## ⚠️ 注意事项 126 | 127 | - 使用`/shell`和`/ssh_brute`命令时请谨慎,确保您有权限执行这些操作。🛡️ 128 | - 下载文件时请遵守版权法律。📜 129 | - 使用AI对话功能时,请注意可能产生的API使用费用。💰 130 | 131 | ## 📊 日志和监控 132 | 133 | 查看服务状态: 134 | ``` 135 | sudo systemctl status tgbot-app 136 | ``` 137 | 138 | 查看服务日志: 139 | ``` 140 | sudo journalctl -u tgbot-app 141 | ``` 142 | 143 | 使用常见的Linux监控工具(如systemctl、top等)来监控程序的资源使用情况。📈 144 | 145 | ## 🤝 贡献 146 | 147 | 欢迎提交问题和拉取请求。对于重大更改,请先开issue讨论您想要改变的内容。👥 148 | 149 | ## 📄 许可证 150 | 151 | [MIT](https://choosealicense.com/licenses/mit/) 152 | 153 | --- 154 | 155 | 🌟 如果您觉得这个项目有用,请给它一个star!非常感谢您的支持! 🙏 156 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release 2 | 3 | on: 4 | push: 5 | tags: ['v*'] 6 | 7 | jobs: 8 | release: 9 | name: Release - ${{ matrix.platform.os }} 10 | runs-on: ${{ matrix.platform.os }} 11 | strategy: 12 | fail-fast: false # 允许其他平台继续构建即使某个平台失败 13 | matrix: 14 | platform: 15 | - os: ubuntu-latest 16 | os-name: linux 17 | target: x86_64-unknown-linux-gnu 18 | binary-postfix: "" 19 | asset-name: linux-amd64 20 | - os: macos-latest 21 | os-name: macos 22 | target: x86_64-apple-darwin 23 | binary-postfix: "" 24 | asset-name: darwin-amd64 25 | # Windows 配置保留注释以便需要时快速启用 26 | # - os: windows-latest 27 | # os-name: windows 28 | # target: x86_64-pc-windows-msvc 29 | # binary-postfix: ".exe" 30 | # asset-name: windows-amd64 31 | 32 | env: 33 | CARGO_TERM_COLOR: always 34 | BINARY_NAME: ${{ github.event.repository.name }} 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v4 39 | 40 | - name: Install Rust toolchain 41 | uses: dtolnay/rust-toolchain@stable 42 | with: 43 | targets: ${{ matrix.platform.target }} 44 | 45 | - name: Setup Rust cache 46 | uses: Swatinem/rust-cache@v2 47 | with: 48 | cache-on-failure: true 49 | shared-key: "${{ matrix.platform.target }}" 50 | 51 | - name: Build release binary 52 | run: | 53 | cargo build --release --target ${{ matrix.platform.target }} 54 | # 显示构建产物的大小 55 | ls -lh target/${{ matrix.platform.target }}/release/${{ env.BINARY_NAME }}${{ matrix.platform.binary-postfix }} 56 | 57 | - name: Generate documentation 58 | if: matrix.platform.os == 'ubuntu-latest' 59 | run: cargo doc --no-deps --document-private-items 60 | 61 | - name: Prepare release archive 62 | shell: bash 63 | run: | 64 | mkdir -p release 65 | # 复制构建产物 66 | cp target/${{ matrix.platform.target }}/release/${{ env.BINARY_NAME }}${{ matrix.platform.binary-postfix }} release/ 67 | 68 | # 复制文档文件 69 | for file in README.md LICENSE CHANGELOG.md; do 70 | if [ -f "$file" ]; then 71 | cp "$file" release/ 72 | fi 73 | done 74 | 75 | cd release 76 | # 使用 tar.gz 格式压缩,更适合跨平台 77 | tar -czf "../${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.tar.gz" * 78 | 79 | # 计算并保存校验和 80 | if command -v sha256sum > /dev/null; then 81 | sha256sum "../${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.tar.gz" > "../${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.sha256" 82 | else 83 | shasum -a 256 "../${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.tar.gz" > "../${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.sha256" 84 | fi 85 | 86 | - name: Prepare documentation archive 87 | if: matrix.platform.os == 'ubuntu-latest' 88 | run: | 89 | cd target/doc 90 | tar -czf "../../${{ env.BINARY_NAME }}-docs.tar.gz" * 91 | cd ../.. 92 | if command -v sha256sum > /dev/null; then 93 | sha256sum "${{ env.BINARY_NAME }}-docs.tar.gz" > "${{ env.BINARY_NAME }}-docs.sha256" 94 | else 95 | shasum -a 256 "${{ env.BINARY_NAME }}-docs.tar.gz" > "${{ env.BINARY_NAME }}-docs.sha256" 96 | fi 97 | 98 | - name: Create GitHub Release 99 | uses: softprops/action-gh-release@v1 100 | with: 101 | files: | 102 | ${{ env.BINARY_NAME }}-${{ matrix.platform.asset-name }}.* 103 | ${{ env.BINARY_NAME }}-docs.* 104 | generate_release_notes: true 105 | env: 106 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use ferrisgram::Bot; 2 | use once_cell::sync::Lazy; 3 | use reqwest::Client; 4 | use reqwest::ClientBuilder; 5 | use serde::{Deserialize, Serialize}; 6 | use std::fmt::Display; 7 | use tokio::process::Command; 8 | 9 | use crate::GLOBAL_CONFIG; 10 | 11 | // telegram单条消息长度不能超过4096个字符 12 | pub const MESSAGE_LEN: usize = 4000; 13 | 14 | /// 验证ID是否存在于配置文件中 15 | #[inline] 16 | pub fn verify_telegram(id: i64) -> bool { 17 | GLOBAL_CONFIG.telegram.ids.contains(&id) 18 | } 19 | 20 | /// 验证telegram-id的宏,减少样板代码 21 | #[macro_export] 22 | macro_rules! verify_telegram_id { 23 | ($chat_id:expr) => { 24 | if !$crate::util::verify_telegram($chat_id) { 25 | tklog::async_fatal!("未知TelegramID进入handler:", $chat_id); 26 | return Ok(GroupIteration::EndGroups); 27 | } 28 | }; 29 | } 30 | 31 | pub static REQWEST_CLIENT: Lazy = Lazy::new(|| { 32 | let mut req_builder = ClientBuilder::new(); 33 | 34 | if !GLOBAL_CONFIG.reqwest.user_agent.is_empty() { 35 | req_builder = req_builder.user_agent(&GLOBAL_CONFIG.reqwest.user_agent); 36 | } 37 | 38 | if !GLOBAL_CONFIG.reqwest.proxy.is_empty() { 39 | req_builder = req_builder.proxy(reqwest::Proxy::all(&GLOBAL_CONFIG.reqwest.proxy).unwrap()) 40 | } 41 | 42 | match req_builder.build() { 43 | Ok(client) => client, 44 | Err(e) => { 45 | // 处理客户端创建错误的情况,例如记录错误日志并采取适当的措施 46 | eprintln!("Error creating client: {}", e); 47 | panic!("Failed to create reqwest client"); 48 | } 49 | } 50 | }); 51 | 52 | /// 出现失败后向用户发送失败信息 53 | #[inline] 54 | pub async fn send_err_msg(bot: Bot, chat_id: i64, msg: T) { 55 | let _ = bot 56 | .send_message(chat_id, format!("错误:{}", msg)) 57 | .parse_mode(String::from("markdown")) 58 | .send() 59 | .await; 60 | } 61 | 62 | /// 分段消息的发送,telegram单条最多4,096个字符 63 | pub async fn chunks_msg>(bot: &Bot, chat_id: i64, message: T) { 64 | for chunk in message.as_ref().chars().collect::>().chunks(4000) { 65 | let chunk_str: String = chunk.iter().collect(); 66 | let _ = bot.send_message(chat_id, chunk_str).send().await; 67 | } 68 | } 69 | 70 | // 执行单条shell命令单参数并返回输出 71 | pub async fn execute_one_shell(shell_cmd: String, arg: impl ToString) -> Result { 72 | let output = Command::new(&shell_cmd) 73 | .arg(arg.to_string()) 74 | .output() 75 | .await 76 | .unwrap() 77 | .stdout; 78 | 79 | Ok(String::from_utf8_lossy(&output).to_string()) 80 | } 81 | 82 | #[derive(Serialize, Deserialize)] 83 | pub struct RequestBody { 84 | pub model: String, 85 | pub messages: Vec, 86 | pub temperature: Option, 87 | } 88 | 89 | #[derive(Serialize, Deserialize)] 90 | pub struct Messages { 91 | pub role: String, 92 | pub content: String, 93 | } 94 | 95 | pub async fn ai_q_s>(content: T) -> anyhow::Result { 96 | let tg_content = content.into(); 97 | let client = Client::new(); 98 | let api_key = &GLOBAL_CONFIG.openai.api_key; 99 | let msg = Messages { 100 | role: "user".to_string(), 101 | content: tg_content.to_string(), 102 | }; 103 | let request_body = RequestBody { 104 | model: GLOBAL_CONFIG.openai.model.clone(), 105 | messages: vec![msg], 106 | temperature: Some(0.7), 107 | }; 108 | let res = client 109 | .post(&GLOBAL_CONFIG.openai.base_url) 110 | .header("Authorization", "Bearer ".to_string() + api_key) 111 | .header("Content-Type", "application/json") 112 | .json(&request_body) 113 | .send() 114 | .await 115 | .unwrap(); 116 | let response_body = res.json::().await.unwrap(); 117 | let rep = response_body["choices"][0]["message"]["content"] 118 | .as_str() 119 | .unwrap() 120 | .trim_start_matches('"') 121 | .trim_end_matches('"'); 122 | 123 | // let _ = bot.send_message(chat_id, rep.to_string()).parse_mode("markdown".to_string()).send().await.unwrap(); 124 | Ok(rep.to_string()) 125 | } 126 | -------------------------------------------------------------------------------- /src/osint/dns.rs: -------------------------------------------------------------------------------- 1 | use crate::util::{chunks_msg, MESSAGE_LEN}; 2 | use ferrisgram::error::Result; 3 | use ferrisgram::types::{InlineKeyboardButton, InlineKeyboardMarkup}; 4 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 5 | use tokio::process::Command; 6 | 7 | pub async fn dns(bot: Bot, ctx: Context) -> Result { 8 | // Same logic as chat applies on unwrapping effective message here. 9 | let msg = ctx.effective_message.unwrap(); 10 | let chat_id = msg.chat.id; 11 | let cm = msg.text.unwrap(); 12 | let d = if cm.starts_with('/') { 13 | cm[5..].trim() 14 | } else { 15 | cm[..].trim() 16 | }; 17 | 18 | // 回调 web待加 19 | let button_dnsrecon = InlineKeyboardButton::callback_button( 20 | "dnsrecon", 21 | format!("osint dns cb_dnsrecon {}", d).as_str(), 22 | ); 23 | let button_dnsenum = InlineKeyboardButton::callback_button( 24 | "dnsenum", 25 | format!("osint dns cb_dnsenum {}", d).as_str(), 26 | ); 27 | let button_dnschecker: InlineKeyboardButton = InlineKeyboardButton::url_button( 28 | "dnschecker-web", 29 | format!("https://dnschecker.org/#A/{}", d).as_str(), 30 | ); 31 | 32 | // let button_google = InlineKeyboardButton::url_button("Google", "https://google.com"); 33 | 34 | // let button_baidu = InlineKeyboardButton::url_button("百度", "https://baidu.com"); 35 | 36 | // dig命令查询 37 | let dig_output = Command::new("dig") 38 | .arg(d) 39 | .output() 40 | .await 41 | .expect("dns命令执行失败") 42 | .stdout; 43 | 44 | bot.send_message( 45 | chat_id, 46 | format!("dig:{}", String::from_utf8_lossy(&dig_output)), 47 | ) 48 | .send() 49 | .await?; 50 | 51 | // nslookup查询 52 | let nslookup_output = Command::new("nslookup") 53 | .arg(d) 54 | .output() 55 | .await 56 | .expect("nslookup命令执行失败") 57 | .stdout; 58 | 59 | // nslookup查询结果后提供回调和web todo 60 | bot.send_message( 61 | chat_id, 62 | format!("nslookup:{}", String::from_utf8_lossy(&nslookup_output)), 63 | ) 64 | .reply_markup(InlineKeyboardMarkup::new(vec![vec![ 65 | button_dnsrecon, 66 | button_dnsenum, 67 | button_dnschecker, 68 | ]])) 69 | .send() 70 | .await?; 71 | 72 | Ok(GroupIteration::EndGroups) 73 | } 74 | 75 | pub async fn cb_dnsenum(arg: &str, bot: Bot, chat_id: i64) -> Result { 76 | let dnsenum_output = Command::new("dnsenum") 77 | .args(["--reserver", arg]) // --reserver进行反向解析 加快扫描速度。保存文件的话可以不加此参数? 78 | .output() 79 | .await 80 | .expect("dnsenum命令执行失败") 81 | .stdout; 82 | 83 | if dnsenum_output.len() > MESSAGE_LEN { 84 | let _ = chunks_msg(&bot, chat_id, String::from_utf8_lossy(&dnsenum_output)).await; 85 | return Ok(GroupIteration::EndGroups); 86 | } 87 | let button_ai = InlineKeyboardButton::callback_button("AI分析", "AI分析 PROMPT_SHELL_OUTPUT"); 88 | 89 | bot.send_message( 90 | chat_id, 91 | format!("dnsenum:{}", String::from_utf8_lossy(&dnsenum_output)), 92 | ) 93 | .reply_markup(InlineKeyboardMarkup::new(vec![vec![button_ai]])) 94 | .send() 95 | .await?; 96 | 97 | Ok(GroupIteration::EndGroups) 98 | } 99 | 100 | pub async fn cb_dnsrecon(arg: &str, bot: Bot, chat_id: i64) -> Result { 101 | let dnsrecon_output = Command::new("dnsrecon") 102 | .args(["-d", arg]) 103 | .output() 104 | .await 105 | .expect("dnsrecon命令执行失败") 106 | .stdout; 107 | 108 | if dnsrecon_output.len() > MESSAGE_LEN { 109 | let _ = chunks_msg(&bot, chat_id, String::from_utf8_lossy(&dnsrecon_output)).await; 110 | return Ok(GroupIteration::EndGroups); 111 | } 112 | 113 | let button_ai: InlineKeyboardButton = 114 | InlineKeyboardButton::callback_button("AI分析", "AI分析 PROMPT_SHELL_OUTPUT"); 115 | 116 | bot.send_message( 117 | chat_id, 118 | format!("dnsrecon:{}", String::from_utf8_lossy(&dnsrecon_output)), 119 | ) 120 | .reply_markup(InlineKeyboardMarkup::new(vec![vec![button_ai]])) 121 | .send() 122 | .await?; 123 | 124 | Ok(GroupIteration::EndGroups) 125 | } 126 | -------------------------------------------------------------------------------- /src/download/yt_dlp_audio.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use crate::GLOBAL_CONFIG; 4 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 5 | 6 | use ferrisgram::error::Result; 7 | // use tokio::process::Command; 8 | 9 | pub async fn ytdlp_audio(bot: Bot, ctx: Context) -> Result { 10 | // Same logic as chat applies on unwrapping effective message here. 11 | let msg = ctx.effective_message.unwrap(); 12 | let chat_id = msg.chat.id; 13 | let cm = msg.text.unwrap(); 14 | let link = if cm.starts_with("/ytdlp_audio") { 15 | cm[13..].trim() 16 | } else { 17 | cm[..].trim() 18 | }; 19 | let cookie = GLOBAL_CONFIG.yt_dlp.cookie.as_str(); 20 | let proxy = GLOBAL_CONFIG.yt_dlp.proxy.as_str(); 21 | let args = GLOBAL_CONFIG.yt_dlp.args.as_str(); 22 | 23 | // let com = match (cookie, proxy) { 24 | // // 将格式mp3换成m4a无法在TG在线听。 25 | // (ck, px) if !ck.is_empty() && !px.is_empty() => { 26 | // format!( 27 | // r#"./yt-dlp -x --audio-format mp3 -o "/root/tgbot-app/tdl_dir/%(title)s.%(ext)s" --cookies {} --proxy {} {}"#, 28 | // ck, px, link 29 | // ) 30 | // } 31 | // (ck, _) if !ck.is_empty() => format!( 32 | // r#"./yt-dlp -x --audio-format mp3 -o "/root/tgbot-app/tdl_dir/%(title)s.%(ext)s" --cookies {} {}"#, 33 | // ck, link 34 | // ), 35 | // (_, px) if !px.is_empty() => format!( 36 | // r#"./yt-dlp -x --audio-format mp3 -o "/root/tgbot-app/tdl_dir/%(title)s.%(ext)s" --proxy {} {}"#, 37 | // px, link 38 | // ), 39 | // _ => format!( 40 | // r#"./yt-dlp -x --audio-format mp3 -o "/root/tgbot-app/tdl_dir/%(title)s.%(ext)s" {}"#, 41 | // link 42 | // ), 43 | // }; 44 | let mut com = Vec::new(); 45 | com.push("./yt-dlp -x --audio-format mp3 -o '/root/tgbot-app/tdl_dir/%(title)s.%(ext)s'"); 46 | 47 | if !cookie.is_empty() { 48 | com.extend_from_slice(&["--cookies", cookie]); 49 | } 50 | 51 | if !proxy.is_empty() { 52 | com.extend_from_slice(&["--proxy", proxy]); 53 | } 54 | 55 | if !args.is_empty() { 56 | com.push(args); 57 | } 58 | 59 | com.push(link); 60 | let command_string = com.join(" "); 61 | 62 | let task = tokio::task::spawn_blocking(move || { 63 | std::process::Command::new("sh") 64 | .arg("-c") 65 | .arg(command_string) 66 | .output() 67 | .unwrap() 68 | }); 69 | let msg = bot 70 | .send_message(chat_id, "正在使用yt-dlp下载音频中···".to_string()) 71 | .disable_notification(true) 72 | .send() 73 | .await 74 | .unwrap(); 75 | let output = task.await; 76 | 77 | let status = output.as_ref().unwrap().status; 78 | 79 | let result = if status.success() { 80 | String::from("音频下载成功,在tdl_dir目录下") 81 | } else { 82 | let file_name = "yt-dlp"; 83 | let path = Path::new(file_name); 84 | if !path.exists() { 85 | let err_msg = r#" 86 | 当前工作目录没有yt-dlp程序: 87 | ```shell 88 | wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp 89 | mv ./yt-dlp /root/tgbot_app 90 | cd !$ 91 | chmod +x yt-dlp 92 | ``` 93 | "#; 94 | String::from(err_msg) 95 | } else { 96 | // let out = output.as_ref().unwrap().stdout.clone(); 97 | // let err = output.unwrap().stderr; 98 | // format!( 99 | // " 100 | // *音频下载失败*: 101 | // stdout: {:?} 102 | // stderr: {:?} 103 | // ", 104 | // out, err 105 | // ) 106 | "音频下载失败".to_string() 107 | } 108 | }; 109 | 110 | bot.send_message(chat_id, result) 111 | .disable_notification(true) 112 | .send() 113 | .await?; 114 | bot.delete_message(chat_id, msg.message_id).send().await?; 115 | // 修改消息不会修改消息时间,不能知晓下载所花费的时间 116 | // bot.edit_message_text(result).chat_id(chat_id).message_id(msg.message_id).send().await?; 117 | 118 | // let Ok(_) = Command::new("sh").arg("-c").arg("tdl up -p /root/tgbot-app/tdl_dir -c 群组ID --rm -t 8 -s 524288 -l 4").output().await else { 119 | // send_err_msg(bot, chat_id, "上传音频失败".to_string()).await; 120 | // return Ok(GroupIteration::EndGroups); 121 | // }; 122 | 123 | // match Command::new("sh") 124 | // .arg("-c") 125 | // .arg("tdl up -p /root/tgbot-app/tdl_dir -c 群组ID --rm -t 8 -s 524288 -l 4") 126 | // .output() 127 | // .await 128 | // { 129 | // Ok(_) => { 130 | // bot.send_message(chat_id, "上传音频成功".to_string()) 131 | // .send() 132 | // .await?; 133 | // } 134 | // Err(e) => { 135 | // send_err_msg(bot, chat_id, format!("上传音频失败:{:?}", e)).await; 136 | // } 137 | // } 138 | 139 | Ok(GroupIteration::EndGroups) 140 | } 141 | -------------------------------------------------------------------------------- /src/osint/ip.rs: -------------------------------------------------------------------------------- 1 | use crate::ai::PROMPT_IP_JSON; 2 | use crate::util::REQWEST_CLIENT; 3 | use crate::util::{ai_q_s, send_err_msg}; 4 | 5 | use ferrisgram::error::Result; 6 | use ferrisgram::types::{InlineKeyboardButton, InlineKeyboardMarkup}; 7 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 8 | use reqwest; 9 | use serde_json::Value; 10 | use tokio::process::Command; 11 | 12 | pub async fn ip(bot: Bot, ctx: Context) -> Result { 13 | // Same logic as chat applies on unwrapping effective message here. 14 | let msg = ctx.effective_message.unwrap(); 15 | let chat_id = msg.chat.id; 16 | let cm = msg.text.unwrap(); 17 | let ip = if cm.starts_with('/') { 18 | // 如果没有提供参数则获取本机IPV4 19 | if cm[..].trim() == "/ip" { 20 | let local_ip = Command::new("curl") 21 | .arg("ipv4.ip.sb") 22 | .output() 23 | .await 24 | .unwrap() 25 | .stdout; 26 | let output = String::from_utf8_lossy(&local_ip); 27 | output.trim().to_string() 28 | } else { 29 | // 使用提供的参数 30 | cm[4..].trim().to_string() 31 | } 32 | } else { 33 | //从本程序传来的IP查询 34 | cm[..].trim().to_string() 35 | }; 36 | 37 | let ip_json_data: Value = match reqwest::get(format!(r"https://ipinfo.io/widget/demo/{}", ip)) 38 | .await 39 | .unwrap() 40 | .json() 41 | .await 42 | { 43 | Ok(v) => v, 44 | Err(_e) => { 45 | match reqwest::get(format!(r"https://api.seeip.org/geoip/{}", ip)) 46 | .await 47 | .unwrap() 48 | .json() 49 | .await 50 | { 51 | Ok(v) => v, 52 | Err(e) => { 53 | let e_msg = format!("获取IP-json数据失败(seeip.org):{:?}", e); 54 | let _ = send_err_msg(bot, chat_id, e_msg).await; 55 | return Ok(GroupIteration::EndGroups); 56 | } 57 | } 58 | } 59 | }; 60 | 61 | let jdata = serde_json::to_string_pretty(&ip_json_data).unwrap(); 62 | 63 | // 回调和web访问 64 | let button_ping0 = InlineKeyboardButton::url_button( 65 | "ping0-web", 66 | format!("https://ip.ping0.cc/ip/{}", ip).as_str(), 67 | ); 68 | let button_ipx = 69 | InlineKeyboardButton::url_button("ipx-web", format!("https://ipx.ac/{}", ip).as_str()); 70 | let button_ai: InlineKeyboardButton = 71 | InlineKeyboardButton::callback_button("AI分析", "AI分析 分析关于IP的JSON数据"); 72 | let button_ip123: InlineKeyboardButton = InlineKeyboardButton::callback_button( 73 | "ip123", 74 | format!("osint ip cb_ip123 {}", ip).as_str(), 75 | ); 76 | 77 | // 发送IP信息并提供回调和web访问 78 | bot.send_message(chat_id, format!("ip数据-json格式:{}", jdata.clone())) 79 | .reply_markup(InlineKeyboardMarkup::new(vec![vec![ 80 | button_ip123, 81 | button_ping0, 82 | button_ipx, 83 | button_ai, 84 | ]])) 85 | // .parse_mode("markdown".to_string()) 86 | .send() 87 | .await?; 88 | // 发送地理位置 89 | if let Some(loc_str) = ip_json_data["data"]["loc"].as_str() { 90 | let loc: Vec = loc_str 91 | .split(',') 92 | .map(|x| x.parse::().unwrap()) 93 | .collect(); 94 | bot.send_location(chat_id, loc[0], loc[1]) 95 | .send() 96 | .await 97 | .unwrap(); 98 | } else { 99 | let lat = ip_json_data["latitude"].as_str(); 100 | let lon = ip_json_data["longitude"].as_str(); 101 | if let (Some(la), Some(lo)) = (lat, lon) { 102 | bot.send_location( 103 | chat_id, 104 | la.parse::().unwrap(), 105 | lo.parse::().unwrap(), 106 | ) 107 | .send() 108 | .await 109 | .unwrap(); 110 | } 111 | }; 112 | // AI分析json数据并总结 113 | let ai_result = ai_q_s(format!("{}:{}", PROMPT_IP_JSON, jdata)).await; 114 | if let Ok(ai_answer) = ai_result { 115 | let _ = bot 116 | .send_message(chat_id, ai_answer) 117 | .parse_mode("markdown".to_string()) 118 | .send() 119 | .await; 120 | } 121 | 122 | Ok(GroupIteration::EndGroups) 123 | } 124 | 125 | pub async fn cb_ip123(arg: &str, bot: Bot, chat_id: i64) -> Result { 126 | let ip123_output: Value = REQWEST_CLIENT 127 | .get(format!("https://ip234.in/fraud_check?ip={}", arg)) 128 | .send() 129 | .await 130 | .unwrap() 131 | .json() 132 | .await 133 | .unwrap(); 134 | 135 | // let button_ai: InlineKeyboardButton = 136 | // InlineKeyboardButton::callback_button("AI分析", "AI分析 PROMPT_SHELL_OUTPUT"); 137 | 138 | bot.send_message( 139 | chat_id, 140 | format!( 141 | "ip123:{}", 142 | serde_json::to_string_pretty(&ip123_output).unwrap() 143 | ), 144 | ) 145 | // .reply_markup(InlineKeyboardMarkup::new(vec![vec![button_ai]])) 146 | .send() 147 | .await?; 148 | 149 | Ok(GroupIteration::EndGroups) 150 | } 151 | -------------------------------------------------------------------------------- /src/handler.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use ferrisgram::error::Result; 4 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 5 | 6 | use tklog::async_info; 7 | use tokio::fs::DirBuilder; 8 | use tokio::fs::File; 9 | use tokio::io::AsyncWriteExt; 10 | 11 | use crate::ai::chatgpt; 12 | use crate::download::ytdlp_audio; 13 | use crate::util::execute_one_shell; 14 | use crate::util::REQWEST_CLIENT; 15 | 16 | // use crate::yt_audio; 17 | // 消息处理函数 18 | pub async fn handler(bot: Bot, ctx: Context) -> Result { 19 | // Command Handler recieves message updates which have chat as a compulsory field. 20 | // Hence we can unwrap effective chat without checking if it is none. 21 | // let chat = ctx.effective_chat.unwrap(); 22 | // Same logic as chat applies on unwrapping effective message here. 23 | 24 | let msg = ctx.clone().effective_message.unwrap(); 25 | let user_id = ctx.clone().effective_user.unwrap().id; 26 | 27 | // let chat_type = msg.chat.r#type; // 私人给机器人发消息是private,私有群组是group,公开群组是supergroup,频道是channel 28 | // async_info!("user_id:",user_id,"-----","chat_id:",chat_id,"chat_type:",chat_type); 29 | tgbot_app::verify_telegram_id!(user_id); 30 | 31 | let chat_id = msg.chat.id; 32 | 33 | let content = msg.text.unwrap(); 34 | let mut content = content.trim(); 35 | 36 | // 如果机器人在群组或超级群组,当授权ID用于以@bot开头,则进行对应处理,否则不予处理 37 | // todo @机器人名时 也能进行回复 38 | let chat_type = msg.chat.r#type; 39 | if ["group", "supergroup"].contains(&chat_type.as_str()) { 40 | if content.starts_with("@bot") { 41 | content = &content[5..]; 42 | }else { 43 | return Ok(GroupIteration::EndGroups); 44 | } 45 | } 46 | 47 | // 斜杠视为命令 48 | if content.starts_with('/') { 49 | async_info!(content, "进入handler,视为命令,转为执行自定义的命令------"); 50 | return Ok(GroupIteration::ResumeGroups); 51 | } 52 | 53 | // 如果是油管链接则下载m4a音频格式并发送 网页版或手机版链接 54 | if content.starts_with(r"https://www.youtube.com") || content.starts_with(r"https://youtu.be") { 55 | // 由于rusty_ytdl库目前不可用且使用unwarp会使程序崩溃(崩溃不受影响,以服务方式部署会自动重启程序) 56 | // 使用rusty_ytdl下载后受到上传大小50MB的限制,超过限制保留到当前工作文件夹 57 | // match yt_audio(&bot, chat_id, content.to_string()).await { 58 | // Ok(_) => return Ok(GroupIteration::EndGroups), 59 | // Err(e) => { 60 | // send_err_msg(bot, chat_id, format!("**Error**: {:#?}", e)).await; 61 | // return Ok(GroupIteration::EndGroups); 62 | // } 63 | // } 64 | 65 | // 备选方案yt-dlp下载音频到tdl_dir目录(目前本人无法将音频上传,需借助tdl工具手动执行命令上传音频到群组等,不受50MB限制,可在线听音频) 66 | let _ = ytdlp_audio(bot, ctx).await; 67 | return Ok(GroupIteration::EndGroups); 68 | } 69 | 70 | //todo! 如果是直接发送的 ip domain 71 | 72 | //TODO 接收图片 。。。 73 | // 目前下载图片后对图片进行file和exiftool命令,发现telegram会对png图片转为jpg 74 | // 接收图片 75 | if let Some(mut photo) = ctx.clone().effective_message.unwrap().photo { 76 | // println!("photo: {:?},len: {}", photo, photo.len()); 77 | // for p in photo { 78 | // // let file = File::create(p.file_unique_id).await?; 79 | // let p_file = bot.get_file(p.file_id).send().await?; 80 | // println!("p_file:{:?}", p_file); 81 | // } 82 | let p = photo.pop().unwrap(); 83 | let p_file = bot.get_file(p.file_id).send().await?; 84 | let file_path = p_file.file_path.unwrap(); 85 | let path = Path::new(&file_path); 86 | let dir = path.parent().unwrap(); 87 | let _file_name = path.file_name().unwrap(); 88 | 89 | let url = format!( 90 | "https://api.telegram.org/file/bot{}/{}", 91 | bot.token, file_path 92 | ); 93 | // 发送 HTTP 请求 94 | let response_bytes = REQWEST_CLIENT 95 | .get(url) 96 | .send() 97 | .await 98 | .unwrap() 99 | .bytes() 100 | .await 101 | .unwrap(); 102 | // 创建本地文件 103 | DirBuilder::new().recursive(true).create(dir).await.unwrap(); 104 | let mut output_file = File::create(path).await.unwrap(); 105 | // 写入磁盘 106 | let _ = output_file.write_all(&response_bytes).await; 107 | 108 | let file_output = execute_one_shell("file".to_string(), &file_path).await; 109 | let exiftool_output = execute_one_shell("exiftool".to_string(), &file_path).await; 110 | 111 | bot.send_message(chat_id, file_output?).send().await?; 112 | 113 | if let Ok(exiftool_output) = exiftool_output { 114 | bot.send_message(chat_id, exiftool_output).send().await?; 115 | } 116 | let _ = tokio::fs::remove_file(path).await; 117 | 118 | return Ok(GroupIteration::EndGroups); 119 | } 120 | 121 | //TODO 接收文件 发送云沙箱 122 | 123 | //默认为AI问答 124 | let _ = chatgpt(bot, ctx).await; 125 | 126 | // Every api method creates a builder which contains various parameters of that respective method. 127 | // bot.copy_message(chat.id, chat.id, msg.message_id) 128 | // // You must use this send() method in order to send the request to the API 129 | // .send() 130 | // .await?; 131 | 132 | // GroupIteration::EndGroups will end iteration of groups for an update. 133 | // This means that rest of the pending groups and their handlers won't be checked 134 | // for this particular update. 135 | Ok(GroupIteration::EndGroups) 136 | } 137 | -------------------------------------------------------------------------------- /src/brute_force/ssh_brute.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | sync::{ 3 | atomic::{AtomicBool, AtomicUsize, Ordering}, 4 | Arc, 5 | }, 6 | time::Duration, 7 | }; 8 | 9 | use crate::GLOBAL_CONFIG; 10 | use async_channel; 11 | use async_ssh2_tokio::client::{AuthMethod, Client, ServerCheckMethod}; 12 | use ferrisgram::error::Result; 13 | use ferrisgram::{error::GroupIteration, ext::Context, Bot}; 14 | use tklog::async_debug; 15 | use tokio::{ 16 | fs::File, 17 | io::{AsyncBufReadExt, BufReader}, 18 | sync::Mutex, 19 | task::JoinHandle, 20 | time::Instant, 21 | }; 22 | 23 | pub async fn ssh_brute(bot: Bot, ctx: Context) -> Result { 24 | // Same logic as chat applies on unwrapping effective message here. 25 | let msg = ctx.effective_message.unwrap(); 26 | let chat_id = msg.chat.id; 27 | let cm = msg.text.unwrap(); 28 | 29 | let message_first_text = bot 30 | .send_message( 31 | chat_id, 32 | "正在准备进行爆破,每5秒更新一次状态(减少TG_API调用速率)".to_string(), 33 | ) 34 | // .parse_mode("markdown".to_string()) 35 | .send() 36 | .await 37 | .unwrap(); 38 | 39 | let host = Arc::new(cm[11..].trim().to_owned()); 40 | 41 | // 获取用户名,默认为 root 42 | let username = GLOBAL_CONFIG 43 | .brute_force 44 | .ssh 45 | .get("username") 46 | .map(|un| un.as_str()) 47 | .unwrap(); 48 | // 获取ssh端口,默认为 22 49 | let port: u16 = GLOBAL_CONFIG 50 | .brute_force 51 | .ssh 52 | .get("port") 53 | .and_then(|port_str| port_str.parse().ok()) 54 | .unwrap_or(22); 55 | // 获取字典,默认为 ./ssh_password.txt 56 | let brute_file = GLOBAL_CONFIG 57 | .brute_force 58 | .ssh 59 | .get("brute_file") 60 | .map(|s| s.as_str()) 61 | .unwrap(); 62 | async_debug!(username,">",brute_file); 63 | // 发送密码字典文件的每一行进行处理 64 | let (tx, rx) = async_channel::unbounded(); 65 | let send_password_joinhandle = tokio::spawn(async move { 66 | let file = File::open(brute_file).await.unwrap(); 67 | let mut lines = BufReader::new(file).lines(); 68 | while let Some(line) = lines.next_line().await.unwrap() { 69 | let _ = tx.send(line).await; 70 | } 71 | drop(tx); 72 | }); 73 | 74 | // 并发任务数,默认为 16 75 | let task_count: usize = GLOBAL_CONFIG 76 | .brute_force 77 | .ssh 78 | .get("threads") 79 | .unwrap() 80 | .parse() 81 | .unwrap(); 82 | // 将TASK_COUNT个任务放进JoinSet中 83 | // let mut set = JoinSet::new(); 84 | // 记录尝试次数 85 | let brute_count = Arc::new(AtomicUsize::new(0)); 86 | let find_passwd = Arc::new(AtomicBool::new(false)); 87 | let password = Arc::new(Mutex::new(String::new())); 88 | // 每个接收密码的处理任务 89 | let mut abort_handles = Vec::with_capacity(task_count); 90 | 91 | // 构建任务读取文件内容并爆破 92 | for _ in 0..task_count { 93 | // 接收文件内容的通道Receive 94 | let rx_clone = rx.clone(); 95 | // 记录尝试次数 96 | let brute_count_clone = Arc::clone(&brute_count); 97 | let host_clone = Arc::clone(&host); 98 | let find_passwd_clone = Arc::clone(&find_passwd); 99 | let password_clone = Arc::clone(&password); 100 | let joinhandle = tokio::task::spawn(async move { 101 | while let Ok(pw_line) = rx_clone.recv().await { 102 | let auth_method: AuthMethod = AuthMethod::with_password(pw_line.as_str()); 103 | 104 | if Client::connect( 105 | (host_clone.as_ref().clone(), port), 106 | username, 107 | auth_method, 108 | ServerCheckMethod::NoCheck, 109 | ) 110 | .await 111 | .is_ok() 112 | { 113 | // println!("已成功登录 密码为:{:?}", pw_line); 114 | // let _ = tx_finder_clone.send(pw_line).await; 115 | find_passwd_clone.store(true, Ordering::Relaxed); 116 | password_clone.lock().await.push_str(&pw_line); 117 | // sleep(Duration::from_millis(2)).await; 118 | return; 119 | } else { 120 | brute_count_clone.fetch_add(1, Ordering::Relaxed); 121 | } 122 | } 123 | }); 124 | // 每个任务进行循环尝试密码登录,成功则向正确密码通道发送密码,无论是否找到发送消息告知任务完毕 125 | abort_handles.push(joinhandle); 126 | } 127 | drop(rx); 128 | let start_time = Instant::now(); // 开始运行的时间 129 | let mut timing = Instant::now(); // 计时器,发送消息的间隔时间 130 | let send_time = Duration::from_secs( 131 | GLOBAL_CONFIG 132 | .brute_force 133 | .ssh 134 | .get("display_message_time_interval_seconds") 135 | .unwrap() 136 | .parse::() 137 | .unwrap(), 138 | ); //每隔多少秒向用户发送消息,以证明程序正在运行 139 | 140 | loop { 141 | if find_passwd.load(Ordering::Relaxed) { 142 | // let password = &finds[0]; 143 | let message = format!( 144 | "+已找到密码: *{}* 耗时:{}秒 已尝试:{}次", 145 | password.lock().await.clone(), 146 | start_time.elapsed().as_secs(), 147 | brute_count.load(Ordering::Relaxed) 148 | ); 149 | _ = bot 150 | .send_message(chat_id, message) 151 | .parse_mode("markdown".to_string()) 152 | .send() 153 | .await; 154 | break; 155 | } 156 | if timing.elapsed() >= send_time { 157 | timing = Instant::now(); 158 | let message = format!( 159 | "=_正在尝试中_。。。每5秒发送一次状态,已运行:{}秒 已尝试:{}次", 160 | start_time.elapsed().as_secs(), 161 | brute_count.load(Ordering::Relaxed) 162 | ); 163 | _ = bot 164 | .edit_message_text(message) 165 | .chat_id(chat_id) 166 | .message_id(message_first_text.message_id) 167 | .parse_mode("markdown".to_string()) 168 | .send() 169 | .await; 170 | } 171 | if abort_handles 172 | .iter() 173 | .all(|jh: &JoinHandle<()>| jh.is_finished()) 174 | && !find_passwd.load(Ordering::Relaxed) 175 | { 176 | let message = format!( 177 | "-密码未找到,耗时:{}秒 已尝试:{}次", 178 | start_time.elapsed().as_secs(), 179 | brute_count.load(Ordering::Relaxed) 180 | ); 181 | _ = bot 182 | .send_message(chat_id, message) 183 | .parse_mode("markdown".to_string()) 184 | .send() 185 | .await; 186 | break; 187 | } 188 | } 189 | 190 | // 清理工作 191 | for i in abort_handles { 192 | i.abort(); 193 | } 194 | // 终止发送密码的任务 195 | send_password_joinhandle.abort(); 196 | // drop(rx); 197 | drop(brute_count); 198 | 199 | Ok(GroupIteration::EndGroups) 200 | } 201 | -------------------------------------------------------------------------------- /src/download/y_ytdl.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use anyhow::anyhow; 4 | use anyhow::Result; 5 | use ferrisgram::input_file::NamedFile; 6 | use ferrisgram::Bot; 7 | use rusty_ytdl::RequestOptions; 8 | use rusty_ytdl::Video; 9 | use rusty_ytdl::VideoOptions; 10 | use rusty_ytdl::VideoQuality; 11 | use rusty_ytdl::VideoSearchOptions; 12 | use tokio::fs::File; 13 | use tokio::io::AsyncReadExt; 14 | 15 | use tgbot_app::util::send_err_msg; 16 | use tgbot_app::GLOBAL_CONFIG; 17 | 18 | // Telegram最大允许发送文件的大小,超过大小则不发 19 | const MAX_FILE_SIZE: usize = 50 * 1024 * 1024; // 50MB 20 | 21 | pub async fn yt_audio(bot: &Bot, chat_id: i64, url: String) -> Result<(), String> { 22 | let msg = bot 23 | .send_message(chat_id, "正在下载音频···".to_string()) 24 | .disable_notification(true) 25 | .send() 26 | .await 27 | .unwrap(); 28 | // 下载高质量音频格式文件 29 | let pathbuf = match down_mp3(&url, VideoQuality::Highest).await { 30 | Ok(pf) => pf, 31 | Err(e) => { 32 | send_err_msg( 33 | bot.clone(), 34 | chat_id, 35 | format!("下载高音质音频出错: {:#?}", e), 36 | ) 37 | .await; 38 | return Ok(()); 39 | } 40 | }; 41 | 42 | let nf = read_audio(pathbuf).await; 43 | let namefile = NamedFile { 44 | file_name: nf.0.clone(), 45 | file_data: nf.1.clone(), 46 | }; 47 | // 高音频小于50MB则发送,大于则下载低音质 48 | if nf.1.len() < MAX_FILE_SIZE { 49 | match bot 50 | .send_audio(chat_id, namefile) 51 | .disable_notification(true) 52 | .send() 53 | .await 54 | { 55 | Ok(_) => { 56 | // 成功发送高品质音频后则删除文件 57 | let _ = tokio::fs::remove_file(nf.0).await; 58 | } 59 | Err(_) => { 60 | //发送失败则下载低品质音频 61 | let pathbuf_low = down_mp3(&url, VideoQuality::Lowest) 62 | .await 63 | .expect("下载低品质音频失败"); 64 | // 构造发送音频参数 65 | let nf_low = read_audio(pathbuf_low).await; 66 | // 检测低品质音频是否超过50MB,如果超过则不发送,telegram发送限制50MB以下。超50MB需自建API服务器,难申请 67 | if nf_low.1.len() > MAX_FILE_SIZE { 68 | if !GLOBAL_CONFIG.y_ytdl.hight_audio_save { 69 | let _ = std::fs::remove_file(nf.0); 70 | } 71 | let _ = std::fs::remove_file(nf_low.0); 72 | return Err("低品质音频超过50MB,停止发送,删除低品质音频。".to_string()); 73 | } 74 | let namefile_low = NamedFile { 75 | file_name: nf_low.0.clone(), 76 | file_data: nf_low.1, 77 | }; 78 | // 如果低音质发送失败则发送一条消息提示 79 | if let Err(error) = bot 80 | .send_audio(chat_id, namefile_low) 81 | .disable_notification(true) 82 | .send() 83 | .await 84 | { 85 | if !GLOBAL_CONFIG.y_ytdl.hight_audio_save { 86 | let _ = std::fs::remove_file(nf.0); 87 | } 88 | let _ = tokio::fs::remove_file(nf_low.0).await; 89 | return Err(format!("低品质音频发送失败。错误:{:#?}", error)); 90 | } else { 91 | let _ = tokio::fs::remove_file(nf.0).await; 92 | let _ = tokio::fs::remove_file(nf_low.0).await; 93 | } 94 | } 95 | } 96 | } else { 97 | // 高品质音频超过50MB会发送失败,将尝试下载低品质音频 98 | let pathbuf_low = down_mp3(&url, VideoQuality::Lowest) 99 | .await 100 | .expect("下载低品质音频失败"); 101 | // 构造发送音频参数 102 | let nf_low = read_audio(pathbuf_low).await; 103 | // 检测低品质音频是否超过50MB,如果超过则不发送,telegram发送限制50MB以下。超50MB需自建API服务器,难申请 104 | if nf_low.1.len() > MAX_FILE_SIZE { 105 | if !GLOBAL_CONFIG.y_ytdl.hight_audio_save { 106 | let _ = std::fs::remove_file(nf.0); 107 | } 108 | let _ = std::fs::remove_file(nf_low.0); 109 | return Err("低品质音频超过50MB,停止发送,删除低品质音频。".to_string()); 110 | } 111 | let namefile_low = NamedFile { 112 | file_name: nf_low.0.clone(), 113 | file_data: nf_low.1, 114 | }; 115 | // 如果发送失败则发送一条消息提示 116 | if let Err(error) = bot 117 | .send_audio(chat_id, namefile_low) 118 | .disable_notification(true) 119 | .send() 120 | .await 121 | { 122 | if !GLOBAL_CONFIG.y_ytdl.hight_audio_save { 123 | let _ = std::fs::remove_file(nf.0); 124 | } 125 | let _ = tokio::fs::remove_file(nf_low.0).await; 126 | return Err(format!("低品质音频发送失败。错误:{:#?}", error)); 127 | } else { 128 | let _ = tokio::fs::remove_file(nf.0).await; 129 | let _ = tokio::fs::remove_file(nf_low.0).await; 130 | } 131 | } 132 | 133 | // 低品质音频发送失败时,高品质音频保存在当前目录,以供上传到TG群组中,使用tdl项目 134 | bot.delete_message(chat_id, msg.message_id) 135 | .send() 136 | .await 137 | .unwrap(); 138 | Ok(()) 139 | } 140 | 141 | // rusty_ytdl crate下载后缀为mp3,并不就一定是mp3格式的音频。也可能是webm 142 | async fn down_mp3(url: &String, video_quality: VideoQuality) -> Result { 143 | // 构建下载音频参数 144 | let video_options = if GLOBAL_CONFIG.y_ytdl.proxy.is_empty() { 145 | VideoOptions { 146 | quality: video_quality.clone(), 147 | filter: VideoSearchOptions::Audio, 148 | ..Default::default() 149 | } 150 | } else { 151 | let proxy = &GLOBAL_CONFIG.y_ytdl.proxy; 152 | if proxy.starts_with("socks5") && proxy.as_str().contains('@') { 153 | let err_msg = r#" 154 | reqwest库不支持带身份验证的socks5,请换成http/https (如果支持了请提交issuse告知我) 155 | 如需使用socks5,需要不带身份验证的,比如:`socks5://1.2.3.4:1080` 156 | "#; 157 | return Err(anyhow!(err_msg)); 158 | // return Err(err_msg); 159 | } 160 | VideoOptions { 161 | quality: video_quality.clone(), 162 | filter: VideoSearchOptions::Audio, 163 | request_options: RequestOptions { 164 | client: Some( 165 | reqwest::ClientBuilder::new() 166 | .use_rustls_tls() 167 | .user_agent( 168 | "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0", 169 | ) 170 | .proxy(reqwest::Proxy::all(proxy).unwrap()) 171 | .build() 172 | .unwrap(), 173 | ), 174 | ..Default::default() 175 | }, 176 | ..Default::default() 177 | } 178 | }; 179 | let audio = Video::new_with_options(url, video_options)?; 180 | // 获取链接标题,“/”在标题中会有转义问题,换成“-” 181 | let mut title = audio 182 | .get_info() 183 | .await? 184 | .video_details 185 | .title 186 | .replace(['/', '⧸'], "-"); 187 | let mut chars: Vec = title.chars().collect(); 188 | // 某些链接标题过长会导致在Telegram发送时失败,进行截断 189 | if chars.len() > 30 { 190 | chars.truncate(30); 191 | title = chars.into_iter().collect(); 192 | } 193 | 194 | // 如果是低质量音频则在文件名后添加_low标识 195 | let file_name = match video_quality { 196 | VideoQuality::Highest => format!("./{title}.mp3"), 197 | VideoQuality::Lowest => format!("./{title}_low.mp3"), 198 | _ => format!("./{title}.mp3"), 199 | }; 200 | let file = std::path::PathBuf::from(&file_name); 201 | dbg!("下载前"); 202 | audio.download(&file).await?; 203 | dbg!("下载后"); 204 | Ok(file) 205 | } 206 | 207 | async fn read_audio(pf: PathBuf) -> (String, Vec) { 208 | let file = File::open(&pf).await.unwrap(); 209 | let metadata = file.metadata().await.unwrap(); 210 | let file_size = metadata.len() as usize; 211 | // 创建一个足够大的 buffer 212 | let mut buffer = Vec::with_capacity(file_size); 213 | // 读取整个文件内容 214 | // file.read_to_end(&mut buffer).await.unwrap(); 215 | let mut reader = tokio::io::BufReader::new(file); 216 | reader.read_to_end(&mut buffer).await.unwrap(); 217 | // 文件名,文件内容 218 | ( 219 | pf.file_name().unwrap().to_str().unwrap().to_string(), 220 | buffer, 221 | ) 222 | } 223 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | //! 多功能Telegram机器人,提供了丰富的实用命令和功能。程序设计为以Linux服务的方式运行,并在出错时自动重启,确保稳定可靠的服务。 2 | //! 推荐在Linux中以服务的方式进行部署 [GitHub](https://github.com/HZzz2/tgbot-app) 3 | 4 | use std::sync::Arc; 5 | 6 | use anyhow::Result; 7 | use ferrisgram::ext::filters::callback_query::All; 8 | use ferrisgram::ext::filters::message; 9 | use ferrisgram::ext::handlers::{CallbackQueryHandler, CommandHandler, MessageHandler}; 10 | use ferrisgram::ext::{Dispatcher, Updater}; 11 | use ferrisgram::types::BotCommand; 12 | use ferrisgram::Bot; 13 | use tokio_cron_scheduler::{JobBuilder, JobScheduler}; 14 | // use tgbot_app::brute_force::sha1_cracker; 15 | use tklog::{async_debug, async_fatal, async_info, Format, ASYNC_LOG, LEVEL}; 16 | 17 | use tgbot_app::GLOBAL_CONFIG; 18 | 19 | mod handler; 20 | mod start; 21 | use handler::handler; 22 | use start::start; 23 | mod callback_handler; 24 | use callback_handler::callback_handler; 25 | 26 | pub mod util; 27 | 28 | pub mod shell; 29 | use shell::{c, ls, ping, shell, shell_no_output}; 30 | pub mod ai; 31 | use ai::chatgpt; 32 | 33 | pub mod download; 34 | pub use download::{aria2c, ytdlp}; 35 | 36 | pub mod server; 37 | pub use server::resend; 38 | 39 | pub mod osint; 40 | pub use osint::{dns, ip}; 41 | 42 | pub mod brute_force; 43 | pub use brute_force::sha1_cracker; 44 | pub use brute_force::ssh_brute; 45 | 46 | pub mod cron; 47 | 48 | /// 配置日志 - debug:控制台输出日志 ;release:文件输出日志 49 | async fn async_log_init() { 50 | let logger = ASYNC_LOG; 51 | 52 | // 判断是debug还是release编译 53 | if cfg!(debug_assertions) { 54 | // 配置全局单例 55 | logger 56 | .set_console(true) // 开启控制台输出 57 | .set_level(LEVEL::Debug) // Set log level to Debug 58 | .set_format(Format::LevelFlag | Format::Date | Format::Time | Format::LongFileName); 59 | async_debug!("tgbot-app正在启动中,已开启debug模式日志,日志输出控制台,不输出到文件"); 60 | } else { 61 | // 配置全局单例 62 | logger 63 | .set_console(false) // Disable console output 64 | .set_level(LEVEL::Info) // Set log level to Info 65 | .set_format(Format::LevelFlag | Format::Date | Format::Time | Format::LongFileName) // Define structured logging output 66 | .set_cutmode_by_time("./logs/tgbot-app-log.log", tklog::MODE::MONTH, 3, true) // 每月,三次备份,压缩 67 | .await; 68 | async_info!("tgbot-app正在启动中,已开启release模式日志,日志输出到文件,不输出控制台"); 69 | } 70 | } 71 | 72 | #[tokio::main] 73 | async fn main() -> Result<(), anyhow::Error> { 74 | async_log_init().await; 75 | 76 | // 获取配置文件信息 77 | let config = GLOBAL_CONFIG.clone(); 78 | async_debug!("config info:", format!("{:#?}", config)); 79 | 80 | let bot_token = &config.telegram.bot_token; 81 | // 此函数创建一个新的机器人实例并相应地处理错误 82 | let bot: Bot = match Bot::new(bot_token, None).await { 83 | Ok(bot) => { 84 | async_info!("tgbot-app启动成功"); 85 | bot 86 | } 87 | Err(error) => { 88 | async_fatal!("创建tgbot-app失败"); 89 | panic!("创建tgbot-app失败: {}", error) 90 | } 91 | }; 92 | 93 | let short_des = r#" 94 | Telegram Bot助手 95 | 开源地址:https://github.com/HZzz2/tgbot-app 96 | "# 97 | .to_string(); 98 | let des: String = r#" 99 | 机器人开源地址: https://github.com/HZzz2/tgbot-app 100 | 欢迎提交功能请求,优化建议, BUG,PR 101 | 可通过机器人执行shell命令,信息搜集,常用命令执行,发送邮件,下载音频或视频等等 102 | "# 103 | .to_string(); 104 | 105 | bot.set_my_description() 106 | .description(des) 107 | .send() 108 | .await 109 | .unwrap(); 110 | bot.set_my_short_description() 111 | .short_description(short_des) 112 | .send() 113 | .await 114 | .unwrap(); 115 | 116 | // bot.set_chat_menu_button() 117 | // .menu_button(MenuButton::MenuButtonWebApp(MenuButtonWebApp { 118 | // text: "GitHub地址".to_string(), 119 | // web_app: WebAppInfo { 120 | // url: "https://github.com/HZzz2/tgbot-app".to_string(), 121 | // }, 122 | // })); 123 | // bot.set_chat_menu_button() 124 | // .menu_button(MenuButton::MenuButtonWebApp(MenuButtonWebApp { 125 | // text: "作者地址".to_string(), 126 | // web_app: WebAppInfo { 127 | // url: "https://github.com/HZzz2".to_string(), 128 | // }, 129 | // })); 130 | 131 | // 调度程序是更新程序内部功能的一部分 132 | // 您可以使用它来添加处理程序。 133 | let dispatcher = &mut Dispatcher::new(&bot); 134 | 135 | let mut botcommadns: Vec = Vec::with_capacity(10); 136 | // add_handler method maps the provided handler in group 0 automatically 137 | // add_handler 方法自动将提供的处理程序映射到组 0 中 138 | dispatcher.add_handler(CommandHandler::new("start", start)); 139 | botcommadns.push(BotCommand { 140 | command: "start".to_string(), 141 | description: "快速开始向导".to_string(), 142 | }); 143 | 144 | // shell 145 | dispatcher.add_handler(CommandHandler::new("ls", ls)); 146 | botcommadns.push(BotCommand { 147 | command: "ls".to_string(), 148 | description: "显示指定工作目录下之内容(列出目前工作目录所含的文件及子目录),默认-lah" 149 | .to_string(), 150 | }); 151 | 152 | dispatcher.add_handler(CommandHandler::new("ping", ping)); 153 | botcommadns.push(BotCommand { 154 | command: "ping".to_string(), 155 | description: "命令用于检测与另一个主机之间的网络连接,默认发送4个数据包".to_string(), 156 | }); 157 | dispatcher.add_handler(CommandHandler::new("c", c)); 158 | botcommadns.push(BotCommand { 159 | command: "c".to_string(), 160 | description: "执行配置文件中设置的常用命令".to_string(), 161 | }); 162 | dispatcher.add_handler(CommandHandler::new("shell", shell)); 163 | botcommadns.push(BotCommand { 164 | command: "shell".to_string(), 165 | description: "执行任意shell命令,并显示结果".to_string(), 166 | }); 167 | dispatcher.add_handler(CommandHandler::new("shell_no_output", shell_no_output)); 168 | botcommadns.push(BotCommand { 169 | command: "shell_no_output".to_string(), 170 | description: "执行任意shell命令,不输出内容,只输出是否执行成功".to_string(), 171 | }); 172 | 173 | // osint 174 | dispatcher.add_handler(CommandHandler::new("ip", ip)); 175 | botcommadns.push(BotCommand { 176 | command: "ip".to_string(), 177 | description: "获取ip信息,地理位置".to_string(), 178 | }); 179 | 180 | dispatcher.add_handler(CommandHandler::new("dns", dns)); 181 | botcommadns.push(BotCommand { 182 | command: "dns".to_string(), 183 | description: "获取DNS相关信息".to_string(), 184 | }); 185 | 186 | dispatcher.add_handler(CommandHandler::new("ssh_brute", ssh_brute)); 187 | botcommadns.push(BotCommand { 188 | command: "ssh_brute".to_string(), 189 | description: "ssh爆破".to_string(), 190 | }); 191 | dispatcher.add_handler(CommandHandler::new("sha1", sha1_cracker)); 192 | botcommadns.push(BotCommand { 193 | command: "sha1".to_string(), 194 | description: "sha1爆破".to_string(), 195 | }); 196 | 197 | // ai 198 | dispatcher.add_handler(CommandHandler::new("chatgpt", chatgpt)); 199 | botcommadns.push(BotCommand { 200 | command: "chatgpt".to_string(), 201 | description: "chatgpt openai模型".to_string(), 202 | }); 203 | 204 | // download 205 | dispatcher.add_handler(CommandHandler::new("ytdlp", ytdlp)); 206 | botcommadns.push(BotCommand { 207 | command: "ytdlp".to_string(), 208 | description: "使用yt-dlp下载画质最佳视频,需下载yt-dlp到工作目录".to_string(), 209 | }); 210 | 211 | dispatcher.add_handler(CommandHandler::new("aria2c", aria2c)); 212 | botcommadns.push(BotCommand { 213 | command: "aria2c".to_string(), 214 | description: "使用aria2c下载文件,支持 HTTP/HTTPS、FTP、SFTP、BitTorrent 和 Metalink,默认16线程,下载的文件在aria2c_download目录下".to_string(), 215 | }); 216 | // server 217 | dispatcher.add_handler(CommandHandler::new("resend", resend)); 218 | botcommadns.push(BotCommand { 219 | command: "resend".to_string(), 220 | description: "使用resend发送邮件,需申请设置api和发件地址".to_string(), 221 | }); 222 | 223 | bot.set_my_commands(botcommadns).send().await.unwrap(); 224 | 225 | // add_handler_to_group is used to map the provided handler to a group manually. 226 | // note that handler groups are processed in ascending order. 227 | dispatcher.add_handler_to_group( 228 | MessageHandler::new( 229 | handler, 230 | message::All::filter(), //接收图片和文件以供查杀检验or? 231 | // This will restrict our echo function to the messages which 232 | // contain either text or a caption. 233 | // message::Text::filter().or(message::Caption::filter()), 234 | ), 235 | -1, 236 | ); 237 | // 回调 238 | dispatcher.add_handler_to_group( 239 | CallbackQueryHandler::new(callback_handler, All::filter()), 240 | 1, 241 | ); 242 | 243 | let mut updater = Updater::new(&bot, dispatcher); 244 | 245 | // cron国定任务执行 246 | 247 | // 创建调度器 248 | let scheduler = JobScheduler::new().await.unwrap(); 249 | 250 | // 添加一个每2秒执行一次的任务 251 | // let job = JobBuilder::new().with_timezone(chrono_tz::Asia::Shanghai) 252 | // .with_cron_job_type() 253 | // .with_schedule("*/2 * * * * *") 254 | // .unwrap() 255 | // .with_run_async(Box::new(|_uuid, mut _l| { 256 | // Box::pin(async move { 257 | // async_info!("JHB run async every 2 seconds id"); 258 | // // async_info!("JHB run async every 2 seconds id {:?}", uuid); 259 | // // let next_tick = l.next_tick_for_job(uuid).await; 260 | // // match next_tick { 261 | // // Ok(Some(ts)) => async_info!("Next time for JHB 2s is {:?}", ts), 262 | // // _ => async_fatal!("Could not get next tick for 2s job"), 263 | // // } 264 | // }) 265 | // })) 266 | // .build() 267 | // .unwrap(); 268 | 269 | // 添加一个天气预报,每日8点执行推送 270 | 271 | // let job1 = JobBuilder::new() 272 | // .with_timezone(chrono_tz::Asia::Shanghai) // 设置任务执行的时区为上海时区(UTC+8)如果没有指定时区,默认使用UTC 273 | // .with_cron_job_type() // 指定这是一个基于cron表达式的任务(而不是基于间隔的任务) 274 | // .with_schedule("0 8 * * * *") //设置cron表达式,定义任务的执行计划 每天上午8点整(0秒)执行 275 | // .unwrap() //如果cron表达式格式正确,继续构建流程 276 | // .with_run_async(Box::new({ 277 | // // 定义要异步执行的逻辑 Box::new(...)创建了一个堆分配的闭包 278 | // let cbot = Arc::new(bot.clone()); 279 | // let config = Arc::new(config.clone()); 280 | // move |_uuid, _l| { 281 | // let cbot = Arc::clone(&cbot); 282 | // let config = Arc::clone(&config); 283 | // Box::pin(async move { 284 | // let tianqi:Value = REQWEST_CLIENT.get("https://cn.apihz.cn/api/tianqi/tqyb.php?id=88888888&key=88888888&sheng=湖南&place=长沙") 285 | // .send().await.unwrap().json().await.unwrap(); 286 | // let str_format = format!(" 287 | // *☀️ 天气预报 ☀️* 288 | 289 | // 🏙️ *地区*: {} 290 | // 🌡️ *温度*: {}°C 291 | // 💧 *湿度*: {}% 292 | // 🌬️ *风速*: {}m/s 293 | // 🍃 *风力等级*: {} 294 | // ", 295 | // tianqi["place"], 296 | // tianqi["temperature"], 297 | // tianqi["humidity"], 298 | // tianqi["windSpeed"], 299 | // tianqi["windScale"] 300 | // ); 301 | // let _ = cbot 302 | // .send_message(config.telegram.ids[0], str_format) 303 | // .parse_mode(String::from("markdown")) 304 | // .send() 305 | // .await; 306 | // }) // Box::pin(async move {...}) 创建了一个固定在堆上的异步Future 307 | // } 308 | // })) 309 | // .build() 310 | // .unwrap(); 311 | 312 | let job = JobBuilder::new() 313 | .with_timezone(chrono_tz::Asia::Shanghai) // 设置任务执行的时区为上海时区(UTC+8)如果没有指定时区,默认使用UTC 314 | .with_cron_job_type() 315 | .with_schedule("0 0 * * * *") //设置cron表达式,定义任务的执行计划 每小时的第 0 分 0 秒执行一次任务 316 | .unwrap() 317 | .with_run_async(Box::new({ 318 | let cbot = Arc::new(bot.clone()); 319 | move |_uuid, _l| { 320 | let cbot = Arc::clone(&cbot); 321 | Box::pin(async move { 322 | cron::tianqi(cbot).await; 323 | }) 324 | } 325 | })) 326 | .build() 327 | .unwrap(); 328 | 329 | // 将任务添加到调度器 330 | scheduler.add(job).await.unwrap(); 331 | // 启动调度器 - 这一步非常重要! 332 | async_info!("启动调度器"); 333 | scheduler.start().await.unwrap(); 334 | 335 | // This method will start long polling through the getUpdates method 336 | // let _ = updater.start_polling(true).await; 337 | match updater.start_polling(true).await { 338 | Ok(_) => { 339 | async_info!("tgbot-app开启长轮询成功"); 340 | } 341 | Err(e) => { 342 | async_fatal!("tgbot-app开启长轮询失败:{:?}", e); 343 | } 344 | } 345 | Ok(()) 346 | } 347 | 348 | 349 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aead" 22 | version = "0.5.2" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" 25 | dependencies = [ 26 | "crypto-common", 27 | "generic-array", 28 | ] 29 | 30 | [[package]] 31 | name = "aes" 32 | version = "0.8.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" 35 | dependencies = [ 36 | "cfg-if", 37 | "cipher", 38 | "cpufeatures", 39 | ] 40 | 41 | [[package]] 42 | name = "aes-gcm" 43 | version = "0.10.3" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" 46 | dependencies = [ 47 | "aead", 48 | "aes", 49 | "cipher", 50 | "ctr", 51 | "ghash", 52 | "subtle", 53 | ] 54 | 55 | [[package]] 56 | name = "ahash" 57 | version = "0.8.11" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 60 | dependencies = [ 61 | "cfg-if", 62 | "const-random", 63 | "once_cell", 64 | "version_check", 65 | "zerocopy 0.7.35", 66 | ] 67 | 68 | [[package]] 69 | name = "aho-corasick" 70 | version = "1.1.3" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 73 | dependencies = [ 74 | "memchr", 75 | ] 76 | 77 | [[package]] 78 | name = "android-tzdata" 79 | version = "0.1.1" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 82 | 83 | [[package]] 84 | name = "android_system_properties" 85 | version = "0.1.5" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 88 | dependencies = [ 89 | "libc", 90 | ] 91 | 92 | [[package]] 93 | name = "anyhow" 94 | version = "1.0.97" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" 97 | 98 | [[package]] 99 | name = "argon2" 100 | version = "0.5.3" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" 103 | dependencies = [ 104 | "base64ct", 105 | "blake2", 106 | "cpufeatures", 107 | "password-hash", 108 | ] 109 | 110 | [[package]] 111 | name = "async-channel" 112 | version = "2.3.1" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" 115 | dependencies = [ 116 | "concurrent-queue", 117 | "event-listener-strategy", 118 | "futures-core", 119 | "pin-project-lite", 120 | ] 121 | 122 | [[package]] 123 | name = "async-ssh2-tokio" 124 | version = "0.8.14" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "c8a622cb76944fb1c007326bf5b7889b7b5a8d5f904fb460e813135c42546cb0" 127 | dependencies = [ 128 | "russh", 129 | "russh-sftp", 130 | "thiserror 2.0.12", 131 | "tokio", 132 | ] 133 | 134 | [[package]] 135 | name = "async-trait" 136 | version = "0.1.88" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" 139 | dependencies = [ 140 | "proc-macro2", 141 | "quote", 142 | "syn", 143 | ] 144 | 145 | [[package]] 146 | name = "autocfg" 147 | version = "1.4.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 150 | 151 | [[package]] 152 | name = "backtrace" 153 | version = "0.3.74" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 156 | dependencies = [ 157 | "addr2line", 158 | "cfg-if", 159 | "libc", 160 | "miniz_oxide", 161 | "object", 162 | "rustc-demangle", 163 | "windows-targets 0.52.6", 164 | ] 165 | 166 | [[package]] 167 | name = "base16ct" 168 | version = "0.2.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 171 | 172 | [[package]] 173 | name = "base64" 174 | version = "0.21.7" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 177 | 178 | [[package]] 179 | name = "base64" 180 | version = "0.22.1" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 183 | 184 | [[package]] 185 | name = "base64ct" 186 | version = "1.7.3" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" 189 | 190 | [[package]] 191 | name = "bcrypt-pbkdf" 192 | version = "0.10.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2" 195 | dependencies = [ 196 | "blowfish", 197 | "pbkdf2", 198 | "sha2", 199 | ] 200 | 201 | [[package]] 202 | name = "bitflags" 203 | version = "1.3.2" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 206 | 207 | [[package]] 208 | name = "bitflags" 209 | version = "2.9.0" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 212 | dependencies = [ 213 | "serde", 214 | ] 215 | 216 | [[package]] 217 | name = "blake2" 218 | version = "0.10.6" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" 221 | dependencies = [ 222 | "digest", 223 | ] 224 | 225 | [[package]] 226 | name = "block-buffer" 227 | version = "0.10.4" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 230 | dependencies = [ 231 | "generic-array", 232 | ] 233 | 234 | [[package]] 235 | name = "block-padding" 236 | version = "0.3.3" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" 239 | dependencies = [ 240 | "generic-array", 241 | ] 242 | 243 | [[package]] 244 | name = "blowfish" 245 | version = "0.9.1" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" 248 | dependencies = [ 249 | "byteorder", 250 | "cipher", 251 | ] 252 | 253 | [[package]] 254 | name = "bumpalo" 255 | version = "3.17.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 258 | 259 | [[package]] 260 | name = "byteorder" 261 | version = "1.5.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 264 | 265 | [[package]] 266 | name = "bytes" 267 | version = "1.10.1" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 270 | 271 | [[package]] 272 | name = "cbc" 273 | version = "0.1.2" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" 276 | dependencies = [ 277 | "cipher", 278 | ] 279 | 280 | [[package]] 281 | name = "cc" 282 | version = "1.2.18" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" 285 | dependencies = [ 286 | "shlex", 287 | ] 288 | 289 | [[package]] 290 | name = "cfg-if" 291 | version = "1.0.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 294 | 295 | [[package]] 296 | name = "cfg_aliases" 297 | version = "0.2.1" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 300 | 301 | [[package]] 302 | name = "chacha20" 303 | version = "0.9.1" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" 306 | dependencies = [ 307 | "cfg-if", 308 | "cipher", 309 | "cpufeatures", 310 | ] 311 | 312 | [[package]] 313 | name = "chrono" 314 | version = "0.4.40" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" 317 | dependencies = [ 318 | "android-tzdata", 319 | "iana-time-zone", 320 | "js-sys", 321 | "num-traits", 322 | "wasm-bindgen", 323 | "windows-link", 324 | ] 325 | 326 | [[package]] 327 | name = "chrono-tz" 328 | version = "0.10.3" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3" 331 | dependencies = [ 332 | "chrono", 333 | "chrono-tz-build", 334 | "phf", 335 | ] 336 | 337 | [[package]] 338 | name = "chrono-tz-build" 339 | version = "0.4.1" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402" 342 | dependencies = [ 343 | "parse-zoneinfo", 344 | "phf_codegen", 345 | ] 346 | 347 | [[package]] 348 | name = "cipher" 349 | version = "0.4.4" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 352 | dependencies = [ 353 | "crypto-common", 354 | "inout", 355 | ] 356 | 357 | [[package]] 358 | name = "concurrent-queue" 359 | version = "2.5.0" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 362 | dependencies = [ 363 | "crossbeam-utils", 364 | ] 365 | 366 | [[package]] 367 | name = "const-oid" 368 | version = "0.9.6" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 371 | 372 | [[package]] 373 | name = "const-random" 374 | version = "0.1.18" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 377 | dependencies = [ 378 | "const-random-macro", 379 | ] 380 | 381 | [[package]] 382 | name = "const-random-macro" 383 | version = "0.1.16" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 386 | dependencies = [ 387 | "getrandom 0.2.15", 388 | "once_cell", 389 | "tiny-keccak", 390 | ] 391 | 392 | [[package]] 393 | name = "core-foundation" 394 | version = "0.9.4" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 397 | dependencies = [ 398 | "core-foundation-sys", 399 | "libc", 400 | ] 401 | 402 | [[package]] 403 | name = "core-foundation-sys" 404 | version = "0.8.7" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 407 | 408 | [[package]] 409 | name = "cpufeatures" 410 | version = "0.2.17" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 413 | dependencies = [ 414 | "libc", 415 | ] 416 | 417 | [[package]] 418 | name = "crc32fast" 419 | version = "1.4.2" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 422 | dependencies = [ 423 | "cfg-if", 424 | ] 425 | 426 | [[package]] 427 | name = "croner" 428 | version = "2.1.0" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "38fd53511eaf0b00a185613875fee58b208dfce016577d0ad4bb548e1c4fb3ee" 431 | dependencies = [ 432 | "chrono", 433 | ] 434 | 435 | [[package]] 436 | name = "crossbeam-channel" 437 | version = "0.5.14" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" 440 | dependencies = [ 441 | "crossbeam-utils", 442 | ] 443 | 444 | [[package]] 445 | name = "crossbeam-utils" 446 | version = "0.8.21" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 449 | 450 | [[package]] 451 | name = "crunchy" 452 | version = "0.2.3" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" 455 | 456 | [[package]] 457 | name = "crypto-bigint" 458 | version = "0.5.5" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" 461 | dependencies = [ 462 | "generic-array", 463 | "rand_core 0.6.4", 464 | "subtle", 465 | "zeroize", 466 | ] 467 | 468 | [[package]] 469 | name = "crypto-common" 470 | version = "0.1.6" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 473 | dependencies = [ 474 | "generic-array", 475 | "rand_core 0.6.4", 476 | "typenum", 477 | ] 478 | 479 | [[package]] 480 | name = "ctr" 481 | version = "0.9.2" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" 484 | dependencies = [ 485 | "cipher", 486 | ] 487 | 488 | [[package]] 489 | name = "curve25519-dalek" 490 | version = "4.1.3" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" 493 | dependencies = [ 494 | "cfg-if", 495 | "cpufeatures", 496 | "curve25519-dalek-derive", 497 | "digest", 498 | "fiat-crypto", 499 | "rustc_version", 500 | "subtle", 501 | "zeroize", 502 | ] 503 | 504 | [[package]] 505 | name = "curve25519-dalek-derive" 506 | version = "0.1.1" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" 509 | dependencies = [ 510 | "proc-macro2", 511 | "quote", 512 | "syn", 513 | ] 514 | 515 | [[package]] 516 | name = "dashmap" 517 | version = "6.1.0" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" 520 | dependencies = [ 521 | "cfg-if", 522 | "crossbeam-utils", 523 | "hashbrown 0.14.5", 524 | "lock_api", 525 | "once_cell", 526 | "parking_lot_core", 527 | ] 528 | 529 | [[package]] 530 | name = "data-encoding" 531 | version = "2.8.0" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" 534 | 535 | [[package]] 536 | name = "delegate" 537 | version = "0.13.3" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "b9b6483c2bbed26f97861cf57651d4f2b731964a28cd2257f934a4b452480d21" 540 | dependencies = [ 541 | "proc-macro2", 542 | "quote", 543 | "syn", 544 | ] 545 | 546 | [[package]] 547 | name = "der" 548 | version = "0.7.9" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 551 | dependencies = [ 552 | "const-oid", 553 | "pem-rfc7468", 554 | "zeroize", 555 | ] 556 | 557 | [[package]] 558 | name = "digest" 559 | version = "0.10.7" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 562 | dependencies = [ 563 | "block-buffer", 564 | "const-oid", 565 | "crypto-common", 566 | "subtle", 567 | ] 568 | 569 | [[package]] 570 | name = "displaydoc" 571 | version = "0.2.5" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 574 | dependencies = [ 575 | "proc-macro2", 576 | "quote", 577 | "syn", 578 | ] 579 | 580 | [[package]] 581 | name = "dyn-clone" 582 | version = "1.0.19" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" 585 | 586 | [[package]] 587 | name = "ecdsa" 588 | version = "0.16.9" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 591 | dependencies = [ 592 | "der", 593 | "digest", 594 | "elliptic-curve", 595 | "rfc6979", 596 | "signature", 597 | "spki", 598 | ] 599 | 600 | [[package]] 601 | name = "ecow" 602 | version = "0.2.3" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "e42fc0a93992b20c58b99e59d61eaf1635a25bfbe49e4275c34ba0aee98119ba" 605 | dependencies = [ 606 | "serde", 607 | ] 608 | 609 | [[package]] 610 | name = "ed25519" 611 | version = "2.2.3" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" 614 | dependencies = [ 615 | "pkcs8", 616 | "signature", 617 | ] 618 | 619 | [[package]] 620 | name = "ed25519-dalek" 621 | version = "2.1.1" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" 624 | dependencies = [ 625 | "curve25519-dalek", 626 | "ed25519", 627 | "rand_core 0.6.4", 628 | "serde", 629 | "sha2", 630 | "subtle", 631 | "zeroize", 632 | ] 633 | 634 | [[package]] 635 | name = "either" 636 | version = "1.15.0" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 639 | 640 | [[package]] 641 | name = "elliptic-curve" 642 | version = "0.13.8" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" 645 | dependencies = [ 646 | "base16ct", 647 | "crypto-bigint", 648 | "digest", 649 | "ff", 650 | "generic-array", 651 | "group", 652 | "hkdf", 653 | "pem-rfc7468", 654 | "pkcs8", 655 | "rand_core 0.6.4", 656 | "sec1", 657 | "subtle", 658 | "zeroize", 659 | ] 660 | 661 | [[package]] 662 | name = "encoding_rs" 663 | version = "0.8.35" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 666 | dependencies = [ 667 | "cfg-if", 668 | ] 669 | 670 | [[package]] 671 | name = "enum_dispatch" 672 | version = "0.3.13" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" 675 | dependencies = [ 676 | "once_cell", 677 | "proc-macro2", 678 | "quote", 679 | "syn", 680 | ] 681 | 682 | [[package]] 683 | name = "equivalent" 684 | version = "1.0.2" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 687 | 688 | [[package]] 689 | name = "errno" 690 | version = "0.3.11" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" 693 | dependencies = [ 694 | "libc", 695 | "windows-sys 0.59.0", 696 | ] 697 | 698 | [[package]] 699 | name = "event-listener" 700 | version = "5.4.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" 703 | dependencies = [ 704 | "concurrent-queue", 705 | "parking", 706 | "pin-project-lite", 707 | ] 708 | 709 | [[package]] 710 | name = "event-listener-strategy" 711 | version = "0.5.4" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" 714 | dependencies = [ 715 | "event-listener", 716 | "pin-project-lite", 717 | ] 718 | 719 | [[package]] 720 | name = "fastrand" 721 | version = "2.3.0" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 724 | 725 | [[package]] 726 | name = "ferrisgram" 727 | version = "0.2.1" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "b5dd31008bdd824da3499cce58fb501b05904885485429e924f9239ef3de64e5" 730 | dependencies = [ 731 | "async-trait", 732 | "dyn-clone", 733 | "mime_guess", 734 | "reqwest 0.11.27", 735 | "serde", 736 | "serde_json", 737 | "tokio", 738 | ] 739 | 740 | [[package]] 741 | name = "ff" 742 | version = "0.13.1" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" 745 | dependencies = [ 746 | "rand_core 0.6.4", 747 | "subtle", 748 | ] 749 | 750 | [[package]] 751 | name = "fiat-crypto" 752 | version = "0.2.9" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" 755 | 756 | [[package]] 757 | name = "flate2" 758 | version = "1.1.1" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" 761 | dependencies = [ 762 | "crc32fast", 763 | "miniz_oxide", 764 | ] 765 | 766 | [[package]] 767 | name = "flurry" 768 | version = "0.5.2" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "cf5efcf77a4da27927d3ab0509dec5b0954bb3bc59da5a1de9e52642ebd4cdf9" 771 | dependencies = [ 772 | "ahash", 773 | "num_cpus", 774 | "parking_lot", 775 | "seize", 776 | ] 777 | 778 | [[package]] 779 | name = "fnv" 780 | version = "1.0.7" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 783 | 784 | [[package]] 785 | name = "foreign-types" 786 | version = "0.3.2" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 789 | dependencies = [ 790 | "foreign-types-shared", 791 | ] 792 | 793 | [[package]] 794 | name = "foreign-types-shared" 795 | version = "0.1.1" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 798 | 799 | [[package]] 800 | name = "form_urlencoded" 801 | version = "1.2.1" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 804 | dependencies = [ 805 | "percent-encoding", 806 | ] 807 | 808 | [[package]] 809 | name = "futures" 810 | version = "0.3.31" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 813 | dependencies = [ 814 | "futures-channel", 815 | "futures-core", 816 | "futures-executor", 817 | "futures-io", 818 | "futures-sink", 819 | "futures-task", 820 | "futures-util", 821 | ] 822 | 823 | [[package]] 824 | name = "futures-channel" 825 | version = "0.3.31" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 828 | dependencies = [ 829 | "futures-core", 830 | "futures-sink", 831 | ] 832 | 833 | [[package]] 834 | name = "futures-core" 835 | version = "0.3.31" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 838 | 839 | [[package]] 840 | name = "futures-executor" 841 | version = "0.3.31" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 844 | dependencies = [ 845 | "futures-core", 846 | "futures-task", 847 | "futures-util", 848 | ] 849 | 850 | [[package]] 851 | name = "futures-io" 852 | version = "0.3.31" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 855 | 856 | [[package]] 857 | name = "futures-macro" 858 | version = "0.3.31" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 861 | dependencies = [ 862 | "proc-macro2", 863 | "quote", 864 | "syn", 865 | ] 866 | 867 | [[package]] 868 | name = "futures-sink" 869 | version = "0.3.31" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 872 | 873 | [[package]] 874 | name = "futures-task" 875 | version = "0.3.31" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 878 | 879 | [[package]] 880 | name = "futures-timer" 881 | version = "3.0.3" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" 884 | 885 | [[package]] 886 | name = "futures-util" 887 | version = "0.3.31" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 890 | dependencies = [ 891 | "futures-channel", 892 | "futures-core", 893 | "futures-io", 894 | "futures-macro", 895 | "futures-sink", 896 | "futures-task", 897 | "memchr", 898 | "pin-project-lite", 899 | "pin-utils", 900 | "slab", 901 | ] 902 | 903 | [[package]] 904 | name = "generic-array" 905 | version = "0.14.7" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 908 | dependencies = [ 909 | "typenum", 910 | "version_check", 911 | "zeroize", 912 | ] 913 | 914 | [[package]] 915 | name = "getrandom" 916 | version = "0.2.15" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 919 | dependencies = [ 920 | "cfg-if", 921 | "js-sys", 922 | "libc", 923 | "wasi 0.11.0+wasi-snapshot-preview1", 924 | "wasm-bindgen", 925 | ] 926 | 927 | [[package]] 928 | name = "getrandom" 929 | version = "0.3.2" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 932 | dependencies = [ 933 | "cfg-if", 934 | "js-sys", 935 | "libc", 936 | "r-efi", 937 | "wasi 0.14.2+wasi-0.2.4", 938 | "wasm-bindgen", 939 | ] 940 | 941 | [[package]] 942 | name = "ghash" 943 | version = "0.5.1" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" 946 | dependencies = [ 947 | "opaque-debug", 948 | "polyval", 949 | ] 950 | 951 | [[package]] 952 | name = "gimli" 953 | version = "0.31.1" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 956 | 957 | [[package]] 958 | name = "governor" 959 | version = "0.8.1" 960 | source = "registry+https://github.com/rust-lang/crates.io-index" 961 | checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb" 962 | dependencies = [ 963 | "cfg-if", 964 | "dashmap", 965 | "futures-sink", 966 | "futures-timer", 967 | "futures-util", 968 | "getrandom 0.3.2", 969 | "no-std-compat", 970 | "nonzero_ext", 971 | "parking_lot", 972 | "portable-atomic", 973 | "quanta", 974 | "rand 0.9.0", 975 | "smallvec", 976 | "spinning_top", 977 | "web-time", 978 | ] 979 | 980 | [[package]] 981 | name = "group" 982 | version = "0.13.0" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 985 | dependencies = [ 986 | "ff", 987 | "rand_core 0.6.4", 988 | "subtle", 989 | ] 990 | 991 | [[package]] 992 | name = "h2" 993 | version = "0.3.26" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 996 | dependencies = [ 997 | "bytes", 998 | "fnv", 999 | "futures-core", 1000 | "futures-sink", 1001 | "futures-util", 1002 | "http 0.2.12", 1003 | "indexmap", 1004 | "slab", 1005 | "tokio", 1006 | "tokio-util", 1007 | "tracing", 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "hashbrown" 1012 | version = "0.14.5" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1015 | 1016 | [[package]] 1017 | name = "hashbrown" 1018 | version = "0.15.2" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 1021 | 1022 | [[package]] 1023 | name = "hermit-abi" 1024 | version = "0.3.9" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 1027 | 1028 | [[package]] 1029 | name = "hex" 1030 | version = "0.4.3" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1033 | 1034 | [[package]] 1035 | name = "hex-literal" 1036 | version = "0.4.1" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" 1039 | 1040 | [[package]] 1041 | name = "hkdf" 1042 | version = "0.12.4" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 1045 | dependencies = [ 1046 | "hmac", 1047 | ] 1048 | 1049 | [[package]] 1050 | name = "hmac" 1051 | version = "0.12.1" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1054 | dependencies = [ 1055 | "digest", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "home" 1060 | version = "0.5.11" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 1063 | dependencies = [ 1064 | "windows-sys 0.59.0", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "http" 1069 | version = "0.2.12" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 1072 | dependencies = [ 1073 | "bytes", 1074 | "fnv", 1075 | "itoa", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "http" 1080 | version = "1.3.1" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 1083 | dependencies = [ 1084 | "bytes", 1085 | "fnv", 1086 | "itoa", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "http-body" 1091 | version = "0.4.6" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 1094 | dependencies = [ 1095 | "bytes", 1096 | "http 0.2.12", 1097 | "pin-project-lite", 1098 | ] 1099 | 1100 | [[package]] 1101 | name = "http-body" 1102 | version = "1.0.1" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1105 | dependencies = [ 1106 | "bytes", 1107 | "http 1.3.1", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "http-body-util" 1112 | version = "0.1.3" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 1115 | dependencies = [ 1116 | "bytes", 1117 | "futures-core", 1118 | "http 1.3.1", 1119 | "http-body 1.0.1", 1120 | "pin-project-lite", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "httparse" 1125 | version = "1.10.1" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 1128 | 1129 | [[package]] 1130 | name = "httpdate" 1131 | version = "1.0.3" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1134 | 1135 | [[package]] 1136 | name = "hyper" 1137 | version = "0.14.32" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" 1140 | dependencies = [ 1141 | "bytes", 1142 | "futures-channel", 1143 | "futures-core", 1144 | "futures-util", 1145 | "h2", 1146 | "http 0.2.12", 1147 | "http-body 0.4.6", 1148 | "httparse", 1149 | "httpdate", 1150 | "itoa", 1151 | "pin-project-lite", 1152 | "socket2", 1153 | "tokio", 1154 | "tower-service", 1155 | "tracing", 1156 | "want", 1157 | ] 1158 | 1159 | [[package]] 1160 | name = "hyper" 1161 | version = "1.6.0" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 1164 | dependencies = [ 1165 | "bytes", 1166 | "futures-channel", 1167 | "futures-util", 1168 | "http 1.3.1", 1169 | "http-body 1.0.1", 1170 | "httparse", 1171 | "itoa", 1172 | "pin-project-lite", 1173 | "smallvec", 1174 | "tokio", 1175 | "want", 1176 | ] 1177 | 1178 | [[package]] 1179 | name = "hyper-rustls" 1180 | version = "0.27.5" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 1183 | dependencies = [ 1184 | "futures-util", 1185 | "http 1.3.1", 1186 | "hyper 1.6.0", 1187 | "hyper-util", 1188 | "rustls", 1189 | "rustls-pki-types", 1190 | "tokio", 1191 | "tokio-rustls", 1192 | "tower-service", 1193 | "webpki-roots", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "hyper-tls" 1198 | version = "0.5.0" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 1201 | dependencies = [ 1202 | "bytes", 1203 | "hyper 0.14.32", 1204 | "native-tls", 1205 | "tokio", 1206 | "tokio-native-tls", 1207 | ] 1208 | 1209 | [[package]] 1210 | name = "hyper-tls" 1211 | version = "0.6.0" 1212 | source = "registry+https://github.com/rust-lang/crates.io-index" 1213 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 1214 | dependencies = [ 1215 | "bytes", 1216 | "http-body-util", 1217 | "hyper 1.6.0", 1218 | "hyper-util", 1219 | "native-tls", 1220 | "tokio", 1221 | "tokio-native-tls", 1222 | "tower-service", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "hyper-util" 1227 | version = "0.1.11" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" 1230 | dependencies = [ 1231 | "bytes", 1232 | "futures-channel", 1233 | "futures-util", 1234 | "http 1.3.1", 1235 | "http-body 1.0.1", 1236 | "hyper 1.6.0", 1237 | "libc", 1238 | "pin-project-lite", 1239 | "socket2", 1240 | "tokio", 1241 | "tower-service", 1242 | "tracing", 1243 | ] 1244 | 1245 | [[package]] 1246 | name = "iana-time-zone" 1247 | version = "0.1.63" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 1250 | dependencies = [ 1251 | "android_system_properties", 1252 | "core-foundation-sys", 1253 | "iana-time-zone-haiku", 1254 | "js-sys", 1255 | "log", 1256 | "wasm-bindgen", 1257 | "windows-core 0.61.0", 1258 | ] 1259 | 1260 | [[package]] 1261 | name = "iana-time-zone-haiku" 1262 | version = "0.1.2" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1265 | dependencies = [ 1266 | "cc", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "icu_collections" 1271 | version = "1.5.0" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 1274 | dependencies = [ 1275 | "displaydoc", 1276 | "yoke", 1277 | "zerofrom", 1278 | "zerovec", 1279 | ] 1280 | 1281 | [[package]] 1282 | name = "icu_locid" 1283 | version = "1.5.0" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1286 | dependencies = [ 1287 | "displaydoc", 1288 | "litemap", 1289 | "tinystr", 1290 | "writeable", 1291 | "zerovec", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "icu_locid_transform" 1296 | version = "1.5.0" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1299 | dependencies = [ 1300 | "displaydoc", 1301 | "icu_locid", 1302 | "icu_locid_transform_data", 1303 | "icu_provider", 1304 | "tinystr", 1305 | "zerovec", 1306 | ] 1307 | 1308 | [[package]] 1309 | name = "icu_locid_transform_data" 1310 | version = "1.5.1" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" 1313 | 1314 | [[package]] 1315 | name = "icu_normalizer" 1316 | version = "1.5.0" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1319 | dependencies = [ 1320 | "displaydoc", 1321 | "icu_collections", 1322 | "icu_normalizer_data", 1323 | "icu_properties", 1324 | "icu_provider", 1325 | "smallvec", 1326 | "utf16_iter", 1327 | "utf8_iter", 1328 | "write16", 1329 | "zerovec", 1330 | ] 1331 | 1332 | [[package]] 1333 | name = "icu_normalizer_data" 1334 | version = "1.5.1" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" 1337 | 1338 | [[package]] 1339 | name = "icu_properties" 1340 | version = "1.5.1" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1343 | dependencies = [ 1344 | "displaydoc", 1345 | "icu_collections", 1346 | "icu_locid_transform", 1347 | "icu_properties_data", 1348 | "icu_provider", 1349 | "tinystr", 1350 | "zerovec", 1351 | ] 1352 | 1353 | [[package]] 1354 | name = "icu_properties_data" 1355 | version = "1.5.1" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" 1358 | 1359 | [[package]] 1360 | name = "icu_provider" 1361 | version = "1.5.0" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1364 | dependencies = [ 1365 | "displaydoc", 1366 | "icu_locid", 1367 | "icu_provider_macros", 1368 | "stable_deref_trait", 1369 | "tinystr", 1370 | "writeable", 1371 | "yoke", 1372 | "zerofrom", 1373 | "zerovec", 1374 | ] 1375 | 1376 | [[package]] 1377 | name = "icu_provider_macros" 1378 | version = "1.5.0" 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" 1380 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1381 | dependencies = [ 1382 | "proc-macro2", 1383 | "quote", 1384 | "syn", 1385 | ] 1386 | 1387 | [[package]] 1388 | name = "idna" 1389 | version = "1.0.3" 1390 | source = "registry+https://github.com/rust-lang/crates.io-index" 1391 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1392 | dependencies = [ 1393 | "idna_adapter", 1394 | "smallvec", 1395 | "utf8_iter", 1396 | ] 1397 | 1398 | [[package]] 1399 | name = "idna_adapter" 1400 | version = "1.2.0" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1403 | dependencies = [ 1404 | "icu_normalizer", 1405 | "icu_properties", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "indexmap" 1410 | version = "2.9.0" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 1413 | dependencies = [ 1414 | "equivalent", 1415 | "hashbrown 0.15.2", 1416 | ] 1417 | 1418 | [[package]] 1419 | name = "inout" 1420 | version = "0.1.4" 1421 | source = "registry+https://github.com/rust-lang/crates.io-index" 1422 | checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" 1423 | dependencies = [ 1424 | "block-padding", 1425 | "generic-array", 1426 | ] 1427 | 1428 | [[package]] 1429 | name = "internal-russh-forked-ssh-key" 1430 | version = "0.6.10+upstream-0.6.7" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | checksum = "33555bd765ace379fe85d97bb6d48b5783054f6048a7d5ec24cd9155e490e266" 1433 | dependencies = [ 1434 | "argon2", 1435 | "bcrypt-pbkdf", 1436 | "ecdsa", 1437 | "ed25519-dalek", 1438 | "hex", 1439 | "hmac", 1440 | "num-bigint-dig", 1441 | "p256", 1442 | "p384", 1443 | "p521", 1444 | "rand_core 0.6.4", 1445 | "rsa", 1446 | "sec1", 1447 | "sha1", 1448 | "sha2", 1449 | "signature", 1450 | "ssh-cipher", 1451 | "ssh-encoding", 1452 | "subtle", 1453 | "zeroize", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "ipnet" 1458 | version = "2.11.0" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1461 | 1462 | [[package]] 1463 | name = "itoa" 1464 | version = "1.0.15" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1467 | 1468 | [[package]] 1469 | name = "js-sys" 1470 | version = "0.3.77" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1473 | dependencies = [ 1474 | "once_cell", 1475 | "wasm-bindgen", 1476 | ] 1477 | 1478 | [[package]] 1479 | name = "lazy_static" 1480 | version = "1.5.0" 1481 | source = "registry+https://github.com/rust-lang/crates.io-index" 1482 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1483 | dependencies = [ 1484 | "spin", 1485 | ] 1486 | 1487 | [[package]] 1488 | name = "libc" 1489 | version = "0.2.171" 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" 1491 | checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 1492 | 1493 | [[package]] 1494 | name = "libm" 1495 | version = "0.2.11" 1496 | source = "registry+https://github.com/rust-lang/crates.io-index" 1497 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 1498 | 1499 | [[package]] 1500 | name = "linux-raw-sys" 1501 | version = "0.9.3" 1502 | source = "registry+https://github.com/rust-lang/crates.io-index" 1503 | checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" 1504 | 1505 | [[package]] 1506 | name = "litemap" 1507 | version = "0.7.5" 1508 | source = "registry+https://github.com/rust-lang/crates.io-index" 1509 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 1510 | 1511 | [[package]] 1512 | name = "lock_api" 1513 | version = "0.4.12" 1514 | source = "registry+https://github.com/rust-lang/crates.io-index" 1515 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1516 | dependencies = [ 1517 | "autocfg", 1518 | "scopeguard", 1519 | ] 1520 | 1521 | [[package]] 1522 | name = "log" 1523 | version = "0.4.27" 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" 1525 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 1526 | 1527 | [[package]] 1528 | name = "maybe-async" 1529 | version = "0.2.10" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" 1532 | dependencies = [ 1533 | "proc-macro2", 1534 | "quote", 1535 | "syn", 1536 | ] 1537 | 1538 | [[package]] 1539 | name = "md5" 1540 | version = "0.7.0" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" 1543 | 1544 | [[package]] 1545 | name = "memchr" 1546 | version = "2.7.4" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1549 | 1550 | [[package]] 1551 | name = "mime" 1552 | version = "0.3.17" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1555 | 1556 | [[package]] 1557 | name = "mime_guess" 1558 | version = "2.0.5" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 1561 | dependencies = [ 1562 | "mime", 1563 | "unicase", 1564 | ] 1565 | 1566 | [[package]] 1567 | name = "miniz_oxide" 1568 | version = "0.8.7" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" 1571 | dependencies = [ 1572 | "adler2", 1573 | ] 1574 | 1575 | [[package]] 1576 | name = "mio" 1577 | version = "1.0.3" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 1580 | dependencies = [ 1581 | "libc", 1582 | "wasi 0.11.0+wasi-snapshot-preview1", 1583 | "windows-sys 0.52.0", 1584 | ] 1585 | 1586 | [[package]] 1587 | name = "native-tls" 1588 | version = "0.2.14" 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" 1590 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 1591 | dependencies = [ 1592 | "libc", 1593 | "log", 1594 | "openssl", 1595 | "openssl-probe", 1596 | "openssl-sys", 1597 | "schannel", 1598 | "security-framework", 1599 | "security-framework-sys", 1600 | "tempfile", 1601 | ] 1602 | 1603 | [[package]] 1604 | name = "nix" 1605 | version = "0.29.0" 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" 1607 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 1608 | dependencies = [ 1609 | "bitflags 2.9.0", 1610 | "cfg-if", 1611 | "cfg_aliases", 1612 | "libc", 1613 | ] 1614 | 1615 | [[package]] 1616 | name = "no-std-compat" 1617 | version = "0.4.1" 1618 | source = "registry+https://github.com/rust-lang/crates.io-index" 1619 | checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" 1620 | 1621 | [[package]] 1622 | name = "nonzero_ext" 1623 | version = "0.3.0" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" 1626 | 1627 | [[package]] 1628 | name = "num-bigint" 1629 | version = "0.4.6" 1630 | source = "registry+https://github.com/rust-lang/crates.io-index" 1631 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 1632 | dependencies = [ 1633 | "num-integer", 1634 | "num-traits", 1635 | "rand 0.8.5", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "num-bigint-dig" 1640 | version = "0.8.4" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1643 | dependencies = [ 1644 | "byteorder", 1645 | "lazy_static", 1646 | "libm", 1647 | "num-integer", 1648 | "num-iter", 1649 | "num-traits", 1650 | "rand 0.8.5", 1651 | "smallvec", 1652 | "zeroize", 1653 | ] 1654 | 1655 | [[package]] 1656 | name = "num-derive" 1657 | version = "0.4.2" 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" 1659 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 1660 | dependencies = [ 1661 | "proc-macro2", 1662 | "quote", 1663 | "syn", 1664 | ] 1665 | 1666 | [[package]] 1667 | name = "num-integer" 1668 | version = "0.1.46" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1671 | dependencies = [ 1672 | "num-traits", 1673 | ] 1674 | 1675 | [[package]] 1676 | name = "num-iter" 1677 | version = "0.1.45" 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" 1679 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 1680 | dependencies = [ 1681 | "autocfg", 1682 | "num-integer", 1683 | "num-traits", 1684 | ] 1685 | 1686 | [[package]] 1687 | name = "num-traits" 1688 | version = "0.2.19" 1689 | source = "registry+https://github.com/rust-lang/crates.io-index" 1690 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1691 | dependencies = [ 1692 | "autocfg", 1693 | "libm", 1694 | ] 1695 | 1696 | [[package]] 1697 | name = "num_cpus" 1698 | version = "1.16.0" 1699 | source = "registry+https://github.com/rust-lang/crates.io-index" 1700 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 1701 | dependencies = [ 1702 | "hermit-abi", 1703 | "libc", 1704 | ] 1705 | 1706 | [[package]] 1707 | name = "object" 1708 | version = "0.36.7" 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" 1710 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1711 | dependencies = [ 1712 | "memchr", 1713 | ] 1714 | 1715 | [[package]] 1716 | name = "once_cell" 1717 | version = "1.21.3" 1718 | source = "registry+https://github.com/rust-lang/crates.io-index" 1719 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1720 | 1721 | [[package]] 1722 | name = "opaque-debug" 1723 | version = "0.3.1" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" 1726 | 1727 | [[package]] 1728 | name = "openssl" 1729 | version = "0.10.72" 1730 | source = "registry+https://github.com/rust-lang/crates.io-index" 1731 | checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" 1732 | dependencies = [ 1733 | "bitflags 2.9.0", 1734 | "cfg-if", 1735 | "foreign-types", 1736 | "libc", 1737 | "once_cell", 1738 | "openssl-macros", 1739 | "openssl-sys", 1740 | ] 1741 | 1742 | [[package]] 1743 | name = "openssl-macros" 1744 | version = "0.1.1" 1745 | source = "registry+https://github.com/rust-lang/crates.io-index" 1746 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1747 | dependencies = [ 1748 | "proc-macro2", 1749 | "quote", 1750 | "syn", 1751 | ] 1752 | 1753 | [[package]] 1754 | name = "openssl-probe" 1755 | version = "0.1.6" 1756 | source = "registry+https://github.com/rust-lang/crates.io-index" 1757 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1758 | 1759 | [[package]] 1760 | name = "openssl-sys" 1761 | version = "0.9.107" 1762 | source = "registry+https://github.com/rust-lang/crates.io-index" 1763 | checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" 1764 | dependencies = [ 1765 | "cc", 1766 | "libc", 1767 | "pkg-config", 1768 | "vcpkg", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "p256" 1773 | version = "0.13.2" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 1776 | dependencies = [ 1777 | "ecdsa", 1778 | "elliptic-curve", 1779 | "primeorder", 1780 | "sha2", 1781 | ] 1782 | 1783 | [[package]] 1784 | name = "p384" 1785 | version = "0.13.1" 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" 1787 | checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" 1788 | dependencies = [ 1789 | "ecdsa", 1790 | "elliptic-curve", 1791 | "primeorder", 1792 | "sha2", 1793 | ] 1794 | 1795 | [[package]] 1796 | name = "p521" 1797 | version = "0.13.3" 1798 | source = "registry+https://github.com/rust-lang/crates.io-index" 1799 | checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" 1800 | dependencies = [ 1801 | "base16ct", 1802 | "ecdsa", 1803 | "elliptic-curve", 1804 | "primeorder", 1805 | "rand_core 0.6.4", 1806 | "sha2", 1807 | ] 1808 | 1809 | [[package]] 1810 | name = "pageant" 1811 | version = "0.0.3" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "bdd27df01428302f915ea74737fe88170dd1bab4cbd00ff9548ca85618fcd4e4" 1814 | dependencies = [ 1815 | "bytes", 1816 | "delegate", 1817 | "futures", 1818 | "log", 1819 | "rand 0.8.5", 1820 | "thiserror 1.0.69", 1821 | "tokio", 1822 | "windows", 1823 | ] 1824 | 1825 | [[package]] 1826 | name = "parking" 1827 | version = "2.2.1" 1828 | source = "registry+https://github.com/rust-lang/crates.io-index" 1829 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" 1830 | 1831 | [[package]] 1832 | name = "parking_lot" 1833 | version = "0.12.3" 1834 | source = "registry+https://github.com/rust-lang/crates.io-index" 1835 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1836 | dependencies = [ 1837 | "lock_api", 1838 | "parking_lot_core", 1839 | ] 1840 | 1841 | [[package]] 1842 | name = "parking_lot_core" 1843 | version = "0.9.10" 1844 | source = "registry+https://github.com/rust-lang/crates.io-index" 1845 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1846 | dependencies = [ 1847 | "cfg-if", 1848 | "libc", 1849 | "redox_syscall", 1850 | "smallvec", 1851 | "windows-targets 0.52.6", 1852 | ] 1853 | 1854 | [[package]] 1855 | name = "parse-zoneinfo" 1856 | version = "0.3.1" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" 1859 | dependencies = [ 1860 | "regex", 1861 | ] 1862 | 1863 | [[package]] 1864 | name = "password-hash" 1865 | version = "0.5.0" 1866 | source = "registry+https://github.com/rust-lang/crates.io-index" 1867 | checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" 1868 | dependencies = [ 1869 | "base64ct", 1870 | "rand_core 0.6.4", 1871 | "subtle", 1872 | ] 1873 | 1874 | [[package]] 1875 | name = "pbkdf2" 1876 | version = "0.12.2" 1877 | source = "registry+https://github.com/rust-lang/crates.io-index" 1878 | checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" 1879 | dependencies = [ 1880 | "digest", 1881 | "hmac", 1882 | ] 1883 | 1884 | [[package]] 1885 | name = "pem-rfc7468" 1886 | version = "0.7.0" 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" 1888 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 1889 | dependencies = [ 1890 | "base64ct", 1891 | ] 1892 | 1893 | [[package]] 1894 | name = "percent-encoding" 1895 | version = "2.3.1" 1896 | source = "registry+https://github.com/rust-lang/crates.io-index" 1897 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1898 | 1899 | [[package]] 1900 | name = "phf" 1901 | version = "0.11.3" 1902 | source = "registry+https://github.com/rust-lang/crates.io-index" 1903 | checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" 1904 | dependencies = [ 1905 | "phf_shared", 1906 | ] 1907 | 1908 | [[package]] 1909 | name = "phf_codegen" 1910 | version = "0.11.3" 1911 | source = "registry+https://github.com/rust-lang/crates.io-index" 1912 | checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" 1913 | dependencies = [ 1914 | "phf_generator", 1915 | "phf_shared", 1916 | ] 1917 | 1918 | [[package]] 1919 | name = "phf_generator" 1920 | version = "0.11.3" 1921 | source = "registry+https://github.com/rust-lang/crates.io-index" 1922 | checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" 1923 | dependencies = [ 1924 | "phf_shared", 1925 | "rand 0.8.5", 1926 | ] 1927 | 1928 | [[package]] 1929 | name = "phf_shared" 1930 | version = "0.11.3" 1931 | source = "registry+https://github.com/rust-lang/crates.io-index" 1932 | checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" 1933 | dependencies = [ 1934 | "siphasher", 1935 | ] 1936 | 1937 | [[package]] 1938 | name = "pin-project-lite" 1939 | version = "0.2.16" 1940 | source = "registry+https://github.com/rust-lang/crates.io-index" 1941 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1942 | 1943 | [[package]] 1944 | name = "pin-utils" 1945 | version = "0.1.0" 1946 | source = "registry+https://github.com/rust-lang/crates.io-index" 1947 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1948 | 1949 | [[package]] 1950 | name = "pkcs1" 1951 | version = "0.7.5" 1952 | source = "registry+https://github.com/rust-lang/crates.io-index" 1953 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1954 | dependencies = [ 1955 | "der", 1956 | "pkcs8", 1957 | "spki", 1958 | ] 1959 | 1960 | [[package]] 1961 | name = "pkcs5" 1962 | version = "0.7.1" 1963 | source = "registry+https://github.com/rust-lang/crates.io-index" 1964 | checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" 1965 | dependencies = [ 1966 | "aes", 1967 | "cbc", 1968 | "der", 1969 | "pbkdf2", 1970 | "scrypt", 1971 | "sha2", 1972 | "spki", 1973 | ] 1974 | 1975 | [[package]] 1976 | name = "pkcs8" 1977 | version = "0.10.2" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1980 | dependencies = [ 1981 | "der", 1982 | "pkcs5", 1983 | "rand_core 0.6.4", 1984 | "spki", 1985 | ] 1986 | 1987 | [[package]] 1988 | name = "pkg-config" 1989 | version = "0.3.32" 1990 | source = "registry+https://github.com/rust-lang/crates.io-index" 1991 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1992 | 1993 | [[package]] 1994 | name = "poly1305" 1995 | version = "0.8.0" 1996 | source = "registry+https://github.com/rust-lang/crates.io-index" 1997 | checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" 1998 | dependencies = [ 1999 | "cpufeatures", 2000 | "opaque-debug", 2001 | "universal-hash", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "polyval" 2006 | version = "0.6.2" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" 2009 | dependencies = [ 2010 | "cfg-if", 2011 | "cpufeatures", 2012 | "opaque-debug", 2013 | "universal-hash", 2014 | ] 2015 | 2016 | [[package]] 2017 | name = "portable-atomic" 2018 | version = "1.11.0" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" 2021 | 2022 | [[package]] 2023 | name = "ppv-lite86" 2024 | version = "0.2.21" 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" 2026 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 2027 | dependencies = [ 2028 | "zerocopy 0.8.24", 2029 | ] 2030 | 2031 | [[package]] 2032 | name = "primeorder" 2033 | version = "0.13.6" 2034 | source = "registry+https://github.com/rust-lang/crates.io-index" 2035 | checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" 2036 | dependencies = [ 2037 | "elliptic-curve", 2038 | ] 2039 | 2040 | [[package]] 2041 | name = "proc-macro2" 2042 | version = "1.0.94" 2043 | source = "registry+https://github.com/rust-lang/crates.io-index" 2044 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 2045 | dependencies = [ 2046 | "unicode-ident", 2047 | ] 2048 | 2049 | [[package]] 2050 | name = "quanta" 2051 | version = "0.12.5" 2052 | source = "registry+https://github.com/rust-lang/crates.io-index" 2053 | checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" 2054 | dependencies = [ 2055 | "crossbeam-utils", 2056 | "libc", 2057 | "once_cell", 2058 | "raw-cpuid", 2059 | "wasi 0.11.0+wasi-snapshot-preview1", 2060 | "web-sys", 2061 | "winapi", 2062 | ] 2063 | 2064 | [[package]] 2065 | name = "quinn" 2066 | version = "0.11.7" 2067 | source = "registry+https://github.com/rust-lang/crates.io-index" 2068 | checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" 2069 | dependencies = [ 2070 | "bytes", 2071 | "cfg_aliases", 2072 | "pin-project-lite", 2073 | "quinn-proto", 2074 | "quinn-udp", 2075 | "rustc-hash", 2076 | "rustls", 2077 | "socket2", 2078 | "thiserror 2.0.12", 2079 | "tokio", 2080 | "tracing", 2081 | "web-time", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "quinn-proto" 2086 | version = "0.11.10" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" 2089 | dependencies = [ 2090 | "bytes", 2091 | "getrandom 0.3.2", 2092 | "rand 0.9.0", 2093 | "ring", 2094 | "rustc-hash", 2095 | "rustls", 2096 | "rustls-pki-types", 2097 | "slab", 2098 | "thiserror 2.0.12", 2099 | "tinyvec", 2100 | "tracing", 2101 | "web-time", 2102 | ] 2103 | 2104 | [[package]] 2105 | name = "quinn-udp" 2106 | version = "0.5.11" 2107 | source = "registry+https://github.com/rust-lang/crates.io-index" 2108 | checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" 2109 | dependencies = [ 2110 | "cfg_aliases", 2111 | "libc", 2112 | "once_cell", 2113 | "socket2", 2114 | "tracing", 2115 | "windows-sys 0.59.0", 2116 | ] 2117 | 2118 | [[package]] 2119 | name = "quote" 2120 | version = "1.0.40" 2121 | source = "registry+https://github.com/rust-lang/crates.io-index" 2122 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 2123 | dependencies = [ 2124 | "proc-macro2", 2125 | ] 2126 | 2127 | [[package]] 2128 | name = "r-efi" 2129 | version = "5.2.0" 2130 | source = "registry+https://github.com/rust-lang/crates.io-index" 2131 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 2132 | 2133 | [[package]] 2134 | name = "rand" 2135 | version = "0.8.5" 2136 | source = "registry+https://github.com/rust-lang/crates.io-index" 2137 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2138 | dependencies = [ 2139 | "libc", 2140 | "rand_chacha 0.3.1", 2141 | "rand_core 0.6.4", 2142 | ] 2143 | 2144 | [[package]] 2145 | name = "rand" 2146 | version = "0.9.0" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" 2149 | dependencies = [ 2150 | "rand_chacha 0.9.0", 2151 | "rand_core 0.9.3", 2152 | "zerocopy 0.8.24", 2153 | ] 2154 | 2155 | [[package]] 2156 | name = "rand_chacha" 2157 | version = "0.3.1" 2158 | source = "registry+https://github.com/rust-lang/crates.io-index" 2159 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 2160 | dependencies = [ 2161 | "ppv-lite86", 2162 | "rand_core 0.6.4", 2163 | ] 2164 | 2165 | [[package]] 2166 | name = "rand_chacha" 2167 | version = "0.9.0" 2168 | source = "registry+https://github.com/rust-lang/crates.io-index" 2169 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 2170 | dependencies = [ 2171 | "ppv-lite86", 2172 | "rand_core 0.9.3", 2173 | ] 2174 | 2175 | [[package]] 2176 | name = "rand_core" 2177 | version = "0.6.4" 2178 | source = "registry+https://github.com/rust-lang/crates.io-index" 2179 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2180 | dependencies = [ 2181 | "getrandom 0.2.15", 2182 | ] 2183 | 2184 | [[package]] 2185 | name = "rand_core" 2186 | version = "0.9.3" 2187 | source = "registry+https://github.com/rust-lang/crates.io-index" 2188 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 2189 | dependencies = [ 2190 | "getrandom 0.3.2", 2191 | ] 2192 | 2193 | [[package]] 2194 | name = "raw-cpuid" 2195 | version = "11.5.0" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" 2198 | dependencies = [ 2199 | "bitflags 2.9.0", 2200 | ] 2201 | 2202 | [[package]] 2203 | name = "redox_syscall" 2204 | version = "0.5.10" 2205 | source = "registry+https://github.com/rust-lang/crates.io-index" 2206 | checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" 2207 | dependencies = [ 2208 | "bitflags 2.9.0", 2209 | ] 2210 | 2211 | [[package]] 2212 | name = "regex" 2213 | version = "1.11.1" 2214 | source = "registry+https://github.com/rust-lang/crates.io-index" 2215 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 2216 | dependencies = [ 2217 | "aho-corasick", 2218 | "memchr", 2219 | "regex-automata", 2220 | "regex-syntax", 2221 | ] 2222 | 2223 | [[package]] 2224 | name = "regex-automata" 2225 | version = "0.4.9" 2226 | source = "registry+https://github.com/rust-lang/crates.io-index" 2227 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 2228 | dependencies = [ 2229 | "aho-corasick", 2230 | "memchr", 2231 | "regex-syntax", 2232 | ] 2233 | 2234 | [[package]] 2235 | name = "regex-syntax" 2236 | version = "0.8.5" 2237 | source = "registry+https://github.com/rust-lang/crates.io-index" 2238 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 2239 | 2240 | [[package]] 2241 | name = "reqwest" 2242 | version = "0.11.27" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" 2245 | dependencies = [ 2246 | "base64 0.21.7", 2247 | "bytes", 2248 | "encoding_rs", 2249 | "futures-core", 2250 | "futures-util", 2251 | "h2", 2252 | "http 0.2.12", 2253 | "http-body 0.4.6", 2254 | "hyper 0.14.32", 2255 | "hyper-tls 0.5.0", 2256 | "ipnet", 2257 | "js-sys", 2258 | "log", 2259 | "mime", 2260 | "mime_guess", 2261 | "native-tls", 2262 | "once_cell", 2263 | "percent-encoding", 2264 | "pin-project-lite", 2265 | "rustls-pemfile 1.0.4", 2266 | "serde", 2267 | "serde_json", 2268 | "serde_urlencoded", 2269 | "sync_wrapper 0.1.2", 2270 | "system-configuration", 2271 | "tokio", 2272 | "tokio-native-tls", 2273 | "tower-service", 2274 | "url", 2275 | "wasm-bindgen", 2276 | "wasm-bindgen-futures", 2277 | "web-sys", 2278 | "winreg", 2279 | ] 2280 | 2281 | [[package]] 2282 | name = "reqwest" 2283 | version = "0.12.15" 2284 | source = "registry+https://github.com/rust-lang/crates.io-index" 2285 | checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" 2286 | dependencies = [ 2287 | "base64 0.22.1", 2288 | "bytes", 2289 | "futures-core", 2290 | "futures-util", 2291 | "http 1.3.1", 2292 | "http-body 1.0.1", 2293 | "http-body-util", 2294 | "hyper 1.6.0", 2295 | "hyper-rustls", 2296 | "hyper-tls 0.6.0", 2297 | "hyper-util", 2298 | "ipnet", 2299 | "js-sys", 2300 | "log", 2301 | "mime", 2302 | "native-tls", 2303 | "once_cell", 2304 | "percent-encoding", 2305 | "pin-project-lite", 2306 | "quinn", 2307 | "rustls", 2308 | "rustls-pemfile 2.2.0", 2309 | "rustls-pki-types", 2310 | "serde", 2311 | "serde_json", 2312 | "serde_urlencoded", 2313 | "sync_wrapper 1.0.2", 2314 | "tokio", 2315 | "tokio-native-tls", 2316 | "tokio-rustls", 2317 | "tokio-socks", 2318 | "tower", 2319 | "tower-service", 2320 | "url", 2321 | "wasm-bindgen", 2322 | "wasm-bindgen-futures", 2323 | "web-sys", 2324 | "webpki-roots", 2325 | "windows-registry", 2326 | ] 2327 | 2328 | [[package]] 2329 | name = "resend-rs" 2330 | version = "0.12.1" 2331 | source = "registry+https://github.com/rust-lang/crates.io-index" 2332 | checksum = "0db0693e3275502b16b58cb478849c8441ad5d86a7cf2ee590b96719f9d33b19" 2333 | dependencies = [ 2334 | "ecow", 2335 | "getrandom 0.3.2", 2336 | "governor", 2337 | "maybe-async", 2338 | "rand 0.9.0", 2339 | "reqwest 0.12.15", 2340 | "serde", 2341 | "serde_json", 2342 | "thiserror 2.0.12", 2343 | ] 2344 | 2345 | [[package]] 2346 | name = "rfc6979" 2347 | version = "0.4.0" 2348 | source = "registry+https://github.com/rust-lang/crates.io-index" 2349 | checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 2350 | dependencies = [ 2351 | "hmac", 2352 | "subtle", 2353 | ] 2354 | 2355 | [[package]] 2356 | name = "ring" 2357 | version = "0.17.14" 2358 | source = "registry+https://github.com/rust-lang/crates.io-index" 2359 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 2360 | dependencies = [ 2361 | "cc", 2362 | "cfg-if", 2363 | "getrandom 0.2.15", 2364 | "libc", 2365 | "untrusted", 2366 | "windows-sys 0.52.0", 2367 | ] 2368 | 2369 | [[package]] 2370 | name = "rsa" 2371 | version = "0.9.8" 2372 | source = "registry+https://github.com/rust-lang/crates.io-index" 2373 | checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" 2374 | dependencies = [ 2375 | "const-oid", 2376 | "digest", 2377 | "num-bigint-dig", 2378 | "num-integer", 2379 | "num-traits", 2380 | "pkcs1", 2381 | "pkcs8", 2382 | "rand_core 0.6.4", 2383 | "sha2", 2384 | "signature", 2385 | "spki", 2386 | "subtle", 2387 | "zeroize", 2388 | ] 2389 | 2390 | [[package]] 2391 | name = "russh" 2392 | version = "0.51.1" 2393 | source = "registry+https://github.com/rust-lang/crates.io-index" 2394 | checksum = "c4816b748109d26daa30e72d231a3a6e42f9e2fffe6c08cbfed63113db0ce884" 2395 | dependencies = [ 2396 | "aes", 2397 | "aes-gcm", 2398 | "bitflags 2.9.0", 2399 | "block-padding", 2400 | "byteorder", 2401 | "bytes", 2402 | "cbc", 2403 | "chacha20", 2404 | "ctr", 2405 | "curve25519-dalek", 2406 | "data-encoding", 2407 | "delegate", 2408 | "der", 2409 | "digest", 2410 | "ecdsa", 2411 | "ed25519-dalek", 2412 | "elliptic-curve", 2413 | "enum_dispatch", 2414 | "flate2", 2415 | "futures", 2416 | "generic-array", 2417 | "getrandom 0.2.15", 2418 | "hex-literal", 2419 | "hmac", 2420 | "home", 2421 | "inout", 2422 | "internal-russh-forked-ssh-key", 2423 | "log", 2424 | "md5", 2425 | "num-bigint", 2426 | "once_cell", 2427 | "p256", 2428 | "p384", 2429 | "p521", 2430 | "pageant", 2431 | "pbkdf2", 2432 | "pkcs1", 2433 | "pkcs5", 2434 | "pkcs8", 2435 | "poly1305", 2436 | "rand 0.8.5", 2437 | "rand_core 0.6.4", 2438 | "rsa", 2439 | "russh-cryptovec", 2440 | "russh-util", 2441 | "sec1", 2442 | "sha1", 2443 | "sha2", 2444 | "signature", 2445 | "spki", 2446 | "ssh-encoding", 2447 | "subtle", 2448 | "thiserror 1.0.69", 2449 | "tokio", 2450 | "typenum", 2451 | "zeroize", 2452 | ] 2453 | 2454 | [[package]] 2455 | name = "russh-cryptovec" 2456 | version = "0.51.1" 2457 | source = "registry+https://github.com/rust-lang/crates.io-index" 2458 | checksum = "5b722480e7117893a8a14ba22298dca3387b24fa1c40eb06f3105b82875c7497" 2459 | dependencies = [ 2460 | "libc", 2461 | "log", 2462 | "nix", 2463 | "ssh-encoding", 2464 | "winapi", 2465 | ] 2466 | 2467 | [[package]] 2468 | name = "russh-sftp" 2469 | version = "2.1.0" 2470 | source = "registry+https://github.com/rust-lang/crates.io-index" 2471 | checksum = "f08ed364d54b74d988c964b464a53a1916379f9441cfd10ca8fb264be1349842" 2472 | dependencies = [ 2473 | "bitflags 2.9.0", 2474 | "bytes", 2475 | "chrono", 2476 | "flurry", 2477 | "log", 2478 | "serde", 2479 | "thiserror 2.0.12", 2480 | "tokio", 2481 | "tokio-util", 2482 | ] 2483 | 2484 | [[package]] 2485 | name = "russh-util" 2486 | version = "0.51.0" 2487 | source = "registry+https://github.com/rust-lang/crates.io-index" 2488 | checksum = "c0c3f1ba8f8ccbe1af83c1a5dc325ecb0b6e176d1444c241c1d684ab216d1b24" 2489 | dependencies = [ 2490 | "chrono", 2491 | "tokio", 2492 | "wasm-bindgen", 2493 | "wasm-bindgen-futures", 2494 | ] 2495 | 2496 | [[package]] 2497 | name = "rustc-demangle" 2498 | version = "0.1.24" 2499 | source = "registry+https://github.com/rust-lang/crates.io-index" 2500 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2501 | 2502 | [[package]] 2503 | name = "rustc-hash" 2504 | version = "2.1.1" 2505 | source = "registry+https://github.com/rust-lang/crates.io-index" 2506 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 2507 | 2508 | [[package]] 2509 | name = "rustc_version" 2510 | version = "0.4.1" 2511 | source = "registry+https://github.com/rust-lang/crates.io-index" 2512 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 2513 | dependencies = [ 2514 | "semver", 2515 | ] 2516 | 2517 | [[package]] 2518 | name = "rustix" 2519 | version = "1.0.5" 2520 | source = "registry+https://github.com/rust-lang/crates.io-index" 2521 | checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" 2522 | dependencies = [ 2523 | "bitflags 2.9.0", 2524 | "errno", 2525 | "libc", 2526 | "linux-raw-sys", 2527 | "windows-sys 0.59.0", 2528 | ] 2529 | 2530 | [[package]] 2531 | name = "rustls" 2532 | version = "0.23.25" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" 2535 | dependencies = [ 2536 | "once_cell", 2537 | "ring", 2538 | "rustls-pki-types", 2539 | "rustls-webpki", 2540 | "subtle", 2541 | "zeroize", 2542 | ] 2543 | 2544 | [[package]] 2545 | name = "rustls-pemfile" 2546 | version = "1.0.4" 2547 | source = "registry+https://github.com/rust-lang/crates.io-index" 2548 | checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" 2549 | dependencies = [ 2550 | "base64 0.21.7", 2551 | ] 2552 | 2553 | [[package]] 2554 | name = "rustls-pemfile" 2555 | version = "2.2.0" 2556 | source = "registry+https://github.com/rust-lang/crates.io-index" 2557 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 2558 | dependencies = [ 2559 | "rustls-pki-types", 2560 | ] 2561 | 2562 | [[package]] 2563 | name = "rustls-pki-types" 2564 | version = "1.11.0" 2565 | source = "registry+https://github.com/rust-lang/crates.io-index" 2566 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 2567 | dependencies = [ 2568 | "web-time", 2569 | ] 2570 | 2571 | [[package]] 2572 | name = "rustls-webpki" 2573 | version = "0.103.1" 2574 | source = "registry+https://github.com/rust-lang/crates.io-index" 2575 | checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" 2576 | dependencies = [ 2577 | "ring", 2578 | "rustls-pki-types", 2579 | "untrusted", 2580 | ] 2581 | 2582 | [[package]] 2583 | name = "rustversion" 2584 | version = "1.0.20" 2585 | source = "registry+https://github.com/rust-lang/crates.io-index" 2586 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 2587 | 2588 | [[package]] 2589 | name = "ryu" 2590 | version = "1.0.20" 2591 | source = "registry+https://github.com/rust-lang/crates.io-index" 2592 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 2593 | 2594 | [[package]] 2595 | name = "salsa20" 2596 | version = "0.10.2" 2597 | source = "registry+https://github.com/rust-lang/crates.io-index" 2598 | checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" 2599 | dependencies = [ 2600 | "cipher", 2601 | ] 2602 | 2603 | [[package]] 2604 | name = "schannel" 2605 | version = "0.1.27" 2606 | source = "registry+https://github.com/rust-lang/crates.io-index" 2607 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 2608 | dependencies = [ 2609 | "windows-sys 0.59.0", 2610 | ] 2611 | 2612 | [[package]] 2613 | name = "scopeguard" 2614 | version = "1.2.0" 2615 | source = "registry+https://github.com/rust-lang/crates.io-index" 2616 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2617 | 2618 | [[package]] 2619 | name = "scrypt" 2620 | version = "0.11.0" 2621 | source = "registry+https://github.com/rust-lang/crates.io-index" 2622 | checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" 2623 | dependencies = [ 2624 | "pbkdf2", 2625 | "salsa20", 2626 | "sha2", 2627 | ] 2628 | 2629 | [[package]] 2630 | name = "sec1" 2631 | version = "0.7.3" 2632 | source = "registry+https://github.com/rust-lang/crates.io-index" 2633 | checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 2634 | dependencies = [ 2635 | "base16ct", 2636 | "der", 2637 | "generic-array", 2638 | "pkcs8", 2639 | "subtle", 2640 | "zeroize", 2641 | ] 2642 | 2643 | [[package]] 2644 | name = "security-framework" 2645 | version = "2.11.1" 2646 | source = "registry+https://github.com/rust-lang/crates.io-index" 2647 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2648 | dependencies = [ 2649 | "bitflags 2.9.0", 2650 | "core-foundation", 2651 | "core-foundation-sys", 2652 | "libc", 2653 | "security-framework-sys", 2654 | ] 2655 | 2656 | [[package]] 2657 | name = "security-framework-sys" 2658 | version = "2.14.0" 2659 | source = "registry+https://github.com/rust-lang/crates.io-index" 2660 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 2661 | dependencies = [ 2662 | "core-foundation-sys", 2663 | "libc", 2664 | ] 2665 | 2666 | [[package]] 2667 | name = "seize" 2668 | version = "0.3.3" 2669 | source = "registry+https://github.com/rust-lang/crates.io-index" 2670 | checksum = "689224d06523904ebcc9b482c6a3f4f7fb396096645c4cd10c0d2ff7371a34d3" 2671 | 2672 | [[package]] 2673 | name = "semver" 2674 | version = "1.0.26" 2675 | source = "registry+https://github.com/rust-lang/crates.io-index" 2676 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 2677 | 2678 | [[package]] 2679 | name = "serde" 2680 | version = "1.0.219" 2681 | source = "registry+https://github.com/rust-lang/crates.io-index" 2682 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 2683 | dependencies = [ 2684 | "serde_derive", 2685 | ] 2686 | 2687 | [[package]] 2688 | name = "serde_derive" 2689 | version = "1.0.219" 2690 | source = "registry+https://github.com/rust-lang/crates.io-index" 2691 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 2692 | dependencies = [ 2693 | "proc-macro2", 2694 | "quote", 2695 | "syn", 2696 | ] 2697 | 2698 | [[package]] 2699 | name = "serde_json" 2700 | version = "1.0.140" 2701 | source = "registry+https://github.com/rust-lang/crates.io-index" 2702 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 2703 | dependencies = [ 2704 | "itoa", 2705 | "memchr", 2706 | "ryu", 2707 | "serde", 2708 | ] 2709 | 2710 | [[package]] 2711 | name = "serde_spanned" 2712 | version = "0.6.8" 2713 | source = "registry+https://github.com/rust-lang/crates.io-index" 2714 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 2715 | dependencies = [ 2716 | "serde", 2717 | ] 2718 | 2719 | [[package]] 2720 | name = "serde_urlencoded" 2721 | version = "0.7.1" 2722 | source = "registry+https://github.com/rust-lang/crates.io-index" 2723 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2724 | dependencies = [ 2725 | "form_urlencoded", 2726 | "itoa", 2727 | "ryu", 2728 | "serde", 2729 | ] 2730 | 2731 | [[package]] 2732 | name = "sha1" 2733 | version = "0.10.6" 2734 | source = "registry+https://github.com/rust-lang/crates.io-index" 2735 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2736 | dependencies = [ 2737 | "cfg-if", 2738 | "cpufeatures", 2739 | "digest", 2740 | ] 2741 | 2742 | [[package]] 2743 | name = "sha2" 2744 | version = "0.10.8" 2745 | source = "registry+https://github.com/rust-lang/crates.io-index" 2746 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 2747 | dependencies = [ 2748 | "cfg-if", 2749 | "cpufeatures", 2750 | "digest", 2751 | ] 2752 | 2753 | [[package]] 2754 | name = "shlex" 2755 | version = "1.3.0" 2756 | source = "registry+https://github.com/rust-lang/crates.io-index" 2757 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2758 | 2759 | [[package]] 2760 | name = "signal-hook-registry" 2761 | version = "1.4.2" 2762 | source = "registry+https://github.com/rust-lang/crates.io-index" 2763 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 2764 | dependencies = [ 2765 | "libc", 2766 | ] 2767 | 2768 | [[package]] 2769 | name = "signature" 2770 | version = "2.2.0" 2771 | source = "registry+https://github.com/rust-lang/crates.io-index" 2772 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 2773 | dependencies = [ 2774 | "digest", 2775 | "rand_core 0.6.4", 2776 | ] 2777 | 2778 | [[package]] 2779 | name = "siphasher" 2780 | version = "1.0.1" 2781 | source = "registry+https://github.com/rust-lang/crates.io-index" 2782 | checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" 2783 | 2784 | [[package]] 2785 | name = "slab" 2786 | version = "0.4.9" 2787 | source = "registry+https://github.com/rust-lang/crates.io-index" 2788 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2789 | dependencies = [ 2790 | "autocfg", 2791 | ] 2792 | 2793 | [[package]] 2794 | name = "smallvec" 2795 | version = "1.15.0" 2796 | source = "registry+https://github.com/rust-lang/crates.io-index" 2797 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 2798 | 2799 | [[package]] 2800 | name = "socket2" 2801 | version = "0.5.9" 2802 | source = "registry+https://github.com/rust-lang/crates.io-index" 2803 | checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" 2804 | dependencies = [ 2805 | "libc", 2806 | "windows-sys 0.52.0", 2807 | ] 2808 | 2809 | [[package]] 2810 | name = "spin" 2811 | version = "0.9.8" 2812 | source = "registry+https://github.com/rust-lang/crates.io-index" 2813 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2814 | 2815 | [[package]] 2816 | name = "spinning_top" 2817 | version = "0.3.0" 2818 | source = "registry+https://github.com/rust-lang/crates.io-index" 2819 | checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" 2820 | dependencies = [ 2821 | "lock_api", 2822 | ] 2823 | 2824 | [[package]] 2825 | name = "spki" 2826 | version = "0.7.3" 2827 | source = "registry+https://github.com/rust-lang/crates.io-index" 2828 | checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 2829 | dependencies = [ 2830 | "base64ct", 2831 | "der", 2832 | ] 2833 | 2834 | [[package]] 2835 | name = "ssh-cipher" 2836 | version = "0.2.0" 2837 | source = "registry+https://github.com/rust-lang/crates.io-index" 2838 | checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" 2839 | dependencies = [ 2840 | "aes", 2841 | "aes-gcm", 2842 | "cbc", 2843 | "chacha20", 2844 | "cipher", 2845 | "ctr", 2846 | "poly1305", 2847 | "ssh-encoding", 2848 | "subtle", 2849 | ] 2850 | 2851 | [[package]] 2852 | name = "ssh-encoding" 2853 | version = "0.2.0" 2854 | source = "registry+https://github.com/rust-lang/crates.io-index" 2855 | checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" 2856 | dependencies = [ 2857 | "base64ct", 2858 | "bytes", 2859 | "pem-rfc7468", 2860 | "sha2", 2861 | ] 2862 | 2863 | [[package]] 2864 | name = "stable_deref_trait" 2865 | version = "1.2.0" 2866 | source = "registry+https://github.com/rust-lang/crates.io-index" 2867 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2868 | 2869 | [[package]] 2870 | name = "subtle" 2871 | version = "2.6.1" 2872 | source = "registry+https://github.com/rust-lang/crates.io-index" 2873 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2874 | 2875 | [[package]] 2876 | name = "syn" 2877 | version = "2.0.100" 2878 | source = "registry+https://github.com/rust-lang/crates.io-index" 2879 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 2880 | dependencies = [ 2881 | "proc-macro2", 2882 | "quote", 2883 | "unicode-ident", 2884 | ] 2885 | 2886 | [[package]] 2887 | name = "sync_wrapper" 2888 | version = "0.1.2" 2889 | source = "registry+https://github.com/rust-lang/crates.io-index" 2890 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 2891 | 2892 | [[package]] 2893 | name = "sync_wrapper" 2894 | version = "1.0.2" 2895 | source = "registry+https://github.com/rust-lang/crates.io-index" 2896 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 2897 | dependencies = [ 2898 | "futures-core", 2899 | ] 2900 | 2901 | [[package]] 2902 | name = "synstructure" 2903 | version = "0.13.1" 2904 | source = "registry+https://github.com/rust-lang/crates.io-index" 2905 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 2906 | dependencies = [ 2907 | "proc-macro2", 2908 | "quote", 2909 | "syn", 2910 | ] 2911 | 2912 | [[package]] 2913 | name = "system-configuration" 2914 | version = "0.5.1" 2915 | source = "registry+https://github.com/rust-lang/crates.io-index" 2916 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" 2917 | dependencies = [ 2918 | "bitflags 1.3.2", 2919 | "core-foundation", 2920 | "system-configuration-sys", 2921 | ] 2922 | 2923 | [[package]] 2924 | name = "system-configuration-sys" 2925 | version = "0.5.0" 2926 | source = "registry+https://github.com/rust-lang/crates.io-index" 2927 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" 2928 | dependencies = [ 2929 | "core-foundation-sys", 2930 | "libc", 2931 | ] 2932 | 2933 | [[package]] 2934 | name = "tempfile" 2935 | version = "3.19.1" 2936 | source = "registry+https://github.com/rust-lang/crates.io-index" 2937 | checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" 2938 | dependencies = [ 2939 | "fastrand", 2940 | "getrandom 0.3.2", 2941 | "once_cell", 2942 | "rustix", 2943 | "windows-sys 0.59.0", 2944 | ] 2945 | 2946 | [[package]] 2947 | name = "tgbot-app" 2948 | version = "0.2.14" 2949 | dependencies = [ 2950 | "anyhow", 2951 | "async-channel", 2952 | "async-ssh2-tokio", 2953 | "chrono", 2954 | "chrono-tz", 2955 | "ferrisgram", 2956 | "once_cell", 2957 | "reqwest 0.12.15", 2958 | "resend-rs", 2959 | "serde", 2960 | "serde_derive", 2961 | "serde_json", 2962 | "tklog", 2963 | "tokio", 2964 | "tokio-cron-scheduler", 2965 | "toml", 2966 | ] 2967 | 2968 | [[package]] 2969 | name = "thiserror" 2970 | version = "1.0.69" 2971 | source = "registry+https://github.com/rust-lang/crates.io-index" 2972 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 2973 | dependencies = [ 2974 | "thiserror-impl 1.0.69", 2975 | ] 2976 | 2977 | [[package]] 2978 | name = "thiserror" 2979 | version = "2.0.12" 2980 | source = "registry+https://github.com/rust-lang/crates.io-index" 2981 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 2982 | dependencies = [ 2983 | "thiserror-impl 2.0.12", 2984 | ] 2985 | 2986 | [[package]] 2987 | name = "thiserror-impl" 2988 | version = "1.0.69" 2989 | source = "registry+https://github.com/rust-lang/crates.io-index" 2990 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2991 | dependencies = [ 2992 | "proc-macro2", 2993 | "quote", 2994 | "syn", 2995 | ] 2996 | 2997 | [[package]] 2998 | name = "thiserror-impl" 2999 | version = "2.0.12" 3000 | source = "registry+https://github.com/rust-lang/crates.io-index" 3001 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 3002 | dependencies = [ 3003 | "proc-macro2", 3004 | "quote", 3005 | "syn", 3006 | ] 3007 | 3008 | [[package]] 3009 | name = "tiny-keccak" 3010 | version = "2.0.2" 3011 | source = "registry+https://github.com/rust-lang/crates.io-index" 3012 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 3013 | dependencies = [ 3014 | "crunchy", 3015 | ] 3016 | 3017 | [[package]] 3018 | name = "tinystr" 3019 | version = "0.7.6" 3020 | source = "registry+https://github.com/rust-lang/crates.io-index" 3021 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 3022 | dependencies = [ 3023 | "displaydoc", 3024 | "zerovec", 3025 | ] 3026 | 3027 | [[package]] 3028 | name = "tinyvec" 3029 | version = "1.9.0" 3030 | source = "registry+https://github.com/rust-lang/crates.io-index" 3031 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 3032 | dependencies = [ 3033 | "tinyvec_macros", 3034 | ] 3035 | 3036 | [[package]] 3037 | name = "tinyvec_macros" 3038 | version = "0.1.1" 3039 | source = "registry+https://github.com/rust-lang/crates.io-index" 3040 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 3041 | 3042 | [[package]] 3043 | name = "tklog" 3044 | version = "0.2.9" 3045 | source = "registry+https://github.com/rust-lang/crates.io-index" 3046 | checksum = "7712822534ae94f7bf122243dbf9d6474f86a1c0a5d4cdaa36fd7bf074b61730" 3047 | dependencies = [ 3048 | "chrono", 3049 | "crossbeam-channel", 3050 | "flate2", 3051 | "log", 3052 | "once_cell", 3053 | "regex", 3054 | "tokio", 3055 | ] 3056 | 3057 | [[package]] 3058 | name = "tokio" 3059 | version = "1.44.1" 3060 | source = "registry+https://github.com/rust-lang/crates.io-index" 3061 | checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" 3062 | dependencies = [ 3063 | "backtrace", 3064 | "bytes", 3065 | "libc", 3066 | "mio", 3067 | "parking_lot", 3068 | "pin-project-lite", 3069 | "signal-hook-registry", 3070 | "socket2", 3071 | "tokio-macros", 3072 | "windows-sys 0.52.0", 3073 | ] 3074 | 3075 | [[package]] 3076 | name = "tokio-cron-scheduler" 3077 | version = "0.13.0" 3078 | source = "registry+https://github.com/rust-lang/crates.io-index" 3079 | checksum = "6a5597b569b4712cf78aa0c9ae29742461b7bda1e49c2a5fdad1d79bf022f8f0" 3080 | dependencies = [ 3081 | "chrono", 3082 | "croner", 3083 | "num-derive", 3084 | "num-traits", 3085 | "tokio", 3086 | "tracing", 3087 | "uuid", 3088 | ] 3089 | 3090 | [[package]] 3091 | name = "tokio-macros" 3092 | version = "2.5.0" 3093 | source = "registry+https://github.com/rust-lang/crates.io-index" 3094 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 3095 | dependencies = [ 3096 | "proc-macro2", 3097 | "quote", 3098 | "syn", 3099 | ] 3100 | 3101 | [[package]] 3102 | name = "tokio-native-tls" 3103 | version = "0.3.1" 3104 | source = "registry+https://github.com/rust-lang/crates.io-index" 3105 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 3106 | dependencies = [ 3107 | "native-tls", 3108 | "tokio", 3109 | ] 3110 | 3111 | [[package]] 3112 | name = "tokio-rustls" 3113 | version = "0.26.2" 3114 | source = "registry+https://github.com/rust-lang/crates.io-index" 3115 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 3116 | dependencies = [ 3117 | "rustls", 3118 | "tokio", 3119 | ] 3120 | 3121 | [[package]] 3122 | name = "tokio-socks" 3123 | version = "0.5.2" 3124 | source = "registry+https://github.com/rust-lang/crates.io-index" 3125 | checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" 3126 | dependencies = [ 3127 | "either", 3128 | "futures-util", 3129 | "thiserror 1.0.69", 3130 | "tokio", 3131 | ] 3132 | 3133 | [[package]] 3134 | name = "tokio-util" 3135 | version = "0.7.14" 3136 | source = "registry+https://github.com/rust-lang/crates.io-index" 3137 | checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" 3138 | dependencies = [ 3139 | "bytes", 3140 | "futures-core", 3141 | "futures-sink", 3142 | "pin-project-lite", 3143 | "tokio", 3144 | ] 3145 | 3146 | [[package]] 3147 | name = "toml" 3148 | version = "0.8.20" 3149 | source = "registry+https://github.com/rust-lang/crates.io-index" 3150 | checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" 3151 | dependencies = [ 3152 | "serde", 3153 | "serde_spanned", 3154 | "toml_datetime", 3155 | "toml_edit", 3156 | ] 3157 | 3158 | [[package]] 3159 | name = "toml_datetime" 3160 | version = "0.6.8" 3161 | source = "registry+https://github.com/rust-lang/crates.io-index" 3162 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 3163 | dependencies = [ 3164 | "serde", 3165 | ] 3166 | 3167 | [[package]] 3168 | name = "toml_edit" 3169 | version = "0.22.24" 3170 | source = "registry+https://github.com/rust-lang/crates.io-index" 3171 | checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" 3172 | dependencies = [ 3173 | "indexmap", 3174 | "serde", 3175 | "serde_spanned", 3176 | "toml_datetime", 3177 | "winnow", 3178 | ] 3179 | 3180 | [[package]] 3181 | name = "tower" 3182 | version = "0.5.2" 3183 | source = "registry+https://github.com/rust-lang/crates.io-index" 3184 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 3185 | dependencies = [ 3186 | "futures-core", 3187 | "futures-util", 3188 | "pin-project-lite", 3189 | "sync_wrapper 1.0.2", 3190 | "tokio", 3191 | "tower-layer", 3192 | "tower-service", 3193 | ] 3194 | 3195 | [[package]] 3196 | name = "tower-layer" 3197 | version = "0.3.3" 3198 | source = "registry+https://github.com/rust-lang/crates.io-index" 3199 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 3200 | 3201 | [[package]] 3202 | name = "tower-service" 3203 | version = "0.3.3" 3204 | source = "registry+https://github.com/rust-lang/crates.io-index" 3205 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 3206 | 3207 | [[package]] 3208 | name = "tracing" 3209 | version = "0.1.41" 3210 | source = "registry+https://github.com/rust-lang/crates.io-index" 3211 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 3212 | dependencies = [ 3213 | "pin-project-lite", 3214 | "tracing-attributes", 3215 | "tracing-core", 3216 | ] 3217 | 3218 | [[package]] 3219 | name = "tracing-attributes" 3220 | version = "0.1.28" 3221 | source = "registry+https://github.com/rust-lang/crates.io-index" 3222 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 3223 | dependencies = [ 3224 | "proc-macro2", 3225 | "quote", 3226 | "syn", 3227 | ] 3228 | 3229 | [[package]] 3230 | name = "tracing-core" 3231 | version = "0.1.33" 3232 | source = "registry+https://github.com/rust-lang/crates.io-index" 3233 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 3234 | dependencies = [ 3235 | "once_cell", 3236 | ] 3237 | 3238 | [[package]] 3239 | name = "try-lock" 3240 | version = "0.2.5" 3241 | source = "registry+https://github.com/rust-lang/crates.io-index" 3242 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 3243 | 3244 | [[package]] 3245 | name = "typenum" 3246 | version = "1.18.0" 3247 | source = "registry+https://github.com/rust-lang/crates.io-index" 3248 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 3249 | 3250 | [[package]] 3251 | name = "unicase" 3252 | version = "2.8.1" 3253 | source = "registry+https://github.com/rust-lang/crates.io-index" 3254 | checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 3255 | 3256 | [[package]] 3257 | name = "unicode-ident" 3258 | version = "1.0.18" 3259 | source = "registry+https://github.com/rust-lang/crates.io-index" 3260 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 3261 | 3262 | [[package]] 3263 | name = "universal-hash" 3264 | version = "0.5.1" 3265 | source = "registry+https://github.com/rust-lang/crates.io-index" 3266 | checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" 3267 | dependencies = [ 3268 | "crypto-common", 3269 | "subtle", 3270 | ] 3271 | 3272 | [[package]] 3273 | name = "untrusted" 3274 | version = "0.9.0" 3275 | source = "registry+https://github.com/rust-lang/crates.io-index" 3276 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3277 | 3278 | [[package]] 3279 | name = "url" 3280 | version = "2.5.4" 3281 | source = "registry+https://github.com/rust-lang/crates.io-index" 3282 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 3283 | dependencies = [ 3284 | "form_urlencoded", 3285 | "idna", 3286 | "percent-encoding", 3287 | ] 3288 | 3289 | [[package]] 3290 | name = "utf16_iter" 3291 | version = "1.0.5" 3292 | source = "registry+https://github.com/rust-lang/crates.io-index" 3293 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 3294 | 3295 | [[package]] 3296 | name = "utf8_iter" 3297 | version = "1.0.4" 3298 | source = "registry+https://github.com/rust-lang/crates.io-index" 3299 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 3300 | 3301 | [[package]] 3302 | name = "uuid" 3303 | version = "1.16.0" 3304 | source = "registry+https://github.com/rust-lang/crates.io-index" 3305 | checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" 3306 | dependencies = [ 3307 | "getrandom 0.3.2", 3308 | ] 3309 | 3310 | [[package]] 3311 | name = "vcpkg" 3312 | version = "0.2.15" 3313 | source = "registry+https://github.com/rust-lang/crates.io-index" 3314 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 3315 | 3316 | [[package]] 3317 | name = "version_check" 3318 | version = "0.9.5" 3319 | source = "registry+https://github.com/rust-lang/crates.io-index" 3320 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3321 | 3322 | [[package]] 3323 | name = "want" 3324 | version = "0.3.1" 3325 | source = "registry+https://github.com/rust-lang/crates.io-index" 3326 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 3327 | dependencies = [ 3328 | "try-lock", 3329 | ] 3330 | 3331 | [[package]] 3332 | name = "wasi" 3333 | version = "0.11.0+wasi-snapshot-preview1" 3334 | source = "registry+https://github.com/rust-lang/crates.io-index" 3335 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3336 | 3337 | [[package]] 3338 | name = "wasi" 3339 | version = "0.14.2+wasi-0.2.4" 3340 | source = "registry+https://github.com/rust-lang/crates.io-index" 3341 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 3342 | dependencies = [ 3343 | "wit-bindgen-rt", 3344 | ] 3345 | 3346 | [[package]] 3347 | name = "wasm-bindgen" 3348 | version = "0.2.100" 3349 | source = "registry+https://github.com/rust-lang/crates.io-index" 3350 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 3351 | dependencies = [ 3352 | "cfg-if", 3353 | "once_cell", 3354 | "rustversion", 3355 | "wasm-bindgen-macro", 3356 | ] 3357 | 3358 | [[package]] 3359 | name = "wasm-bindgen-backend" 3360 | version = "0.2.100" 3361 | source = "registry+https://github.com/rust-lang/crates.io-index" 3362 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 3363 | dependencies = [ 3364 | "bumpalo", 3365 | "log", 3366 | "proc-macro2", 3367 | "quote", 3368 | "syn", 3369 | "wasm-bindgen-shared", 3370 | ] 3371 | 3372 | [[package]] 3373 | name = "wasm-bindgen-futures" 3374 | version = "0.4.50" 3375 | source = "registry+https://github.com/rust-lang/crates.io-index" 3376 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 3377 | dependencies = [ 3378 | "cfg-if", 3379 | "js-sys", 3380 | "once_cell", 3381 | "wasm-bindgen", 3382 | "web-sys", 3383 | ] 3384 | 3385 | [[package]] 3386 | name = "wasm-bindgen-macro" 3387 | version = "0.2.100" 3388 | source = "registry+https://github.com/rust-lang/crates.io-index" 3389 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 3390 | dependencies = [ 3391 | "quote", 3392 | "wasm-bindgen-macro-support", 3393 | ] 3394 | 3395 | [[package]] 3396 | name = "wasm-bindgen-macro-support" 3397 | version = "0.2.100" 3398 | source = "registry+https://github.com/rust-lang/crates.io-index" 3399 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 3400 | dependencies = [ 3401 | "proc-macro2", 3402 | "quote", 3403 | "syn", 3404 | "wasm-bindgen-backend", 3405 | "wasm-bindgen-shared", 3406 | ] 3407 | 3408 | [[package]] 3409 | name = "wasm-bindgen-shared" 3410 | version = "0.2.100" 3411 | source = "registry+https://github.com/rust-lang/crates.io-index" 3412 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 3413 | dependencies = [ 3414 | "unicode-ident", 3415 | ] 3416 | 3417 | [[package]] 3418 | name = "web-sys" 3419 | version = "0.3.77" 3420 | source = "registry+https://github.com/rust-lang/crates.io-index" 3421 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 3422 | dependencies = [ 3423 | "js-sys", 3424 | "wasm-bindgen", 3425 | ] 3426 | 3427 | [[package]] 3428 | name = "web-time" 3429 | version = "1.1.0" 3430 | source = "registry+https://github.com/rust-lang/crates.io-index" 3431 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 3432 | dependencies = [ 3433 | "js-sys", 3434 | "wasm-bindgen", 3435 | ] 3436 | 3437 | [[package]] 3438 | name = "webpki-roots" 3439 | version = "0.26.8" 3440 | source = "registry+https://github.com/rust-lang/crates.io-index" 3441 | checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" 3442 | dependencies = [ 3443 | "rustls-pki-types", 3444 | ] 3445 | 3446 | [[package]] 3447 | name = "winapi" 3448 | version = "0.3.9" 3449 | source = "registry+https://github.com/rust-lang/crates.io-index" 3450 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3451 | dependencies = [ 3452 | "winapi-i686-pc-windows-gnu", 3453 | "winapi-x86_64-pc-windows-gnu", 3454 | ] 3455 | 3456 | [[package]] 3457 | name = "winapi-i686-pc-windows-gnu" 3458 | version = "0.4.0" 3459 | source = "registry+https://github.com/rust-lang/crates.io-index" 3460 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3461 | 3462 | [[package]] 3463 | name = "winapi-x86_64-pc-windows-gnu" 3464 | version = "0.4.0" 3465 | source = "registry+https://github.com/rust-lang/crates.io-index" 3466 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3467 | 3468 | [[package]] 3469 | name = "windows" 3470 | version = "0.58.0" 3471 | source = "registry+https://github.com/rust-lang/crates.io-index" 3472 | checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" 3473 | dependencies = [ 3474 | "windows-core 0.58.0", 3475 | "windows-targets 0.52.6", 3476 | ] 3477 | 3478 | [[package]] 3479 | name = "windows-core" 3480 | version = "0.58.0" 3481 | source = "registry+https://github.com/rust-lang/crates.io-index" 3482 | checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" 3483 | dependencies = [ 3484 | "windows-implement 0.58.0", 3485 | "windows-interface 0.58.0", 3486 | "windows-result 0.2.0", 3487 | "windows-strings 0.1.0", 3488 | "windows-targets 0.52.6", 3489 | ] 3490 | 3491 | [[package]] 3492 | name = "windows-core" 3493 | version = "0.61.0" 3494 | source = "registry+https://github.com/rust-lang/crates.io-index" 3495 | checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" 3496 | dependencies = [ 3497 | "windows-implement 0.60.0", 3498 | "windows-interface 0.59.1", 3499 | "windows-link", 3500 | "windows-result 0.3.2", 3501 | "windows-strings 0.4.0", 3502 | ] 3503 | 3504 | [[package]] 3505 | name = "windows-implement" 3506 | version = "0.58.0" 3507 | source = "registry+https://github.com/rust-lang/crates.io-index" 3508 | checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" 3509 | dependencies = [ 3510 | "proc-macro2", 3511 | "quote", 3512 | "syn", 3513 | ] 3514 | 3515 | [[package]] 3516 | name = "windows-implement" 3517 | version = "0.60.0" 3518 | source = "registry+https://github.com/rust-lang/crates.io-index" 3519 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 3520 | dependencies = [ 3521 | "proc-macro2", 3522 | "quote", 3523 | "syn", 3524 | ] 3525 | 3526 | [[package]] 3527 | name = "windows-interface" 3528 | version = "0.58.0" 3529 | source = "registry+https://github.com/rust-lang/crates.io-index" 3530 | checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" 3531 | dependencies = [ 3532 | "proc-macro2", 3533 | "quote", 3534 | "syn", 3535 | ] 3536 | 3537 | [[package]] 3538 | name = "windows-interface" 3539 | version = "0.59.1" 3540 | source = "registry+https://github.com/rust-lang/crates.io-index" 3541 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 3542 | dependencies = [ 3543 | "proc-macro2", 3544 | "quote", 3545 | "syn", 3546 | ] 3547 | 3548 | [[package]] 3549 | name = "windows-link" 3550 | version = "0.1.1" 3551 | source = "registry+https://github.com/rust-lang/crates.io-index" 3552 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 3553 | 3554 | [[package]] 3555 | name = "windows-registry" 3556 | version = "0.4.0" 3557 | source = "registry+https://github.com/rust-lang/crates.io-index" 3558 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 3559 | dependencies = [ 3560 | "windows-result 0.3.2", 3561 | "windows-strings 0.3.1", 3562 | "windows-targets 0.53.0", 3563 | ] 3564 | 3565 | [[package]] 3566 | name = "windows-result" 3567 | version = "0.2.0" 3568 | source = "registry+https://github.com/rust-lang/crates.io-index" 3569 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 3570 | dependencies = [ 3571 | "windows-targets 0.52.6", 3572 | ] 3573 | 3574 | [[package]] 3575 | name = "windows-result" 3576 | version = "0.3.2" 3577 | source = "registry+https://github.com/rust-lang/crates.io-index" 3578 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 3579 | dependencies = [ 3580 | "windows-link", 3581 | ] 3582 | 3583 | [[package]] 3584 | name = "windows-strings" 3585 | version = "0.1.0" 3586 | source = "registry+https://github.com/rust-lang/crates.io-index" 3587 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 3588 | dependencies = [ 3589 | "windows-result 0.2.0", 3590 | "windows-targets 0.52.6", 3591 | ] 3592 | 3593 | [[package]] 3594 | name = "windows-strings" 3595 | version = "0.3.1" 3596 | source = "registry+https://github.com/rust-lang/crates.io-index" 3597 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 3598 | dependencies = [ 3599 | "windows-link", 3600 | ] 3601 | 3602 | [[package]] 3603 | name = "windows-strings" 3604 | version = "0.4.0" 3605 | source = "registry+https://github.com/rust-lang/crates.io-index" 3606 | checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" 3607 | dependencies = [ 3608 | "windows-link", 3609 | ] 3610 | 3611 | [[package]] 3612 | name = "windows-sys" 3613 | version = "0.48.0" 3614 | source = "registry+https://github.com/rust-lang/crates.io-index" 3615 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 3616 | dependencies = [ 3617 | "windows-targets 0.48.5", 3618 | ] 3619 | 3620 | [[package]] 3621 | name = "windows-sys" 3622 | version = "0.52.0" 3623 | source = "registry+https://github.com/rust-lang/crates.io-index" 3624 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 3625 | dependencies = [ 3626 | "windows-targets 0.52.6", 3627 | ] 3628 | 3629 | [[package]] 3630 | name = "windows-sys" 3631 | version = "0.59.0" 3632 | source = "registry+https://github.com/rust-lang/crates.io-index" 3633 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 3634 | dependencies = [ 3635 | "windows-targets 0.52.6", 3636 | ] 3637 | 3638 | [[package]] 3639 | name = "windows-targets" 3640 | version = "0.48.5" 3641 | source = "registry+https://github.com/rust-lang/crates.io-index" 3642 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 3643 | dependencies = [ 3644 | "windows_aarch64_gnullvm 0.48.5", 3645 | "windows_aarch64_msvc 0.48.5", 3646 | "windows_i686_gnu 0.48.5", 3647 | "windows_i686_msvc 0.48.5", 3648 | "windows_x86_64_gnu 0.48.5", 3649 | "windows_x86_64_gnullvm 0.48.5", 3650 | "windows_x86_64_msvc 0.48.5", 3651 | ] 3652 | 3653 | [[package]] 3654 | name = "windows-targets" 3655 | version = "0.52.6" 3656 | source = "registry+https://github.com/rust-lang/crates.io-index" 3657 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 3658 | dependencies = [ 3659 | "windows_aarch64_gnullvm 0.52.6", 3660 | "windows_aarch64_msvc 0.52.6", 3661 | "windows_i686_gnu 0.52.6", 3662 | "windows_i686_gnullvm 0.52.6", 3663 | "windows_i686_msvc 0.52.6", 3664 | "windows_x86_64_gnu 0.52.6", 3665 | "windows_x86_64_gnullvm 0.52.6", 3666 | "windows_x86_64_msvc 0.52.6", 3667 | ] 3668 | 3669 | [[package]] 3670 | name = "windows-targets" 3671 | version = "0.53.0" 3672 | source = "registry+https://github.com/rust-lang/crates.io-index" 3673 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 3674 | dependencies = [ 3675 | "windows_aarch64_gnullvm 0.53.0", 3676 | "windows_aarch64_msvc 0.53.0", 3677 | "windows_i686_gnu 0.53.0", 3678 | "windows_i686_gnullvm 0.53.0", 3679 | "windows_i686_msvc 0.53.0", 3680 | "windows_x86_64_gnu 0.53.0", 3681 | "windows_x86_64_gnullvm 0.53.0", 3682 | "windows_x86_64_msvc 0.53.0", 3683 | ] 3684 | 3685 | [[package]] 3686 | name = "windows_aarch64_gnullvm" 3687 | version = "0.48.5" 3688 | source = "registry+https://github.com/rust-lang/crates.io-index" 3689 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 3690 | 3691 | [[package]] 3692 | name = "windows_aarch64_gnullvm" 3693 | version = "0.52.6" 3694 | source = "registry+https://github.com/rust-lang/crates.io-index" 3695 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 3696 | 3697 | [[package]] 3698 | name = "windows_aarch64_gnullvm" 3699 | version = "0.53.0" 3700 | source = "registry+https://github.com/rust-lang/crates.io-index" 3701 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 3702 | 3703 | [[package]] 3704 | name = "windows_aarch64_msvc" 3705 | version = "0.48.5" 3706 | source = "registry+https://github.com/rust-lang/crates.io-index" 3707 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 3708 | 3709 | [[package]] 3710 | name = "windows_aarch64_msvc" 3711 | version = "0.52.6" 3712 | source = "registry+https://github.com/rust-lang/crates.io-index" 3713 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 3714 | 3715 | [[package]] 3716 | name = "windows_aarch64_msvc" 3717 | version = "0.53.0" 3718 | source = "registry+https://github.com/rust-lang/crates.io-index" 3719 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 3720 | 3721 | [[package]] 3722 | name = "windows_i686_gnu" 3723 | version = "0.48.5" 3724 | source = "registry+https://github.com/rust-lang/crates.io-index" 3725 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 3726 | 3727 | [[package]] 3728 | name = "windows_i686_gnu" 3729 | version = "0.52.6" 3730 | source = "registry+https://github.com/rust-lang/crates.io-index" 3731 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3732 | 3733 | [[package]] 3734 | name = "windows_i686_gnu" 3735 | version = "0.53.0" 3736 | source = "registry+https://github.com/rust-lang/crates.io-index" 3737 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 3738 | 3739 | [[package]] 3740 | name = "windows_i686_gnullvm" 3741 | version = "0.52.6" 3742 | source = "registry+https://github.com/rust-lang/crates.io-index" 3743 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3744 | 3745 | [[package]] 3746 | name = "windows_i686_gnullvm" 3747 | version = "0.53.0" 3748 | source = "registry+https://github.com/rust-lang/crates.io-index" 3749 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 3750 | 3751 | [[package]] 3752 | name = "windows_i686_msvc" 3753 | version = "0.48.5" 3754 | source = "registry+https://github.com/rust-lang/crates.io-index" 3755 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 3756 | 3757 | [[package]] 3758 | name = "windows_i686_msvc" 3759 | version = "0.52.6" 3760 | source = "registry+https://github.com/rust-lang/crates.io-index" 3761 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3762 | 3763 | [[package]] 3764 | name = "windows_i686_msvc" 3765 | version = "0.53.0" 3766 | source = "registry+https://github.com/rust-lang/crates.io-index" 3767 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 3768 | 3769 | [[package]] 3770 | name = "windows_x86_64_gnu" 3771 | version = "0.48.5" 3772 | source = "registry+https://github.com/rust-lang/crates.io-index" 3773 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 3774 | 3775 | [[package]] 3776 | name = "windows_x86_64_gnu" 3777 | version = "0.52.6" 3778 | source = "registry+https://github.com/rust-lang/crates.io-index" 3779 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3780 | 3781 | [[package]] 3782 | name = "windows_x86_64_gnu" 3783 | version = "0.53.0" 3784 | source = "registry+https://github.com/rust-lang/crates.io-index" 3785 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 3786 | 3787 | [[package]] 3788 | name = "windows_x86_64_gnullvm" 3789 | version = "0.48.5" 3790 | source = "registry+https://github.com/rust-lang/crates.io-index" 3791 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 3792 | 3793 | [[package]] 3794 | name = "windows_x86_64_gnullvm" 3795 | version = "0.52.6" 3796 | source = "registry+https://github.com/rust-lang/crates.io-index" 3797 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3798 | 3799 | [[package]] 3800 | name = "windows_x86_64_gnullvm" 3801 | version = "0.53.0" 3802 | source = "registry+https://github.com/rust-lang/crates.io-index" 3803 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 3804 | 3805 | [[package]] 3806 | name = "windows_x86_64_msvc" 3807 | version = "0.48.5" 3808 | source = "registry+https://github.com/rust-lang/crates.io-index" 3809 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 3810 | 3811 | [[package]] 3812 | name = "windows_x86_64_msvc" 3813 | version = "0.52.6" 3814 | source = "registry+https://github.com/rust-lang/crates.io-index" 3815 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3816 | 3817 | [[package]] 3818 | name = "windows_x86_64_msvc" 3819 | version = "0.53.0" 3820 | source = "registry+https://github.com/rust-lang/crates.io-index" 3821 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 3822 | 3823 | [[package]] 3824 | name = "winnow" 3825 | version = "0.7.4" 3826 | source = "registry+https://github.com/rust-lang/crates.io-index" 3827 | checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" 3828 | dependencies = [ 3829 | "memchr", 3830 | ] 3831 | 3832 | [[package]] 3833 | name = "winreg" 3834 | version = "0.50.0" 3835 | source = "registry+https://github.com/rust-lang/crates.io-index" 3836 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 3837 | dependencies = [ 3838 | "cfg-if", 3839 | "windows-sys 0.48.0", 3840 | ] 3841 | 3842 | [[package]] 3843 | name = "wit-bindgen-rt" 3844 | version = "0.39.0" 3845 | source = "registry+https://github.com/rust-lang/crates.io-index" 3846 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 3847 | dependencies = [ 3848 | "bitflags 2.9.0", 3849 | ] 3850 | 3851 | [[package]] 3852 | name = "write16" 3853 | version = "1.0.0" 3854 | source = "registry+https://github.com/rust-lang/crates.io-index" 3855 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 3856 | 3857 | [[package]] 3858 | name = "writeable" 3859 | version = "0.5.5" 3860 | source = "registry+https://github.com/rust-lang/crates.io-index" 3861 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 3862 | 3863 | [[package]] 3864 | name = "yoke" 3865 | version = "0.7.5" 3866 | source = "registry+https://github.com/rust-lang/crates.io-index" 3867 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 3868 | dependencies = [ 3869 | "serde", 3870 | "stable_deref_trait", 3871 | "yoke-derive", 3872 | "zerofrom", 3873 | ] 3874 | 3875 | [[package]] 3876 | name = "yoke-derive" 3877 | version = "0.7.5" 3878 | source = "registry+https://github.com/rust-lang/crates.io-index" 3879 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 3880 | dependencies = [ 3881 | "proc-macro2", 3882 | "quote", 3883 | "syn", 3884 | "synstructure", 3885 | ] 3886 | 3887 | [[package]] 3888 | name = "zerocopy" 3889 | version = "0.7.35" 3890 | source = "registry+https://github.com/rust-lang/crates.io-index" 3891 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 3892 | dependencies = [ 3893 | "zerocopy-derive 0.7.35", 3894 | ] 3895 | 3896 | [[package]] 3897 | name = "zerocopy" 3898 | version = "0.8.24" 3899 | source = "registry+https://github.com/rust-lang/crates.io-index" 3900 | checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" 3901 | dependencies = [ 3902 | "zerocopy-derive 0.8.24", 3903 | ] 3904 | 3905 | [[package]] 3906 | name = "zerocopy-derive" 3907 | version = "0.7.35" 3908 | source = "registry+https://github.com/rust-lang/crates.io-index" 3909 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3910 | dependencies = [ 3911 | "proc-macro2", 3912 | "quote", 3913 | "syn", 3914 | ] 3915 | 3916 | [[package]] 3917 | name = "zerocopy-derive" 3918 | version = "0.8.24" 3919 | source = "registry+https://github.com/rust-lang/crates.io-index" 3920 | checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" 3921 | dependencies = [ 3922 | "proc-macro2", 3923 | "quote", 3924 | "syn", 3925 | ] 3926 | 3927 | [[package]] 3928 | name = "zerofrom" 3929 | version = "0.1.6" 3930 | source = "registry+https://github.com/rust-lang/crates.io-index" 3931 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 3932 | dependencies = [ 3933 | "zerofrom-derive", 3934 | ] 3935 | 3936 | [[package]] 3937 | name = "zerofrom-derive" 3938 | version = "0.1.6" 3939 | source = "registry+https://github.com/rust-lang/crates.io-index" 3940 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 3941 | dependencies = [ 3942 | "proc-macro2", 3943 | "quote", 3944 | "syn", 3945 | "synstructure", 3946 | ] 3947 | 3948 | [[package]] 3949 | name = "zeroize" 3950 | version = "1.8.1" 3951 | source = "registry+https://github.com/rust-lang/crates.io-index" 3952 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3953 | 3954 | [[package]] 3955 | name = "zerovec" 3956 | version = "0.10.4" 3957 | source = "registry+https://github.com/rust-lang/crates.io-index" 3958 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 3959 | dependencies = [ 3960 | "yoke", 3961 | "zerofrom", 3962 | "zerovec-derive", 3963 | ] 3964 | 3965 | [[package]] 3966 | name = "zerovec-derive" 3967 | version = "0.10.3" 3968 | source = "registry+https://github.com/rust-lang/crates.io-index" 3969 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 3970 | dependencies = [ 3971 | "proc-macro2", 3972 | "quote", 3973 | "syn", 3974 | ] 3975 | --------------------------------------------------------------------------------