This commit is contained in:
2025-03-11 18:28:29 +01:00
parent 1e63c31115
commit 736a8c98c7
5 changed files with 1394 additions and 10 deletions

5
.env.example Normal file
View File

@@ -0,0 +1,5 @@
IRC_SERVER=
IRC_PORT=6697
IRC_TLS=true
IRC_NICK=
IRC_PASSWORD=

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/target /target
.env

1293
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,13 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
dotenvy = "0.15.7"
futures = "0.3.31"
irc = { version = "1.0.0", default-features = false, features = ["tls-rust", "tokio-rustls"] }
phf = "0.11.3" phf = "0.11.3"
rustls = "0.23.23"
tokio = { version = "1.44.0", features = ["full"] }
webpki-roots = "0.26.8"
[build-dependencies] [build-dependencies]
phf_codegen = "0.11.3" phf_codegen = "0.11.3"

View File

@@ -1,5 +1,11 @@
use futures::stream::StreamExt;
use std::{io, str::FromStr}; use std::{io, str::FromStr};
use irc::{
client::{Client, data::Config},
proto::Command,
};
type Error = Box<dyn std::error::Error + Send + Sync>; type Error = Box<dyn std::error::Error + Send + Sync>;
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
@@ -112,23 +118,96 @@ impl FromStr for Message {
} }
} }
fn main() -> Result<()> { #[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv().ok();
let irc_server = std::env::var("IRC_SERVER")?;
let irc_port: u16 = std::env::var("IRC_PORT")?.parse()?;
let irc_tls: bool = std::env::var("IRC_TLS")?.parse()?;
let irc_nick = std::env::var("IRC_NICK")?;
let irc_password = std::env::var("IRC_PASSWORD")?;
let mut buffer = String::new(); let mut buffer = String::new();
let stdin = io::stdin(); // We get `Stdin` here. let stdin = io::stdin(); // We get `Stdin` here.
let (tx, mut rx) = tokio::sync::mpsc::channel(12);
let config = Config {
nickname: Some(irc_nick),
server: Some(irc_server),
port: Some(irc_port),
use_tls: Some(irc_tls),
channels: vec!["#p2000".to_owned()],
..Config::default()
};
let mut client = Client::from_config(config).await?;
client.identify()?;
let mut stream = client.stream()?;
tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
client.send(msg)?;
}
Ok::<(), Error>(())
});
let tx_ = tx.clone();
tokio::spawn(async move {
while let Some(message) = stream.next().await.transpose()? {
print!("{}", &message);
if let Command::NOTICE(a, b) = message.command {
if a == "p2000" && b.starts_with("This nickname is registered.") {
tx_.send(Command::NICKSERV(vec![
"identify".into(),
irc_password.clone(),
]))
.await?;
}
}
}
Ok::<(), Error>(())
});
// thread::spawn(move || {
// // irc thread
// let config = rustls::ClientConfig::builder()
// .with_root_certificates(rustls::RootCertStore {
// roots: webpki_roots::TLS_SERVER_ROOTS.into(),
// })
// .with_no_client_auth();
// let mut conn = rustls::ClientConnection::new(Arc::new(config), "irc.avii.nl".try_into()?)?;
// let mut socket = std::net::TcpStream::connect("irc.avii.nl:6697")?;
// let mut tls = rustls::Stream::new(&mut conn, &mut socket);
// tls.write_all(b"CAP LS 302\r\n")?;
// tls.write_all(b"NICK p2000\r\n")?;
// tls.write_all(b"USER p2000 0 * :p2000\r\n")?;
// tls.write_all(b"CAP END\r\n")?;
// tls.write_all(b"JOIN #p2000\r\n")?;
// while let Ok(msg) = rx.recv() {
// dbg!(&msg);
// tls.write_all(format!("PRIVMSG #p2000 :{}\r\n", msg).as_bytes())?;
// }
// Ok::<(), Error>(())
// });
while stdin.read_line(&mut buffer)? > 0 { while stdin.read_line(&mut buffer)? > 0 {
if let Err(e) = process(&buffer) { if let Ok(msg) = Message::from_str(&buffer) {
eprintln!("Error: {:?}", e); for msg in msg.to_string().lines() {
println!("{}", msg);
let _ = tx
.send(Command::PRIVMSG("#p2000".to_string(), msg.to_string()))
.await;
}
} }
buffer.clear(); buffer.clear();
} }
Ok(()) Ok(())
} }
fn process(s: &str) -> Result<Message> {
let message = Message::from_str(s)?;
println!("{}", &message);
Ok(message)
}