implement download permission request system for chats
This commit is contained in:
parent
c00d1686a5
commit
d0fd88119c
4 changed files with 230 additions and 2 deletions
|
|
@ -17,4 +17,12 @@ request_not_found: "Request not found"
|
||||||
request_approved: "Request has been approved. The user should now be able to download"
|
request_approved: "Request has been approved. The user should now be able to download"
|
||||||
your_request_approved: "Congrats! Your request has been approved. Now you should be able to download"
|
your_request_approved: "Congrats! Your request has been approved. Now you should be able to download"
|
||||||
request_declined: "Request has been declined (deleted)."
|
request_declined: "Request has been declined (deleted)."
|
||||||
your_request_declined: "huge L for ya - ur request has been deleted and fuck you"
|
your_request_declined: "huge L for ya - ur request has been deleted and fuck you"
|
||||||
|
chat_already_can_download: "This chat already has permission for all users to download. Enjoy!"
|
||||||
|
chat_already_has_requested: "Downloading permission request for this chat is pending. Wait patiently or this shithole will be nuked"
|
||||||
|
admin_notify_chat_request: "Chat %{chat} awaits request approval"
|
||||||
|
chat_request_added: "Downloading permission request for this chat has been added. Admins have been notified. Wait for approval or decline, bot will reply when that happens"
|
||||||
|
chat_request_list_header: "Current chat requests for downloading:\n"
|
||||||
|
chat_request_not_found: "Chat request not found"
|
||||||
|
chat_request_approved: "Chat request has been approved. Now everyone in this chat can download"
|
||||||
|
chat_request_declined: "Very bad news! This chat will be drone-striked tomorrow (chat request declined)"
|
||||||
|
|
@ -3,6 +3,7 @@ pub mod dl;
|
||||||
pub mod notify;
|
pub mod notify;
|
||||||
pub mod op;
|
pub mod op;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
|
pub mod request_chat;
|
||||||
pub mod sanitize;
|
pub mod sanitize;
|
||||||
pub mod start;
|
pub mod start;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use crate::db::DbPool;
|
||||||
use super::dl::cmd_download;
|
use super::dl::cmd_download;
|
||||||
use super::op::cmd_op;
|
use super::op::cmd_op;
|
||||||
use super::request::{cmd_listrequests, cmd_request, cmd_approve, cmd_decline};
|
use super::request::{cmd_listrequests, cmd_request, cmd_approve, cmd_decline};
|
||||||
|
use super::request_chat::{cmd_listrequests_chat, cmd_request_chat, cmd_approve_chat, cmd_decline_chat};
|
||||||
use super::start::{cmd_start, handle_my_chat_member};
|
use super::start::{cmd_start, handle_my_chat_member};
|
||||||
|
|
||||||
fn parse_env<T>(name: &str) -> T
|
fn parse_env<T>(name: &str) -> T
|
||||||
|
|
@ -66,7 +67,11 @@ fn schema() -> UpdateHandler<HandlerErr> {
|
||||||
.branch(case![Command::Request(text)].endpoint(cmd_request))
|
.branch(case![Command::Request(text)].endpoint(cmd_request))
|
||||||
.branch(case![Command::ListRequests].endpoint(cmd_listrequests))
|
.branch(case![Command::ListRequests].endpoint(cmd_listrequests))
|
||||||
.branch(case![Command::Approve(text)].endpoint(cmd_approve))
|
.branch(case![Command::Approve(text)].endpoint(cmd_approve))
|
||||||
.branch(case![Command::Decline(text)].endpoint(cmd_decline));
|
.branch(case![Command::Decline(text)].endpoint(cmd_decline))
|
||||||
|
.branch(case![Command::RequestChat(text)].endpoint(cmd_request_chat))
|
||||||
|
.branch(case![Command::ListRequestsChat].endpoint(cmd_listrequests_chat))
|
||||||
|
.branch(case![Command::ApproveChat(text)].endpoint(cmd_approve_chat))
|
||||||
|
.branch(case![Command::DeclineChat(text)].endpoint(cmd_decline_chat));
|
||||||
|
|
||||||
let message_handler = Update::filter_message().branch(command_handler);
|
let message_handler = Update::filter_message().branch(command_handler);
|
||||||
let raw_message_handler = Update::filter_message().branch(dptree::endpoint(handle_message));
|
let raw_message_handler = Update::filter_message().branch(dptree::endpoint(handle_message));
|
||||||
|
|
@ -116,6 +121,7 @@ enum Command {
|
||||||
Download(String),
|
Download(String),
|
||||||
#[command(alias = "op")]
|
#[command(alias = "op")]
|
||||||
OP,
|
OP,
|
||||||
|
|
||||||
#[command(alias = "request")]
|
#[command(alias = "request")]
|
||||||
Request(String),
|
Request(String),
|
||||||
#[command(alias = "listrequests")]
|
#[command(alias = "listrequests")]
|
||||||
|
|
@ -124,6 +130,15 @@ enum Command {
|
||||||
Approve(String),
|
Approve(String),
|
||||||
#[command(alias = "decline")]
|
#[command(alias = "decline")]
|
||||||
Decline(String),
|
Decline(String),
|
||||||
|
|
||||||
|
#[command(alias = "request_chat")]
|
||||||
|
RequestChat(String),
|
||||||
|
#[command(alias = "listrequests_chat")]
|
||||||
|
ListRequestsChat,
|
||||||
|
#[command(alias = "approve_chat")]
|
||||||
|
ApproveChat(String),
|
||||||
|
#[command(alias = "decline_chat")]
|
||||||
|
DeclineChat(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn cmd_test(bot: Bot, msg: Message, _db: DbPool) -> HandlerResult {
|
async fn cmd_test(bot: Bot, msg: Message, _db: DbPool) -> HandlerResult {
|
||||||
|
|
|
||||||
204
src/bot/request_chat.rs
Normal file
204
src/bot/request_chat.rs
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
use rust_i18n::t;
|
||||||
|
use sqlx::Row;
|
||||||
|
use teloxide::types::Recipient;
|
||||||
|
use teloxide::prelude::*;
|
||||||
|
use tracing::{event, Level};
|
||||||
|
|
||||||
|
use super::notify::notify_admins;
|
||||||
|
use super::types::HandlerResult;
|
||||||
|
use crate::db::user::find_or_create_user;
|
||||||
|
use crate::db::chat::find_or_create_chat;
|
||||||
|
use crate::db::{DbPool, Chat};
|
||||||
|
use crate::{parse_integer, reply_i18n_and_return};
|
||||||
|
|
||||||
|
pub async fn cmd_request_chat(bot: Bot, msg: Message, text: String, db: DbPool) -> HandlerResult {
|
||||||
|
if text.len() < 16 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "request_text_is_too_short");
|
||||||
|
} else if text.len() > 100 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "request_text_is_too_long");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user) = msg.from() {
|
||||||
|
let user = find_or_create_user(&db, user).await?;
|
||||||
|
let chat = find_or_create_chat(&db, &msg.chat).await?;
|
||||||
|
|
||||||
|
if chat.can_download == 1 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "chat_already_can_download");
|
||||||
|
}
|
||||||
|
|
||||||
|
let requests: i64 = sqlx::query("SELECT COUNT(1) FROM request_chat WHERE requested_for = $1;")
|
||||||
|
.bind(chat.id)
|
||||||
|
.fetch_one(&db)
|
||||||
|
.await?
|
||||||
|
.get(0);
|
||||||
|
if requests > 0 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "chat_already_has_requested");
|
||||||
|
}
|
||||||
|
|
||||||
|
// put the chat request
|
||||||
|
sqlx::query("INSERT INTO request_chat (requested_by,requested_for,message,is_approved) VALUES ($1,$2,$3,$4);")
|
||||||
|
.bind(user.id)
|
||||||
|
.bind(chat.id)
|
||||||
|
.bind(text)
|
||||||
|
.bind(0)
|
||||||
|
.execute(&db)
|
||||||
|
.await?;
|
||||||
|
event!(Level::INFO, "added chat request for {}", chat);
|
||||||
|
|
||||||
|
// notify admins
|
||||||
|
notify_admins(
|
||||||
|
&bot,
|
||||||
|
&db,
|
||||||
|
t!("admin_notify_chat_request", chat = chat.to_string()).to_string(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
bot.send_message(msg.chat.id, t!("chat_request_added")).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(sqlx::FromRow, Debug)]
|
||||||
|
struct RequestChatWithChat {
|
||||||
|
pub request_id: i64,
|
||||||
|
pub message: String,
|
||||||
|
#[sqlx(flatten)]
|
||||||
|
pub chat: Chat,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_listrequests_chat(bot: Bot, msg: Message, db: DbPool) -> HandlerResult {
|
||||||
|
if let Some(user) = msg.from() {
|
||||||
|
let user = find_or_create_user(&db, user).await?;
|
||||||
|
if user.is_admin != 1 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "not_an_admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
let requests: Vec<RequestChatWithChat> = sqlx::query_as(
|
||||||
|
"SELECT request_chat.id AS request_id, request_chat.message, chat.*
|
||||||
|
FROM request_chat
|
||||||
|
INNER JOIN chat ON request_chat.requested_for = chat.id
|
||||||
|
WHERE request_chat.is_approved = 0;",
|
||||||
|
)
|
||||||
|
.fetch_all(&db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut list = String::new();
|
||||||
|
list.push_str(t!("chat_request_list_header").to_string().as_str());
|
||||||
|
for request in requests {
|
||||||
|
let fmt = format!(
|
||||||
|
"{}: {}: {}\n",
|
||||||
|
request.request_id, request.chat, request.message
|
||||||
|
);
|
||||||
|
list.push_str(fmt.as_str());
|
||||||
|
}
|
||||||
|
bot.send_message(msg.chat.id, list).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_approve_chat(bot: Bot, msg: Message, id: String, db: DbPool) -> HandlerResult {
|
||||||
|
let id: i64 = parse_integer!(bot, msg.chat.id, id);
|
||||||
|
|
||||||
|
if let Some(user) = msg.from() {
|
||||||
|
let user = find_or_create_user(&db, user).await?;
|
||||||
|
if user.is_admin != 1 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "not_an_admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get request
|
||||||
|
let res: Result<RequestChatWithChat, sqlx::Error> = sqlx::query_as(
|
||||||
|
"SELECT request_chat.id AS request_id, request_chat.message, chat.*
|
||||||
|
FROM request_chat
|
||||||
|
INNER JOIN chat ON request_chat.requested_for = chat.id
|
||||||
|
WHERE request_chat.is_approved = 0
|
||||||
|
LIMIT 1;",
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.fetch_one(&db)
|
||||||
|
.await;
|
||||||
|
let request = match res {
|
||||||
|
Ok(request) => request,
|
||||||
|
Err(e) => match e {
|
||||||
|
sqlx::Error::RowNotFound => {
|
||||||
|
bot.send_message(msg.chat.id, t!("chat_request_not_found"))
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => return Err(Box::new(e)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// approve request
|
||||||
|
sqlx::query("UPDATE request_chat SET approved_by = $1, is_approved = 1 WHERE id = $2;")
|
||||||
|
.bind(user.id)
|
||||||
|
.bind(request.request_id)
|
||||||
|
.execute(&db)
|
||||||
|
.await?;
|
||||||
|
event!(
|
||||||
|
Level::INFO,
|
||||||
|
"approved chat request {} by {} for {}",
|
||||||
|
request.request_id,
|
||||||
|
user,
|
||||||
|
request.chat
|
||||||
|
);
|
||||||
|
// notify target chat
|
||||||
|
bot.send_message(Recipient::Id(ChatId(request.chat.tg_id)), t!("chat_request_approved")).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_decline_chat(bot: Bot, msg: Message, id: String, db: DbPool) -> HandlerResult {
|
||||||
|
let id: i64 = parse_integer!(bot, msg.chat.id, id);
|
||||||
|
|
||||||
|
if let Some(user) = msg.from() {
|
||||||
|
let user = find_or_create_user(&db, user).await?;
|
||||||
|
if user.is_admin != 1 {
|
||||||
|
reply_i18n_and_return!(bot, msg.chat.id, "not_an_admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get request
|
||||||
|
let res: Result<RequestChatWithChat, sqlx::Error> = sqlx::query_as(
|
||||||
|
"SELECT request_chat.id AS request_id, request_chat.message, chat.*
|
||||||
|
FROM request_chat
|
||||||
|
INNER JOIN chat ON request_chat.requested_for = chat.id
|
||||||
|
WHERE request_chat.is_approved = 0
|
||||||
|
LIMIT 1;",
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.fetch_one(&db)
|
||||||
|
.await;
|
||||||
|
let request = match res {
|
||||||
|
Ok(request) => request,
|
||||||
|
Err(e) => match e {
|
||||||
|
sqlx::Error::RowNotFound => {
|
||||||
|
bot.send_message(msg.chat.id, t!("chat_request_not_found"))
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => return Err(Box::new(e)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// decline request
|
||||||
|
sqlx::query("DELETE FROM request_chat WHERE id = $1;")
|
||||||
|
.bind(request.request_id)
|
||||||
|
.execute(&db).await?;
|
||||||
|
event!(
|
||||||
|
Level::INFO,
|
||||||
|
"declined request {} by {} for {}",
|
||||||
|
request.request_id,
|
||||||
|
user,
|
||||||
|
request.chat
|
||||||
|
);
|
||||||
|
bot.send_message(msg.chat.id, t!("request_declined"))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// notify target chat
|
||||||
|
bot.send_message(Recipient::Id(ChatId(request.chat.tg_id)), t!("chat_request_declined")).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue