Additional Bug fixes
This commit is contained in:
@@ -150,6 +150,8 @@ async fn run_bot() {
|
||||
|
||||
let config = Arc::new(Config::load().expect("Failed to load config"));
|
||||
|
||||
tokio::fs::create_dir_all("data").await.ok();
|
||||
|
||||
let db = Arc::new(Database::open("data/db.sqlite").expect("Failed to open database"));
|
||||
db.run_migrations().await.expect("Failed to run migrations");
|
||||
|
||||
@@ -201,6 +203,23 @@ async fn handle_message(
|
||||
msg: Message,
|
||||
storage: Arc<InMemStorage<BotState>>,
|
||||
ctx: BotContext,
|
||||
) -> HandlerResult {
|
||||
let chat_id = msg.chat.id;
|
||||
if let Err(e) = handle_message_inner(bot.clone(), msg, storage, ctx).await {
|
||||
tracing::error!("handle_message error: {}", e);
|
||||
let _ = bot.send_message(chat_id, "<b>An error occurred.</b> Please try again.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
async fn handle_message_inner(
|
||||
bot: Bot,
|
||||
msg: Message,
|
||||
storage: Arc<InMemStorage<BotState>>,
|
||||
ctx: BotContext,
|
||||
) -> HandlerResult {
|
||||
let user = match &msg.from {
|
||||
Some(u) => u.clone(),
|
||||
@@ -219,7 +238,9 @@ async fn handle_message(
|
||||
};
|
||||
|
||||
if matches!(db_user.role, UserRole::Banned) || !ctx.moderation.is_allowed(user_id).await {
|
||||
bot.send_message(chat_id, "[ Banned ] You are not allowed to use this service.").await?;
|
||||
bot.send_message(chat_id, "<b>[ Banned ]</b> You are not allowed to use this service.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
dialogue.exit().await?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -232,7 +253,9 @@ async fn handle_message(
|
||||
"/reload" => {
|
||||
if is_admin(&bot, msg.chat.id, user.id).await {
|
||||
ctx.moderation.load().await?;
|
||||
bot.send_message(chat_id, "Moderation lists reloaded.").await?;
|
||||
bot.send_message(chat_id, "<b>Moderation lists reloaded.</b>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
@@ -312,6 +335,23 @@ async fn handle_callback(
|
||||
q: CallbackQuery,
|
||||
storage: Arc<InMemStorage<BotState>>,
|
||||
ctx: BotContext,
|
||||
) -> HandlerResult {
|
||||
let chat_id = q.message.as_ref().map(|m| m.chat().id).unwrap_or(ChatId(q.from.id.0 as i64));
|
||||
if let Err(e) = handle_callback_inner(bot.clone(), q, storage, ctx).await {
|
||||
tracing::error!("handle_callback error: {}", e);
|
||||
let _ = bot.send_message(chat_id, "<b>An error occurred.</b> Please try again.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
async fn handle_callback_inner(
|
||||
bot: Bot,
|
||||
q: CallbackQuery,
|
||||
storage: Arc<InMemStorage<BotState>>,
|
||||
ctx: BotContext,
|
||||
) -> HandlerResult {
|
||||
// CallbackQuery (and the Message it may contain) are very large structs.
|
||||
// Extract only the fields we need and drop q before the first .await so
|
||||
@@ -323,8 +363,10 @@ async fn handle_callback(
|
||||
let message_id = q.message.as_ref().map(|m| m.id());
|
||||
drop(q);
|
||||
|
||||
bot.answer_callback_query(&callback_id).await.ok();
|
||||
|
||||
if !ctx.moderation.is_allowed(user_id).await {
|
||||
bot.answer_callback_query(&callback_id).text("Not allowed").await?;
|
||||
bot.answer_callback_query(&callback_id).text("Not allowed").await.ok();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -332,7 +374,7 @@ async fn handle_callback(
|
||||
|
||||
let parts: Vec<&str> = data.split(':').collect();
|
||||
if parts.len() < 3 || parts[0] != "v1" {
|
||||
bot.answer_callback_query(&callback_id).await?;
|
||||
bot.answer_callback_query(&callback_id).await.ok();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -357,15 +399,15 @@ async fn handle_callback(
|
||||
"menu" => match parts[2] {
|
||||
"upload_media" => {
|
||||
dialogue.update(BotState::UploadStaging { items: vec![], upload_type: UploadType::Media }).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Media).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Media, ctx.config.upload_limits.max_batch_size).await?;
|
||||
}
|
||||
"upload_doc" => {
|
||||
dialogue.update(BotState::UploadStaging { items: vec![], upload_type: UploadType::Document }).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Document).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Document, ctx.config.upload_limits.max_batch_size).await?;
|
||||
}
|
||||
"upload_text" => {
|
||||
dialogue.update(BotState::UploadStaging { items: vec![], upload_type: UploadType::Text }).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Text).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Text, ctx.config.upload_limits.max_batch_size).await?;
|
||||
}
|
||||
"prev_uploads" => {
|
||||
dialogue.update(BotState::ViewingPrevious { page: 0 }).await?;
|
||||
@@ -373,7 +415,9 @@ async fn handle_callback(
|
||||
}
|
||||
"report" => {
|
||||
dialogue.update(BotState::Reporting).await?;
|
||||
bot.send_message(chat_id, "Send me the content link or content ID to report.").await?;
|
||||
bot.send_message(chat_id, "Send me the <code>content link</code> or <code>content ID</code> to report.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
}
|
||||
"main" => {
|
||||
send_main_menu(&bot, chat_id, &dialogue).await?;
|
||||
@@ -385,7 +429,7 @@ async fn handle_callback(
|
||||
let state = dialogue.get_or_default().await?;
|
||||
if let BotState::UploadStaging { items, .. } = state {
|
||||
if items.is_empty() {
|
||||
bot.answer_callback_query(&callback_id).text("No items to upload.").await?;
|
||||
bot.answer_callback_query(&callback_id).text("No items to upload.").await.ok();
|
||||
} else {
|
||||
let options = UploadOptions {
|
||||
allow_download: true,
|
||||
@@ -398,7 +442,9 @@ async fn handle_callback(
|
||||
}
|
||||
"cancel" => {
|
||||
if let Some(mid) = message_id {
|
||||
bot.edit_message_text(chat_id, mid, "Upload cancelled.").await.ok();
|
||||
bot.edit_message_text(chat_id, mid, "<i>Upload cancelled.</i>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await.ok();
|
||||
}
|
||||
dialogue.update(BotState::MainMenu).await?;
|
||||
}
|
||||
@@ -425,7 +471,9 @@ async fn handle_callback(
|
||||
}
|
||||
}
|
||||
"set_password" => {
|
||||
bot.send_message(chat_id, "Send the password (max 32 chars) or /skip to skip.").await?;
|
||||
bot.send_message(chat_id, "Send the <code>password</code> (max <b>32</b> chars) or <code>/skip</code> to skip.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
}
|
||||
"confirm_final" => {
|
||||
let state = dialogue.get_or_default().await?;
|
||||
@@ -436,7 +484,7 @@ async fn handle_callback(
|
||||
}
|
||||
"back" => {
|
||||
dialogue.update(BotState::UploadStaging { items: vec![], upload_type: UploadType::Media }).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Media).await?;
|
||||
send_staging_message(&bot, chat_id, &[], UploadType::Media, ctx.config.upload_limits.max_batch_size).await?;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
@@ -456,7 +504,6 @@ async fn handle_callback(
|
||||
_ => {}
|
||||
}
|
||||
|
||||
bot.answer_callback_query(&callback_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -481,30 +528,31 @@ async fn send_main_menu(bot: &Bot, chat_id: ChatId, dialogue: &BotDialogue) -> H
|
||||
],
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Upload Text ]", "v1:menu:upload_text"),
|
||||
InlineKeyboardButton::callback("[ Previous Uploads ]", "v1:menu:prev_uploads"),
|
||||
InlineKeyboardButton::callback("[ My Uploads ]", "v1:menu:prev_uploads"),
|
||||
],
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Report Content ]", "v1:menu:report"),
|
||||
],
|
||||
]);
|
||||
bot.send_message(chat_id, "Choose from the menu below. Administrators can be contacted here: @harmfulmeowbot")
|
||||
bot.send_message(chat_id, "<b>Main Menu</b>\n\nChoose from the menu below.\n<i>Administrators can be contacted here:</i> <a href=\"https://t.me/harmfulmeowbot?start=submit\">t.me/harmfulmeowbot?start=submit</a>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.reply_markup(keyboard)
|
||||
.await?;
|
||||
dialogue.update(BotState::MainMenu).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_staging_message(bot: &Bot, chat_id: ChatId, items: &[StagedItem], upload_type: UploadType) -> HandlerResult {
|
||||
async fn send_staging_message(bot: &Bot, chat_id: ChatId, items: &[StagedItem], upload_type: UploadType, max_batch_size: usize) -> HandlerResult {
|
||||
let type_label = match upload_type {
|
||||
UploadType::Media => "Media",
|
||||
UploadType::Document => "Documents",
|
||||
UploadType::Text => "Text",
|
||||
};
|
||||
let text = if items.is_empty() {
|
||||
format!("[ Staging {} (0/10) ]\n\nSend me files to add them.", type_label)
|
||||
format!("<b>[ Staging {} ]</b>\n\n<i>Send me files to add them.</i>\n\n<code>0/{}</code> items", type_label, max_batch_size)
|
||||
} else {
|
||||
let list: String = items.iter().map(|i| format!("- {}\n", i.file_name)).collect();
|
||||
format!("[ Staging {} ({}/10) ]\n\n{}", type_label, items.len(), list)
|
||||
let list: String = items.iter().map(|i| format!("• <code>{}</code>\n", i.file_name)).collect();
|
||||
format!("<b>[ Staging {} ]</b> <code>{}/{}</code>\n\n{}", type_label, items.len(), max_batch_size, list)
|
||||
};
|
||||
|
||||
let keyboard = InlineKeyboardMarkup::new(vec![vec![
|
||||
@@ -513,6 +561,7 @@ async fn send_staging_message(bot: &Bot, chat_id: ChatId, items: &[StagedItem],
|
||||
]]);
|
||||
|
||||
bot.send_message(chat_id, text)
|
||||
.parse_mode(ParseMode::Html)
|
||||
.reply_markup(keyboard)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -528,7 +577,9 @@ async fn handle_staging_message(
|
||||
upload_type: UploadType,
|
||||
) -> HandlerResult {
|
||||
if items.len() >= ctx.config.upload_limits.max_batch_size {
|
||||
bot.send_message(msg.chat.id, "Maximum batch size reached.").await?;
|
||||
bot.send_message(msg.chat.id, "<b>Maximum batch size reached.</b>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -598,7 +649,7 @@ async fn handle_staging_message(
|
||||
if let Some(item) = new_item {
|
||||
items.push(item);
|
||||
dialogue.update(BotState::UploadStaging { items: items.clone(), upload_type }).await?;
|
||||
send_staging_message(bot, chat_id, &items, upload_type).await?;
|
||||
send_staging_message(bot, chat_id, &items, upload_type, ctx.config.upload_limits.max_batch_size).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -611,22 +662,22 @@ async fn refresh_options_message(
|
||||
options: &UploadOptions,
|
||||
) -> HandlerResult {
|
||||
let destroy_text = match options.max_views {
|
||||
Some(n) => format!("Auto-destroy: {} views", n),
|
||||
None => "Auto-destroy: Off".to_string(),
|
||||
Some(n) => format!("Auto-destroy: <b>{}</b> views", n),
|
||||
None => "Auto-destroy: <i>Off</i>".to_string(),
|
||||
};
|
||||
let download_text = if options.allow_download {
|
||||
"Allow download: Yes"
|
||||
"Allow download: <b>Yes</b>"
|
||||
} else {
|
||||
"Allow download: No"
|
||||
"Allow download: <b>No</b>"
|
||||
};
|
||||
let password_text = if options.password.is_some() {
|
||||
"Password: Set"
|
||||
"Password: <b>Set</b>"
|
||||
} else {
|
||||
"Password: None"
|
||||
"Password: <i>None</i>"
|
||||
};
|
||||
|
||||
let text = format!(
|
||||
"[ Upload Options ]\n\n{}\n{}\n{}\n\nConfirm when ready.",
|
||||
"<b>[ Upload Options ]</b>\n\n{}\n{}\n{}\n\n<i>Confirm when ready.</i>",
|
||||
destroy_text, download_text, password_text
|
||||
);
|
||||
|
||||
@@ -640,11 +691,12 @@ async fn refresh_options_message(
|
||||
],
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Back ]", "v1:opt:back"),
|
||||
InlineKeyboardButton::callback("[ Confirm & Upload ]", "v1:opt:confirm_final"),
|
||||
InlineKeyboardButton::callback("[ Confirm ]", "v1:opt:confirm_final"),
|
||||
],
|
||||
]);
|
||||
|
||||
bot.send_message(chat_id, text)
|
||||
.parse_mode(ParseMode::Html)
|
||||
.reply_markup(keyboard)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -659,11 +711,15 @@ async fn finalize_upload(
|
||||
dialogue: &BotDialogue,
|
||||
ctx: &BotContext,
|
||||
) -> HandlerResult {
|
||||
let status_msg = bot.send_message(chat_id, "[ Encrypting and storing... ]").await?;
|
||||
let status_msg = bot.send_message(chat_id, "<i>[ Encrypting and storing... ]</i>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
|
||||
let total_size: u64 = items.iter().map(|i| i.size).sum();
|
||||
if total_size > ctx.config.upload_limits.max_total_batch_bytes {
|
||||
bot.edit_message_text(chat_id, status_msg.id, "[ Error: total batch size exceeds limit. ]").await?;
|
||||
bot.edit_message_text(chat_id, status_msg.id, "<b>[ Error ]</b> Total batch size exceeds limit.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
dialogue.update(BotState::MainMenu).await?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -672,7 +728,9 @@ async fn finalize_upload(
|
||||
if let Ok(temp_path) = std::fs::canonicalize(&ctx.config.storage.paths.temp) {
|
||||
if let Ok(info) = fs2::available_space(&temp_path) {
|
||||
if info < total_size * 2 {
|
||||
bot.edit_message_text(chat_id, status_msg.id, "[ Error: insufficient storage space. ]").await?;
|
||||
bot.edit_message_text(chat_id, status_msg.id, "<b>[ Error ]</b> Insufficient storage space.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
dialogue.update(BotState::MainMenu).await?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -767,10 +825,14 @@ async fn finalize_upload(
|
||||
attrs.join(", ")
|
||||
};
|
||||
|
||||
let result_text = format!(
|
||||
"[ Upload Complete ]\n\nLink: <code>{}</code>\n\nFiles: {} | {}",
|
||||
let mut result_text = format!(
|
||||
"<b>[ Upload Complete ]</b>\n\nLink: <code>{}</code>\n\nFiles: <b>{}</b> | <i>{}</i>",
|
||||
link, items.len(), attr_text
|
||||
);
|
||||
if let Some(ref pw) = options.password {
|
||||
let direct_link = format!("{}/?cxid={}&sc={}", base_url, content_id.as_str(), pw);
|
||||
result_text.push_str(&format!("\n\n<i>Direct Access Link:</i> <code>{}</code>", direct_link));
|
||||
}
|
||||
|
||||
bot.edit_message_text(chat_id, status_msg.id, result_text)
|
||||
.parse_mode(ParseMode::Html)
|
||||
@@ -793,12 +855,14 @@ async fn show_previous_uploads(
|
||||
let total_pages = (total + 9) / 10;
|
||||
|
||||
if items.is_empty() {
|
||||
bot.send_message(chat_id, "You have no uploads.").await?;
|
||||
bot.send_message(chat_id, "<i>You have no uploads.</i>")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let base_url = &ctx.config.server.base_url;
|
||||
let mut text = format!("[ Your Uploads ] Page {}/{}\n\n", page + 1, total_pages.max(1));
|
||||
let mut text = format!("<b>[ My Uploads ]</b> Page {}/{}\n\n", page + 1, total_pages.max(1));
|
||||
for content in &items {
|
||||
let file_repo = ContentFileRepo::new(ctx.db.conn());
|
||||
let files = file_repo.list_by_content(&content.id).await?;
|
||||
@@ -814,10 +878,28 @@ async fn show_previous_uploads(
|
||||
}
|
||||
let attr_text = if attrs.is_empty() { "no options".to_string() } else { attrs.join(", ") };
|
||||
|
||||
text.push_str(&format!(
|
||||
"- <code>{}</code> ({} files) [{}]\n {}?cxid={}\n\n",
|
||||
content.id.as_str(), files.len(), attr_text, base_url, content.id.as_str()
|
||||
));
|
||||
if content.password_hash.is_some() {
|
||||
text.push_str(&format!(
|
||||
"• <code>{}</code> ({} files) [{}]\n {}?cxid={} <i>(password protected)</i>\n",
|
||||
content.id.as_str(), files.len(), attr_text, base_url, content.id.as_str()
|
||||
));
|
||||
} else {
|
||||
text.push_str(&format!(
|
||||
"• <code>{}</code> ({} files) [{}]\n {}?cxid={}\n",
|
||||
content.id.as_str(), files.len(), attr_text, base_url, content.id.as_str()
|
||||
));
|
||||
}
|
||||
text.push('\n');
|
||||
}
|
||||
|
||||
let mut keyboard_rows = vec![];
|
||||
for content in &items {
|
||||
keyboard_rows.push(vec![
|
||||
InlineKeyboardButton::callback(
|
||||
format!("[ Del {} ]", content.id.as_str()),
|
||||
format!("v1:admin:delcontent:{}", content.id.as_str())
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
let mut buttons = vec![];
|
||||
@@ -828,10 +910,12 @@ async fn show_previous_uploads(
|
||||
if page + 1 < total_pages {
|
||||
buttons.push(InlineKeyboardButton::callback(">>", format!("v1:prev:page:{}", page + 1)));
|
||||
}
|
||||
|
||||
let keyboard = InlineKeyboardMarkup::new(vec![buttons, vec![
|
||||
keyboard_rows.push(buttons);
|
||||
keyboard_rows.push(vec![
|
||||
InlineKeyboardButton::callback("[ Main Menu ]", "v1:menu:main"),
|
||||
]]);
|
||||
]);
|
||||
|
||||
let keyboard = InlineKeyboardMarkup::new(keyboard_rows);
|
||||
|
||||
bot.send_message(chat_id, text)
|
||||
.parse_mode(ParseMode::Html)
|
||||
@@ -860,7 +944,7 @@ async fn handle_report(
|
||||
|
||||
for &group_id in &ctx.config.groups.review_group_ids {
|
||||
let report_text = format!(
|
||||
"[ NEW REPORT ] #{}\n\nCXID: <code>{}</code>\nReporter: <code>{}</code>\nOwner: <code>{}</code>\nUploaded: {}\nFiles: {}",
|
||||
"<b>[ NEW REPORT ]</b> #{}\n\nCXID: <code>{}</code>\nReporter: <code>{}</code>\nOwner: <code>{}</code>\nUploaded: <i>{}</i>\nFiles: <b>{}</b>",
|
||||
report_id,
|
||||
cxid,
|
||||
reporter_id,
|
||||
@@ -871,7 +955,7 @@ async fn handle_report(
|
||||
|
||||
let keyboard = InlineKeyboardMarkup::new(vec![
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Delete + Blacklist ]", format!("v1:admin:delblk:{}", report_id)),
|
||||
InlineKeyboardButton::callback("[ Rmv + Ban ]", format!("v1:admin:delblk:{}", report_id)),
|
||||
InlineKeyboardButton::callback("[ Delete Only ]", format!("v1:admin:del:{}", report_id)),
|
||||
],
|
||||
vec![
|
||||
@@ -887,7 +971,9 @@ async fn handle_report(
|
||||
.ok();
|
||||
}
|
||||
|
||||
bot.send_message(chat_id, "Report submitted. Moderators will review it shortly.").await?;
|
||||
bot.send_message(chat_id, "<b>Report submitted.</b> Moderators will review it shortly.")
|
||||
.parse_mode(ParseMode::Html)
|
||||
.await?;
|
||||
dialogue.update(BotState::MainMenu).await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -899,8 +985,37 @@ async fn handle_admin_callback(
|
||||
parts: &[&str],
|
||||
ctx: &BotContext,
|
||||
) -> HandlerResult {
|
||||
match parts[2] {
|
||||
"delcontent" => {
|
||||
let cxid = parts[3];
|
||||
let content_id = ContentId::try_from(cxid)?;
|
||||
let content_repo = ContentRepo::new(ctx.db.conn());
|
||||
let content = match content_repo.get(&content_id).await? {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
bot.send_message(chat_id, "<b>Content not found.</b>")
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let is_admin = is_admin_in_chat(bot, chat_id, UserId(user_id as u64)).await;
|
||||
if !is_admin && content.user_id != user_id {
|
||||
bot.send_message(chat_id, "<b>Unauthorized.</b>")
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
ctx.pipeline.delete_content(&content_id, ctx.config.content.keep_content).await.ok();
|
||||
content_repo.set_status(&content_id, ContentStatus::Deleted).await.ok();
|
||||
bot.send_message(chat_id, format!("Content <code>{}</code> deleted.", cxid))
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if !is_admin_in_chat(bot, chat_id, UserId(user_id as u64)).await {
|
||||
bot.send_message(chat_id, "Unauthorized.").await?;
|
||||
bot.send_message(chat_id, "<b>Unauthorized.</b>")
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -909,7 +1024,8 @@ async fn handle_admin_callback(
|
||||
let report = match report_repo.get(report_id).await? {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
bot.send_message(chat_id, "Report not found.").await?;
|
||||
bot.send_message(chat_id, "<b>Report not found.</b>")
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
@@ -918,27 +1034,28 @@ async fn handle_admin_callback(
|
||||
let content = match content_repo.get(&report.content_id).await? {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
bot.send_message(chat_id, "Content not found.").await?;
|
||||
bot.send_message(chat_id, "<b>Content not found.</b>")
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match parts[2] {
|
||||
"delblk" => {
|
||||
ctx.pipeline.delete_content(&report.content_id, !ctx.config.content.keep_content).await.ok();
|
||||
ctx.pipeline.delete_content(&report.content_id, ctx.config.content.keep_content).await.ok();
|
||||
content_repo.set_status(&report.content_id, ContentStatus::Deleted).await.ok();
|
||||
ctx.moderation.blacklist(content.user_id).await.ok();
|
||||
let user_repo = UserRepo::new(ctx.db.conn());
|
||||
user_repo.set_role(content.user_id, "banned").await.ok();
|
||||
report_repo.resolve(report_id, ReportStatus::Actioned, user_id).await.ok();
|
||||
bot.send_message(chat_id, format!("Deleted content {} and blacklisted user {}", report.content_id.as_str(), content.user_id))
|
||||
bot.send_message(chat_id, format!("Deleted content <code>{}</code> and blacklisted user <code>{}</code>", report.content_id.as_str(), content.user_id))
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
}
|
||||
"del" => {
|
||||
ctx.pipeline.delete_content(&report.content_id, !ctx.config.content.keep_content).await.ok();
|
||||
ctx.pipeline.delete_content(&report.content_id, ctx.config.content.keep_content).await.ok();
|
||||
content_repo.set_status(&report.content_id, ContentStatus::Deleted).await.ok();
|
||||
report_repo.resolve(report_id, ReportStatus::Actioned, user_id).await.ok();
|
||||
bot.send_message(chat_id, format!("Deleted content {}", report.content_id.as_str()))
|
||||
bot.send_message(chat_id, format!("Deleted content <code>{}</code>", report.content_id.as_str()))
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
}
|
||||
"blk" => {
|
||||
@@ -946,12 +1063,12 @@ async fn handle_admin_callback(
|
||||
let user_repo = UserRepo::new(ctx.db.conn());
|
||||
user_repo.set_role(content.user_id, "banned").await.ok();
|
||||
report_repo.resolve(report_id, ReportStatus::Actioned, user_id).await.ok();
|
||||
bot.send_message(chat_id, format!("Blacklisted user {}", content.user_id))
|
||||
bot.send_message(chat_id, format!("Blacklisted user <code>{}</code>", content.user_id))
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
}
|
||||
"ign" => {
|
||||
report_repo.resolve(report_id, ReportStatus::Dismissed, user_id).await.ok();
|
||||
bot.send_message(chat_id, format!("Ignored report #{}", report_id))
|
||||
bot.send_message(chat_id, format!("Ignored report <code>#{}</code>", report_id))
|
||||
.parse_mode(ParseMode::Html).await?;
|
||||
}
|
||||
_ => {}
|
||||
|
||||
Reference in New Issue
Block a user