chore: Upgrade dependencies and fix lint errors

Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
Awiteb 2024-05-26 21:53:33 +03:00
parent 9100ebcb11
commit 99b3d5418d
Signed by: awiteb
GPG key ID: 3F6B55640AA6682F
5 changed files with 898 additions and 628 deletions

1441
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,19 +12,19 @@ version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
chrono = "0.4.31" chrono = "0.4.38"
dotenv = "0.15.0" dotenv = "0.15.0"
grammers-client = "= 0.4.0" grammers-client = "0.6.0"
grammers-session = "= 0.4.0" grammers-session = "0.5.2"
lazy_static = "1.4.0" lazy_static = "1.4.0"
log = "0.4.20" log = "0.4.21"
pretty_env_logger = "0.5.0" pretty_env_logger = "0.5.0"
promptly = "0.3.1" promptly = "0.3.1"
salvo = {version = "0.58.3", features = ["logging", "affix"]} salvo = {version = "0.67.2", features = ["logging", "affix", "rustls"]}
serde = {version = "1.0.192", features = ["derive"]} serde = {version = "1.0.202", features = ["derive"]}
serde_json = "1.0.108" serde_json = "1.0.117"
sha256 = "1.4.0" sha256 = "1.5.0"
tokio = {version = "1.34.0", features = ["macros", "rt-multi-thread", "signal"]} tokio = {version = "1.37.0", features = ["macros", "rt-multi-thread", "signal"]}
[lints.rust] [lints.rust]
unsafe_code = "forbid" unsafe_code = "forbid"

View file

