Skip to content

Commit

Permalink
end to end flow
Browse files Browse the repository at this point in the history
  • Loading branch information
m1guelpf committed Nov 15, 2023
1 parent 10a3d9d commit e69d79d
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 49 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[package]
license = "MIT"
edition = "2021"
version = "0.1.0"
readme = "README.md"
name = "world-id-telegram"
authors = ["Miguel Piedrafita <[email protected]>"]
version = "0.1.0"
edition = "2021"
repository = "https://github.com/worldcoin/world-id-telegram"
license = "MIT"
description = "Add sybil-resistance to Telegram groups with World ID."
keywords = [
"telegram",
Expand All @@ -15,21 +16,21 @@ keywords = [
"world-id",
"worldcoin",
]
readme = "README.md"

[dependencies]
log = "0.4"
rand = "0.8"
url = "2.4.1"
indoc = "2.0.4"
dashmap = "5.5"
axum = "0.6.20"
dotenvy = "0.15.7"
serde_with = "3.3"
reqwest = "0.11.22"
serde_json = "1.0.108"
humantime-serde = "1.1"
pretty_env_logger = "0.5"
tokio = { version = "1.32", features = ["full"] }
config = { version = "0.13", features = ["toml"] }
serde = { version = "1.0", features = ["derive"] }
teloxide = { version = "0.12", features = ["macros"] }
dotenvy = "0.15.7"
axum = "0.6.20"
reqwest = "0.11.22"
serde_json = "1.0.108"
17 changes: 8 additions & 9 deletions src/bot/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use teloxide::{
Bot,
};

use crate::{bot::HandlerResult, config::GroupsConfig};
use crate::{
bot::HandlerResult,
config::{AppConfig, GroupsConfig},
};

#[derive(BotCommands)]
#[command(rename_rule = "lowercase", description = "Available commands:")]
Expand All @@ -22,7 +25,7 @@ pub enum Command {

pub async fn command_handler(
bot: Bot,
config: Arc<GroupsConfig>,
config: Arc<AppConfig>,
msg: Message,
me: Me,
text: String,
Expand All @@ -31,8 +34,8 @@ pub async fn command_handler(
return Ok(());
}

if !config.is_group_allowed(msg.chat.id) {
return on_group_not_allowed(bot, config, msg).await;
if !config.groups_config.is_group_allowed(msg.chat.id) {
return on_group_not_allowed(bot, &config.groups_config, msg).await;
}

let Ok(command) = BotCommands::parse(text.as_str(), me.username()) else {
Expand Down Expand Up @@ -77,11 +80,7 @@ pub async fn command_handler(
Ok(())
}

pub async fn on_group_not_allowed(
bot: Bot,
config: Arc<GroupsConfig>,
msg: Message,
) -> HandlerResult {
pub async fn on_group_not_allowed(bot: Bot, config: &GroupsConfig, msg: Message) -> HandlerResult {
log::error!(
"Unknown chat {} with id {}",
msg.chat.title().unwrap_or_default(),
Expand Down
29 changes: 16 additions & 13 deletions src/bot/join_check/mod.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
use std::sync::Arc;

use teloxide::{
prelude::*,
types::{ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup, MessageId, User},
utils::html::escape,
};
use url::Url;

use crate::{
bot::{commands::on_group_not_allowed, HandlerResult, JoinRequest, JoinRequests},
config::GroupsConfig,
config::AppConfig,
};

pub async fn join_handler(
bot: Bot,
msg: Message,
users: Vec<User>,
config: Arc<GroupsConfig>,
config: Arc<AppConfig>,
join_requests: JoinRequests,
) -> HandlerResult {
if !config.is_group_allowed(msg.chat.id) {
return on_group_not_allowed(bot, config, msg).await;
if !config.groups_config.is_group_allowed(msg.chat.id) {
return on_group_not_allowed(bot, &config.groups_config, msg).await;
}

let chat_cfg = config.get(msg.chat.id);
let chat_cfg = config.groups_config.get(msg.chat.id);

for user in users {
let join_requests = join_requests.clone();
Expand All @@ -44,7 +44,9 @@ pub async fn join_handler(

let verify_button = InlineKeyboardButton::url(
"Verify with World ID",
Url::parse("https://example.com").unwrap(),
config
.app_url
.join(&format!("verify/{}/{}", msg.chat.id, msg.id))?,
);

let msg_id = bot
Expand All @@ -55,15 +57,15 @@ pub async fn join_handler(
.await?
.id;

join_requests.insert(msg_id, JoinRequest::new(user.id, msg.chat.id));
join_requests.insert((msg.chat.id, msg_id), JoinRequest::new(user.id));

tokio::spawn({
let bot = bot.clone();
let ban_after = chat_cfg.ban_after;
async move {
tokio::time::sleep(ban_after).await;

if let Some((_, data)) = join_requests.remove(&msg_id) {
if let Some((_, data)) = join_requests.remove(&(msg.chat.id, msg_id)) {
if !data.is_verified {
bot.ban_chat_member(msg.chat.id, data.user_id)
.await
Expand All @@ -83,23 +85,24 @@ pub async fn join_handler(

pub async fn on_verified(
bot: Bot,
chat_id: ChatId,
msg_id: MessageId,
join_requests: JoinRequests,
) -> HandlerResult {
let mut join_req = join_requests
.get_mut(&msg_id)
.get_mut(&(chat_id, msg_id))
.ok_or("Can't find the message id in group dialogue")?;

let Some(permissions) = bot.get_chat(join_req.chat_id).await?.permissions() else {
let Some(permissions) = bot.get_chat(chat_id).await?.permissions() else {
return Err("Can't get the group permissions".into());
};

join_req.is_verified = true;

bot.restrict_chat_member(join_req.chat_id, join_req.user_id, permissions)
bot.restrict_chat_member(chat_id, join_req.user_id, permissions)
.await?;

bot.delete_message(join_req.chat_id, msg_id).await?;
bot.delete_message(chat_id, msg_id).await?;

Ok(())
}
8 changes: 3 additions & 5 deletions src/bot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,19 @@ mod commands;
mod join_check;

type HandlerResult = Result<(), HandlerError>;
pub type JoinRequests = Arc<DashMap<MessageId, JoinRequest>>;
pub type JoinRequests = Arc<DashMap<(ChatId, MessageId), JoinRequest>>;
type HandlerError = Box<dyn std::error::Error + Send + Sync>;

#[derive(Clone)]
pub struct JoinRequest {
pub user_id: UserId,
pub chat_id: ChatId,
pub is_verified: bool,
}

impl JoinRequest {
fn new(user_id: UserId, chat_id: ChatId) -> Self {
fn new(user_id: UserId) -> Self {
Self {
user_id,
chat_id,
is_verified: false,
}
}
Expand All @@ -51,7 +49,7 @@ pub async fn start(bot: Bot, config: AppConfig, join_requests: JoinRequests) {

Dispatcher::builder(bot, handler)
.default_handler(|_| async {})
.dependencies(dptree::deps![Arc::new(config.groups_config), join_requests])
.dependencies(dptree::deps![Arc::new(config), join_requests])
.enable_ctrlc_handler()
.build()
.dispatch()
Expand Down
11 changes: 9 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ use teloxide::{
types::{ChatId, User, UserId},
utils::html::escape,
};
use url::Url;

#[derive(Debug, Clone, Default, Deserialize)]
#[derive(Debug, Clone, Deserialize)]
pub struct AppConfig {
pub app_url: Url,
pub app_id: String,
pub bot_token: String,
#[serde(flatten, default)]
Expand Down Expand Up @@ -85,7 +87,12 @@ pub struct MessagesText {
impl MessagesText {
pub fn create_welcome_msg(&self, user: &User, chat_name: &str) -> String {
self.new_user_template
.replace("{TAGUSER}", &user.mention().unwrap())
.replace(
"{TAGUSER}",
&user.mention().unwrap_or_else(|| {
format!("[{}](tg://user?id={})", user.full_name(), user.id,)
}),
)
.replace("{CHATNAME}", &escape(chat_name))
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use dashmap::DashMap;
use dotenvy::dotenv;
use std::sync::Arc;
use teloxide::{requests::Requester, types::MessageId, Bot};
use teloxide::{
requests::Requester,
types::{ChatId, MessageId},
Bot,
};

use crate::{bot::JoinRequest, config::AppConfig};

Expand All @@ -15,7 +19,7 @@ async fn main() {
pretty_env_logger::init();

let config = AppConfig::try_read().expect("Failed to read config");
let join_requests = Arc::new(DashMap::<MessageId, JoinRequest>::new());
let join_requests = Arc::new(DashMap::<(ChatId, MessageId), JoinRequest>::new());

let bot = Bot::new(&config.bot_token);
let bot_data = bot.get_me().await.expect("Failed to get bot account");
Expand Down
Loading

0 comments on commit e69d79d

Please sign in to comment.