Customizable Rust Twitch Bot
Find a file
2025-01-30 13:10:02 -03:00
src magic module test 2025-01-30 13:08:33 -03:00
.gitignore gitignore 2025-01-30 13:10:02 -03:00
Cargo.lock init 2025-01-25 11:45:10 -05:00
Cargo.toml listener obj 2025-01-27 13:07:33 -05:00
readme.md Badges & Doc adj 2025-01-29 07:52:41 -05:00

Twitch chat bot written in rust

Quick Start

Run a Simple bot with Built in functionality

  1. Generate a twitch access token

  2. Define an .env file with the following

login_name=BOTNAME
access_token=ACCESS_TOKEN
bot_channels=BOTNAME
prefix=`
bot_admins=ADMIN
  1. Build & run
cargo run

Example Bots

Use the following commands to build and run built-in bots. No coding required!

New Bot

Run an empty simple bot that logs into chat and has minimum built in functions

cargo run --bin new_bot

WIP Customized Fun Bot

Run a forcebot with fun catered customizations

ongoing work in progress

cargo run --bin fun_bot

Simple Debug Listener

Run a bot that listens to all messages and output to console

cargo run --bin simple_debug_listener

Simple Command Bot

Run a bot that uses the test chat Command . Commands are prefixed and must be ran by a chatter with a vip badge or above

cargo run --bin simple_command_bot

Moderator Reactor

Run a bot that listens for messages with the moderator badge, and replies to that mod with an emote

cargo run --bin moderator_reactor

Module loaded Bot

Run a bot that has a test chat Command. As the command was loaded through a module, moderators or broadcastors can enable or disable the module through chat commands

cargo run --bin simple_module

Example Code

New Bot

Uses Env defined variables to create and run the bot

use forcebot_rs_v2::Bot;

#[tokio::main]
pub async fn main() {

    /* 1. Create the bot using env */
    let bot = Bot::new();

    /* 2. Run the bot */
    bot.run().await;

}

Customize with Modules

A Module is a group of bot objects (eg Command) that elevated users can manage through built in disable and enable commands

Create a custom Module by :

  1. Defining Functions that create the Custom Bot Objects (eg Command)

  2. Define a function that creates a Module with the Custom Bot Objects loaded

use forcebot_rs_v2::Bot;

#[tokio::main]
pub async fn main() {

    /* Create the bot using env */
    let mut bot = Bot::new();

    /* load the Module */
    bot.load_module(custom_mod::new());

    /* Run the bot */
    bot.run().await;

}


pub mod custom_mod {
    use std::sync::Arc;

    use forcebot_rs_v2::{asyncfn_box, Badge, Bot, Command, Module};
    use twitch_irc::message::ServerMessage;


    /// Module with a loaded command
    pub fn new() -> Module {
        /* 1. Create a new module */
        let mut custom_mod = Module::new("test".to_string(), "".to_string());

        /* 2. Load the cmd into a new module */
        custom_mod.load_command(cmd_test());

        custom_mod

    }

    pub fn cmd_test() -> Command {
        /* 1. Create a new cmd */
        let mut cmd = Command::new("test".to_string(),"".to_string());

        /* 2. Define exec callback  */
        async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
            if let ServerMessage::Privmsg(msg) = message {
                let _= bot.client.say_in_reply_to(
                    &msg, "test return".to_string()).await;
            }
            Result::Err("Not Valid message type".to_string()) 
        }

        /* 3. Set Command flags */
        cmd.set_exec_fn(asyncfn_box(execbody));
        cmd.set_admin_only(false);
        cmd.set_min_badge(Badge::Moderator);

        cmd
        }
}

Simple Debug Listener

Bot with a simple listener that listens for all messages and prints in output

use std::sync::Arc;

use forcebot_rs_v2::{asyncfn_box, Bot, Listener};
use twitch_irc::message::ServerMessage;

#[tokio::main]
pub async fn main() {

    /* 1. Create the bot using env */
    let mut bot = Bot::new();

    /* 2a. Create a new blank Listener */
    let mut listener = Listener::new();

    /* 2b. Set a trigger condition function for listener */
    listener.set_trigger_cond_fn(
        |_:Arc<Bot>,_:ServerMessage| true
    );

    /* 2c. Define an async fn callback execution */
    async fn execbody(_:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
        dbg!(message);
        Result::Ok("Success".to_string()) 
    }

    /* 2d. Set and Store the execution body using `async_box()`  */
    listener.set_exec_fn(asyncfn_box(execbody));

    /* 3. Load the listener into the bot */
    bot.load_listener(listener);

    /* 4. Run the bot */
    bot.run().await;

}

Moderator Reactor

Example listener listens for a moderator badge and reply in chat

use std::sync::Arc;

use forcebot_rs_v2::Bot;
use forcebot_rs_v2::asyncfn_box;
use forcebot_rs_v2::Listener;
use twitch_irc::message::ServerMessage;


#[tokio::main]
pub async fn main() {

    /* Create the bot using env */
    let mut bot = Bot::new();

    /* 1. Create a new blank Listener */
    let mut listener = Listener::new();

    /* 2. Set a trigger condition function for listener */
    listener.set_trigger_cond_fn(
        |_:Arc<Bot>,message:ServerMessage| 
            if let ServerMessage::Privmsg(msg) = message {
                
                for badge in msg.badges {
                    if matches!(badge, x if x.name == "moderator") {
                        // dbg!("moderator found");
                        return true;
                    }
                } 
                false
            } else { false }
    );

    /* 3. Define an async fn callback execution */
    async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
        if let ServerMessage::Privmsg(msg) = message {
            let _ = bot.client.say_in_reply_to(&msg, "pepeKneel".to_string()).await ;
            return Result::Ok("Success".to_string()) ;
        }
        Result::Err("Not Valid message type".to_string()) 
    }

    /* 4. Set and Store the execution body using `async_box()`  */
    listener.set_exec_fn(asyncfn_box(execbody));

    /* 5. Load the listener into the bot */
    bot.load_listener(listener);

    /* Run the bot */
    bot.run().await;

}


Simple Test Command

use std::sync::Arc;

use forcebot_rs_v2::Bot;
use forcebot_rs_v2::asyncfn_box;
use forcebot_rs_v2::Command;
use twitch_irc::message::ServerMessage;


#[tokio::main]
pub async fn main() {

    /* Create the bot using env */
    let mut bot = Bot::new();

    /* 1. Create a new blank cmd */
    let mut cmd = Command::new("test".to_string(),"".to_string());

    /* 2. Define an async fn callback execution */
    async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
        if let ServerMessage::Privmsg(msg) = message {
            let _ = bot.client.say_in_reply_to(&msg, String::from("test success")).await;
            return Result::Ok("Success".to_string()) ;
        }
        Result::Err("Not Valid message type".to_string()) 
    }

    /* 3. Set and Store the execution body using `async_box()`  */
    cmd.set_exec_fn(asyncfn_box(execbody));

    /* 4. optionally, remove admin only default flag */
    cmd.set_admin_only(false);

    /* 5. optionally, set min badge*/
    cmd.set_min_badge("broadcaster".to_string());
// 
    /* 6. Load the cmd into the bot */
    bot.load_command(cmd);

    /* Run the bot */
    bot.run().await;

}

Crate Rust Documentation

Create Crate documentation

Clean Build Documentation

cargo clean && cargo doc

Open Crate Doc

cargo doc --open