Instead, all instance ids are now usize (like message ids). This allows me to enforce the fact that no two instances of a Bot must have the same id by generating the ids in the Bot. Reusing the same id for multiple instances that send their events to the same place can lead to race conditions depending on how events are handled. For example, the old instance might still be shutting down while the new instance is already connected to a room, leading to an InstanceEvent::Stopped from the old instance that seemingly applies to the new instance.
99 lines
2.3 KiB
Rust
99 lines
2.3 KiB
Rust
use std::time::Duration;
|
|
|
|
use euphoxide::{
|
|
api::{Data, Message, Nick, Send},
|
|
client::conn::ClientConnHandle,
|
|
};
|
|
use euphoxide_bot::{Bot, BotEvent, ServerConfig};
|
|
|
|
async fn set_nick(conn: &ClientConnHandle) -> anyhow::Result<()> {
|
|
conn.send_only(Nick {
|
|
name: "examplebot".to_string(),
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn send_pong(conn: &ClientConnHandle, msg: Message) -> anyhow::Result<()> {
|
|
conn.send_only(Send {
|
|
content: "Pong!".to_string(),
|
|
parent: Some(msg.id),
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn send_pyramid(conn: &ClientConnHandle, msg: Message) -> anyhow::Result<()> {
|
|
let mut parent = msg.id;
|
|
|
|
for _ in 0..3 {
|
|
let first = conn
|
|
.send(Send {
|
|
content: "brick".to_string(),
|
|
parent: Some(parent),
|
|
})
|
|
.await?;
|
|
|
|
conn.send_only(Send {
|
|
content: "brick".to_string(),
|
|
parent: Some(parent),
|
|
})
|
|
.await?;
|
|
|
|
parent = first.await?.0.id;
|
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
}
|
|
|
|
conn.send_only(Send {
|
|
content: "brick".to_string(),
|
|
parent: Some(parent),
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn on_data(conn: ClientConnHandle, data: Data) {
|
|
let result = match data {
|
|
Data::SnapshotEvent(_) => set_nick(&conn).await,
|
|
Data::SendEvent(event) if event.0.content == "!ping" => send_pong(&conn, event.0).await,
|
|
Data::SendEvent(event) if event.0.content == "!pyramid" => {
|
|
send_pyramid(&conn, event.0).await
|
|
}
|
|
_ => Ok(()),
|
|
};
|
|
|
|
if let Err(err) = result {
|
|
println!("Error while responding: {err}");
|
|
}
|
|
}
|
|
|
|
async fn run() -> anyhow::Result<()> {
|
|
let mut bot = Bot::new();
|
|
|
|
let config = ServerConfig::default()
|
|
.instance("test")
|
|
.with_username("examplebot");
|
|
|
|
bot.add_instance(config);
|
|
|
|
while let Some(event) = bot.recv().await {
|
|
if let BotEvent::Packet { conn, packet, .. } = event {
|
|
let data = packet.into_data()?;
|
|
tokio::task::spawn(on_data(conn, data));
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
loop {
|
|
if let Err(err) = run().await {
|
|
println!("Error while running: {err}");
|
|
}
|
|
}
|
|
}
|