feat: add IRC channel support
Add comprehensive IRC over TLS channel implementation with: - TLS support with optional certificate verification - SASL PLAIN authentication (IRCv3) - NickServ IDENTIFY authentication - Server password support (for bouncers like ZNC) - Channel and private message (DM) support - Message splitting for IRC 512-byte line limit - UTF-8 safe splitting at character boundaries - Case-insensitive nickname allowlist - IRC style prefix for LLM responses (plain text only) - Configurable via TOML or onboard wizard All 959 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ef00cc9a66
commit
b208cc940e
4 changed files with 1226 additions and 2 deletions
1002
src/channels/irc.rs
Normal file
1002
src/channels/irc.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,7 @@ pub mod cli;
|
|||
pub mod discord;
|
||||
pub mod email_channel;
|
||||
pub mod imessage;
|
||||
pub mod irc;
|
||||
pub mod matrix;
|
||||
pub mod slack;
|
||||
pub mod telegram;
|
||||
|
|
@ -11,6 +12,7 @@ pub mod whatsapp;
|
|||
pub use cli::CliChannel;
|
||||
pub use discord::DiscordChannel;
|
||||
pub use imessage::IMessageChannel;
|
||||
pub use irc::IrcChannel;
|
||||
pub use matrix::MatrixChannel;
|
||||
pub use slack::SlackChannel;
|
||||
pub use telegram::TelegramChannel;
|
||||
|
|
@ -241,6 +243,7 @@ pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Resul
|
|||
("iMessage", config.channels_config.imessage.is_some()),
|
||||
("Matrix", config.channels_config.matrix.is_some()),
|
||||
("WhatsApp", config.channels_config.whatsapp.is_some()),
|
||||
("IRC", config.channels_config.irc.is_some()),
|
||||
] {
|
||||
println!(" {} {name}", if configured { "✅" } else { "❌" });
|
||||
}
|
||||
|
|
@ -347,6 +350,24 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(ref irc) = config.channels_config.irc {
|
||||
channels.push((
|
||||
"IRC",
|
||||
Arc::new(IrcChannel::new(
|
||||
irc.server.clone(),
|
||||
irc.port,
|
||||
irc.nickname.clone(),
|
||||
irc.username.clone(),
|
||||
irc.channels.clone(),
|
||||
irc.allowed_users.clone(),
|
||||
irc.server_password.clone(),
|
||||
irc.nickserv_password.clone(),
|
||||
irc.sasl_password.clone(),
|
||||
irc.verify_tls.unwrap_or(true),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No real-time channels configured. Run `zeroclaw onboard` first.");
|
||||
return Ok(());
|
||||
|
|
@ -514,6 +535,21 @@ pub async fn start_channels(config: Config) -> Result<()> {
|
|||
)));
|
||||
}
|
||||
|
||||
if let Some(ref irc) = config.channels_config.irc {
|
||||
channels.push(Arc::new(IrcChannel::new(
|
||||
irc.server.clone(),
|
||||
irc.port,
|
||||
irc.nickname.clone(),
|
||||
irc.username.clone(),
|
||||
irc.channels.clone(),
|
||||
irc.allowed_users.clone(),
|
||||
irc.server_password.clone(),
|
||||
irc.nickserv_password.clone(),
|
||||
irc.sasl_password.clone(),
|
||||
irc.verify_tls.unwrap_or(true),
|
||||
)));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No channels configured. Run `zeroclaw onboard` to set up channels.");
|
||||
return Ok(());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue