Compare commits
9 Commits
cca87da403
...
827a5022d1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
827a5022d1 | ||
|
|
ed211f2d72 | ||
|
|
412a54d647 | ||
|
|
1006fbe5c1 | ||
|
|
a9919a9307 | ||
|
|
4a37792c0c | ||
|
|
2bac30e711 | ||
|
|
a58fca01f9 | ||
|
|
089ef3218c |
2
migrations/2025-04-10-120721_media_table/down.sql
Normal file
2
migrations/2025-04-10-120721_media_table/down.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DROP TABLE media;
|
||||||
|
|
||||||
6
migrations/2025-04-10-120721_media_table/up.sql
Normal file
6
migrations/2025-04-10-120721_media_table/up.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE media (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
token VARCHAR NOT NULL,
|
||||||
|
media_type VARCHAR NOT NULL,
|
||||||
|
file_id VARCHAR NOT NULL
|
||||||
|
);
|
||||||
@ -71,8 +71,9 @@ pub async fn secret_command_handler(
|
|||||||
admin_password: String,
|
admin_password: String,
|
||||||
) -> Result<(), teloxide::RequestError> {
|
) -> Result<(), teloxide::RequestError> {
|
||||||
println!("Admin Pass: {}", admin_password);
|
println!("Admin Pass: {}", admin_password);
|
||||||
|
let tguser = msg.from.clone().unwrap();
|
||||||
let user = db
|
let user = db
|
||||||
.get_or_init_user(msg.from.clone().unwrap().id.0 as i64)
|
.get_or_init_user(tguser.id.0 as i64, &tguser.first_name)
|
||||||
.await;
|
.await;
|
||||||
println!("MSG: {}", msg.html_text().unwrap());
|
println!("MSG: {}", msg.html_text().unwrap());
|
||||||
match cmd {
|
match cmd {
|
||||||
|
|||||||
52
src/db.rs
52
src/db.rs
@ -62,7 +62,7 @@ impl DB {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_or_init_user(&mut self, userid: i64) -> User {
|
pub async fn get_or_init_user(&mut self, userid: i64, firstname: &str) -> User {
|
||||||
use self::schema::users::dsl::*;
|
use self::schema::users::dsl::*;
|
||||||
let connection = &mut self.pool.get().await.unwrap();
|
let connection = &mut self.pool.get().await.unwrap();
|
||||||
|
|
||||||
@ -76,7 +76,11 @@ impl DB {
|
|||||||
match user {
|
match user {
|
||||||
Some(existing_user) => existing_user,
|
Some(existing_user) => existing_user,
|
||||||
None => diesel::insert_into(users)
|
None => diesel::insert_into(users)
|
||||||
.values((id.eq(userid as i64), is_admin.eq(false)))
|
.values((
|
||||||
|
id.eq(userid as i64),
|
||||||
|
is_admin.eq(false),
|
||||||
|
first_name.eq(firstname),
|
||||||
|
))
|
||||||
.get_result(connection)
|
.get_result(connection)
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@ -212,4 +216,48 @@ impl DB {
|
|||||||
|
|
||||||
Ok(new_event)
|
Ok(new_event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_media(
|
||||||
|
&mut self,
|
||||||
|
literal: &str,
|
||||||
|
) -> Result<Vec<Media>, Box<dyn std::error::Error>> {
|
||||||
|
use self::schema::media::dsl::*;
|
||||||
|
let conn = &mut self.pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let media_items = media.filter(token.eq(literal)).load::<Media>(conn).await?;
|
||||||
|
|
||||||
|
Ok(media_items)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn drop_media(&mut self, literal: &str) -> Result<usize, Box<dyn std::error::Error>> {
|
||||||
|
use self::schema::media::dsl::*;
|
||||||
|
let conn = &mut self.pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let deleted_count = diesel::delete(media.filter(token.eq(literal)))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(deleted_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_media(
|
||||||
|
&mut self,
|
||||||
|
literal: &str,
|
||||||
|
mediatype: String,
|
||||||
|
fileid: i64,
|
||||||
|
) -> Result<Media, Box<dyn std::error::Error>> {
|
||||||
|
use self::schema::media::dsl::*;
|
||||||
|
let conn = &mut self.pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let new_media = diesel::insert_into(media)
|
||||||
|
.values((
|
||||||
|
token.eq(literal),
|
||||||
|
media_type.eq(mediatype),
|
||||||
|
file_id.eq(fileid),
|
||||||
|
))
|
||||||
|
.get_result::<Media>(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(new_media)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,15 @@ pub struct Literal {
|
|||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Queryable, Debug, Identifiable)]
|
||||||
|
#[diesel(table_name = media)]
|
||||||
|
pub struct Media {
|
||||||
|
pub id: i32,
|
||||||
|
pub token: String,
|
||||||
|
pub media_type: String,
|
||||||
|
pub file_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Debug, Identifiable)]
|
#[derive(Queryable, Debug, Identifiable)]
|
||||||
#[diesel(table_name = messages)]
|
#[diesel(table_name = messages)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
|
|||||||
@ -16,6 +16,15 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
media (id) {
|
||||||
|
id -> Int4,
|
||||||
|
token -> Varchar,
|
||||||
|
media_type -> Varchar,
|
||||||
|
file_id -> Varchar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
messages (id) {
|
messages (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
@ -66,6 +75,7 @@ diesel::joinable!(reservations -> users (user_id));
|
|||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
events,
|
events,
|
||||||
literals,
|
literals,
|
||||||
|
media,
|
||||||
messages,
|
messages,
|
||||||
reservations,
|
reservations,
|
||||||
teloxide_dialogues,
|
teloxide_dialogues,
|
||||||
|
|||||||
131
src/main.rs
131
src/main.rs
@ -11,8 +11,10 @@ use db::schema::events;
|
|||||||
use envconfig::Envconfig;
|
use envconfig::Envconfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use teloxide::dispatching::dialogue::serializer::Json;
|
use teloxide::dispatching::dialogue::serializer::Json;
|
||||||
use teloxide::dispatching::dialogue::{InMemStorage, PostgresStorage};
|
use teloxide::dispatching::dialogue::{GetChatId, InMemStorage, PostgresStorage};
|
||||||
use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup};
|
use teloxide::types::{
|
||||||
|
InlineKeyboardButton, InlineKeyboardMarkup, MediaKind, MessageKind, ReplyMarkup,
|
||||||
|
};
|
||||||
use teloxide::{
|
use teloxide::{
|
||||||
payloads::SendMessageSetters,
|
payloads::SendMessageSetters,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -90,17 +92,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.inspect(|u: Update| {
|
.inspect(|u: Update| {
|
||||||
eprintln!("{u:#?}"); // Print the update to the console with inspect
|
eprintln!("{u:#?}"); // Print the update to the console with inspect
|
||||||
})
|
})
|
||||||
|
.branch(Update::filter_callback_query().endpoint(callback_handler))
|
||||||
.branch(command_handler(config))
|
.branch(command_handler(config))
|
||||||
.branch(
|
.branch(
|
||||||
Update::filter_message()
|
Update::filter_message()
|
||||||
.filter_async(async |msg: Message, mut db: DB| {
|
.filter_async(async |msg: Message, mut db: DB| {
|
||||||
let user = db.get_or_init_user(msg.from.unwrap().id.0 as i64).await;
|
let tguser = msg.from.unwrap();
|
||||||
|
let user = db
|
||||||
|
.get_or_init_user(tguser.id.0 as i64, &tguser.first_name)
|
||||||
|
.await;
|
||||||
user.is_admin
|
user.is_admin
|
||||||
})
|
})
|
||||||
.enter_dialogue::<Message, PostgresStorage<Json>, State>()
|
.enter_dialogue::<Message, PostgresStorage<Json>, State>()
|
||||||
.branch(
|
.branch(
|
||||||
Update::filter_message()
|
Update::filter_message()
|
||||||
.filter(|msg: Message| msg.text().unwrap_or("") == "edit")
|
.filter(|msg: Message| {
|
||||||
|
msg.text().unwrap_or("").to_lowercase().as_str() == "edit"
|
||||||
|
})
|
||||||
.endpoint(edit_msg_cmd_handler),
|
.endpoint(edit_msg_cmd_handler),
|
||||||
)
|
)
|
||||||
.branch(dptree::case![State::Edit { literal, lang }].endpoint(edit_msg_handler)),
|
.branch(dptree::case![State::Edit { literal, lang }].endpoint(edit_msg_handler)),
|
||||||
@ -117,6 +125,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn callback_handler(
|
||||||
|
bot: Bot,
|
||||||
|
mut db: DB,
|
||||||
|
q: CallbackQuery,
|
||||||
|
) -> Result<(), teloxide::RequestError> {
|
||||||
|
bot.answer_callback_query(&q.id).await?;
|
||||||
|
|
||||||
|
if let Some(ref data) = q.data {
|
||||||
|
match data.as_str() {
|
||||||
|
"more_info" => {
|
||||||
|
answer_message(
|
||||||
|
&bot,
|
||||||
|
q.chat_id()
|
||||||
|
.clone()
|
||||||
|
.map(|i| i.0)
|
||||||
|
.unwrap_or(q.from.id.0 as i64),
|
||||||
|
&mut db,
|
||||||
|
"more_info",
|
||||||
|
None as Option<InlineKeyboardMarkup>,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
_ => {} // do nothing, yet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn edit_msg_cmd_handler(
|
async fn edit_msg_cmd_handler(
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
mut db: DB,
|
mut db: DB,
|
||||||
@ -165,16 +202,28 @@ async fn edit_msg_handler(
|
|||||||
(literal, lang): (String, String),
|
(literal, lang): (String, String),
|
||||||
msg: Message,
|
msg: Message,
|
||||||
) -> Result<(), teloxide::RequestError> {
|
) -> Result<(), teloxide::RequestError> {
|
||||||
match msg.html_text() {
|
use teloxide::utils::render::Renderer;
|
||||||
Some(text) => {
|
|
||||||
db.set_literal(&literal, &text).await.unwrap();
|
let chat_id = msg.chat.id;
|
||||||
bot.send_message(msg.chat.id, "Updated text of message!")
|
println!("Type: {:#?}", msg.kind);
|
||||||
.await
|
let msg = if let MessageKind::Common(msg) = msg.kind {
|
||||||
.unwrap();
|
msg
|
||||||
|
} else {
|
||||||
|
println!("Not a Common, somehow");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
match msg.media_kind {
|
||||||
|
MediaKind::Text(text) => {
|
||||||
|
let html_text = Renderer::new(&text.text, &text.entities).as_html();
|
||||||
|
db.set_literal(&literal, &html_text).await.unwrap();
|
||||||
|
bot.send_message(chat_id, "Updated text of message!")
|
||||||
|
.await?;
|
||||||
dialogue.exit().await.unwrap();
|
dialogue.exit().await.unwrap();
|
||||||
}
|
}
|
||||||
None => {
|
_ => {
|
||||||
bot.send_message(msg.chat.id, "Send text!").await.unwrap();
|
bot.send_message(chat_id, "this type of message is not supported yet")
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +253,10 @@ fn command_handler(
|
|||||||
.branch(
|
.branch(
|
||||||
dptree::entry()
|
dptree::entry()
|
||||||
.filter_async(async |msg: Message, mut db: DB| {
|
.filter_async(async |msg: Message, mut db: DB| {
|
||||||
let user = db.get_or_init_user(msg.from.unwrap().id.0 as i64).await;
|
let tguser = msg.from.unwrap();
|
||||||
|
let user = db
|
||||||
|
.get_or_init_user(tguser.id.0 as i64, &tguser.first_name)
|
||||||
|
.await;
|
||||||
user.is_admin
|
user.is_admin
|
||||||
})
|
})
|
||||||
.filter_command::<AdminCommands>()
|
.filter_command::<AdminCommands>()
|
||||||
@ -218,27 +270,22 @@ async fn user_command_handler(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
cmd: UserCommands,
|
cmd: UserCommands,
|
||||||
) -> Result<(), teloxide::RequestError> {
|
) -> Result<(), teloxide::RequestError> {
|
||||||
|
let tguser = msg.from.clone().unwrap();
|
||||||
let user = db
|
let user = db
|
||||||
.get_or_init_user(msg.from.clone().unwrap().id.0 as i64)
|
.get_or_init_user(tguser.id.0 as i64, &tguser.first_name)
|
||||||
.await;
|
.await;
|
||||||
println!("MSG: {}", msg.html_text().unwrap());
|
println!("MSG: {}", msg.html_text().unwrap());
|
||||||
match cmd {
|
match cmd {
|
||||||
UserCommands::Start => {
|
UserCommands::Start => {
|
||||||
let literal = "start";
|
let mut db2 = db.clone();
|
||||||
let text = db
|
answer_message(
|
||||||
.get_literal_value(literal)
|
&bot,
|
||||||
.await
|
msg.chat.id.0,
|
||||||
.unwrap()
|
&mut db,
|
||||||
.unwrap_or("Please, set content of this message".into());
|
"start",
|
||||||
let msg = bot
|
Some(make_start_buttons(&mut db2).await),
|
||||||
.send_message(msg.chat.id, text)
|
)
|
||||||
.reply_markup(make_start_buttons(&mut db).await)
|
.await
|
||||||
.parse_mode(teloxide::types::ParseMode::Html)
|
|
||||||
.await?;
|
|
||||||
db.set_message_literal(msg.chat.id.0, msg.id.0, literal)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
UserCommands::Help => {
|
UserCommands::Help => {
|
||||||
bot.send_message(msg.chat.id, UserCommands::descriptions().to_string())
|
bot.send_message(msg.chat.id, UserCommands::descriptions().to_string())
|
||||||
@ -248,6 +295,32 @@ async fn user_command_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn answer_message<RM: Into<ReplyMarkup>>(
|
||||||
|
bot: &Bot,
|
||||||
|
chat_id: i64,
|
||||||
|
db: &mut DB,
|
||||||
|
literal: &str,
|
||||||
|
keyboard: Option<RM>,
|
||||||
|
) -> Result<(), teloxide::RequestError> {
|
||||||
|
let text = db
|
||||||
|
.get_literal_value(literal)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap_or("Please, set content of this message".into());
|
||||||
|
let msg = bot.send_message(ChatId(chat_id), text);
|
||||||
|
let msg = match keyboard {
|
||||||
|
Some(kbd) => msg.reply_markup(kbd),
|
||||||
|
None => msg,
|
||||||
|
};
|
||||||
|
let msg = msg.parse_mode(teloxide::types::ParseMode::Html);
|
||||||
|
println!("ENTS: {:?}", msg.entities);
|
||||||
|
let msg = msg.await?;
|
||||||
|
db.set_message_literal(msg.chat.id.0, msg.id.0, literal)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn make_start_buttons(db: &mut DB) -> InlineKeyboardMarkup {
|
async fn make_start_buttons(db: &mut DB) -> InlineKeyboardMarkup {
|
||||||
let mut buttons: Vec<Vec<InlineKeyboardButton>> = db
|
let mut buttons: Vec<Vec<InlineKeyboardButton>> = db
|
||||||
.get_all_events()
|
.get_all_events()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user