Compare commits

..

No commits in common. "0c71fd379635815e6d00db81a48800b904afd445" and "ccd38178ea661818cb25870211a9557fcbed47d9" have entirely different histories.

6 changed files with 22 additions and 198 deletions

View File

@ -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))
}
}

View File

@ -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> {

View File

@ -1,6 +1,5 @@
#![allow(clippy::unwrap_used)]
mod callback_info_tests;
use dotenvy;
use super::CallDB;

View File

@ -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());
}

View File

@ -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))
}

View File

@ -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()),
))
}