twitchchat 0.6.8

interface to the irc-side of twitch's chat system
Documentation

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 want serde support, then include features = ["serde_derive"] in your Cargo.toml

a demo of it:

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);
    }
}