all ready
This commit is contained in:
parent
dde441bf9f
commit
3eba88b3dd
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@ -1,3 +1,15 @@
|
|||||||
{
|
{
|
||||||
"rust-analyzer.showUnlinkedFileNotification": false
|
"rust-analyzer.showUnlinkedFileNotification": false,
|
||||||
|
"sqltools.connections": [
|
||||||
|
{
|
||||||
|
"previewLimit": 50,
|
||||||
|
"server": "postgresql",
|
||||||
|
"port": 5432,
|
||||||
|
"askForPassword": true,
|
||||||
|
"driver": "PostgreSQL",
|
||||||
|
"name": "hangitbot",
|
||||||
|
"database": "hangitbot",
|
||||||
|
"username": "hangitbot"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -2379,9 +2379,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sea-query"
|
name = "sea-query"
|
||||||
version = "0.30.2"
|
version = "0.30.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb3e6bba153bb198646c8762c48414942a38db27d142e44735a133cabddcc820"
|
checksum = "4166a1e072292d46dc91f31617c2a1cdaf55a8be4b5c9f4bf2ba248e3ac4999b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
use std::{collections::HashMap, error::Error};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rand::{rngs::OsRng, Rng};
|
use rand::{rngs::OsRng, Rng};
|
||||||
use sea_orm::DbErr;
|
use sea_orm::DbErr;
|
||||||
use strfmt::Format;
|
use strfmt::Format;
|
||||||
use teloxide::{
|
use teloxide::{
|
||||||
payloads::{SendMessage, SendMessageSetters},
|
payloads::SendMessageSetters,
|
||||||
prelude::Bot,
|
prelude::Bot,
|
||||||
requests::{JsonRequest, Requester},
|
requests::Requester,
|
||||||
types::{Message, ParseMode},
|
types::{Message, ParseMode},
|
||||||
utils::{command::BotCommands, markdown::escape},
|
utils::command::BotCommands,
|
||||||
|
RequestError,
|
||||||
};
|
};
|
||||||
use wd_log::log_error_ln;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Args,
|
config::Args,
|
||||||
@ -65,43 +65,42 @@ impl CommandHandler {
|
|||||||
bot: &Bot,
|
bot: &Bot,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
text: String,
|
text: String,
|
||||||
) -> JsonRequest<SendMessage> {
|
) -> Result<Message, RequestError> {
|
||||||
bot.send_message(message.chat.id, text)
|
bot.send_message(message.chat.id, text)
|
||||||
.reply_to_message_id(message.id)
|
.reply_to_message_id(message.id)
|
||||||
.parse_mode(ParseMode::MarkdownV2)
|
.parse_mode(ParseMode::MarkdownV2)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn help_handler(
|
pub async fn help_handler(
|
||||||
&self,
|
&self,
|
||||||
bot: &Bot,
|
bot: &Bot,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<JsonRequest<SendMessage>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Message, RequestError> {
|
||||||
Ok(self
|
self.send_text_reply(bot, message, Commands::descriptions().to_string())
|
||||||
.send_text_reply(bot, message, Commands::descriptions().to_string())
|
.await
|
||||||
.await)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn about_handler(
|
pub async fn about_handler(
|
||||||
&self,
|
&self,
|
||||||
bot: &Bot,
|
bot: &Bot,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<JsonRequest<SendMessage>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Message, RequestError> {
|
||||||
Ok(self
|
self.send_text_reply(bot, message, BOT_ABOUT.to_string())
|
||||||
.send_text_reply(bot, message, BOT_ABOUT.to_string())
|
.await
|
||||||
.await)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn hangit_handler(
|
pub async fn hangit_handler(
|
||||||
&self,
|
&self,
|
||||||
bot: &Bot,
|
bot: &Bot,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<JsonRequest<SendMessage>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Message, RequestError> {
|
||||||
let reply = match message.reply_to_message() {
|
let reply = match message.reply_to_message() {
|
||||||
Some(reply) => reply,
|
Some(reply) => reply,
|
||||||
None => {
|
None => {
|
||||||
return Ok(self
|
return self
|
||||||
.send_text_reply(bot, message, BOT_TEXT_NO_TARGET.to_string())
|
.send_text_reply(bot, message, BOT_TEXT_NO_TARGET.to_string())
|
||||||
.await)
|
.await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ impl CommandHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut vars = HashMap::new();
|
let mut vars = HashMap::new();
|
||||||
|
|
||||||
let index = if is_self {
|
let index = if is_self {
|
||||||
OsRng.gen::<usize>() % BOT_TEXT_HANGED_SELF.len()
|
OsRng.gen::<usize>() % BOT_TEXT_HANGED_SELF.len()
|
||||||
} else {
|
} else {
|
||||||
@ -132,56 +131,46 @@ impl CommandHandler {
|
|||||||
.controller
|
.controller
|
||||||
.hangit(&user.full_name(), message.chat.id)
|
.hangit(&user.full_name(), message.chat.id)
|
||||||
.await;
|
.await;
|
||||||
Ok(self
|
self.send_text_reply(bot, reply, text.format(&vars).unwrap())
|
||||||
.send_text_reply(bot, reply, escape(&text.format(&vars).unwrap()))
|
.await
|
||||||
.await)
|
}
|
||||||
|
None => {
|
||||||
|
self.send_text_reply(bot, message, BOT_TEXT_IS_CHANNEL.to_string())
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
None => Ok(self
|
|
||||||
.send_text_reply(bot, message, BOT_TEXT_IS_CHANNEL.to_string())
|
|
||||||
.await),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn top_handler(
|
pub async fn top_handler(&self, bot: &Bot, message: &Message) -> Result<Message, RequestError> {
|
||||||
&self,
|
let chat = &message.chat;
|
||||||
bot: &Bot,
|
let scope = match chat.is_group() || chat.is_supergroup() {
|
||||||
message: &Message,
|
|
||||||
) -> Result<JsonRequest<SendMessage>, Box<dyn Error + Send + Sync>> {
|
|
||||||
let chat_id = message.chat.id;
|
|
||||||
let scope = match chat_id.is_group() {
|
|
||||||
true => BOT_TEXT_TOP_GROUP,
|
true => BOT_TEXT_TOP_GROUP,
|
||||||
false => BOT_TEXT_TOP_GLOBAL,
|
false => BOT_TEXT_TOP_GLOBAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut index = 1;
|
let mut index = 1;
|
||||||
let mut text = format!("{}-{}\n\n", BOT_TEXT_TOP_TITLE, scope);
|
let mut text = format!("{}\\-{}\n\n", BOT_TEXT_TOP_TITLE, scope);
|
||||||
let results = match self.controller.top(chat_id).await {
|
let results = match self.controller.top(chat).await {
|
||||||
Ok(r) => match r {
|
Some(result) => result,
|
||||||
Some(result) => result,
|
None => {
|
||||||
None => {
|
return self
|
||||||
return Ok(self
|
.send_text_reply(bot, message, BOT_TEXT_TOP_NONE.to_string())
|
||||||
.send_text_reply(bot, message, BOT_TEXT_TOP_NONE.to_string())
|
.await
|
||||||
.await)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(error) => {
|
|
||||||
log_error_ln!("{}", error);
|
|
||||||
return Err(Box::new(error));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for result in results {
|
for result in results {
|
||||||
let mut vars = HashMap::new();
|
let mut vars: HashMap<String, String> = HashMap::new();
|
||||||
|
|
||||||
vars.insert("name".to_string(), result.name);
|
vars.insert("name".to_string(), result.name);
|
||||||
vars.insert("count".to_string(), result.counts.to_string());
|
vars.insert("count".to_string(), result.counts.to_string());
|
||||||
|
|
||||||
let record = BOT_TEXT_TOP_TEMPLATE.format(&vars).unwrap();
|
let record = BOT_TEXT_TOP_TEMPLATE.format(&vars).unwrap();
|
||||||
|
|
||||||
text = format!("{}{} {}\n", text, index, record);
|
text = format!("{}{}\\. {}\n", text, index, record);
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.send_text_reply(bot, message, text).await)
|
self.send_text_reply(bot, message, text).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
use models::prelude::*;
|
use models::prelude::*;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelTrait, ColumnTrait, Database, DatabaseConnection, DbErr, EntityTrait,
|
ActiveModelTrait, ColumnTrait, ConnectionTrait, Database, DatabaseConnection,
|
||||||
PaginatorTrait, QueryFilter, QueryOrder, Set, TransactionTrait,
|
DbErr, EntityTrait, QueryFilter, QueryOrder, QuerySelect, QueryTrait, Set, TransactionTrait, FromQueryResult, prelude::BigDecimal,
|
||||||
};
|
};
|
||||||
use teloxide::types::ChatId;
|
use teloxide::types::{Chat, ChatId};
|
||||||
use wd_log::{log_info_ln, log_warn_ln};
|
use wd_log::{log_debug_ln, log_error_ln, log_info_ln, log_warn_ln};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, FromQueryResult)]
|
||||||
|
pub struct TopData {
|
||||||
|
pub name: String,
|
||||||
|
pub counts: BigDecimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
@ -63,28 +71,49 @@ impl Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// stats
|
/// stats
|
||||||
pub async fn top(&self, group_id: ChatId) -> Result<Option<Vec<StatsModel>>, DbErr> {
|
pub async fn top(&self, chat: &Chat) -> Option<Vec<TopData>> {
|
||||||
const LIMIT: u64 = 10;
|
const LIMIT: u64 = 10;
|
||||||
let transcation = self.db.begin().await?;
|
let transcation = match self.db.begin().await {
|
||||||
|
Ok(t) => t,
|
||||||
let query = match group_id.is_group() {
|
Err(error) => {
|
||||||
true => {
|
log_error_ln!("{}", error);
|
||||||
Stats::find()
|
return None;
|
||||||
.filter(StatsColumn::GroupId.eq(group_id.0))
|
|
||||||
.order_by_desc(StatsColumn::Counts)
|
|
||||||
.paginate(&transcation, LIMIT)
|
|
||||||
.fetch()
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
Stats::find()
|
|
||||||
.order_by_desc(StatsColumn::Counts)
|
|
||||||
.paginate(&transcation, LIMIT)
|
|
||||||
.fetch()
|
|
||||||
.await?
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(query))
|
let query = match chat.is_group() || chat.is_supergroup() {
|
||||||
|
true => {
|
||||||
|
Stats::find()
|
||||||
|
.filter(StatsColumn::GroupId.eq(chat.id.0))
|
||||||
|
.order_by_desc(StatsColumn::Counts)
|
||||||
|
.limit(LIMIT).into_model()
|
||||||
|
.all(&transcation)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
let query = Stats::find()
|
||||||
|
.select_only()
|
||||||
|
.column(StatsColumn::Name)
|
||||||
|
.column_as(StatsColumn::Counts.sum(), "counts")
|
||||||
|
.group_by(StatsColumn::Name)
|
||||||
|
.order_by_desc(StatsColumn::Counts.sum())
|
||||||
|
.limit(LIMIT);
|
||||||
|
|
||||||
|
log_debug_ln!(
|
||||||
|
"SQL: {:?}",
|
||||||
|
query.build(transcation.get_database_backend()).to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
query.into_model().all(&transcation).await
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match query {
|
||||||
|
Ok(query) => Some(query),
|
||||||
|
Err(error) => {
|
||||||
|
log_error_ln!("{}", error);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
src/main.rs
23
src/main.rs
@ -43,14 +43,25 @@ async fn main() {
|
|||||||
|
|
||||||
Commands::repl(bot, move |bot: Bot, message: Message, cmd: Commands| {
|
Commands::repl(bot, move |bot: Bot, message: Message, cmd: Commands| {
|
||||||
let command_handler = command_handler.clone();
|
let command_handler = command_handler.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let _ = match cmd {
|
let r = match cmd {
|
||||||
Commands::Help => command_handler.clone().help_handler(&bot, &message).await,
|
Commands::Help => command_handler.help_handler(&bot, &message).await,
|
||||||
Commands::About => command_handler.clone().about_handler(&bot, &message).await,
|
Commands::About => command_handler.about_handler(&bot, &message).await,
|
||||||
Commands::Top => command_handler.clone().top_handler(&bot, &message).await,
|
Commands::Top => command_handler.top_handler(&bot, &message).await,
|
||||||
Commands::HangIt => command_handler.clone().hangit_handler(&bot, &message).await,
|
Commands::HangIt => command_handler.hangit_handler(&bot, &message).await,
|
||||||
};
|
};
|
||||||
Ok(())
|
|
||||||
|
match r {
|
||||||
|
Ok(_r) => {
|
||||||
|
log_debug_ln!("will send: {:?}", _r.text());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
log_error_ln!("{:?}", err);
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub const BOT_ABOUT: &'static str =
|
pub const BOT_ABOUT: &'static str =
|
||||||
"*Hang it bot*\n\nHang your boss up!\n[Github](https://github.com/senseab/saysthbot-reborn) @ssthbot";
|
"*Hang it bot*\n\nHang your boss up\\!\n[Github](https://github.com/senseab/hangitbot) @hangitbot";
|
||||||
|
|
||||||
pub const BOT_TEXT_NO_TARGET: &'static str = "请在回复某一条信息时使用该指令";
|
pub const BOT_TEXT_NO_TARGET: &'static str = "请在回复某一条信息时使用该指令";
|
||||||
pub const BOT_TEXT_IS_CHANNEL: &'static str = "这不是个人,吊不起来";
|
pub const BOT_TEXT_IS_CHANNEL: &'static str = "这不是个人,吊不起来";
|
||||||
|
Loading…
Reference in New Issue
Block a user