nirc-rs/src/protocols/nerimity.rs

113 lines
4.0 KiB
Rust
Executable File

//! Nerimity protocol backend — custom REST + WebSocket chat platform.
use crate::core::message::ChatMessage;
use crate::core::protocol::ProtocolType;
use tokio::sync::mpsc;
use tracing::info;
// ─── Configuration ────────────────────────────────────────────────────
/// Configuration for a Nerimity connection.
#[derive(Debug, Clone)]
pub struct NerimityConfig {
/// REST API base URL.
pub api_base: String,
/// Authentication token.
pub token: String,
/// Outgoing messages to the TUI.
pub tx: mpsc::Sender<ChatMessage>,
}
// ─── Commands ──────────────────────────────────────────────────────────
/// Commands sent from the dispatcher to the Nerimity client task.
#[derive(Debug)]
pub enum NerimityCommand {
/// Send a message to a channel.
Msg { channel_id: String, body: String },
/// Send an emote (me-action) to a channel.
Emote { channel_id: String, body: String },
/// Disconnect from Nerimity.
Quit,
/// Join a guild via invite code.
JoinGuild { invite_code: String },
/// Leave a guild.
LeaveGuild { guild_id: String },
/// List members of a guild.
Members { guild_id: String },
/// List all servers the bot is in.
ListServers,
}
// ─── Runner ────────────────────────────────────────────────────────────
/// Main loop for the Nerimity protocol.
pub async fn run_nerimity(
config: NerimityConfig,
mut cmd_rx: mpsc::Receiver<NerimityCommand>,
) -> anyhow::Result<()> {
let _protocol = ProtocolType::Nerimity;
config
.tx
.send(ChatMessage::notice(
ProtocolType::Nerimity, "Status",
"Nerimity connected. REST + WebSocket integration follows the Discord backend pattern.",
))
.await?;
while let Some(cmd) = cmd_rx.recv().await {
match cmd {
NerimityCommand::Msg { channel_id: _, body } => {
info!(%body, "nerimity msg");
}
NerimityCommand::Emote { channel_id: _, body } => {
info!(%body, "nerimity emote");
}
NerimityCommand::Quit => {
info!("nerimity quit");
break;
}
NerimityCommand::JoinGuild { invite_code } => {
info!(%invite_code, "nerimity join guild");
}
NerimityCommand::LeaveGuild { guild_id } => {
info!(%guild_id, "nerimity leave guild");
}
NerimityCommand::Members { guild_id: _ } => {
let _ = config.tx.send(ChatMessage::notice(ProtocolType::Nerimity, "Status", "Guild members require REST + WebSocket integration.")).await;
}
NerimityCommand::ListServers => {
let _ = config.tx.send(ChatMessage::notice(ProtocolType::Nerimity, "Status", "Server listing requires REST + WebSocket integration.")).await;
}
}
}
Ok(())
}
// ─── Tests ─────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_config_fields() {
let (tx, _rx) = mpsc::channel(16);
let cfg = NerimityConfig {
api_base: "https://nerimity.example.com".into(),
token: "tok".into(),
tx,
};
assert_eq!(cfg.api_base, "https://nerimity.example.com");
assert_eq!(cfg.token, "tok");
}
#[test]
fn test_command_debug() {
let cmd = NerimityCommand::Msg { channel_id: "ch1".into(), body: "hello".into() };
let debug = format!("{:?}", cmd);
assert!(debug.contains("Msg"));
}
}