forked from nolan/titlebot-ng-ng
Add context to commands
Added some additional basic commands
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
use std::env;
|
||||
|
||||
use libmagbot::config::MagbotConfig;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let (Some(homeserver_url), Some(username), Some(password)) =
|
||||
(env::args().nth(1), env::args().nth(2), env::args().nth(3))
|
||||
else {
|
||||
eprintln!(
|
||||
"Usage: {} <homeserver_url> <username> <password>",
|
||||
env::args().next().unwrap()
|
||||
);
|
||||
let config = MagbotConfig::from_env()?;
|
||||
let Ok(homeserver_fqdn) = env::var("HOMESERVER_URL") else {
|
||||
eprintln!("Set the homeserver fqdn as the `HOMESERVER_URL` environment variable");
|
||||
std::process::exit(1)
|
||||
};
|
||||
|
||||
libmagbot::login_and_sync(homeserver_url, username, password).await?;
|
||||
libmagbot::login_and_sync(homeserver_fqdn, config.username, config.password).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,14 +1,53 @@
|
||||
use matrix_sdk::{
|
||||
Room,
|
||||
event_handler::Ctx,
|
||||
ruma::events::room::message::{OriginalSyncRoomMessageEvent, RoomMessageEventContent},
|
||||
};
|
||||
|
||||
use crate::MagbotContext;
|
||||
|
||||
/// Sets up the bot to listen for title suggestions
|
||||
pub async fn start(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// set to listening
|
||||
// send message that magbot is listening
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Stops the bot from listening for title suggestions
|
||||
pub async fn stop(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// clear out saved titles
|
||||
// set state to sleeping
|
||||
// send message that magbot is no longer listening
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Shows available commands
|
||||
pub async fn help(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// send message with available commands
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Records title suggestions
|
||||
pub async fn suggest(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
text: &str,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// save the title into memory with author
|
||||
// react to the original message to show it was saved
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -17,12 +56,21 @@ pub async fn get_titles(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
text: &str,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// sends all the titles with an initial reaction to be used for voting
|
||||
// save the message ids into context for count_votes()?
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Counts the votes of title suggestions
|
||||
pub async fn count_votes(event: &OriginalSyncRoomMessageEvent, room: &Room) -> anyhow::Result<()> {
|
||||
pub async fn count_votes(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// count the reactions of the title messages
|
||||
// send message with winning title
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -31,6 +79,7 @@ pub async fn not_implemented(
|
||||
event: &OriginalSyncRoomMessageEvent,
|
||||
room: &Room,
|
||||
text: &str,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
// get '!' to the next '<space>' char and output as a command
|
||||
let content = RoomMessageEventContent::text_plain("The command `{cmd}` is not implemented");
|
||||
|
||||
@@ -4,7 +4,7 @@ use serde::Deserialize;
|
||||
|
||||
/// The status of the bot
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
enum MagbotStatus {
|
||||
pub enum MagbotStatus {
|
||||
/// Bot is waiting for title suggestions
|
||||
Running,
|
||||
|
||||
@@ -19,10 +19,10 @@ impl Default for MagbotStatus {
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct MagbotConfig {
|
||||
username: String,
|
||||
password: String,
|
||||
room_id: String,
|
||||
status: MagbotStatus,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
pub room_id: String,
|
||||
pub status: MagbotStatus,
|
||||
}
|
||||
impl MagbotConfig {
|
||||
pub fn from_env() -> anyhow::Result<Self> {
|
||||
|
||||
+59
-9
@@ -1,13 +1,41 @@
|
||||
use matrix_sdk::{
|
||||
Client, Room, RoomState,
|
||||
config::SyncSettings,
|
||||
event_handler::Ctx,
|
||||
ruma::events::room::message::{MessageType, OriginalSyncRoomMessageEvent},
|
||||
};
|
||||
|
||||
mod commands;
|
||||
mod config;
|
||||
use crate::config::MagbotStatus;
|
||||
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> anyhow::Result<()> {
|
||||
mod commands;
|
||||
pub mod config;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct MagbotContext {
|
||||
pub(crate) status: MagbotStatus,
|
||||
pub(crate) titles: Vec<TitleSuggestion>,
|
||||
}
|
||||
impl Default for MagbotContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
status: MagbotStatus::Sleeping,
|
||||
titles: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A title suggestion
|
||||
#[derive(Clone, Debug)]
|
||||
struct TitleSuggestion {
|
||||
pub(crate) user: String,
|
||||
pub(crate) title: String,
|
||||
}
|
||||
|
||||
async fn on_room_message(
|
||||
event: OriginalSyncRoomMessageEvent,
|
||||
room: Room,
|
||||
ctx: Ctx<MagbotContext>,
|
||||
) -> anyhow::Result<()> {
|
||||
if room.state() != RoomState::Joined {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -17,28 +45,44 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
|
||||
};
|
||||
|
||||
match &text_content.body {
|
||||
// start listening for titles
|
||||
s if s.to_lowercase().starts_with("!showstart") => {
|
||||
commands::start(&event, &room, ctx).await?;
|
||||
}
|
||||
|
||||
// stop listening for titles
|
||||
s if s.to_lowercase().starts_with("!showstop") => {
|
||||
commands::stop(&event, &room, ctx).await?;
|
||||
}
|
||||
|
||||
// shows available commands
|
||||
s if s.to_lowercase().starts_with("!help") => {
|
||||
commands::help(&event, &room, ctx).await?;
|
||||
}
|
||||
|
||||
// submit a title suggestion
|
||||
s if s.to_lowercase().starts_with("!suggest") => {
|
||||
commands::suggest(&event, &room, s).await?;
|
||||
commands::suggest(&event, &room, s, ctx).await?;
|
||||
}
|
||||
|
||||
// retrieve list of titles
|
||||
s if s.to_lowercase().starts_with("!gettitles") => {
|
||||
commands::get_titles(&event, &room, s).await?;
|
||||
commands::get_titles(&event, &room, s, ctx).await?;
|
||||
}
|
||||
|
||||
// count upvotes on posted suggestions
|
||||
s if s.to_lowercase().starts_with("!countvotes") => {
|
||||
commands::count_votes(&event, &room).await?;
|
||||
commands::count_votes(&event, &room, ctx).await?;
|
||||
}
|
||||
|
||||
// generate chaotic text using Ollama
|
||||
s if s.to_lowercase().starts_with("!mayhem") => {
|
||||
commands::not_implemented(&event, &room, s).await?;
|
||||
commands::not_implemented(&event, &room, s, ctx).await?;
|
||||
}
|
||||
|
||||
// output the voting URL where users can cast votes
|
||||
s if s.to_lowercase().starts_with("!voteurl") => {
|
||||
commands::not_implemented(&event, &room, s).await?;
|
||||
commands::not_implemented(&event, &room, s, ctx).await?;
|
||||
}
|
||||
|
||||
// message is not a command; ie just a regular message
|
||||
@@ -54,6 +98,8 @@ pub async fn login_and_sync(
|
||||
username: String,
|
||||
password: String,
|
||||
) -> anyhow::Result<()> {
|
||||
let context = MagbotContext::default();
|
||||
|
||||
// Note that when encryption is enabled, you should use a persistent store to be
|
||||
// able to restore the session with a working encryption setup.
|
||||
// See the `persist_session` example.
|
||||
@@ -65,7 +111,7 @@ pub async fn login_and_sync(
|
||||
client
|
||||
.matrix_auth()
|
||||
.login_username(&username, &password)
|
||||
.initial_device_display_name("command bot")
|
||||
.initial_device_display_name("magbot-rs")
|
||||
.await?;
|
||||
|
||||
println!("logged in as {username}");
|
||||
@@ -73,6 +119,10 @@ pub async fn login_and_sync(
|
||||
// An initial sync to set up state and so our bot doesn't respond to old
|
||||
// messages.
|
||||
let response = client.sync_once(SyncSettings::default()).await.unwrap();
|
||||
|
||||
// adding context for state and title suggestions
|
||||
client.add_event_handler_context(context);
|
||||
|
||||
// add our CommandBot to be notified of incoming messages, we do this after the
|
||||
// initial sync to avoid responding to messages before the bot was running.
|
||||
client.add_event_handler(on_room_message);
|
||||
|
||||
Reference in New Issue
Block a user