use std::error::Error;
use std::sync::Arc;
use rustybook::{
Context,
EventHandler,
Message,
Rustybook,
User,
};
use rustybook_logging::{
Logger,
TracingHookConfig,
};
use tracing::level_filters::LevelFilter;
struct Handler;
impl EventHandler for Handler {
async fn ready(&self, _ctx: Context, user: User) {
logger().verb(format!("ready: id={} name={:?}", user.id, user.name));
}
async fn message(&self, ctx: Context, msg: Message) {
logger().verb(format!(
"message: thread={} sender={} text={:?}",
msg.thread_id, msg.sender_id, msg.text
));
match msg.text.as_deref() {
Some("hi") => {
if let Err(error) = ctx.client().send_text(&msg.thread_id, "hello").await {
logger().warn(format!("failed to auto-reply: {error}"));
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
Some(message) => {
if let Some(user) = ctx.client().user().await
&& msg.sender_id != user.id
&& let Err(error) = ctx.client().send_text(&msg.thread_id, message).await
{
logger().warn(format!("failed to echo: {error}"));
}
}
#[cfg(not(all(feature = "messenger", feature = "cache")))]
Some(_) => {}
None => {}
}
}
async fn typing(&self, _ctx: Context, typing: rustybook::Typing) {
logger().verb(format!(
"typing: user_id={} thread_id={:?} is_typing={}",
typing.user_id, typing.thread_id, typing.is_typing
));
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
init_logging();
let mut args = std::env::args();
let _bin = args.next();
let Some(cookies_path) = args.next() else {
eprintln!("usage: cargo run --example messenger --features messenger -- <cookies.json>");
return Ok(());
};
let client = Rustybook::builder()
.cookies_file_path(cookies_path)
.online(true)
.build()?;
client.start(Arc::new(Handler)).await?;
logger().verb("listening for events (Ctrl+C to stop)");
tokio::signal::ctrl_c().await?;
client.stop().await?;
Ok(())
}
fn init_logging() {
let logger = logger();
if let Err(error) = logger.install_tracing_hook_from_config() {
eprintln!("failed to install tracing hook subscriber: {error}");
}
}
fn logger() -> Logger {
let tracing_config = TracingHookConfig::builder()
.level_filter(LevelFilter::DEBUG)
.filter("rustybook=debug,rustybook_messenger=debug")
.include_level(true)
.include_target(true)
.include_fields(true)
.build();
Logger::builder().tracing_config(tracing_config).build()
}