use log::{error, info};
use rusqlite::params;
use telexide_fork::{
api::types::{CreateChatInviteLink, GetChat, GetChatAdministrators, SendMessage},
model::{AdministratorMemberStatus, Chat, ChatMember},
prelude::*,
};
use crate::persistence::types::{Channel, DBKey};
#[must_use]
pub fn get_all(ctx: &Context, user_id: i64) -> Vec<Channel> {
let guard = ctx.data.read();
let map = guard.get::<DBKey>().expect("db");
let conn = map.get().unwrap();
let mut stmt = conn
.prepare("SELECT id, link, name FROM channels WHERE registered_by = ? ORDER BY id ASC")
.unwrap();
let channels = stmt
.query_map(params![user_id], |row| {
Ok(Channel {
id: row.get(0)?,
registered_by: user_id,
link: row.get(1)?,
name: row.get(2)?,
})
})
.unwrap()
.map(Result::unwrap)
.collect();
channels
}
pub async fn admins(ctx: &Context, chat_id: i64, user_id: i64) -> Vec<AdministratorMemberStatus> {
let admins = ctx
.api
.get_chat_administrators(GetChatAdministrators { chat_id })
.await;
if admins.is_err() {
let res = ctx
.api
.send_message(SendMessage::new(
user_id,
"Error! You must add this bot as admin of the group/channel.",
))
.await;
if res.is_err() {
let err = res.err().unwrap();
error!("[register] send message {}", err);
}
return vec![];
}
let admins = admins.unwrap();
admins
.iter()
.filter_map(|u| {
if let ChatMember::Administrator(admin) = u {
Some(admin.clone())
} else {
None
}
})
.collect()
}
pub async fn try_register(ctx: &Context, chat_id: i64, registered_by: i64) -> bool {
info!("try_register begin");
let (mut invite_link, username, title, is_channel) = {
match ctx.api.get_chat(GetChat { chat_id }).await.unwrap() {
Chat::Channel(c) => (c.invite_link, c.username, Some(c.title), true),
Chat::Group(c) => (c.invite_link, c.username, Some(c.title), false),
Chat::SuperGroup(c) => (c.invite_link, c.username, Some(c.title), false),
Chat::Private(_) => (None, None, None, false),
}
};
if invite_link.is_none() && username.is_none() {
if let Ok(invite) = ctx
.api
.create_chat_invite_link(CreateChatInviteLink {
chat_id,
expire_date: None,
member_limit: None,
})
.await
{
invite_link = Some(invite.invite_link);
}
}
let link: String = {
if let Some(invite_link) = invite_link {
invite_link.to_string()
} else if let Some(username) = username {
format!("https://t.me/{username}")
} else {
String::new()
}
};
if link.is_empty() {
info!(
"[register] Unable to extract invite link / username for {}",
chat_id
);
return false;
}
let admins = admins(ctx, chat_id, registered_by).await;
let mut found = false;
let me = ctx.api.get_me().await.unwrap(); for admin in admins {
if admin.user.is_bot
&& admin.user.id == me.id
&& admin.can_manage_chat
&& ((is_channel
&& admin.can_post_messages.is_some()
&& admin.can_post_messages.unwrap())
|| (!is_channel
&& admin.can_pin_messages.is_some()
&& admin.can_pin_messages.unwrap()))
{
found = true;
break;
}
}
if !found {
let res = ctx
.api
.send_message(SendMessage::new(
registered_by,
"The bot must be admin of the channel/group, and shall be able to:\n\n\
1. manage the chat.\n2. post messages\n3. pin messages",
))
.await;
if res.is_err() {
let err = res.err().unwrap();
error!("[register] send message {}", err);
}
return false;
}
let title = title.unwrap();
let res = {
let guard = ctx.data.read();
let map = guard.get::<DBKey>().expect("db");
let conn = map.get().unwrap();
conn.execute(
"INSERT OR IGNORE INTO channels(id, registered_by, link, name) VALUES(?, ?, ?, ?)",
params![chat_id, registered_by, link, title],
)
};
if res.is_err() {
let err = res.err().unwrap();
error!("[register] {}", err);
let res = ctx
.api
.send_message(SendMessage::new(registered_by, &err.to_string()))
.await;
if res.is_err() {
let err = res.err().unwrap();
error!("[register] send message {}", err);
}
return false;
}
let res = ctx
.api
.send_message(SendMessage::new(
registered_by,
&format!("Channel/Group {title} registered succesfully!"),
))
.await;
if res.is_err() {
let err = res.err().unwrap();
error!("[final register] {}", err);
}
info!("try_register end");
true
}