twitchchat

Crates.io doc.rs Crates.io CircleCI AppVeyor

interface to the irc portion of twitch's chat

you provide implementations of ReadAdapter and WriteAdapter

or, wrap an std::io::Read and std::io::Write with ReadAdapter and WriteAdapter

...and this provides all of the types for Twitch chat message.

see the docs for more info

if you don't want serde support, then include default-features = false in your Cargo.toml

a demo of it: ```rust fn main() { use std::net::TcpStream; use twitchchat::commands::PrivMsg; use twitchchat::{Client, Writer, UserConfig, sync_adapters};

// create a userconfig
let userconfig = UserConfig::builder()
    .nick(env!("MY_TWITCH_NAME"))
    .token(env!("MY_TWITCH_PASS"))
    // enable these capabilities
    .tags()
    .membership()
    .commands()
    // build the config
    .build()
    .expect("semi-valid config");

// connect to twitch
let read = TcpStream::connect(twitchchat::TWITCH_IRC_ADDRESS).expect("connect");
// clone the tcpstream
let write = read.try_clone().expect("must be able to clone");

// create the adapters adapter
let (read, write) = sync_adapters(read, write);

// create a new client from the read, write pairs
let mut client = Client::new(read, write);

// when we receive a PrivMsg run this function
// tok allows us to remove this later, if we want
let _tok = client.on(move |msg: PrivMsg, w: Writer| {
    const KAPPA: usize = 25;
    // print out `user: message`
    println!("{}: {}", msg.display_name().unwrap(), msg.message());

    let kappas = msg
        .emotes()
        .iter()
        // filter Kappas
        .filter(|e| e.id == KAPPA)
        // count how many times it appears
        .map(|d| d.ranges.len())
        .sum::<usize>();

    // if someone sent more than 3 Kappas, send a Kappa back
    if kappas >= 3 {
        // using the provided Writer
        w.send(msg.channel(), "Kappa").unwrap();
    }
});

// log if the broadcaster, a sub or a mod talks
client.on(move |msg: PrivMsg, _: Writer| {
    use twitchchat::BadgeKind::{Broadcaster, Subscriber};

    let name = msg.display_name().unwrap_or_else(|| msg.irc_name());
    let badges = msg
        .badges()
        .iter()
        // filter to just the "BadgeKind"
        .map(|badge| badge.kind.clone())
        .collect::<Vec<_>>();

    match (
        badges.contains(&Broadcaster),
        badges.contains(&Subscriber),
        msg.moderator(), // or badges.contains(&Moderator)
    ) {
        (true, _, _) => println!("{} is the broadcaster", name),
        (_, true, _) => println!("{} is a subscriber", name),
        (_, _, true) => println!("{} is a mod", name),
        (_, _, _) => {
            // just a normal viewer
        }
    };
});

// 'register' (sends out creds.) with the server
client.register(userconfig).expect("register with twitch");

// blocks the thread until the server tells us who we were
match client.wait_for_ready() {
    // and print it out
    Ok(user) => {
        // id: 23196011, name: Some("museun"), color: Some(OrangeRed)
        println!(
            "id: {}, name: {:?}, color: {:?}",
            user.user_id, user.display_name, user.color
        )
    }
    Err(twitchchat::Error::InvalidRegistration) => {
        eprintln!("invalid nick/pass");
        std::process::exit(1);
    }
    Err(err) => panic!(err),
};

// get a clone of the writer, this allows you to write to the connection
let w = client.writer();
// join a channel
w.join("museun").unwrap();

{
    // not needed here, but the writer is clonable
    // you can also get another one from the `client`
    let w = w.clone();
    std::thread::spawn(move || {
        std::thread::sleep(std::time::Duration::from_secs(3));
        w.send("museun", "VoHiYo").unwrap();
    });
}

// block this thread until the connection ends
// this will call the filters when it receives the appropirate message
if let Err(err) = client.run() {
    eprintln!("error while running: {}", err);
    std::process::exit(1);
}

} ```