Compare commits
No commits in common. "adad94ad4337217e4c9c402f4f138c49c011eb40" and "bee93b32d1f2248fb267fad39c070fe736213871" have entirely different histories.
adad94ad43
...
bee93b32d1
84
mainbot.js
84
mainbot.js
@ -1,32 +1,21 @@
|
|||||||
// db - is set globally
|
// db - is set globally
|
||||||
|
|
||||||
const PROJECTS_COUNT = 2
|
|
||||||
|
|
||||||
const start_msg = {
|
|
||||||
buttons: [
|
|
||||||
[{ name: { literal: "show_projects" }, callback_name: "project_0" }],
|
|
||||||
[{ name: { literal: "more_info_btn" }, callback_name: "more_info" }],
|
|
||||||
[{ name: { literal: "leave_application" }, callback_name: "leave_application" }],
|
|
||||||
[{ name: { literal: "ask_question_btn" }, callback_name: "ask_question" }],
|
|
||||||
], // default is `null`
|
|
||||||
replace: true,
|
|
||||||
state: "start"
|
|
||||||
};
|
|
||||||
const dialog = {
|
const dialog = {
|
||||||
commands: {
|
commands: {
|
||||||
start: start_msg,
|
start: {
|
||||||
|
buttons: start_buttons, // default is `null`
|
||||||
|
state: "start"
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
buttons: [
|
||||||
|
[{name: {name: "Def"}, callback_name: "defcall"}]
|
||||||
|
],
|
||||||
|
state: "none"
|
||||||
|
},
|
||||||
|
somecomplicatedcmd: {}
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
more_info: {
|
more_info: {},
|
||||||
buttons: [
|
|
||||||
[{ name: { name: "На главную" }, callback_name: "start" }],
|
|
||||||
]
|
|
||||||
},
|
|
||||||
start: start_msg,
|
|
||||||
leave_application: {
|
|
||||||
handler: leave_application
|
|
||||||
},
|
|
||||||
ask_question: {}
|
|
||||||
},
|
},
|
||||||
stateful_msg_handlers: {
|
stateful_msg_handlers: {
|
||||||
start: {}, // everything is by default, so just send message `start`
|
start: {}, // everything is by default, so just send message `start`
|
||||||
@ -40,43 +29,36 @@ const dialog = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function leave_application(user) {
|
function enter_name() {}
|
||||||
print(JSON.stringify(user))
|
|
||||||
user_application(user)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
function enter_name() { }
|
|
||||||
|
|
||||||
const fmt = (number) => number.toString().padStart(2, '0');
|
const fmt = (number) => number.toString().padStart(2, '0');
|
||||||
|
|
||||||
function add_project_callbacks(point) {
|
const formatDate = (date) => {
|
||||||
for (const i of Array(PROJECTS_COUNT).keys()) {
|
const [h, m, d, M, y] = [
|
||||||
buttons = [
|
date.getHours(),
|
||||||
[],
|
date.getMinutes(),
|
||||||
[{ name: { name: "На главную" }, callback_name: "start" }]
|
date.getDate(),
|
||||||
]
|
date.getMonth(),
|
||||||
if (i > 0) {
|
date.getFullYear()
|
||||||
buttons[0].push({ name: { literal: "prev_project" }, callback_name: `project_${i - 1}` })
|
];
|
||||||
}
|
return `${fmt(h)}:${fmt(m)} ${fmt(d)}-${fmt(M + 1)}-${y}`
|
||||||
if (i < PROJECTS_COUNT - 1) {
|
};
|
||||||
buttons[0].push({ name: { literal: "next_project" }, callback_name: `project_${i + 1}` })
|
|
||||||
}
|
|
||||||
|
|
||||||
point[`project_${i}`] = {
|
function start_buttons() {
|
||||||
replace: true,
|
const now = new Date();
|
||||||
buttons: buttons
|
const dateFormated = formatDate(now);
|
||||||
}
|
|
||||||
}
|
// return 1
|
||||||
|
return [
|
||||||
|
[{name: {name: dateFormated}, callback_name: "no"}],
|
||||||
|
[{name: {name: "Hello!"}, callback_name: "no"}],
|
||||||
|
]
|
||||||
}
|
}
|
||||||
add_project_callbacks(dialog.buttons)
|
|
||||||
print(JSON.stringify(dialog.buttons))
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
version: 1.1,
|
version: 1.1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// {config, dialog}
|
// {config, dialog}
|
||||||
const c = { config: config, dialog: dialog }
|
const c = {config: config, dialog: dialog}
|
||||||
c
|
c
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
use log::{error, info};
|
use log::info;
|
||||||
use quickjs_rusty::serde::to_js;
|
|
||||||
use std::{
|
use std::{
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
@ -67,39 +66,6 @@ async fn handle_botmessage(bot: Bot, mut db: DB, bm: BotMessage, msg: Message) -
|
|||||||
let user = update_user_tg(user, &tguser);
|
let user = update_user_tg(user, &tguser);
|
||||||
user.update_user(&mut db).await?;
|
user.update_user(&mut db).await?;
|
||||||
|
|
||||||
let is_propagate: bool = match bm.get_handler() {
|
|
||||||
Some(handler) => 'prop: {
|
|
||||||
let ctx = match handler.context() {
|
|
||||||
Some(ctx) => ctx,
|
|
||||||
// falling back to propagation
|
|
||||||
None => break 'prop true,
|
|
||||||
};
|
|
||||||
let jsuser = to_js(ctx, &tguser).unwrap();
|
|
||||||
match handler.call_args(vec![jsuser]) {
|
|
||||||
Ok(v) => {
|
|
||||||
if v.is_bool() {
|
|
||||||
v.to_bool().unwrap_or(true)
|
|
||||||
} else if v.is_int() {
|
|
||||||
v.to_int().unwrap_or(1) != 0
|
|
||||||
} else {
|
|
||||||
// falling back to propagation
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
error!("Failed to get return of handler, err: {err}");
|
|
||||||
// falling back to propagation
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_propagate {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let buttons = bm
|
let buttons = bm
|
||||||
.resolve_buttons(&mut db)
|
.resolve_buttons(&mut db)
|
||||||
.await?
|
.await?
|
||||||
@ -136,39 +102,6 @@ async fn handle_callback(bot: Bot, mut db: DB, bm: BotMessage, q: CallbackQuery)
|
|||||||
let user = update_user_tg(user, &tguser);
|
let user = update_user_tg(user, &tguser);
|
||||||
user.update_user(&mut db).await?;
|
user.update_user(&mut db).await?;
|
||||||
|
|
||||||
let is_propagate: bool = match bm.get_handler() {
|
|
||||||
Some(handler) => 'prop: {
|
|
||||||
let ctx = match handler.context() {
|
|
||||||
Some(ctx) => ctx,
|
|
||||||
// falling back to propagation
|
|
||||||
None => break 'prop true,
|
|
||||||
};
|
|
||||||
let jsuser = to_js(ctx, &tguser).unwrap();
|
|
||||||
match handler.call_args(vec![jsuser]) {
|
|
||||||
Ok(v) => {
|
|
||||||
if v.is_bool() {
|
|
||||||
v.to_bool().unwrap_or(true)
|
|
||||||
} else if v.is_int() {
|
|
||||||
v.to_int().unwrap_or(1) != 0
|
|
||||||
} else {
|
|
||||||
// falling back to propagation
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
error!("Failed to get return of handler, err: {err}");
|
|
||||||
// falling back to propagation
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_propagate {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let buttons = bm
|
let buttons = bm
|
||||||
.resolve_buttons(&mut db)
|
.resolve_buttons(&mut db)
|
||||||
.await?
|
.await?
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
pub mod application;
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex, PoisonError};
|
use std::sync::{Arc, Mutex, PoisonError};
|
||||||
@ -13,12 +12,12 @@ use itertools::Itertools;
|
|||||||
use quickjs_rusty::serde::from_js;
|
use quickjs_rusty::serde::from_js;
|
||||||
use quickjs_rusty::utils::create_empty_object;
|
use quickjs_rusty::utils::create_empty_object;
|
||||||
use quickjs_rusty::utils::create_string;
|
use quickjs_rusty::utils::create_string;
|
||||||
|
use quickjs_rusty::Context;
|
||||||
use quickjs_rusty::ContextError;
|
use quickjs_rusty::ContextError;
|
||||||
use quickjs_rusty::ExecutionError;
|
use quickjs_rusty::ExecutionError;
|
||||||
use quickjs_rusty::JsFunction;
|
use quickjs_rusty::JsFunction;
|
||||||
use quickjs_rusty::OwnedJsValue as JsValue;
|
use quickjs_rusty::OwnedJsValue as JsValue;
|
||||||
use quickjs_rusty::ValueError;
|
use quickjs_rusty::ValueError;
|
||||||
use quickjs_rusty::{Context, OwnedJsObject};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -122,13 +121,6 @@ impl BotFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context(&self) -> Option<*mut quickjs_rusty::JSContext> {
|
|
||||||
match &self.func {
|
|
||||||
FunctionMarker::Function(js_function) => Some(js_function.context()),
|
|
||||||
FunctionMarker::StrTemplate(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(&self) -> ScriptResult<JsValue> {
|
pub fn call(&self) -> ScriptResult<JsValue> {
|
||||||
self.call_args(Default::default())
|
self.call_args(Default::default())
|
||||||
}
|
}
|
||||||
@ -506,10 +498,6 @@ impl BotMessage {
|
|||||||
pub fn is_replace(&self) -> bool {
|
pub fn is_replace(&self) -> bool {
|
||||||
self.replace
|
self.replace
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_handler(&self) -> Option<&BotFunction> {
|
|
||||||
self.handler.as_ref()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BotMessage {
|
impl BotMessage {
|
||||||
@ -665,17 +653,6 @@ impl Runner {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_attacher<F, R>(&mut self, f: F) -> ScriptResult<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&Context, &mut OwnedJsObject) -> R,
|
|
||||||
{
|
|
||||||
let context = self.context.lock().unwrap();
|
|
||||||
let mut global = context.global()?;
|
|
||||||
|
|
||||||
let res = f(&context, &mut global);
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_script(&self, content: &str) -> ScriptResult<JsValue> {
|
pub fn run_script(&self, content: &str) -> ScriptResult<JsValue> {
|
||||||
let ctx = match self.context.lock() {
|
let ctx = match self.context.lock() {
|
||||||
Ok(ctx) => ctx,
|
Ok(ctx) => ctx,
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
use std::sync::RwLock;
|
|
||||||
|
|
||||||
use log::info;
|
|
||||||
use quickjs_rusty::{context::Context, serde::from_js, OwnedJsObject};
|
|
||||||
use teloxide::Bot;
|
|
||||||
use tokio::runtime::Handle;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
db::{application::Application, message_forward::MessageForward, CallDB, DB},
|
|
||||||
message_answerer::MessageAnswerer,
|
|
||||||
send_application_to_chat, BotError,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::ScriptError;
|
|
||||||
|
|
||||||
pub fn attach_user_application(
|
|
||||||
c: &Context,
|
|
||||||
o: &mut OwnedJsObject,
|
|
||||||
db: &DB,
|
|
||||||
bot: &Bot,
|
|
||||||
) -> Result<(), ScriptError> {
|
|
||||||
let db: std::sync::Arc<RwLock<DB>> = std::sync::Arc::new(RwLock::new(db.clone()));
|
|
||||||
let dbbox = Box::new(db.clone());
|
|
||||||
let db: &'static _ = Box::leak(dbbox);
|
|
||||||
|
|
||||||
let bot: std::sync::Arc<RwLock<Bot>> = std::sync::Arc::new(RwLock::new(bot.clone()));
|
|
||||||
let botbox = Box::new(bot.clone());
|
|
||||||
let bot: &'static _ = Box::leak(botbox);
|
|
||||||
|
|
||||||
let user_application =
|
|
||||||
c.create_callback(move |q: OwnedJsObject| -> Result<_, ScriptError> {
|
|
||||||
let db = db.clone();
|
|
||||||
let user: teloxide::types::User = match from_js(q.context(), &q) {
|
|
||||||
Ok(q) => q,
|
|
||||||
Err(_) => todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let application = futures::executor::block_on(
|
|
||||||
Application::new(user.clone()).store_db(&mut db.write().unwrap()),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let db2 = db.clone();
|
|
||||||
let msg = tokio::task::block_in_place(move || {
|
|
||||||
Handle::current().block_on(async move {
|
|
||||||
send_application_to_chat(
|
|
||||||
&bot.read().unwrap(),
|
|
||||||
&mut db2.write().unwrap(),
|
|
||||||
&application,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
});
|
|
||||||
let msg = match msg {
|
|
||||||
Ok(msg) => msg,
|
|
||||||
Err(err) => {
|
|
||||||
info!("Got err: {err}");
|
|
||||||
return Err(ScriptError::MutexError("🤦♂️".to_string()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (chat_id, msg_id) = futures::executor::block_on(
|
|
||||||
MessageAnswerer::new(
|
|
||||||
&bot.read().unwrap(),
|
|
||||||
&mut db.write().unwrap(),
|
|
||||||
user.id.0 as i64,
|
|
||||||
)
|
|
||||||
.answer("left_application_msg", None, None),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
futures::executor::block_on(
|
|
||||||
MessageForward::new(msg.chat.id.0, msg.id.0, chat_id, msg_id, false)
|
|
||||||
.store_db(&mut db.write().unwrap()),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let ret = true;
|
|
||||||
Ok(ret)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
o.set_property("user_application", user_application.into_value())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -2,7 +2,6 @@ use chrono::{DateTime, FixedOffset, Local};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::DbResult;
|
use super::DbResult;
|
||||||
use super::DB;
|
|
||||||
use crate::query_call_consume;
|
use crate::query_call_consume;
|
||||||
use crate::CallDB;
|
use crate::CallDB;
|
||||||
|
|
||||||
@ -37,13 +36,4 @@ where
|
|||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub async fn store_db(self, db: &mut DB) -> DbResult<Self> {
|
|
||||||
let db = db.get_database().await;
|
|
||||||
let ci = db.collection::<Self>("applications");
|
|
||||||
|
|
||||||
ci.insert_one(&self).await?;
|
|
||||||
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ use bson::doc;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::DbResult;
|
use super::DbResult;
|
||||||
use super::DB;
|
|
||||||
use crate::query_call_consume;
|
use crate::query_call_consume;
|
||||||
use crate::CallDB;
|
use crate::CallDB;
|
||||||
|
|
||||||
@ -43,15 +42,6 @@ impl MessageForward {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub async fn store_db(self, db: &mut DB) -> DbResult<Self> {
|
|
||||||
let db = db.get_database().await;
|
|
||||||
let ci = db.collection::<Self>("message_forward");
|
|
||||||
|
|
||||||
ci.insert_one(&self).await?;
|
|
||||||
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get<D: CallDB>(
|
pub async fn get<D: CallDB>(
|
||||||
db: &mut D,
|
db: &mut D,
|
||||||
chat_id: i64,
|
chat_id: i64,
|
||||||
|
|||||||
@ -23,8 +23,6 @@ use crate::{BotDialogue, BotError, BotResult, CallbackStore, State};
|
|||||||
|
|
||||||
pub fn admin_handler() -> BotHandler {
|
pub fn admin_handler() -> BotHandler {
|
||||||
dptree::entry()
|
dptree::entry()
|
||||||
// keep on top to cancel any action
|
|
||||||
.branch(cancel_handler())
|
|
||||||
.branch(
|
.branch(
|
||||||
Update::filter_callback_query()
|
Update::filter_callback_query()
|
||||||
.filter_async(async |q: CallbackQuery, mut db: DB| {
|
.filter_async(async |q: CallbackQuery, mut db: DB| {
|
||||||
@ -199,17 +197,6 @@ async fn button_edit_callback(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_handler() -> BotHandler {
|
|
||||||
Update::filter_message()
|
|
||||||
.filter(|msg: Message| msg.text() == Some("/cancel"))
|
|
||||||
.enter_dialogue::<Message, MongodbStorage<Json>, State>()
|
|
||||||
.endpoint(async |bot: Bot, msg: Message, dialogue: BotDialogue| {
|
|
||||||
dialogue.exit().await?;
|
|
||||||
bot.send_message(msg.chat.id, "Диалог закончен!").await?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command_handler() -> BotHandler {
|
fn command_handler() -> BotHandler {
|
||||||
Update::filter_message()
|
Update::filter_message()
|
||||||
.filter_async(async |msg: Message, mut db: DB| {
|
.filter_async(async |msg: Message, mut db: DB| {
|
||||||
@ -313,10 +300,6 @@ async fn support_reply_handler(
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let text = format!(
|
|
||||||
"Сообщение от поддержки:\n{}\nЧтобы закончить диалог, нажмите на /cancel",
|
|
||||||
text
|
|
||||||
);
|
|
||||||
let msg = bot
|
let msg = bot
|
||||||
.send_message(ChatId(mf.source_chat_id), text)
|
.send_message(ChatId(mf.source_chat_id), text)
|
||||||
.parse_mode(ParseMode::Html);
|
.parse_mode(ParseMode::Html);
|
||||||
|
|||||||
@ -10,7 +10,6 @@ pub mod mongodb_storage;
|
|||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
use bot_manager::BotManager;
|
use bot_manager::BotManager;
|
||||||
use botscript::application::attach_user_application;
|
|
||||||
use botscript::{BotMessage, Runner, RunnerConfig, ScriptError, ScriptResult};
|
use botscript::{BotMessage, Runner, RunnerConfig, ScriptError, ScriptResult};
|
||||||
use db::application::Application;
|
use db::application::Application;
|
||||||
use db::bots::BotInstance;
|
use db::bots::BotInstance;
|
||||||
@ -132,8 +131,7 @@ impl BotController {
|
|||||||
pub async fn with_db(mut db: DB, token: &str, script: &str) -> ScriptResult<Self> {
|
pub async fn with_db(mut db: DB, token: &str, script: &str) -> ScriptResult<Self> {
|
||||||
let bot = Bot::new(token);
|
let bot = Bot::new(token);
|
||||||
|
|
||||||
let mut runner = Runner::init_with_db(&mut db)?;
|
let runner = Runner::init_with_db(&mut db)?;
|
||||||
runner.call_attacher(|c, o| attach_user_application(c, o, &db, &bot))??;
|
|
||||||
let rc = runner.init_config(script)?;
|
let rc = runner.init_config(script)?;
|
||||||
let rc = Arc::new(RwLock::new(rc));
|
let rc = Arc::new(RwLock::new(rc));
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user