@ -18,7 +18,7 @@ use std::sync::Arc;
use salvo::{catcher::Catcher, http::HeaderValue, hyper::header, logging::Logger, prelude::*}; use salvo::{catcher::Catcher, http::HeaderValue, hyper::header, logging::Logger, prelude::*};
use crate::PingList; use crate::{superbot, PingList};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct AppState { pub(crate) struct AppState {
@ -61,7 +61,7 @@ impl AppState {
impl<'a> MessageSchema<'a> { impl<'a> MessageSchema<'a> {
/// Create new [`Message`] instance with `200 OK` status /// Create new [`Message`] instance with `200 OK` status
fn new(message: &'a str) -> Self { const fn new(message: &'a str) -> Self {
Self { Self {
message, message,
status: true, status: true,
@ -78,20 +78,23 @@ impl<'a> MessageSchema<'a> {
} }
fn write_json_body(res: &mut Response, json_body: impl serde::Serialize) { fn write_json_body(res: &mut Response, json_body: impl serde::Serialize) {
res.write_body(serde_json::to_string(&json_body).unwrap()) res.write_body(serde_json::to_string(&json_body).expect("This should not fail"))
.ok(); .ok();
} }
#[handler] #[handler]
async fn ping(req: &Request, res: &mut Response, depot: &mut Depot) { async fn ping(req: &Request, res: &mut Response, depot: &mut Depot) {
let bot_username = req.param::<String>("bot_username").unwrap().to_lowercase(); let bot_username = req
let app_state = depot.obtain::<Arc<AppState>>().unwrap(); .param::<String>("bot_username")
.expect("The path param is required");
let app_state = depot
.obtain::<Arc<AppState>>()
.expect("The app state is injected");
let msg = if !app_state.bots.contains(&bot_username) { let msg = if !app_state.bots.contains(&bot_username) {
MessageSchema::new("Is not authorized to check the status of this bot") MessageSchema::new("Is not authorized to check the status of this bot")
.code(StatusCode::BAD_REQUEST) .code(StatusCode::BAD_REQUEST)
} else if let Ok(telegram_id) = } else if let Ok(telegram_id) = superbot::send_start(&app_state.tg_client, &bot_username).await
crate::superbot::send_start(&app_state.tg_client, &bot_username).await
{ {
if crate::PINGED_BOTS.check(telegram_id) { if crate::PINGED_BOTS.check(telegram_id) {
MessageSchema::new("Alive") MessageSchema::new("Alive")
@ -107,7 +110,7 @@ async fn ping(req: &Request, res: &mut Response, depot: &mut Depot) {
#[handler] #[handler]
async fn handle404(res: &mut Response, ctrl: &mut FlowCtrl) { async fn handle404(res: &mut Response, ctrl: &mut FlowCtrl) {
if let Some(StatusCode::NOT_FOUND) = res.status_code { if res.status_code == Some(StatusCode::NOT_FOUND) {
write_json_body( write_json_body(
res, res,
MessageSchema::new("Not Found").code(StatusCode::NOT_FOUND), MessageSchema::new("Not Found").code(StatusCode::NOT_FOUND),
@ -129,7 +132,9 @@ async fn handle_server_errors(res: &mut Response, ctrl: &mut FlowCtrl) {
#[handler] #[handler]
async fn auth(req: &Request, res: &mut Response, depot: &mut Depot, ctrl: &mut FlowCtrl) { async fn auth(req: &Request, res: &mut Response, depot: &mut Depot, ctrl: &mut FlowCtrl) {
let app_state = depot.obtain::<Arc<AppState>>().unwrap(); let app_state = depot
.obtain::<Arc<AppState>>()
.expect("The app state is injected");
log::info!("New auth request"); log::info!("New auth request");
if let Some(token) = req.headers().get("Authorization") { if let Some(token) = req.headers().get("Authorization") {
if let Ok(token) = token.to_str() { if let Ok(token) = token.to_str() {

View file

@ -14,10 +14,12 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0>. // along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0>.
#![doc = include_str!("../README.md")]
use std::{env, fs, sync::Mutex}; use std::{env, fs, sync::Mutex};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use salvo::Listener; use salvo::{conn::TcpListener, Listener};
mod api; mod api;
mod superbot; mod superbot;
@ -40,7 +42,9 @@ impl PingList for Mutex<Vec<PingedBot>> {
fn clear_outdead(&self) { fn clear_outdead(&self) {
log::info!("Clear the dead pings"); log::info!("Clear the dead pings");
let dead_time = chrono::Utc::now().timestamp() - 60; let dead_time = chrono::Utc::now().timestamp() - 60;
let mut bots = self.lock().unwrap(); let mut bots = self
.lock()
.expect("Another holder paniced while holding the lock");
*bots = bots *bots = bots
.iter() .iter()
.filter(|b| b.ping_in > dead_time) .filter(|b| b.ping_in > dead_time)
@ -50,7 +54,9 @@ impl PingList for Mutex<Vec<PingedBot>> {
fn add_new(&self, telegram_id: u64) { fn add_new(&self, telegram_id: u64) {
log::debug!("Adding new bot to the list: {telegram_id}"); log::debug!("Adding new bot to the list: {telegram_id}");
self.lock().unwrap().push(PingedBot::new(telegram_id)); self.lock()
.expect("Another holder paniced while holding the lock")
.push(PingedBot::new(telegram_id));
} }
fn check(&self, telegram_id: u64) -> bool { fn check(&self, telegram_id: u64) -> bool {
@ -58,7 +64,7 @@ impl PingList for Mutex<Vec<PingedBot>> {
self.clear_outdead(); self.clear_outdead();
let result = self let result = self
.lock() .lock()
.unwrap() .expect("Another holder paniced while holding the lock")
.iter() .iter()
.any(|b| b.telegram_id == telegram_id && b.is_response); .any(|b| b.telegram_id == telegram_id && b.is_response);
log::debug!("Response status: {result}"); log::debug!("Response status: {result}");
@ -67,7 +73,9 @@ impl PingList for Mutex<Vec<PingedBot>> {
fn new_res(&self, telegram_id: u64) { fn new_res(&self, telegram_id: u64) {
log::debug!("New res from: {telegram_id}"); log::debug!("New res from: {telegram_id}");
let mut bots = self.lock().unwrap(); let mut bots = self
.lock()
.expect("Another holder paniced while holding the lock");
*bots = bots *bots = bots
.iter() .iter()
.cloned() .cloned()
@ -92,12 +100,13 @@ impl PingedBot {
} }
} }
pub(crate) fn new_res(mut self) -> Self { pub(crate) const fn new_res(mut self) -> Self {
self.is_response = true; self.is_response = true;
self self
} }
} }
#[allow(clippy::absolute_paths)]
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
lazy_static! { lazy_static! {
@ -147,21 +156,11 @@ async fn main() -> Result<()> {
let app_state = api::AppState::new(bots, tokens, client.clone()); let app_state = api::AppState::new(bots, tokens, client.clone());
let handler_client = client.clone(); let handler_client = client.clone();
let acceptor = salvo::conn::TcpListener::new(format!("{host}:{port}")) let acceptor = TcpListener::new(format!("{host}:{port}")).bind().await;
.bind()
.await;
let client_handler = tokio::spawn(async move { superbot::handler(handler_client).await }); let client_handler = tokio::spawn(async move { superbot::handler(handler_client).await });
let server_handler = tokio::spawn(async move { let server_handler = tokio::spawn(async move {
salvo::Server::new(acceptor) salvo::Server::new(acceptor)
.serve_with_graceful_shutdown( .serve(api::service(app_state))
api::service(app_state),
async {
tokio::signal::ctrl_c()
.await
.expect("Faild to listen to ctrl_c event");
},
None,
)
.await .await
}); });

View file

@ -16,6 +16,7 @@
use grammers_client::{Client, Config, InitParams, SignInError, Update}; use grammers_client::{Client, Config, InitParams, SignInError, Update};
use grammers_session::Session; use grammers_session::Session;
use tokio::{signal, time};
use crate::PingList; use crate::PingList;
@ -34,7 +35,7 @@ pub(crate) async fn login(api_hash: String, api_id: i32) -> crate::Result<(Clien
if !client.is_authorized().await? { if !client.is_authorized().await? {
println!("Signing in..."); println!("Signing in...");
let phone: String = promptly::prompt("Enter your phone number (international format)")?; let phone: String = promptly::prompt("Enter your phone number (international format)")?;
let token = client.request_login_code(&phone, api_id, &api_hash).await?; let token = client.request_login_code(&phone).await?;
let code: String = promptly::prompt("Enter the code you received")?; let code: String = promptly::prompt("Enter the code you received")?;
let signed_in = client.sign_in(&token, &code).await; let signed_in = client.sign_in(&token, &code).await;
match signed_in { match signed_in {
@ -47,7 +48,7 @@ pub(crate) async fn login(api_hash: String, api_id: i32) -> crate::Result<(Clien
.await?; .await?;
} }
Ok(_) => (), Ok(_) => (),
Err(e) => panic!("{e}"), Err(e) => return Err(e.into()),
} }
let me = client.get_me().await?; let me = client.get_me().await?;
println!( println!(
@ -82,7 +83,7 @@ fn update_handler(upd: Update) {
pub(crate) async fn handler(client: Client) { pub(crate) async fn handler(client: Client) {
loop { loop {
tokio::select! { tokio::select! {
_ = tokio::signal::ctrl_c() => { _ = signal::ctrl_c() => {
break; break;
} }
Ok(Some(update)) = client.next_update() => { Ok(Some(update)) = client.next_update() => {
@ -101,7 +102,7 @@ pub(crate) async fn send_start(client: &Client, bot_username: &str) -> crate::Re
crate::PINGED_BOTS.add_new(telegram_id); crate::PINGED_BOTS.add_new(telegram_id);
client.send_message(chat, "/start").await?; client.send_message(chat, "/start").await?;
// Sleep, wating the response // Sleep, wating the response
tokio::time::sleep(std::time::Duration::from_secs(2)).await; time::sleep(time::Duration::from_secs(2)).await;
Ok(telegram_id) Ok(telegram_id)
} else { } else {
Err(format!("Invalid username `{bot_username}`").into()) Err(format!("Invalid username `{bot_username}`").into())