inline 模式
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -1126,6 +1126,7 @@ dependencies = [
 | 
				
			|||||||
 "migration",
 | 
					 "migration",
 | 
				
			||||||
 "models",
 | 
					 "models",
 | 
				
			||||||
 "rand",
 | 
					 "rand",
 | 
				
			||||||
 | 
					 "regex",
 | 
				
			||||||
 "reqwest",
 | 
					 "reqwest",
 | 
				
			||||||
 "sea-orm",
 | 
					 "sea-orm",
 | 
				
			||||||
 "shadow-rs",
 | 
					 "shadow-rs",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ futures = "0.3.29"
 | 
				
			|||||||
strfmt = "^0.2.4"
 | 
					strfmt = "^0.2.4"
 | 
				
			||||||
reqwest= "^0.11"
 | 
					reqwest= "^0.11"
 | 
				
			||||||
rand="^0.8.5"
 | 
					rand="^0.8.5"
 | 
				
			||||||
 | 
					regex = "^1.10.2"
 | 
				
			||||||
#lazy_static="^1.4.0"
 | 
					#lazy_static="^1.4.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.clap]
 | 
					[dependencies.clap]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										218
									
								
								src/commands.rs
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								src/commands.rs
									
									
									
									
									
								
							@@ -1,7 +1,5 @@
 | 
				
			|||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use rand::{rngs::OsRng, Rng};
 | 
					 | 
				
			||||||
use sea_orm::DbErr;
 | 
					 | 
				
			||||||
use strfmt::Format;
 | 
					use strfmt::Format;
 | 
				
			||||||
use teloxide::{
 | 
					use teloxide::{
 | 
				
			||||||
    payloads::SendMessageSetters,
 | 
					    payloads::SendMessageSetters,
 | 
				
			||||||
@@ -13,13 +11,13 @@ use teloxide::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    config::Args,
 | 
					 | 
				
			||||||
    db_controller::Controller,
 | 
					    db_controller::Controller,
 | 
				
			||||||
    messages::{
 | 
					    messages::{
 | 
				
			||||||
        BOT_ABOUT, BOT_TEXT_HANGED, BOT_TEXT_HANGED_SELF, BOT_TEXT_IS_CHANNEL, BOT_TEXT_NO_TARGET,
 | 
					        BOT_ABOUT, BOT_TEXT_HANG_ANONYMOUS, BOT_TEXT_HANG_BOT, BOT_TEXT_HANG_CHANNEL,
 | 
				
			||||||
        BOT_TEXT_TOP_GLOBAL, BOT_TEXT_TOP_GROUP, BOT_TEXT_TOP_NONE, BOT_TEXT_TOP_TEMPLATE,
 | 
					        BOT_TEXT_IS_CHANNEL, BOT_TEXT_NO_TARGET, BOT_TEXT_TOP_GLOBAL, BOT_TEXT_TOP_GROUP,
 | 
				
			||||||
        BOT_TEXT_TOP_TITLE, BOT_TEXT_HANG_BOT, BOT_TEXT_HANG_ANONYMOUS, BOT_TEXT_HANG_CHANNEL,
 | 
					        BOT_TEXT_TOP_NONE, BOT_TEXT_TOP_TEMPLATE, BOT_TEXT_TOP_TITLE,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    utils::hangit_text,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(BotCommands, PartialEq, Debug, Clone)]
 | 
					#[derive(BotCommands, PartialEq, Debug, Clone)]
 | 
				
			||||||
@@ -44,146 +42,96 @@ impl Default for Commands {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					async fn send_text_reply(bot: &Bot, message: &Message, text: String) -> Result<(), RequestError> {
 | 
				
			||||||
pub struct CommandHandler {
 | 
					    bot.send_message(message.chat.id, text)
 | 
				
			||||||
    pub controller: Controller,
 | 
					        .reply_to_message_id(message.id)
 | 
				
			||||||
 | 
					        .parse_mode(ParseMode::MarkdownV2)
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl CommandHandler {
 | 
					pub async fn help_handler(bot: &Bot, message: &Message) -> Result<(), RequestError> {
 | 
				
			||||||
    pub async fn new(config: &Args) -> Result<Self, DbErr> {
 | 
					    send_text_reply(bot, message, Commands::descriptions().to_string()).await
 | 
				
			||||||
        Ok(Self {
 | 
					}
 | 
				
			||||||
            controller: Controller::new(config.database_uri.to_owned()).await?,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn init(&self) -> Result<(), DbErr> {
 | 
					pub async fn about_handler(bot: &Bot, message: &Message) -> Result<(), RequestError> {
 | 
				
			||||||
        self.controller.migrate().await
 | 
					    send_text_reply(bot, message, BOT_ABOUT.to_string()).await
 | 
				
			||||||
    }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn send_text_reply(
 | 
					pub async fn hangit_handler(
 | 
				
			||||||
        &self,
 | 
					    db: &Controller,
 | 
				
			||||||
        bot: &Bot,
 | 
					    bot: &Bot,
 | 
				
			||||||
        message: &Message,
 | 
					    message: &Message,
 | 
				
			||||||
        text: String,
 | 
					) -> Result<(), RequestError> {
 | 
				
			||||||
    ) -> Result<Message, RequestError> {
 | 
					    let reply = match message.reply_to_message() {
 | 
				
			||||||
        bot.send_message(message.chat.id, text)
 | 
					        Some(reply) => reply,
 | 
				
			||||||
            .reply_to_message_id(message.id)
 | 
					        None => {
 | 
				
			||||||
            .parse_mode(ParseMode::MarkdownV2)
 | 
					            return send_text_reply(bot, message, BOT_TEXT_NO_TARGET.to_string()).await;
 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn help_handler(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        bot: &Bot,
 | 
					 | 
				
			||||||
        message: &Message,
 | 
					 | 
				
			||||||
    ) -> Result<Message, RequestError> {
 | 
					 | 
				
			||||||
        self.send_text_reply(bot, message, Commands::descriptions().to_string())
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn about_handler(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        bot: &Bot,
 | 
					 | 
				
			||||||
        message: &Message,
 | 
					 | 
				
			||||||
    ) -> Result<Message, RequestError> {
 | 
					 | 
				
			||||||
        self.send_text_reply(bot, message, BOT_ABOUT.to_string())
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn hangit_handler(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        bot: &Bot,
 | 
					 | 
				
			||||||
        message: &Message,
 | 
					 | 
				
			||||||
    ) -> Result<Message, RequestError> {
 | 
					 | 
				
			||||||
        let reply = match message.reply_to_message() {
 | 
					 | 
				
			||||||
            Some(reply) => reply,
 | 
					 | 
				
			||||||
            None => {
 | 
					 | 
				
			||||||
                return self
 | 
					 | 
				
			||||||
                    .send_text_reply(bot, message, BOT_TEXT_NO_TARGET.to_string())
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match reply.from() {
 | 
					 | 
				
			||||||
            Some(user) => {
 | 
					 | 
				
			||||||
                if user.is_bot {
 | 
					 | 
				
			||||||
                    return self.send_text_reply(bot, reply, BOT_TEXT_HANG_BOT.to_string()).await
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if user.is_anonymous() {
 | 
					 | 
				
			||||||
                    return self.send_text_reply(bot, reply, BOT_TEXT_HANG_ANONYMOUS.to_string()).await
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if user.is_channel() {
 | 
					 | 
				
			||||||
                    return self.send_text_reply(bot, reply, BOT_TEXT_HANG_CHANNEL.to_string()).await
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let is_self = match message.from() {
 | 
					 | 
				
			||||||
                    Some(f) => f.first_name == user.first_name,
 | 
					 | 
				
			||||||
                    None => false,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let mut vars = HashMap::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let index = if is_self {
 | 
					 | 
				
			||||||
                    OsRng.gen::<usize>() % BOT_TEXT_HANGED_SELF.len()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    OsRng.gen::<usize>() % BOT_TEXT_HANGED.len()
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let text = if is_self {
 | 
					 | 
				
			||||||
                    BOT_TEXT_HANGED_SELF[index]
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    BOT_TEXT_HANGED[index]
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let name = escape(user.first_name.as_str());
 | 
					 | 
				
			||||||
                vars.insert("name".to_string(), name.as_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let _ = self
 | 
					 | 
				
			||||||
                    .controller
 | 
					 | 
				
			||||||
                    .hangit(&user.full_name(), message.chat.id)
 | 
					 | 
				
			||||||
                    .await;
 | 
					 | 
				
			||||||
                self.send_text_reply(bot, reply, text.format(&vars).unwrap())
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            None => {
 | 
					 | 
				
			||||||
                self.send_text_reply(bot, message, BOT_TEXT_IS_CHANNEL.to_string())
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn top_handler(&self, bot: &Bot, message: &Message) -> Result<Message, RequestError> {
 | 
					    match reply.from() {
 | 
				
			||||||
        let chat = &message.chat;
 | 
					        Some(user) => {
 | 
				
			||||||
        let scope = match chat.is_group() || chat.is_supergroup() {
 | 
					            if user.is_bot {
 | 
				
			||||||
            true => BOT_TEXT_TOP_GROUP,
 | 
					                return send_text_reply(bot, message, BOT_TEXT_HANG_BOT.to_string()).await;
 | 
				
			||||||
            false => BOT_TEXT_TOP_GLOBAL,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut index = 1;
 | 
					 | 
				
			||||||
        let mut text = format!("{}\\-{}\n\n", BOT_TEXT_TOP_TITLE, scope);
 | 
					 | 
				
			||||||
        let results = match self.controller.top(chat).await {
 | 
					 | 
				
			||||||
            Some(result) => result,
 | 
					 | 
				
			||||||
            None => {
 | 
					 | 
				
			||||||
                return self
 | 
					 | 
				
			||||||
                    .send_text_reply(bot, message, BOT_TEXT_TOP_NONE.to_string())
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for result in results {
 | 
					            if user.is_anonymous() {
 | 
				
			||||||
            let mut vars: HashMap<String, String> = HashMap::new();
 | 
					                return send_text_reply(bot, message, BOT_TEXT_HANG_ANONYMOUS.to_string()).await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            vars.insert("name".to_string(), escape(result.name.as_str()));
 | 
					            if user.is_channel() {
 | 
				
			||||||
            vars.insert("count".to_string(), result.counts.to_string());
 | 
					                return send_text_reply(bot, message, BOT_TEXT_HANG_CHANNEL.to_string()).await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let record = BOT_TEXT_TOP_TEMPLATE.format(&vars).unwrap();
 | 
					            let is_self = match message.from() {
 | 
				
			||||||
 | 
					                Some(f) => f.first_name == user.first_name,
 | 
				
			||||||
 | 
					                None => false,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            text = format!("{}{}\\. {}\n", text, index, record);
 | 
					            let _ = db.hangit(&user.full_name(), message.chat.id).await;
 | 
				
			||||||
            index += 1;
 | 
					            send_text_reply(
 | 
				
			||||||
 | 
					                bot,
 | 
				
			||||||
 | 
					                reply,
 | 
				
			||||||
 | 
					                hangit_text(user.first_name.to_string(), is_self, true),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        None => send_text_reply(bot, message, BOT_TEXT_IS_CHANNEL.to_string()).await,
 | 
				
			||||||
        self.send_text_reply(bot, message, text).await
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn top_handler(
 | 
				
			||||||
 | 
					    db: &Controller,
 | 
				
			||||||
 | 
					    bot: &Bot,
 | 
				
			||||||
 | 
					    message: &Message,
 | 
				
			||||||
 | 
					) -> Result<(), RequestError> {
 | 
				
			||||||
 | 
					    let chat = &message.chat;
 | 
				
			||||||
 | 
					    let scope = match chat.is_group() || chat.is_supergroup() {
 | 
				
			||||||
 | 
					        true => BOT_TEXT_TOP_GROUP,
 | 
				
			||||||
 | 
					        false => BOT_TEXT_TOP_GLOBAL,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut index = 1;
 | 
				
			||||||
 | 
					    let mut text = format!("{}\\-{}\n\n", BOT_TEXT_TOP_TITLE, scope);
 | 
				
			||||||
 | 
					    let results = match db.top(chat).await {
 | 
				
			||||||
 | 
					        Some(result) => result,
 | 
				
			||||||
 | 
					        None => {
 | 
				
			||||||
 | 
					            return send_text_reply(bot, message, BOT_TEXT_TOP_NONE.to_string()).await;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for result in results {
 | 
				
			||||||
 | 
					        let mut vars: HashMap<String, String> = HashMap::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vars.insert("name".to_string(), escape(result.name.as_str()));
 | 
				
			||||||
 | 
					        vars.insert("count".to_string(), result.counts.to_string());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let record = BOT_TEXT_TOP_TEMPLATE.format(&vars).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        text = format!("{}{}\\. {}\n", text, index, record);
 | 
				
			||||||
 | 
					        index += 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    send_text_reply(bot, message, text).await
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,8 @@ use sea_orm::{
 | 
				
			|||||||
use teloxide::types::{Chat, ChatId};
 | 
					use teloxide::types::{Chat, ChatId};
 | 
				
			||||||
use wd_log::{log_debug_ln, log_error_ln, log_info_ln};
 | 
					use wd_log::{log_debug_ln, log_error_ln, log_info_ln};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const LIMIT: u64 = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, FromQueryResult)]
 | 
					#[derive(Debug, FromQueryResult)]
 | 
				
			||||||
pub struct TopData {
 | 
					pub struct TopData {
 | 
				
			||||||
    pub name: String,
 | 
					    pub name: String,
 | 
				
			||||||
@@ -32,7 +34,7 @@ impl Controller {
 | 
				
			|||||||
        if let Err(err) = Migrator::install(&self.db).await {
 | 
					        if let Err(err) = Migrator::install(&self.db).await {
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(err);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if let Err(err) = Migrator::up(&self.db, None).await {
 | 
					        if let Err(err) = Migrator::up(&self.db, None).await {
 | 
				
			||||||
            Err(err)
 | 
					            Err(err)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -70,9 +72,23 @@ impl Controller {
 | 
				
			|||||||
        transcation.commit().await
 | 
					        transcation.commit().await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn update_group(&self, name: String, group_id: ChatId) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        log_debug_ln!("name={:?}", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let transcation = self.db.begin().await?;
 | 
				
			||||||
 | 
					        match Stats::find().filter(StatsColumn::GroupId.eq(0)).filter(StatsColumn::Name.eq(name)).one(&transcation).await? {
 | 
				
			||||||
 | 
					            Some(one) => {
 | 
				
			||||||
 | 
					                let mut one: StatsActiveModel = one.into();
 | 
				
			||||||
 | 
					                one.group_id = Set(group_id.0);
 | 
				
			||||||
 | 
					                one.save(&transcation).await?;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            None => {},
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        transcation.commit().await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// stats
 | 
					    /// stats
 | 
				
			||||||
    pub async fn top(&self, chat: &Chat) -> Option<Vec<TopData>> {
 | 
					    pub async fn top(&self, chat: &Chat) -> Option<Vec<TopData>> {
 | 
				
			||||||
        const LIMIT: u64 = 10;
 | 
					 | 
				
			||||||
        let transcation = match self.db.begin().await {
 | 
					        let transcation = match self.db.begin().await {
 | 
				
			||||||
            Ok(t) => t,
 | 
					            Ok(t) => t,
 | 
				
			||||||
            Err(error) => {
 | 
					            Err(error) => {
 | 
				
			||||||
@@ -89,9 +105,10 @@ impl Controller {
 | 
				
			|||||||
            .order_by_desc(StatsColumn::Counts.sum())
 | 
					            .order_by_desc(StatsColumn::Counts.sum())
 | 
				
			||||||
            .limit(LIMIT);
 | 
					            .limit(LIMIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let query = match chat.is_group() || chat.is_supergroup() {
 | 
					        let query = if chat.is_group() || chat.is_supergroup() {
 | 
				
			||||||
            true => query.filter(StatsColumn::GroupId.eq(chat.id.0)),
 | 
					            query.filter(StatsColumn::GroupId.eq(chat.id.0))
 | 
				
			||||||
            false => query,
 | 
					        } else {
 | 
				
			||||||
 | 
					            query
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log_debug_ln!(
 | 
					        log_debug_ln!(
 | 
				
			||||||
@@ -109,4 +126,26 @@ impl Controller {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn find_by_name(&self, name: &String) -> Option<Vec<StatsModel>> {
 | 
				
			||||||
 | 
					        let transcation = match self.db.begin().await {
 | 
				
			||||||
 | 
					            Ok(t) => t,
 | 
				
			||||||
 | 
					            Err(error) => {
 | 
				
			||||||
 | 
					                log_error_ln!("{}", error);
 | 
				
			||||||
 | 
					                return None;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let result = Stats::find()
 | 
				
			||||||
 | 
					            .filter(StatsColumn::Name.contains(name))
 | 
				
			||||||
 | 
					            .limit(LIMIT).all(&transcation).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match result {
 | 
				
			||||||
 | 
					            Ok(result) => Some(result),
 | 
				
			||||||
 | 
					            Err(error) => {
 | 
				
			||||||
 | 
					                log_error_ln!("{}", error);
 | 
				
			||||||
 | 
					                None
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/inline_query.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/inline_query.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					use teloxide::{
 | 
				
			||||||
 | 
					    prelude::Bot,
 | 
				
			||||||
 | 
					    requests::{Request, Requester},
 | 
				
			||||||
 | 
					    types::{
 | 
				
			||||||
 | 
					        ChatId, ChosenInlineResult, InlineQuery, InlineQueryResult, InlineQueryResultArticle,
 | 
				
			||||||
 | 
					        InputMessageContent, InputMessageContentText,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    RequestError,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use wd_log::{log_error_ln, log_debug_ln};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    db_controller::Controller,
 | 
				
			||||||
 | 
					    messages::BOT_TEXT_INLINE_HANG,
 | 
				
			||||||
 | 
					    utils::{hangit_text, IS_SELF, NEED_ESCAPE},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn inline_menu(db: &Controller, bot: &Bot, q: InlineQuery) -> Result<(), RequestError> {
 | 
				
			||||||
 | 
					    let name = q.query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut results = match db.find_by_name(&name).await {
 | 
				
			||||||
 | 
					        Some(list) => list
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(|n| {
 | 
				
			||||||
 | 
					                InlineQueryResult::Article(InlineQueryResultArticle::new(
 | 
				
			||||||
 | 
					                    n.name.clone(),
 | 
				
			||||||
 | 
					                    format!("{} {}", BOT_TEXT_INLINE_HANG, n.name),
 | 
				
			||||||
 | 
					                    InputMessageContent::Text(InputMessageContentText::new(hangit_text(
 | 
				
			||||||
 | 
					                        n.name.clone(),
 | 
				
			||||||
 | 
					                        q.from.first_name == n.name,
 | 
				
			||||||
 | 
					                        !NEED_ESCAPE,
 | 
				
			||||||
 | 
					                    ))),
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .collect::<Vec<_>>(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        None => vec![],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    results.push(InlineQueryResult::Article(InlineQueryResultArticle::new(
 | 
				
			||||||
 | 
					        name.clone(),
 | 
				
			||||||
 | 
					        format!("{} {}", BOT_TEXT_INLINE_HANG, name),
 | 
				
			||||||
 | 
					        InputMessageContent::Text(InputMessageContentText::new(hangit_text(
 | 
				
			||||||
 | 
					            name,
 | 
				
			||||||
 | 
					            !IS_SELF,
 | 
				
			||||||
 | 
					            !NEED_ESCAPE,
 | 
				
			||||||
 | 
					        ))),
 | 
				
			||||||
 | 
					    )));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bot.answer_inline_query(&q.id, results).send().await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn inline_anwser(db: &Controller, a: ChosenInlineResult) -> Result<(), RequestError> {
 | 
				
			||||||
 | 
					    log_debug_ln!("{:#?}", a);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if let Err(err) = db.hangit(&a.result_id, ChatId(0)).await {
 | 
				
			||||||
 | 
					        log_error_ln!("{:?}", err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										111
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,17 +1,23 @@
 | 
				
			|||||||
mod commands;
 | 
					mod commands;
 | 
				
			||||||
mod config;
 | 
					mod config;
 | 
				
			||||||
mod db_controller;
 | 
					mod db_controller;
 | 
				
			||||||
 | 
					mod inline_query;
 | 
				
			||||||
mod messages;
 | 
					mod messages;
 | 
				
			||||||
 | 
					mod utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use commands::{CommandHandler, Commands};
 | 
					use commands::{about_handler, hangit_handler, help_handler, top_handler, Commands};
 | 
				
			||||||
use config::Args;
 | 
					use config::Args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use db_controller::Controller;
 | 
				
			||||||
 | 
					use inline_query::{inline_anwser, inline_menu};
 | 
				
			||||||
use teloxide::{
 | 
					use teloxide::{
 | 
				
			||||||
    prelude::*,
 | 
					    prelude::*,
 | 
				
			||||||
    requests::{Request, Requester},
 | 
					    requests::{Request, Requester},
 | 
				
			||||||
 | 
					    types::{Me, Update},
 | 
				
			||||||
    utils::command::BotCommands,
 | 
					    utils::command::BotCommands,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use utils::message_handler;
 | 
				
			||||||
use wd_log::{
 | 
					use wd_log::{
 | 
				
			||||||
    log_debug_ln, log_error_ln, log_info_ln, log_panic, set_level, set_prefix, DEBUG, INFO,
 | 
					    log_debug_ln, log_error_ln, log_info_ln, log_panic, set_level, set_prefix, DEBUG, INFO,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -28,43 +34,77 @@ async fn main() {
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        set_level(INFO);
 | 
					        set_level(INFO);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let command_handler = match CommandHandler::new(&args).await {
 | 
					
 | 
				
			||||||
        Err(err) => log_panic!("{}", err),
 | 
					    let db_controller = match db_controller::Controller::new(args.database_uri.to_owned()).await {
 | 
				
			||||||
        Ok(c) => c,
 | 
					        Ok(db) => db,
 | 
				
			||||||
 | 
					        Err(err) => {
 | 
				
			||||||
 | 
					            log_panic!("{:?}", err);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    command_handler.init().await.unwrap();
 | 
					    if let Err(err) = db_controller.migrate().await {
 | 
				
			||||||
 | 
					        log_panic!("{:?}", err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let bot = Bot::new(args.tgbot_token.to_owned())
 | 
					    let bot = Bot::new(args.tgbot_token.to_owned())
 | 
				
			||||||
        .set_api_url(reqwest::Url::parse(&args.api_url.as_str()).unwrap());
 | 
					        .set_api_url(reqwest::Url::parse(&args.api_url.as_str()).unwrap());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get_me(&bot).await;
 | 
					    let me = get_me(&bot).await;
 | 
				
			||||||
    register_commands(&bot).await;
 | 
					    register_commands(&bot).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Commands::repl(bot, move |bot: Bot, message: Message, cmd: Commands| {
 | 
					    let handler = dptree::entry()
 | 
				
			||||||
        let command_handler = command_handler.clone();
 | 
					        .branch(
 | 
				
			||||||
 | 
					            Update::filter_message()
 | 
				
			||||||
 | 
					                .branch(dptree::entry().filter_command::<Commands>().endpoint(
 | 
				
			||||||
 | 
					                    |db: Controller, bot: Bot, message: Message, cmd: Commands| async move {
 | 
				
			||||||
 | 
					                        let r = match cmd {
 | 
				
			||||||
 | 
					                            Commands::Help => help_handler(&bot, &message).await,
 | 
				
			||||||
 | 
					                            Commands::About => about_handler(&bot, &message).await,
 | 
				
			||||||
 | 
					                            Commands::Top => top_handler(&db, &bot, &message).await,
 | 
				
			||||||
 | 
					                            Commands::HangIt => hangit_handler(&db, &bot, &message).await,
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        async move {
 | 
					                        match r {
 | 
				
			||||||
            let r = match cmd {
 | 
					                            Ok(_) => Ok(()),
 | 
				
			||||||
                Commands::Help => command_handler.help_handler(&bot, &message).await,
 | 
					                            Err(err) => {
 | 
				
			||||||
                Commands::About => command_handler.about_handler(&bot, &message).await,
 | 
					                                log_error_ln!("{:?}", err);
 | 
				
			||||||
                Commands::Top => command_handler.top_handler(&bot, &message).await,
 | 
					                                Err(err)
 | 
				
			||||||
                Commands::HangIt => command_handler.hangit_handler(&bot, &message).await,
 | 
					                            }
 | 
				
			||||||
            };
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					                .branch(
 | 
				
			||||||
 | 
					                    dptree::filter(|msg: Message| msg.chat.is_group() || msg.chat.is_supergroup())
 | 
				
			||||||
 | 
					                        .endpoint(|db: Controller, msg: Message, me: Me| async move {
 | 
				
			||||||
 | 
					                            let r = message_handler(&db, msg, &me).await;
 | 
				
			||||||
 | 
					                            match r {
 | 
				
			||||||
 | 
					                                Ok(_) => Ok(()),
 | 
				
			||||||
 | 
					                                Err(err) => {
 | 
				
			||||||
 | 
					                                    log_error_ln!("{:?}", err);
 | 
				
			||||||
 | 
					                                    Err(err)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .branch(
 | 
				
			||||||
 | 
					            Update::filter_inline_query().endpoint(
 | 
				
			||||||
 | 
					                |db: Controller, bot: Bot, q: InlineQuery| async move {
 | 
				
			||||||
 | 
					                    inline_menu(&db, &bot, q).await
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .branch(Update::filter_chosen_inline_result().endpoint(
 | 
				
			||||||
 | 
					            |db: Controller, a: ChosenInlineResult| async move { inline_anwser(&db, a).await },
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match r {
 | 
					    Dispatcher::builder(bot, handler)
 | 
				
			||||||
                Ok(_r) => {
 | 
					        .dependencies(dptree::deps![db_controller, me])
 | 
				
			||||||
                    log_debug_ln!("will send: {:?}", _r.text());
 | 
					        .default_handler(|upd| async move { log_debug_ln!("unhandled update: {:?}", upd) })
 | 
				
			||||||
                    Ok(())
 | 
					        .enable_ctrlc_handler()
 | 
				
			||||||
                }
 | 
					        .build()
 | 
				
			||||||
                Err(err) => {
 | 
					        .dispatch()
 | 
				
			||||||
                    log_error_ln!("{:?}", err);
 | 
					        .await;
 | 
				
			||||||
                    Err(err)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
    .await;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn register_commands(bot: &Bot) {
 | 
					async fn register_commands(bot: &Bot) {
 | 
				
			||||||
@@ -75,13 +115,16 @@ async fn register_commands(bot: &Bot) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn get_me(bot: &Bot) {
 | 
					async fn get_me(bot: &Bot) -> Me {
 | 
				
			||||||
    match bot.get_me().send().await {
 | 
					    match bot.get_me().send().await {
 | 
				
			||||||
        Ok(result) => log_info_ln!(
 | 
					        Ok(result) => {
 | 
				
			||||||
            "connect succeed: id={}, botname=\"{}\"",
 | 
					            log_info_ln!(
 | 
				
			||||||
            result.id,
 | 
					                "connect succeed: id={}, botname=\"{}\"",
 | 
				
			||||||
            result.username()
 | 
					                result.id,
 | 
				
			||||||
        ),
 | 
					                result.username()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            result
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Err(error) => log_panic!("{}", error),
 | 
					        Err(error) => log_panic!("{}", error),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,8 @@ const BOT_TEXT_HANGED_2: &'static str = "因为 {name} 太过逆天,我们把
 | 
				
			|||||||
const BOT_TEXT_HANGED_3: &'static str = "{name} 吊在了路灯上,TA 兴风作浪的时代结束了……";
 | 
					const BOT_TEXT_HANGED_3: &'static str = "{name} 吊在了路灯上,TA 兴风作浪的时代结束了……";
 | 
				
			||||||
const BOT_TEXT_HANGED_4: &'static str = "吊在路灯上的 {name} 正在接受大家的鄙视……";
 | 
					const BOT_TEXT_HANGED_4: &'static str = "吊在路灯上的 {name} 正在接受大家的鄙视……";
 | 
				
			||||||
const BOT_TEXT_HANGED_5: &'static str = "对 {name} 来说,绳命来得快去得也快,只有路灯是永恒的……";
 | 
					const BOT_TEXT_HANGED_5: &'static str = "对 {name} 来说,绳命来得快去得也快,只有路灯是永恒的……";
 | 
				
			||||||
const BOT_TEXT_HANGED_6: &'static str = "被套上麻袋的 {name} 在经历了一顿胖揍之后,最后还是成了路灯的挂件……";
 | 
					const BOT_TEXT_HANGED_6: &'static str =
 | 
				
			||||||
 | 
					    "被套上麻袋的 {name} 在经历了一顿胖揍之后,最后还是成了路灯的挂件……";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const BOT_TEXT_HANGED: [&str; 6] = [
 | 
					pub const BOT_TEXT_HANGED: [&str; 6] = [
 | 
				
			||||||
    BOT_TEXT_HANGED_1,
 | 
					    BOT_TEXT_HANGED_1,
 | 
				
			||||||
@@ -26,7 +27,8 @@ pub const BOT_TEXT_HANGED: [&str; 6] = [
 | 
				
			|||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BOT_TEXT_HANGED_SELF_1: &'static str = "{name} 承受不了自己所做的一切,选择了自行了断……";
 | 
					const BOT_TEXT_HANGED_SELF_1: &'static str = "{name} 承受不了自己所做的一切,选择了自行了断……";
 | 
				
			||||||
const BOT_TEXT_HANGED_SELF_2: &'static str = "对于 {name} 来说,把自己吊在路灯上可能是最好的选择了……";
 | 
					const BOT_TEXT_HANGED_SELF_2: &'static str =
 | 
				
			||||||
 | 
					    "对于 {name} 来说,把自己吊在路灯上可能是最好的选择了……";
 | 
				
			||||||
const BOT_TEXT_HANGED_SELF_3: &'static str = "{name} 最终还是选择了逃避……";
 | 
					const BOT_TEXT_HANGED_SELF_3: &'static str = "{name} 最终还是选择了逃避……";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const BOT_TEXT_HANGED_SELF: [&str; 3] = [
 | 
					pub const BOT_TEXT_HANGED_SELF: [&str; 3] = [
 | 
				
			||||||
@@ -37,4 +39,5 @@ pub const BOT_TEXT_HANGED_SELF: [&str; 3] = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub const BOT_TEXT_HANG_BOT: &'static str = "机器人是无法被吊死的……";
 | 
					pub const BOT_TEXT_HANG_BOT: &'static str = "机器人是无法被吊死的……";
 | 
				
			||||||
pub const BOT_TEXT_HANG_CHANNEL: &'static str = "这是个频道……";
 | 
					pub const BOT_TEXT_HANG_CHANNEL: &'static str = "这是个频道……";
 | 
				
			||||||
pub const BOT_TEXT_HANG_ANONYMOUS: &'static str = "这是个幽灵……";
 | 
					pub const BOT_TEXT_HANG_ANONYMOUS: &'static str = "这是个幽灵……";
 | 
				
			||||||
 | 
					pub const BOT_TEXT_INLINE_HANG: &'static str = "吊死";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								src/utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/utils.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use rand::{rngs::OsRng, Rng};
 | 
				
			||||||
 | 
					use regex::Regex;
 | 
				
			||||||
 | 
					use strfmt::Format;
 | 
				
			||||||
 | 
					use teloxide::{
 | 
				
			||||||
 | 
					    types::{Me, Message},
 | 
				
			||||||
 | 
					    utils::markdown::escape,
 | 
				
			||||||
 | 
					    RequestError,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use wd_log::{log_debug_ln, log_error_ln};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    db_controller::Controller,
 | 
				
			||||||
 | 
					    messages::{BOT_TEXT_HANGED, BOT_TEXT_HANGED_SELF},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const IS_SELF: bool = true;
 | 
				
			||||||
 | 
					pub const NEED_ESCAPE: bool = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn hangit_text(name: String, is_self: bool, need_escape: bool) -> String {
 | 
				
			||||||
 | 
					    let mut vars = HashMap::new();
 | 
				
			||||||
 | 
					    let index = if is_self {
 | 
				
			||||||
 | 
					        OsRng.gen::<usize>() % BOT_TEXT_HANGED_SELF.len()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        OsRng.gen::<usize>() % BOT_TEXT_HANGED.len()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let text = if is_self {
 | 
				
			||||||
 | 
					        BOT_TEXT_HANGED_SELF[index]
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        BOT_TEXT_HANGED[index]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let name = if need_escape {
 | 
				
			||||||
 | 
					        escape(name.as_str())
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    vars.insert("name".to_string(), name.as_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    text.format(&vars).unwrap()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn message_handler(db: &Controller, msg: Message, me: &Me) -> Result<(), RequestError> {
 | 
				
			||||||
 | 
					    let text = match msg.text() {
 | 
				
			||||||
 | 
					        Some(t) => t.to_owned(),
 | 
				
			||||||
 | 
					        None => {
 | 
				
			||||||
 | 
					            log_debug_ln!("{:?}", msg);
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let formats = vec![BOT_TEXT_HANGED.to_vec(), BOT_TEXT_HANGED_SELF.to_vec()]
 | 
				
			||||||
 | 
					        .concat()
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .map(|i| Regex::new(&format!("^{}$", i.replace("{name}", "(.+)"))).unwrap())
 | 
				
			||||||
 | 
					        .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if let Some(via_bot) = msg.via_bot {
 | 
				
			||||||
 | 
					        if via_bot.is_bot && via_bot.id == me.id {
 | 
				
			||||||
 | 
					            for f in formats {
 | 
				
			||||||
 | 
					                log_debug_ln!("Regexp {:?}", f);
 | 
				
			||||||
 | 
					                if !f.is_match(text.as_str()) {
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if let Some(cap) = f.captures(text.as_str()) {
 | 
				
			||||||
 | 
					                    if let Some(name) = cap.get(1) {
 | 
				
			||||||
 | 
					                        log_debug_ln!("got username: {:?}", name.as_str());
 | 
				
			||||||
 | 
					                        if let Err(error) = db
 | 
				
			||||||
 | 
					                            .update_group(name.as_str().to_string(), msg.chat.id)
 | 
				
			||||||
 | 
					                            .await
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            log_error_ln!("{:?}", error);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user