Compare commits
No commits in common. "0c71fd379635815e6d00db81a48800b904afd445" and "ccd38178ea661818cb25870211a9557fcbed47d9" have entirely different histories.
0c71fd3796
...
ccd38178ea
@ -1,62 +0,0 @@
|
||||
use crate::query_call_consume;
|
||||
use crate::CallDB;
|
||||
use bson::oid::ObjectId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::DbResult;
|
||||
use bson::doc;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct CallbackInfo<C>
|
||||
where
|
||||
C: Serialize,
|
||||
{
|
||||
pub _id: bson::oid::ObjectId,
|
||||
#[serde(flatten)]
|
||||
pub callback: C,
|
||||
}
|
||||
|
||||
impl<C> CallbackInfo<C>
|
||||
where
|
||||
C: Serialize + for<'a> Deserialize<'a> + Send + Sync,
|
||||
{
|
||||
pub fn new(callback: C) -> Self {
|
||||
Self {
|
||||
_id: Default::default(),
|
||||
callback,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
self._id.to_hex()
|
||||
}
|
||||
|
||||
query_call_consume!(store, self, db, Self, {
|
||||
let db = db.get_database().await;
|
||||
let ci = db.collection::<Self>("callback_info");
|
||||
|
||||
ci.insert_one(&self).await?;
|
||||
|
||||
Ok(self)
|
||||
});
|
||||
|
||||
pub async fn get<D: CallDB>(db: &mut D, id: &str) -> DbResult<Option<Self>> {
|
||||
let db = db.get_database().await;
|
||||
let ci = db.collection::<Self>("callback_info");
|
||||
|
||||
let id = match ObjectId::parse_str(id) {
|
||||
Ok(id) => id,
|
||||
Err(_) => return Ok(None),
|
||||
};
|
||||
|
||||
Ok(ci
|
||||
.find_one(doc! {
|
||||
"_id": id
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_callback<D: CallDB>(db: &mut D, id: &str) -> DbResult<Option<C>> {
|
||||
Self::get(db, id).await.map(|co| co.map(|c| c.callback))
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
pub mod callback_info;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use enum_stringify::EnumStringify;
|
||||
@ -37,7 +35,6 @@ pub struct User {
|
||||
pub language_code: Option<String>,
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! query_call {
|
||||
($func_name:ident, $self:ident, $db:ident, $return_type:ty, $body:block) => {
|
||||
pub async fn $func_name<D: CallDB>(&$self, $db: &mut D)
|
||||
@ -45,14 +42,6 @@ macro_rules! query_call {
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! query_call_consume {
|
||||
($func_name:ident, $self:ident, $db:ident, $return_type:ty, $body:block) => {
|
||||
pub async fn $func_name<D: CallDB>($self, $db: &mut D)
|
||||
-> DbResult<$return_type> $body
|
||||
};
|
||||
}
|
||||
|
||||
impl User {
|
||||
query_call!(update_user, self, db, (), {
|
||||
let db_collection = db.get_database().await.collection::<Self>("users");
|
||||
@ -147,11 +136,7 @@ impl CallDB for DB {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum DbError {
|
||||
#[error("error while processing mongodb query: {0}")]
|
||||
MongodbError(#[from] mongodb::error::Error),
|
||||
}
|
||||
pub type DbError = mongodb::error::Error;
|
||||
pub type DbResult<T> = Result<T, DbError>;
|
||||
|
||||
#[async_trait]
|
||||
@ -163,7 +148,7 @@ pub trait CallDB {
|
||||
let db = self.get_database().await;
|
||||
let users = db.collection::<User>("users");
|
||||
|
||||
Ok(users.find(doc! {}).await?.try_collect().await?)
|
||||
users.find(doc! {}).await?.try_collect().await
|
||||
}
|
||||
|
||||
async fn set_admin(&mut self, userid: i64, isadmin: bool) -> DbResult<()> {
|
||||
@ -283,7 +268,7 @@ pub trait CallDB {
|
||||
let db = self.get_database().await;
|
||||
let events = db.collection::<Event>("events");
|
||||
|
||||
Ok(events.find(doc! {}).await?.try_collect().await?)
|
||||
events.find(doc! {}).await?.try_collect().await
|
||||
}
|
||||
|
||||
async fn create_event(&mut self, event_datetime: chrono::DateTime<Utc>) -> DbResult<Event> {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
mod callback_info_tests;
|
||||
use dotenvy;
|
||||
|
||||
use super::CallDB;
|
||||
@ -1,28 +0,0 @@
|
||||
use super::super::callback_info::CallbackInfo;
|
||||
use super::setup_db;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename = "snake_case")]
|
||||
pub enum Callback {
|
||||
#[default]
|
||||
MoreInfo,
|
||||
NextPage,
|
||||
}
|
||||
|
||||
type CI = CallbackInfo<Callback>;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_store() {
|
||||
let mut db = setup_db().await;
|
||||
|
||||
let ci = CI::new(Default::default());
|
||||
|
||||
let ci = ci.store(&mut db).await.unwrap();
|
||||
|
||||
let ci = CI::get(&mut db, &ci.get_id()).await.unwrap();
|
||||
|
||||
assert!(ci.is_some());
|
||||
}
|
||||
80
src/main.rs
80
src/main.rs
@ -1,12 +1,9 @@
|
||||
pub mod admin;
|
||||
pub mod db;
|
||||
pub mod mongodb_storage;
|
||||
pub mod utils;
|
||||
|
||||
use db::callback_info::CallbackInfo;
|
||||
use log::{info, warn};
|
||||
use log::info;
|
||||
use std::time::Duration;
|
||||
use utils::create_callback_button;
|
||||
|
||||
use crate::admin::{admin_command_handler, AdminCommands};
|
||||
use crate::admin::{secret_command_handler, SecretCommands};
|
||||
@ -73,16 +70,6 @@ pub enum State {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename = "snake_case")]
|
||||
pub enum Callback {
|
||||
MoreInfo,
|
||||
ProjectPage { id: u32 },
|
||||
}
|
||||
|
||||
type CallbackStore = CallbackInfo<Callback>;
|
||||
|
||||
pub struct BotController {
|
||||
pub bot: Bot,
|
||||
pub db: DB,
|
||||
@ -188,39 +175,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
async fn callback_handler(bot: Bot, mut db: DB, q: CallbackQuery) -> BotResult<()> {
|
||||
bot.answer_callback_query(&q.id).await?;
|
||||
|
||||
let data = match q.data {
|
||||
Some(ref data) => data,
|
||||
None => {
|
||||
// not really our case to handle
|
||||
return Ok(());
|
||||
if let Some(ref data) = q.data {
|
||||
match data.as_str() {
|
||||
"more_info" => {
|
||||
answer_message(
|
||||
&bot,
|
||||
q.chat_id().map(|i| i.0).unwrap_or(q.from.id.0 as i64),
|
||||
&mut db,
|
||||
"more_info",
|
||||
None as Option<InlineKeyboardMarkup>,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
_ => {} // do nothing, yet
|
||||
}
|
||||
};
|
||||
|
||||
let callback = match CallbackStore::get_callback(&mut db, data).await? {
|
||||
Some(callback) => callback,
|
||||
None => {
|
||||
warn!("Not found callback for data: {data}");
|
||||
// doing this silently beacuse end user shouldn't know about backend internal data
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match callback {
|
||||
Callback::MoreInfo => {
|
||||
answer_message(
|
||||
&bot,
|
||||
q.chat_id().map(|i| i.0).unwrap_or(q.from.id.0 as i64),
|
||||
&mut db,
|
||||
"more_info",
|
||||
None as Option<InlineKeyboardMarkup>,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
Callback::ProjectPage { id } => {
|
||||
bot.send_message(q.from.id, format!("Some project No: {id}"))
|
||||
.await?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -611,21 +580,10 @@ async fn make_start_buttons(db: &mut DB) -> BotResult<InlineKeyboardMarkup> {
|
||||
)]
|
||||
})
|
||||
.collect();
|
||||
buttons.push(vec![
|
||||
InlineKeyboardButton::callback(
|
||||
"More info",
|
||||
CallbackStore::new(Callback::MoreInfo)
|
||||
.store(db)
|
||||
.await?
|
||||
.get_id(),
|
||||
),
|
||||
create_callback_button(
|
||||
"show_projects",
|
||||
CallbackStore::new(Callback::ProjectPage { id: 1 }),
|
||||
db,
|
||||
)
|
||||
.await?,
|
||||
]);
|
||||
buttons.push(vec![InlineKeyboardButton::callback(
|
||||
"More info",
|
||||
"more_info",
|
||||
)]);
|
||||
|
||||
Ok(InlineKeyboardMarkup::new(buttons))
|
||||
}
|
||||
|
||||
28
src/utils.rs
28
src/utils.rs
@ -1,28 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use teloxide::types::InlineKeyboardButton;
|
||||
|
||||
use crate::{
|
||||
db::{callback_info::CallbackInfo, CallDB},
|
||||
BotResult,
|
||||
};
|
||||
|
||||
pub async fn create_callback_button<C, D>(
|
||||
literal: &str,
|
||||
ci: CallbackInfo<C>,
|
||||
db: &mut D,
|
||||
) -> BotResult<InlineKeyboardButton>
|
||||
where
|
||||
C: Serialize + for<'a> Deserialize<'a> + Send + Sync,
|
||||
D: CallDB + Send,
|
||||
{
|
||||
let text = db
|
||||
.get_literal_value(literal)
|
||||
.await?
|
||||
.unwrap_or("Please, set content of this message".into());
|
||||
let ci = ci.store(db).await?;
|
||||
|
||||
Ok(InlineKeyboardButton::new(
|
||||
text,
|
||||
teloxide::types::InlineKeyboardButtonKind::CallbackData(ci.get_id()),
|
||||
))
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user