forcebot_core | ||
moderator_reactor | ||
new_empty_bot | ||
simple_command_bot | ||
simple_debug_listener | ||
simple_module_example | ||
.gitignore | ||
Cargo.lock | ||
Cargo.toml | ||
readme.md |
Customizable Twitch chat bot written in rust
Quick Start
Run a Simple bot with Built in functionality
-
Generate a twitch access token
- Get a Bot Chat Token here - https://twitchtokengenerator.com
- More Info - https://dev.twitch.tv/docs/authentication
-
Define an
.env
file with the following
login_name=BOTNAME
access_token=ACCESS_TOKEN
bot_channels=BOTNAME
prefix=`
bot_admins=ADMIN
- Build & run
cargo run -p forcebot_core
Features
Built In Chat Commands
-
quiet on
/quiet off
- Moderators & Broadcasters can quiet the bot -
enable $module$
/disable $module$
- Moderators & Broadcasters can enable or disableModules
of bot functionality through chatCommands
Custom Modules can be coded to load additional functionality
Developers an create Modules that add more bot functionality
The main forcebot_core
Binary crate includes the following Custom Modules
debug
- outputs to console messages from the channel where it was enabled. Toggle debug with the Commandsdebug on
ordebug off
guest_badge
- Temporary badges can be issued to chattersbesty
- Tomfoolerypyramid
- for detecting & handling pyramids
forcebot_core
Bot Library
forcebot_core
library API provides Custom package developers a way to add functionality by addingModules
that contain Bot Objects likeCommands
andListeners
Listeners
andCommands
listen for a defined callback trigger condition and run an defined execution callbackCommands
are similar toListeners
with refined trigger conditions including using botprefix
with theCommand
, triggers based onBadge
, and more- Workspace for package developers to independently code their own
Modules
Workspaces
Workspace comes with binary crates with working or example bots that use forcebot_core
library
moderator_reactor
- bot kneels to all moderator messagessimple_module_example
- bot has atest
Module
with atest
Command
. Moderators & Broadcasters can manage theModule
in chat withenable
/disable
Commands
new_empty_bot
- while empty, hasdisable
andenable
chatCommands
. This is an example of the bot without any loaded modulessimple_command_bot
- bot responds to atest
Command
. As the command was not loaded through aModule
,disable
&enable
commands don't work on thetest
command. This could be a GlobalCommand
simple_debug_listener
- bot outputs all twitchServerMessages
received to terminal
Example Bots
Use the following to build and run built-in bots. No coding required!
New Empty Bot
Run an empty simple bot that logs into chat and has minimum built in functions
cargo run -p new_empty_bot
Full Featured Forcebot
Run a forcebot with fun catered customizations
cargo run -p forcebot_core
Simple Debug Listener
Run a bot that listens to all messages and output to console
cargo run -p 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 -p 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 -p 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 -p simple_module_example
Workspace packages
Source is a workspace of packages . In particular, forcebot_core
is the main library crate to use
TIP : if you want to start customizing you own bot, create a binary package in the workspace for your bot's binary crate
More info about workspaces - https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html
Creating a new package
To create a new package
- Create a new package
For example, to create a new binary crate in the workspace
cargo new my_new_bot
- In the newly created directory for your package, adjust the
Cargo.toml
to the following
[dependencies]
forcebot_core = {path = "../forcebot_core"}
dotenv = "0.15.0"
lazy_static = "1.5.0"
tokio = { version = "1.33.0", features = ["full"] }
twitch-irc = "5.0.1"
-
Copy
main.rs
from thenew_empty_bot
package into your package -
Optionally, customize your
main()
to load modules before starting the bot -
Build and run your package
cargo run -p my_new_bot
Example Code
New Bot
Uses Env defined variables to create and run the bot
use forcebot_core::Bot;
#[tokio::main]
pub async fn main() {
/* 1. Create the bot using env */
let bot = Bot::new().await;
/* 2. Run the bot */
bot.run().await;
}
Customize by Loading Custom Modules
A Module
is a group of bot objects (eg Command
) that elevated users can manage through built in disable
and enable
commands
Custom Modules
can be loaded into a new bot with minimum coding : just load the modules and run the bot
use forcebot_core::{custom_mods::{debug, guest_badge, pyramid}, Bot};
#[tokio::main]
pub async fn main() {
/* Create the bot using env */
let bot = Bot::new().await;
/* 1. Load the module into the bot */
bot.load_module(funbot_objs::create_module()).await;
/* 2. Load Custom Modules */
bot.load_module(guest_badge::create_module()).await;
bot.load_module(pyramid::create_module()).await;
bot.load_module(debug::create_module()).await;
/* 3. Run the bot */
bot.run().await;
}
Create your own Custom Modules
Create a custom Module
by :
-
Defining Functions that create the Custom Bot Objects (eg
Command
) -
Define a function that creates a
Module
with the Custom Bot Objects loaded
use forcebot_core::Bot;
#[tokio::main]
pub async fn main() {
/* Create the bot using env */
let bot = Bot::new().await;
/* load the Module */
bot.load_module(custom_mod::new()).await;
/* Run the bot */
bot.run().await;
}
pub mod custom_mod {
use std::sync::Arc;
use forcebot_core::{execution_async, Badge, Bot, Command, Module};
use twitch_irc::message::ServerMessage;
/// Module definition with a loaded command
pub fn new() -> Module {
/* 1. Create a new module */
let mut custom_mod = Module::new(
vec!["test".to_string()],
"".to_string());
/* 2. Load the cmd into a new module */
custom_mod.load_command(cmd_test());
custom_mod
}
/// Command definition
pub fn cmd_test() -> Command {
/* 1. Create a new cmd */
let mut cmd = Command::new(vec!["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.chat.lock().await.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(execution_async(execbody));
cmd.set_admin_only(false);
cmd.set_min_badge(Badge::Vip);
cmd
}
}
Simple Debug Listener
Bot with a simple listener that listens for all messages and prints in output
use std::sync::Arc;
use forcebot_core::{execution_async, Bot, Listener};
use twitch_irc::message::ServerMessage;
#[tokio::main]
pub async fn main() {
/* 1. Create the bot using env */
let bot = Bot::new().await;
/* 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); /* outputs message to debug */
Result::Ok("Success".to_string())
}
/* 2d. Set and Store the execution body using `execution_async()` */
listener.set_exec_fn(execution_async(execbody));
/* 3. Load the listener into the bot */
bot.load_listener(listener).await;
/* 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_core::Bot;
use forcebot_core::execution_async;
use forcebot_core::Listener;
use twitch_irc::message::ServerMessage;
#[tokio::main]
pub async fn main() {
/* Create the bot using env */
let bot = Bot::new().await;
/* 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.chat.lock().await.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 `execution_async()` */
listener.set_exec_fn(execution_async(execbody));
/* 5. Load the listener into the bot */
bot.load_listener(listener).await;
/* Run the bot */
bot.run().await;
}
Simple Test Command
use std::sync::Arc;
use forcebot_core::Badge;
use forcebot_core::Bot;
use forcebot_core::execution_async;
use forcebot_core::Command;
use twitch_irc::message::ServerMessage;
#[tokio::main]
pub async fn main() {
/* Create the bot using env */
let bot = Bot::new().await;
/* 1. Create a new blank cmd */
let mut cmd = Command::new(vec!["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.chat.lock().await.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 `execution_async()` */
cmd.set_exec_fn(execution_async(execbody));
/* 4. optionally, remove admin only default flag */
cmd.set_admin_only(false);
/* 5. optionally, set min badge*/
cmd.set_min_badge(Badge::Moderator);
/* 6. Load the cmd into the bot */
bot.load_command(cmd).await;
/* Run the bot */
bot.run().await;
}
Crate Rust API Documentation
Create forcebot_rs_v2
Rust Crate documentation
Documentation - Clean Build & Open in Default Browser
cargo clean && cargo doc --open