add_user, add_group features.

This commit is contained in:
AB
2020-11-29 16:23:27 +03:00
parent 61474a07c5
commit c848b4b632
5 changed files with 212 additions and 44 deletions

View File

@ -1,11 +1,11 @@
use crate::db;
use html_escape::encode_text;
use telegram_bot::prelude::*;
use telegram_bot::{Api, Error, Message, MessageKind, ParseMode, UpdateKind};
use tokio::time::delay_for;
use html_escape::encode_text;
pub(crate) async fn here(api: Api, message: Message) -> Result<(), Error> {
let members: Vec<telegram_bot::User> = db::get_members(&message.chat.id()).unwrap();
let members: Vec<telegram_bot::User> = db::get_members(message.chat.id()).unwrap();
for u in &members {
println!("Found user {:?}", u);
}
@ -13,7 +13,11 @@ pub(crate) async fn here(api: Api, message: Message) -> Result<(), Error> {
for user in members {
let mention = match user.username {
Some(username) => format!("@{}", username),
_ => format!("<a href=\"tg://user?id={}\">{}</a>", encode_text(&user.id.to_string()), encode_text(&user.first_name)),
_ => format!(
"<a href=\"tg://user?id={}\">{}</a>",
encode_text(&user.id.to_string()),
encode_text(&user.first_name)
),
};
msg = format!("{} {}", msg, mention);
}

178
src/db.rs
View File

@ -1,19 +1,13 @@
use rusqlite::{named_params, params, Connection, Result};
use crate::errors;
use crate::utils;
use rusqlite::{named_params, params, Connection, Error, Result};
use std::time::SystemTime;
use telegram_bot::*;
#[derive(Debug, Clone)]
pub struct User {
id: i64,
username: Option<String>,
first_name: String,
last_name: Option<String>,
date: i32,
}
#[derive(Debug, Clone)]
pub struct Conf {
id: i64,
title: Option<String>,
id: telegram_bot::ChatId,
title: String,
date: i32,
}
@ -23,12 +17,12 @@ pub(crate) fn open() -> Result<Connection> {
Ok(db)
}
pub(crate) fn get_user(id: i64) -> Result<telegram_bot::User> {
pub(crate) fn get_user(id: telegram_bot::UserId) -> Result<telegram_bot::User, errors::Error> {
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 rows = stmt.query_named(&[(":id", &id.to_string())])?;
let mut users = Vec::new();
while let Some(row) = rows.next()? {
@ -42,9 +36,35 @@ pub(crate) fn get_user(id: i64) -> Result<telegram_bot::User> {
})
}
Ok(users[0].clone())
if users.len() == 0 {
Err(errors::Error::UserNotFound)
} else {
Ok(users[0].clone())
}
}
pub(crate) fn get_conf(id: telegram_bot::ChatId) -> Result<Conf, errors::Error> {
let conn = open()?;
let mut stmt = conn.prepare("SELECT id, title, date FROM conf WHERE id = :id")?;
let mut rows = stmt.query_named(&[(":id", &id.to_string())])?;
let mut confs = Vec::new();
while let Some(row) = rows.next()? {
confs.push(Conf {
id: telegram_bot::ChatId::new(row.get(0)?),
title: row.get(1)?,
date: row.get(2)?,
})
}
//println!("Confs: {:?}", confs);
if confs.len() == 0 {
Err(errors::Error::ConfNotFound)
} else {
Ok(confs[0].clone())
}}
pub(crate) fn get_confs() -> Result<Vec<Conf>> {
let conn = open()?;
let mut stmt = conn.prepare("SELECT id, title, date FROM conf")?;
@ -54,19 +74,18 @@ pub(crate) fn get_confs() -> Result<Vec<Conf>> {
while let Some(row) = rows.next()? {
confs.push(Conf {
id: row.get(0)?,
id: telegram_bot::ChatId::new(row.get(0)?),
title: row.get(1)?,
date: row.get(2)?,
})
}
println!("Confs: {:?}", confs);
//println!("Confs: {:?}", confs);
Ok(confs)
}
pub(crate) fn get_members(id: &telegram_bot::ChatId) -> Result<Vec<telegram_bot::User>> {
pub(crate) fn get_members(id: telegram_bot::ChatId) -> Result<Vec<telegram_bot::User>> {
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
@ -77,7 +96,7 @@ pub(crate) fn get_members(id: &telegram_bot::ChatId) -> Result<Vec<telegram_bot:
ON r.conf_id = c.id
WHERE c.id = :id",
)?;
let mut rows = stmt.query_named(&[(":id", &str_id)])?;
let mut rows = stmt.query_named(&[(":id", &id.to_string())])?;
let mut users = Vec::new();
while let Some(row) = rows.next()? {
@ -93,3 +112,122 @@ pub(crate) fn get_members(id: &telegram_bot::ChatId) -> Result<Vec<telegram_bot:
Ok(users)
}
pub(crate) async fn add_conf(api: Api, message: Message) -> Result<(), Error> {
let conn = open()?;
let title = utils::get_title(&message);
match get_conf(message.chat.id()) {
Ok(conf) => {
let update = Conf {
id: message.chat.id(),
title,
date: 0
};
let mut stmt = conn.prepare(
"UPDATE conf
SET
title = :title
WHERE
id = :id",
)?;
stmt.execute_named(&[
(":id", &update.id.to_string()),
(":title", &update.title),
])?;
//println!("Conf {:?} updated: {:?}", update.title, get_conf(update.id));
}
Err(e) => {
let update = Conf {
id: message.chat.id(),
title,
date: 0
};
let unix_time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
let mut stmt = conn.prepare(
"UPDATE conf
SET
title = :title,
date = :date
WHERE
id = :id",
)?;
stmt.execute_named(&[
(":id", &update.id.to_string()),
(":title", &update.title),
(":date", &unix_time),
])?;
//println!("Conf {:?} added: {:?}", update.title, get_conf(update.id));
}
_ => {}
}
Ok(())
}
pub(crate) async fn add_user(api: Api, message: Message) -> Result<(), Error> {
let conn = open()?;
match get_user(message.from.id) {
Ok(user) => {
let update = telegram_bot::User {
id: message.from.id,
first_name: message.from.first_name,
last_name: message.from.last_name,
username: message.from.username,
is_bot: false,
language_code: None
};
let mut stmt = conn.prepare(
"UPDATE user
SET
username = :username,
first_name = :first_name,
last_name = :last_name
WHERE
id = :id",
)?;
stmt.execute_named(&[
(":id", &update.id.to_string()),
(":username", &update.username),
(":first_name", &update.first_name),
(":last_name", &update.last_name),
])?;
//println!("User {} updated: {:?}", update.first_name, get_user(user.id));
}
Err(e) => {
let unix_time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
let user = telegram_bot::User {
id: message.from.id,
first_name: message.from.first_name,
last_name: message.from.last_name,
username: message.from.username,
is_bot: false,
language_code: None
};
let mut stmt = conn.prepare(
"INSERT OR IGNORE INTO
user('id', 'username', 'first_name', 'last_name', 'date')
VALUES (:id, :username, :first_name, :last_name, :date)",
)?;
stmt.execute_named(&[
(":id", &user.id.to_string()),
(":username", &user.username),
(":first_name", &user.first_name),
(":last_name", &user.last_name),
(":date", &unix_time),
])?;
//println!("User added: {:?}", user);
},
_ => {},
}
Ok(())
}

29
src/errors.rs Normal file
View File

@ -0,0 +1,29 @@
use rusqlite::Error as sqlite_error;
use rusqlite::{named_params, params, Connection, Result};
use telegram_bot::Error as tg_error;
use std::{fmt, io};
#[derive(Debug)]
pub(crate) enum Error {
UserNotFound,
SQLITE3Error(sqlite_error),
TelegramError(tg_error),
ConfNotFound,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "An error occurred.")
}
}
impl From<sqlite_error> for Error {
fn from(e: sqlite_error) -> Error {
return Error::SQLITE3Error(e);
}
}
impl From<tg_error> for Error {
fn from(e: tg_error) -> Error {
return Error::TelegramError(e);
}
}

View File

@ -6,17 +6,16 @@ use telegram_bot::*;
mod commands;
mod db;
mod errors;
mod utils;
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",
};
let title = utils::get_title(&message);
println!(
"<{}>[{}::{}({})]: {}",
"<{}({})>[{}({})]: {}",
&message.chat.id(),
title,
&message.from.id,
@ -25,7 +24,6 @@ async fn handler(api: Api, message: Message) -> Result<(), Error> {
);
match data.as_str() {
"/here" => commands::here(api, message).await?,
_ => (),
}
}
@ -36,13 +34,7 @@ async fn handler(api: Api, message: Message) -> Result<(), Error> {
}
#[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));
*/
async fn main() -> Result<(), errors::Error> {
let token = env::var("TELEGRAM_BOT_TOKEN").expect("TELEGRAM_BOT_TOKEN not set");
let api = Api::new(token);
@ -52,16 +44,11 @@ async fn main() -> Result<(), Error> {
// If the received update contains a new message...
let update = update?;
if let UpdateKind::Message(message) = update.kind {
db::add_user(api.clone(), message.clone()).await?;
db::add_conf(api.clone(), message.clone()).await?;
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: [] }
*/

10
src/utils.rs Normal file
View File

@ -0,0 +1,10 @@
use telegram_bot::*;
pub(crate) fn get_title(message: &telegram_bot::Message) -> String {
match &message.chat {
MessageChat::Supergroup(chat) => chat.title.clone(),
MessageChat::Group(chat) => chat.title.clone(),
MessageChat::Private(chat) => "PRIVATE".to_string(),
_ => "PRIVATE".to_string()
}
}