commit 0aed600fa3944143255b3424c6ec44474a063415 Author: AB Date: Sat Nov 28 17:31:08 2020 +0300 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f247c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +memory.sqlite3 + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..469a034 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "desubot" +version = "0.1.0" +authors = ["AB "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bytes = "0.5" +tokio = { version = "0.2", features = ["full"]} + +tracing = "0.1.9" +tracing-futures = "0.2" +multipart = { version = "0.16", default-features = false, features = ["client"] } + +telegram-bot = "0.8.0" + +hyper = "0.13" +hyper-tls = { version = "0.4", optional = true } +futures = "0.3" +hyper-rustls = { version = "0.19", optional = true } + +rusqlite = "0.24.1" \ No newline at end of file diff --git a/assets/scheme.sql b/assets/scheme.sql new file mode 100644 index 0000000..c7d446c --- /dev/null +++ b/assets/scheme.sql @@ -0,0 +1,45 @@ +CREATE TABLE `word` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `word` TEXT UNIQUE +); +CREATE TABLE sqlite_sequence(name,seq); +CREATE TABLE `user` ( + `id` INTEGER NOT NULL UNIQUE, + `username` TEXT NOT NULL, + `first_name` INTEGER NOT NULL, + `last_name` INTEGER NOT NULL, + `date` INTEGER NOT NULL, + PRIMARY KEY(`id`) +); +CREATE TABLE `conf` ( + `id` NUMERIC NOT NULL UNIQUE, + `title` TEXT, + `date` INTEGER NOT NULL, + PRIMARY KEY(`id`) +); +CREATE TABLE IF NOT EXISTS "relations" ( + `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + `word_id` INTEGER NOT NULL, + `user_id` INTEGER NOT NULL, + `conf_id` INTEGER NOT NULL, + `date` INTEGER NOT NULL, `msg_id` INTEGER NULL, + FOREIGN KEY(`word_id`) REFERENCES `word`(`id`) ON DELETE CASCADE, + FOREIGN KEY(`user_id`) REFERENCES `user`(`id`), + FOREIGN KEY(`conf_id`) REFERENCES `conf`(`id`) +); +CREATE TABLE `reset` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `user_id` INTEGER, + `conf_id` INTEGER, + `date` INTEGER, + `relation_id` INTEGER, + FOREIGN KEY(`user_id`) REFERENCES `user`(`id`) +); +CREATE TABLE `alert` ( +`conf_id`TEXT NOT NULL, +`user_id`TEXT NOT NULL, +`created`TEXT NOT NULL, +`time`TEXT NOT NULL, +`message`TEXT +); +CREATE TABLE `xxx_message` (`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `text`TEXT UNIQUE NULL); \ No newline at end of file diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 0000000..d731025 --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,22 @@ +use crate::db; +use telegram_bot::prelude::*; +use telegram_bot::{Api, Error, Message, MessageKind, ParseMode, UpdateKind}; +use tokio::time::delay_for; + +pub(crate) async fn here(api: Api, message: Message) -> Result<(), Error> { + let members: Vec = db::get_members(&message.chat.id()).unwrap(); + let mut msg = "I summon you, ".to_string(); + for user in members { + let mention = match user.username { + Some(username) => format!("@{}", username), + _ => format!("[{}](tg://user?id={})", user.first_name, user.id), + }; + msg = format!("{} {}", msg, mention); + } + + api.send(message.text_reply(msg).parse_mode(ParseMode::MarkdownV2)) + .await?; + //api.send(message.chat.text("Text to message chat")).await?; + //api.send(message.from.text("Private text")).await?; + Ok(()) +} diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..b8b2e70 --- /dev/null +++ b/src/db.rs @@ -0,0 +1,95 @@ +use rusqlite::{named_params, params, Connection, Result}; +use telegram_bot::*; + +#[derive(Debug, Clone)] +pub struct User { + id: i64, + username: Option, + first_name: String, + last_name: Option, + date: i32, +} + +#[derive(Debug, Clone)] +pub struct Conf { + id: i64, + title: Option, + date: i32, +} + +pub(crate) fn open() -> Result { + let path = "./memory.sqlite3"; + let db = Connection::open(&path)?; + Ok(db) +} + +pub(crate) fn get_user(id: i64) -> Result { + let conn = open()?; + let mut stmt = + conn.prepare("SELECT id, username, first_name, last_name, date FROM user WHERE id = :id")?; + + let mut rows = stmt.query_named(&[(":id", &id)])?; + let mut users = Vec::new(); + + while let Some(row) = rows.next()? { + users.push(telegram_bot::User { + id: UserId::new(row.get(0)?), + username: row.get(1)?, + is_bot: false, + first_name: row.get(2)?, + last_name: row.get(3)?, + language_code: None, + }) + } + + Ok(users[0].clone()) +} + +pub(crate) fn get_confs() -> Result> { + let conn = open()?; + let mut stmt = conn.prepare("SELECT id, title, date FROM conf")?; + + let mut rows = stmt.query(params![])?; + let mut confs = Vec::new(); + + while let Some(row) = rows.next()? { + confs.push(Conf { + id: row.get(0)?, + title: row.get(1)?, + date: row.get(2)?, + }) + } + println!("Confs: {:?}", confs); + + Ok(confs) +} + +pub(crate) fn get_members(id: &telegram_bot::ChatId) -> Result> { + let conn = open()?; + let str_id = id.to_string(); + let mut stmt = conn.prepare( + " + SELECT DISTINCT(u.username), u.id, u.first_name, u.last_name, u.date + FROM relations r + JOIN user u + ON u.id = r.user_id + LEFT JOIN conf c + ON r.conf_id = c.id + WHERE c.id = :id", + )?; + let mut rows = stmt.query_named(&[(":id", &str_id)])?; + let mut users = Vec::new(); + + while let Some(row) = rows.next()? { + users.push(telegram_bot::User { + id: UserId::new(row.get(1)?), + username: row.get(0)?, + is_bot: false, + first_name: row.get(2)?, + last_name: row.get(3)?, + language_code: None, + }) + } + + Ok(users) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..990f184 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,67 @@ +use std::env; + +use futures::StreamExt; +use telegram_bot::types::chat::MessageChat; +use telegram_bot::*; + +mod commands; +mod db; + +async fn handler(api: Api, message: Message) -> Result<(), Error> { + match message.kind { + MessageKind::Text { ref data, .. } => { + let title = match &message.chat { + MessageChat::Supergroup(chat) => &chat.title, + _ => "test", + }; + + println!( + "<{}>[{}::{}({})]: {}", + &message.chat.id(), + title, + &message.from.id, + &message.from.first_name, + data + ); + match data.as_str() { + "/here" => commands::here(api, message).await?, + + _ => (), + } + } + _ => (), + }; + + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + /* + println!("get_user: {:?}", db::get_user(1228494339)); + println!("get_confs: {:?}", db::get_confs()); + println!("get_members: {:?}", db::get_members(-1001233797421)); + + */ + let token = env::var("TELEGRAM_BOT_TOKEN").expect("TELEGRAM_BOT_TOKEN not set"); + let api = Api::new(token); + + // Fetch new updates via long poll method + let mut stream = api.stream(); + while let Some(update) = stream.next().await { + // If the received update contains a new message... + let update = update?; + if let UpdateKind::Message(message) = update.kind { + handler(api.clone(), message).await?; + } + } + Ok(()) +} +/* +{ id: MessageId(94793), from: + User { id: UserId(124317807), first_name: "Холм", last_name: Some("Вечный"), username: Some("ultradesu"), is_bot: false, language_code: Some("en") }, + date: 1606564847, + chat: Supergroup(Supergroup { id: SupergroupId(-1001233797421), title: "Квантовый Аллах", username: None, invite_link: None }), + forward: None, reply_to_message: None, edit_date: None, kind: Text { data: "пук", entities: [] } + + */