use anyhow::Result;
use clap::Parser;
use tokio::select;
use tokio::signal::ctrl_c;
#[derive(Parser)]
#[command(author, version)]
struct Args {
#[arg(long)]
login: Option<String>,
#[arg(long)]
token: Option<String>,
#[arg(long)]
channel: Vec<String>,
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let args = Args::parse();
let credentials = match args.login.zip(args.token) {
Some((login, token)) => tmi::client::Credentials::new(login, token),
None => tmi::client::Credentials::anon(),
};
let channels = args.channel;
println!("Connecting as {}", credentials.login());
let mut client = tmi::Client::builder()
.credentials(credentials)
.connect()
.await?;
client.join_all(&channels).await?;
println!("Joined the following channels: {}", channels.join(", "));
select! {
_ = ctrl_c() => {
Ok(())
}
res = tokio::spawn(run(client, channels)) => {
res?
}
}
}
async fn run(mut client: tmi::Client, channels: Vec<String>) -> Result<()> {
loop {
let msg = client.recv().await?;
match msg.as_typed()? {
tmi::Message::Privmsg(msg) => on_msg(&mut client, msg).await?,
tmi::Message::Reconnect => {
client.reconnect().await?;
client.join_all(&channels).await?;
}
tmi::Message::Ping(ping) => client.pong(&ping).await?,
_ => {}
};
}
}
async fn on_msg(client: &mut tmi::Client, msg: tmi::Privmsg<'_>) -> Result<()> {
println!("{}: {}", msg.sender().name(), msg.text());
if client.credentials().is_anon() {
return Ok(());
}
if !msg.text().starts_with("!yo") {
return Ok(());
}
client
.privmsg(msg.channel(), "yo")
.reply_to(msg.id())
.send()
.await?;
println!("< {} yo", msg.channel());
Ok(())
}