reorg workspaces
This commit is contained in:
parent
2a6b512ce1
commit
46cff68bc1
27 changed files with 519 additions and 180 deletions
Cargo.lockCargo.toml
forcebot_core
Cargo.toml
src
moderator_reactor
new_empty_bot
readme.mdsimple_command_bot
simple_debug_listener
simple_module_example
120
Cargo.lock
generated
120
Cargo.lock
generated
|
@ -19,9 +19,9 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.85"
|
||||
version = "0.1.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
|
||||
checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -63,9 +63,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.10"
|
||||
version = "1.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
|
||||
checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
@ -142,7 +142,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "forcebot-rs-v2"
|
||||
name = "forcebot_core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
|
@ -200,13 +200,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.13.3+wasi-0.2.2",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -271,15 +272,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moderator_reactor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"forcebot_core",
|
||||
"lazy_static",
|
||||
"tokio",
|
||||
"twitch-irc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
|
||||
checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
|
@ -292,6 +304,17 @@ dependencies = [
|
|||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_empty_bot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"forcebot_core",
|
||||
"lazy_static",
|
||||
"tokio",
|
||||
"twitch-irc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
|
@ -318,9 +341,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
|||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.68"
|
||||
version = "0.10.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
|
||||
checksum = "f5e534d133a060a3c19daec1eb3e98ec6f4685978834f2dbadfe2ec215bab64e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
|
@ -344,9 +367,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
|
@ -436,9 +459,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.43"
|
||||
version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
|
@ -500,6 +523,39 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_command_bot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"forcebot_core",
|
||||
"lazy_static",
|
||||
"tokio",
|
||||
"twitch-irc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_debug_listener"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"forcebot_core",
|
||||
"lazy_static",
|
||||
"tokio",
|
||||
"twitch-irc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_module_example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"forcebot_core",
|
||||
"lazy_static",
|
||||
"tokio",
|
||||
"twitch-irc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -527,9 +583,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
version = "2.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -538,9 +594,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.15.0"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
|
||||
checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
|
@ -687,9 +743,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
|
@ -703,6 +759,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.13.3+wasi-0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
@ -784,3 +849,12 @@ name = "windows_x86_64_msvc"
|
|||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
|
31
Cargo.toml
31
Cargo.toml
|
@ -1,24 +1,7 @@
|
|||
[package]
|
||||
name = "forcebot-rs-v2"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
default-run = "forcebot-rs-v2"
|
||||
|
||||
[dependencies]
|
||||
dotenv = "0.15.0"
|
||||
lazy_static = "1.5.0"
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
twitch-irc = "5.0.1"
|
||||
|
||||
|
||||
# [[bin]]
|
||||
# name = "simple_bot"
|
||||
# path = "src/simple_bot.rs"
|
||||
|
||||
# [[bin]]
|
||||
# name = "simple_bot_listener"
|
||||
# path = "src/simple_bot_listener.rs"
|
||||
|
||||
# [lib]
|
||||
# name = "botlib"
|
||||
# path = "src/lib.rs"
|
||||
[workspace]
|
||||
members = [
|
||||
"forcebot_core",
|
||||
"simple_module_example",
|
||||
"new_empty_bot",
|
||||
"simple_debug_listener",
|
||||
"moderator_reactor", "simple_command_bot"]
|
||||
|
|
11
forcebot_core/Cargo.toml
Normal file
11
forcebot_core/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "forcebot_core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
default-run = "fun_bot"
|
||||
|
||||
[dependencies]
|
||||
dotenv = "0.15.0"
|
||||
lazy_static = "1.5.0"
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
twitch-irc = "5.0.1"
|
|
@ -1,9 +1,9 @@
|
|||
//! WIP Fun forcebot with catered customizations #todo
|
||||
//!
|
||||
//! Custom modules that can be managed in chat through `disable` and `enable` commands
|
||||
//! - funbot
|
||||
//! - guests
|
||||
//! - pyramid
|
||||
//! - `besty`
|
||||
//! - `guests`
|
||||
//! - `pyramid`
|
||||
//!
|
||||
//!
|
||||
//! Be sure the followig is defined in `.env`
|
||||
|
@ -17,7 +17,10 @@
|
|||
//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
|
||||
//! - More Info - <https://dev.twitch.tv/docs/authentication>
|
||||
|
||||
use forcebot_rs_v2::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
// use forcebot_rs_v2::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
use forcebot_core::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
|
@ -41,16 +44,17 @@ pub async fn main() {
|
|||
pub mod funbot_objs {
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::{execution_async, Badge, Bot, Command, Module};
|
||||
use forcebot_core::{execution_async, modules::Status, Badge, Bot, Command, Module};
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
/// Create a Module with a loaded Command object
|
||||
pub fn create_module() -> Module {
|
||||
let mut custom_mod = Module::new(
|
||||
vec!["funbot".to_string()],
|
||||
"".to_string());
|
||||
vec!["besty".to_string()],
|
||||
"Now Aware of besty xdd666 ".to_string());
|
||||
|
||||
custom_mod.load_command(create_cmd_test());
|
||||
custom_mod.set_status_by_default(Status::Disabled);
|
||||
|
||||
custom_mod
|
||||
}
|
||||
|
@ -73,6 +77,7 @@ pub mod funbot_objs {
|
|||
|
||||
cmd.set_admin_only(false);
|
||||
cmd.set_min_badge(Badge::Vip);
|
||||
|
||||
cmd
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
|
||||
//! - More Info - <https://dev.twitch.tv/docs/authentication>
|
||||
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_core::Bot;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
|
@ -17,7 +17,7 @@
|
|||
//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
|
||||
//! - More Info - <https://dev.twitch.tv/docs/authentication>
|
||||
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_core::Bot;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
|
@ -37,7 +37,7 @@ pub async fn main() {
|
|||
pub mod custom_mod {
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::{execution_async, Badge, Bot, Command, Module};
|
||||
use forcebot_core::{execution_async, Badge, Bot, Command, Module};
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
|
|
@ -5,10 +5,16 @@ use twitch_irc::{login::StaticLoginCredentials, message::{PrivmsgMessage, Server
|
|||
use dotenv::dotenv;
|
||||
use std::{env, sync::Arc, time::{Duration, Instant}};
|
||||
|
||||
use crate::{Badge, Command, Listener, Module};
|
||||
// use crate::{Badge, Command, Listener, Module};
|
||||
use super::bot_objects::command::Command;
|
||||
|
||||
use super::{bot_objects::built_in_objects, modules::{self, Status}};
|
||||
use crate::botcore::bot_objects::Badge;
|
||||
use crate::botcore::bot_objects::listener::Listener;
|
||||
use super::super::botcore::modules::Module;
|
||||
// use super::
|
||||
|
||||
use super:: {bot_objects::built_in_objects, modules::{self, Status}};
|
||||
|
||||
|
||||
/// Twitch chat bot
|
||||
pub struct Bot
|
||||
|
@ -73,7 +79,7 @@ impl Bot
|
|||
|
||||
/// Creates a new `Bot` using bot information
|
||||
///
|
||||
/// Bot joined channels will include channels from `.env` and `botchannels` argument
|
||||
/// Bot will join `botchannels` argument
|
||||
pub fn new_from(bot_login_name:String,oauth_token:String,prefix:String,botchannels:Vec<String>) -> Bot {
|
||||
|
||||
dotenv().ok();
|
||||
|
@ -90,10 +96,6 @@ impl Bot
|
|||
let mut botchannels_all = Vec::new();
|
||||
botchannels_all.extend(botchannels);
|
||||
|
||||
for chnl in env::var("bot_channels").unwrap().split(',') {
|
||||
botchannels_all.push(chnl.to_owned());
|
||||
}
|
||||
|
||||
|
||||
let mut admins = Vec::new();
|
||||
|
|
@ -105,8 +105,16 @@ pub mod built_in_objects {
|
|||
use std::{sync::Arc, time::{Duration, Instant}};
|
||||
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
use super::{execution_async,command::Command,Bot,Badge,super::modules::Status};
|
||||
|
||||
// use super::execution_async;
|
||||
// use super::command::Command;
|
||||
// use super::Bot;
|
||||
// use super::Badge;
|
||||
// use super::super::modules::Status;
|
||||
// ::{execution_async, modules::Status, Badge, Bot, Command};
|
||||
|
||||
use crate::{execution_async, modules::Status, Badge, Bot, Command};
|
||||
|
||||
|
||||
/// create a vector of command build in objects
|
||||
|
@ -146,14 +154,14 @@ pub mod built_in_objects {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 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);
|
||||
cmd.set_min_badge(Badge::Moderator /* ::Moderator */);
|
||||
cmd
|
||||
|
||||
}
|
||||
|
@ -201,7 +209,7 @@ pub mod built_in_objects {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 3. Set and Store the execution body using `execution_async()` */
|
||||
cmd.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 4. optionally, remove admin only default flag */
|
||||
|
@ -304,7 +312,7 @@ pub mod built_in_objects {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 3. Set and Store the execution body using `execution_async()` */
|
||||
cmd.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 4. optionally, remove admin only default flag */
|
|
@ -2,7 +2,9 @@ use std::sync::Arc;
|
|||
|
||||
use twitch_irc::message::{PrivmsgMessage, ServerMessage};
|
||||
|
||||
use crate::{botcore::bot::Bot, command_condition_async, execution_async, Badge};
|
||||
// use crate::{botcore::bot::Bot, command_condition_async, execution_async, Badge};
|
||||
use super::{execution_async,Bot,Badge,command_condition_async};
|
||||
|
||||
|
||||
use super::{CommandTrigger, ExecBody};
|
||||
|
||||
|
@ -80,7 +82,7 @@ impl Command
|
|||
/// /* 2. define an async function */
|
||||
/// async fn condition01(_:Arc<Bot>,_:ServerMessage) -> bool { true }
|
||||
///
|
||||
/// /* 3. Set and Store the execution body using `async_box()` */
|
||||
/// /* 3. Set and Store the execution body using `execution_async()` */
|
||||
/// cmd.set_custom_cond_async(condition_async(condition01));
|
||||
/// ```
|
||||
///
|
|
@ -2,13 +2,22 @@ use std::sync::Arc;
|
|||
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
use crate::{execution_async, listener_condition_async, Bot};
|
||||
|
||||
use super::{execution_async,Bot,listener_condition_async};
|
||||
|
||||
use super::{ExecBody, ListenerTrigger};
|
||||
|
||||
/// Bot `Listener`` that stores trigger condition callback and a execution functon
|
||||
/// Bot `Listener` that stores trigger condition callback and a execution functon
|
||||
///
|
||||
/// Use `asyncfn_box()` on custom async execution bodies
|
||||
/// Use `Listener` functions to define the Trigger Condition & Execution callbacks.
|
||||
/// When the Trigger callback is `true`, the Execution callback runs in the bot loop
|
||||
///
|
||||
/// Create a new empty `Listener` with `new()`
|
||||
///
|
||||
/// Use the following on the empty listener before loading it into the bot to set the callbacks
|
||||
///
|
||||
/// - `set_trigger_cond_fn()` - to define the Trigger condition callback
|
||||
///
|
||||
/// - `set_exec_fn()` - to define the Execution Callback
|
||||
#[derive(Clone)]
|
||||
pub struct Listener
|
||||
{
|
||||
|
@ -23,14 +32,22 @@ pub struct Listener
|
|||
impl Listener
|
||||
{
|
||||
|
||||
/// Creates a new empty `Listener` .
|
||||
/// Call `set_trigger_cond_fn()` and `set_exec_fn()` to trigger & execution function callbacks
|
||||
/// Creates a new empty `Listener`
|
||||
///
|
||||
/// Use `Listener` functions to define the Trigger Condition & Execution callbacks.
|
||||
/// When the Trigger callback is `true`, the Execution callback runs in the bot loop
|
||||
///
|
||||
/// Use the following on the empty listener before loading it into the bot to set the callbacks
|
||||
///
|
||||
/// - `set_trigger_cond_fn()` - to define the Trigger condition callback
|
||||
///
|
||||
/// - `set_exec_fn()` - to define the Execution Callback
|
||||
pub fn new() -> Listener {
|
||||
|
||||
async fn execbody(_:Arc<Bot>,_:ServerMessage) -> Result<String,String> {Result::Ok("success".to_string()) }
|
||||
async fn condition01(_:Arc<Bot>,_:ServerMessage) -> bool { true }
|
||||
Listener {
|
||||
trigger_cond_fn : |_:Arc<Bot>,_:ServerMessage| false,
|
||||
trigger_cond_fn : |_:Arc<Bot>,_:ServerMessage| true,
|
||||
trigger_cond_async : Arc::new(listener_condition_async(condition01)),
|
||||
exec_fn : Arc::new(execution_async(execbody)),
|
||||
}
|
||||
|
@ -45,7 +62,7 @@ impl Listener
|
|||
///
|
||||
/// Same as `set_trigger_cond_fn()` , but async define
|
||||
///
|
||||
/// Use`asyncfn_box()` on the async fn when storing
|
||||
/// Use`condition_async()` on the async fn when storing
|
||||
///
|
||||
/// Example -
|
||||
/// ```rust
|
||||
|
@ -55,7 +72,7 @@ impl Listener
|
|||
/// /* 2. define an async function */
|
||||
/// async fn condition01(_:Arc<Bot>,_:ServerMessage) -> bool { true }
|
||||
///
|
||||
/// /* 3. Set and Store the execution body using `async_box()` */
|
||||
/// /* 3. Set and Store the execution body using `execution_async()` */
|
||||
/// listener.set_trigger_cond_async(condition_async(condition01));
|
||||
/// ```
|
||||
///
|
||||
|
@ -66,7 +83,7 @@ impl Listener
|
|||
|
||||
/// sets the execution body of the listener for when it triggers
|
||||
///
|
||||
/// Use`asyncfn_box()` on the async fn when storing
|
||||
/// Use`execution_async()` on the async fn when storing
|
||||
///
|
||||
/// Example -
|
||||
/// ```rust
|
||||
|
@ -76,8 +93,8 @@ impl Listener
|
|||
/// /* 2. define an async function */
|
||||
/// async fn execbody(_:Arc<Bot>,_:ServerMessage) -> Result<String,String> {Result::Ok("success".to_string()) }
|
||||
///
|
||||
/// /* 3. Set and Store the execution body using `async_box()` */
|
||||
/// listener.set_exec_fn(asyncfn_box(execbody));
|
||||
/// /* 3. Set and Store the execution body using `execution_async()` */
|
||||
/// listener.set_exec_fn(execution_async(execbody));
|
||||
/// ```
|
||||
///
|
||||
pub fn set_exec_fn(&mut self,exec_fn:ExecBody ) {
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
use super::bot_objects::command::Command;
|
||||
use super::bot_objects::listener::Listener;
|
||||
|
||||
use crate::{Command, Listener};
|
||||
|
||||
#[derive(PartialEq, Eq,Debug,Clone)]
|
||||
pub enum Status {
|
||||
|
@ -33,7 +34,7 @@ impl Module
|
|||
bot_read_description,
|
||||
listeners: vec![],
|
||||
commands: vec![],
|
||||
default_status_per_channel: Status::Disabled,
|
||||
default_status_per_channel: Status::Enabled,
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,14 @@ use std::sync::{Arc, Mutex};
|
|||
|
||||
use twitch_irc::message::{PrivmsgMessage, ServerMessage};
|
||||
|
||||
use crate::{listener_condition_async, Badge, Bot, Command, Listener, Module};
|
||||
// use crate::{execution_async, listener_condition_async, Badge, Bot, Command, Listener, Module};
|
||||
use super::super::botcore::bot_objects::execution_async;
|
||||
use super::super::botcore::bot_objects::listener_condition_async;
|
||||
use super::super::botcore::bot_objects::listener::Listener;
|
||||
use super::super::botcore::modules::Module;
|
||||
use super::super::botcore::bot::Bot;
|
||||
use super::super::botcore::bot_objects::command::Command;
|
||||
use super::super::botcore::bot_objects::Badge;
|
||||
|
||||
/// pyramid module
|
||||
///
|
||||
|
@ -58,15 +65,15 @@ fn create_pyramid_detector() -> Listener {
|
|||
/* 4. Define an async fn callback execution */
|
||||
async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
|
||||
if let ServerMessage::Privmsg(msg) = message {
|
||||
if detect_pyramid_complete_ok(bot.clone(), msg.clone()).await {
|
||||
// if detect_pyramid_complete_ok(bot.clone(), msg.clone()).await {
|
||||
let _ = bot.client.say_in_reply_to(&msg, "Clap".to_string()).await ;
|
||||
return Result::Ok("Success".to_string()) ;
|
||||
}
|
||||
// }
|
||||
}
|
||||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 5. Set and Store the execution body using `async_box()` */
|
||||
/* 5. Set and Store the execution body using `execution_async()` */
|
||||
listener.set_exec_fn(Box::new(move |a,b| Box::pin(execbody(a,b))));
|
||||
|
||||
listener
|
||||
|
@ -78,16 +85,17 @@ async fn detect_pyramid_complete_ok(_bot:Arc<Bot>,msg:PrivmsgMessage) -> bool {
|
|||
|
||||
let msgtext = msg.message_text.replace("\u{e0000}","").trim().to_string();
|
||||
let msgchannel = msg.channel_login;
|
||||
let msgchatter = msg.sender.login;
|
||||
|
||||
// 1. Check if Pyramid started in chat > and recognize pyramid started
|
||||
if !is_pyramid_started(msgchannel.clone()) & check_start_pyramid(msgchannel.clone(),msgtext.clone(),) {
|
||||
set_pyramid_started(msgchannel.clone(),true);
|
||||
push_to_compare(msgchannel.clone(),get_start_pattern(msgchannel.clone()));
|
||||
push_to_compare(msgchannel.clone(),msgchatter.clone(),get_start_pattern(msgchannel.clone()));
|
||||
|
||||
}
|
||||
|
||||
if is_pyramid_started(msgchannel.clone()) {
|
||||
push_to_compare(msgchannel.clone(),msgtext.clone());
|
||||
push_to_compare(msgchannel.clone(),msgchatter.clone(),msgtext.clone());
|
||||
}
|
||||
|
||||
// 2a. If Pyramid Not Started, Assume message is a potential start pattern
|
||||
|
@ -111,8 +119,8 @@ async fn detect_pyramid_complete_ok(_bot:Arc<Bot>,msg:PrivmsgMessage) -> bool {
|
|||
|
||||
|
||||
lazy_static!{
|
||||
/// Message Compare stack per channel (channel:String,msgstack:Vec<String>)
|
||||
pub static ref COMPARE_MSG_STACK_PER_CHNL: Mutex<Vec<(String,Mutex<Vec<String>>)>> = Mutex::new(vec![]);
|
||||
/// Message Compare stack per channel (channel:String,msgstack:Vec<(chatter:String,message:String)>)
|
||||
pub static ref COMPARE_MSG_STACK_PER_CHNL: Mutex<Vec<(String,Mutex<Vec<(String,String)>>)>> = Mutex::new(vec![]);
|
||||
#[derive(Debug)]
|
||||
/// Pyramid Started per channel (channel:String,started:bool)
|
||||
pub static ref PYRAMID_STARTED_PER_CHNL: Mutex<Vec<(String,Mutex<bool>)>> = Mutex::new(vec![]);
|
||||
|
@ -126,7 +134,7 @@ lazy_static!{
|
|||
|
||||
}
|
||||
|
||||
fn read_top_of_compare(channel:String) -> Option<String> {
|
||||
fn read_top_of_compare(channel:String) -> Option<(String,String)> {
|
||||
|
||||
let comp_perchnl = COMPARE_MSG_STACK_PER_CHNL.lock().unwrap();
|
||||
|
||||
|
@ -142,7 +150,7 @@ fn read_top_of_compare(channel:String) -> Option<String> {
|
|||
|
||||
}
|
||||
|
||||
fn pop_top_of_compare(channel:String) -> Option<String> {
|
||||
fn pop_top_of_compare(channel:String) -> Option<(String,String)> {
|
||||
let comp_perchnl = COMPARE_MSG_STACK_PER_CHNL.lock().unwrap();
|
||||
|
||||
for rec in comp_perchnl.iter() {
|
||||
|
@ -218,7 +226,7 @@ fn get_start_pattern(channel:String) -> String {
|
|||
|
||||
|
||||
/// pushes message to compare stack
|
||||
fn push_to_compare(channel:String,message:String) {
|
||||
fn push_to_compare(channel:String,chatter:String,message:String) {
|
||||
let mut comp_perchnl = COMPARE_MSG_STACK_PER_CHNL.lock().unwrap();
|
||||
|
||||
let mut found = false;
|
||||
|
@ -226,12 +234,12 @@ fn push_to_compare(channel:String,message:String) {
|
|||
if rec.0 == channel {
|
||||
found = true;
|
||||
let mut msg_stack = rec.1.lock().unwrap();
|
||||
msg_stack.push(message.clone());
|
||||
msg_stack.push((chatter.clone(),message.clone()));
|
||||
// dbg!("Push message to cmp stack ; result last cmp_pchnl - ",comp_perchnl.last());
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
comp_perchnl.push((channel,Mutex::new(vec![message])));
|
||||
comp_perchnl.push((channel,Mutex::new(vec![(chatter,message)])));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -247,21 +255,21 @@ fn check_start_pyramid(channel:String,msgtext: String) -> bool {
|
|||
fn symmetry_ok(channel:String) -> bool {
|
||||
let mut temp_stack = TEMP_MSG_STACK.lock().unwrap();
|
||||
let mut checking_started = false;
|
||||
if !(read_top_of_compare(channel.clone()).unwrap_or("".to_string()) == get_start_pattern(channel.clone())) {
|
||||
if !(read_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1 == get_start_pattern(channel.clone())) {
|
||||
return false;
|
||||
}
|
||||
loop {
|
||||
|
||||
if !checking_started && read_top_of_compare(channel.clone()).unwrap_or("".to_string()) == get_start_pattern(channel.clone()) {
|
||||
if !checking_started && read_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1 == get_start_pattern(channel.clone()) {
|
||||
checking_started = true;
|
||||
}
|
||||
if temp_stack.last().is_none() || read_top_of_compare(channel.clone()).unwrap_or("".to_string()).len() > temp_stack.last().unwrap_or(&"".to_string()).len() {
|
||||
temp_stack.push(pop_top_of_compare(channel.clone()).unwrap_or("".to_string()));
|
||||
if temp_stack.last().is_none() || read_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1.len() > temp_stack.last().unwrap_or(&"".to_string()).len() {
|
||||
temp_stack.push(pop_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1);
|
||||
|
||||
} else if temp_stack.last().is_some() && read_top_of_compare(channel.clone()).unwrap_or("".to_string()).len() < temp_stack.last().unwrap_or(&"".to_string()).len() {
|
||||
} else if temp_stack.last().is_some() && read_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1.len() < temp_stack.last().unwrap_or(&"".to_string()).len() {
|
||||
|
||||
temp_stack.pop();
|
||||
if temp_stack.last().unwrap_or(&"".to_string()).clone() == read_top_of_compare(channel.clone()).unwrap_or("".to_string()) {
|
||||
if temp_stack.last().unwrap_or(&"".to_string()).clone() == read_top_of_compare(channel.clone()).unwrap_or(("".to_string(),"".to_string())).1 {
|
||||
temp_stack.pop();
|
||||
|
||||
continue;
|
||||
|
@ -272,7 +280,7 @@ fn symmetry_ok(channel:String) -> bool {
|
|||
}
|
||||
|
||||
} else { /* dbg!("failed catchall"); */ return false; }
|
||||
if checking_started && read_top_of_compare(channel.clone()).unwrap() == get_start_pattern(channel.clone()) {
|
||||
if checking_started && read_top_of_compare(channel.clone()).unwrap().1 == get_start_pattern(channel.clone()) {
|
||||
|
||||
temp_stack.clear();
|
||||
return true;
|
||||
|
@ -284,7 +292,9 @@ fn symmetry_ok(channel:String) -> bool {
|
|||
}
|
||||
|
||||
|
||||
/// pyramid interruptor #todo
|
||||
/// #todo
|
||||
///
|
||||
/// pyramid interruptor
|
||||
///
|
||||
/// pick chatters that will be interrupted if they solo build
|
||||
///
|
||||
|
@ -311,7 +321,7 @@ fn create_interruptor_cmd() -> Command {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 3. Set and Store the execution body using `execution_async()` */
|
||||
cmd.set_exec_fn(Box::new(move |a,b| Box::pin(execbody(a,b))));
|
||||
|
||||
/* 4. optionally, remove admin only default flag */
|
||||
|
@ -324,5 +334,47 @@ fn create_interruptor_cmd() -> Command {
|
|||
cmd
|
||||
}
|
||||
|
||||
/// #todo
|
||||
fn create_interruptor_module(channel:String) -> Module {
|
||||
/* 1. Create a new module */
|
||||
let modname = format!("interruptor {}",channel);
|
||||
let mut custom_mod = Module::new(
|
||||
vec![modname],
|
||||
"".to_string());
|
||||
|
||||
/* 2. Load the cmd into a new module */
|
||||
custom_mod.load_listener(create_interruptor_listener());
|
||||
|
||||
custom_mod
|
||||
|
||||
}
|
||||
|
||||
/// #todo
|
||||
fn create_interruptor_listener() -> Listener {
|
||||
/* 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 `execution_async()` */
|
||||
listener.set_exec_fn(execution_async(execbody));
|
||||
|
||||
listener
|
||||
|
||||
}
|
||||
|
||||
/// #todo
|
||||
///
|
||||
/// Returns Some(chatter) if the pyramid in progress is being built by a solo
|
||||
fn solo_building(channel:String) -> Option<String> {
|
||||
None
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
//! `forcebot-rs-v2` : Twitch chat bot written in rust.
|
||||
//! `forcebot_core` library for `forcebot-rs-v2` Twitch chat bot
|
||||
//!
|
||||
//! Customize by adding additional bot objects
|
||||
//!
|
||||
|
@ -7,7 +7,7 @@
|
|||
//! Uses Env defined variables to create and run the bot
|
||||
//!
|
||||
//! ```rust
|
||||
//! use forcebot_rs_v2::Bot;
|
||||
//! use forcebot_core::Bot;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! pub async fn main() {
|
||||
|
@ -27,11 +27,10 @@
|
|||
//!
|
||||
//! 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
|
||||
//!
|
||||
//! ```rust
|
||||
//! use forcebot_rs_v2::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
//! use forcebot_core::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! pub async fn main() {
|
||||
|
@ -60,7 +59,7 @@
|
|||
//!
|
||||
//!
|
||||
//! ```rust
|
||||
//! use forcebot_rs_v2::Bot;
|
||||
//! use forcebot_core::Bot;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! pub async fn main() {
|
||||
|
@ -79,7 +78,7 @@
|
|||
//! pub mod custom_mod {
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! use forcebot_rs_v2::{execution_async, Badge, Bot, Command, Module};
|
||||
//! use forcebot_core::{execution_async, Badge, Bot, Command, Module};
|
||||
//! use twitch_irc::message::ServerMessage;
|
||||
//!
|
||||
//!
|
||||
|
@ -129,7 +128,7 @@
|
|||
//! ```rust
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! use forcebot_rs_v2::{execution_async, Bot, Listener};
|
||||
//! use forcebot_core::{execution_async, Bot, Listener};
|
||||
//! use twitch_irc::message::ServerMessage;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
|
@ -152,7 +151,7 @@
|
|||
//! Result::Ok("Success".to_string())
|
||||
//! }
|
||||
//!
|
||||
//! /* 2d. Set and Store the execution body using `async_box()` */
|
||||
//! /* 2d. Set and Store the execution body using `execution_async()` */
|
||||
//! listener.set_exec_fn(execution_async(execbody));
|
||||
//!
|
||||
//! /* 3. Load the listener into the bot */
|
||||
|
@ -171,9 +170,9 @@
|
|||
//!
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! use forcebot_rs_v2::Bot;
|
||||
//! use forcebot_rs_v2::execution_async;
|
||||
//! use forcebot_rs_v2::Listener;
|
||||
//! use forcebot_core::Bot;
|
||||
//! use forcebot_core::execution_async;
|
||||
//! use forcebot_core::Listener;
|
||||
//! use twitch_irc::message::ServerMessage;
|
||||
//!
|
||||
//!
|
||||
|
@ -211,7 +210,7 @@
|
|||
//! Result::Err("Not Valid message type".to_string())
|
||||
//! }
|
||||
//!
|
||||
//! /* 4. Set and Store the execution body using `async_box()` */
|
||||
//! /* 4. Set and Store the execution body using `execution_async()` */
|
||||
//! listener.set_exec_fn(execution_async(execbody));
|
||||
//!
|
||||
//! /* 5. Load the listener into the bot */
|
||||
|
@ -226,12 +225,13 @@
|
|||
|
||||
pub mod botcore;
|
||||
pub mod custom_mods;
|
||||
pub use crate::botcore::bot::Bot;
|
||||
pub use crate::botcore::bot_objects::execution_async;
|
||||
pub use crate::botcore::bot_objects::command_condition_async;
|
||||
pub use crate::botcore::bot_objects::listener_condition_async;
|
||||
pub use crate::botcore::bot_objects::listener::Listener;
|
||||
pub use crate::botcore::bot_objects::command::Command;
|
||||
pub use crate::botcore::modules::Module;
|
||||
pub use crate::botcore::bot_objects::Badge;
|
||||
pub use crate::botcore::modules;
|
||||
pub use botcore::bot::Bot;
|
||||
pub use botcore::bot_objects::execution_async;
|
||||
pub use botcore::bot_objects::command_condition_async;
|
||||
pub use botcore::bot_objects::listener_condition_async;
|
||||
pub use botcore::bot_objects::listener::Listener;
|
||||
// pub use crate::botcore::bot_objects::command::Command;
|
||||
pub use botcore::bot_objects::command::Command;
|
||||
pub use botcore::modules::Module;
|
||||
pub use botcore::bot_objects::Badge;
|
||||
pub use botcore::modules;
|
11
moderator_reactor/Cargo.toml
Normal file
11
moderator_reactor/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "moderator_reactor"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_rs_v2::execution_async;
|
||||
use forcebot_rs_v2::Listener;
|
||||
use forcebot_core::Bot;
|
||||
use forcebot_core::execution_async;
|
||||
use forcebot_core::Listener;
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ pub async fn main() {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 4. Set and Store the execution body using `async_box()` */
|
||||
/* 4. Set and Store the execution body using `execution_async()` */
|
||||
listener.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 5. Load the listener into the bot */
|
11
new_empty_bot/Cargo.toml
Normal file
11
new_empty_bot/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "new_empty_bot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"
|
|
@ -10,8 +10,7 @@
|
|||
//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
|
||||
//! - More Info - <https://dev.twitch.tv/docs/authentication>
|
||||
|
||||
use forcebot_rs_v2::botcore::bot::Bot;
|
||||
|
||||
use forcebot_core::Bot;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
129
readme.md
129
readme.md
|
@ -1,4 +1,4 @@
|
|||
Twitch chat bot written in rust
|
||||
Customizable Twitch chat bot written in rust
|
||||
|
||||
# Quick Start
|
||||
|
||||
|
@ -22,28 +22,47 @@ bot_admins=ADMIN
|
|||
3. Build & run
|
||||
|
||||
```
|
||||
cargo run
|
||||
cargo run -p forcebot_core
|
||||
```
|
||||
|
||||
# Features
|
||||
|
||||
- Quick Start to use full feature set bot
|
||||
- Moderators & Broadcasters can `disable` or `enable` `Modules` of bot functionality through chat `Commands`
|
||||
- Full Feature Set `forcebot_core` bot has the following modules loaded
|
||||
- `guest_badge` - Temporary badges can be issued to chatters
|
||||
- `besty` - Tomfoolery
|
||||
- `pyramid` - for detecting & handling pyramids
|
||||
- `forcebot_core` library API provides Custom package developers a way to add functionality by adding `Modules` that contain Bot Objects like `Commands` and `Listeners`
|
||||
- `Listeners` and `Commands` listen for a defined callback trigger condition and run an defined execution callback
|
||||
- `Commands` are similar to `Listeners` with refined trigger conditions including using bot `prefix` with the `Command` , triggers based on `Badge` , and more
|
||||
- Workspace for package developers to independently code their own `Modules`
|
||||
- Workspace comes with binary crates with working or example bots that use `forcebot_core` library
|
||||
- `moderator_reactor` - bot kneels to all moderator messages
|
||||
- `simple_module_example` - bot has a `test` `Module` with a `test` `Command` .Moderators & Broadcasters can manage the `Module` in chat with `enable` / `disable` `Commands`
|
||||
- `new_empty_bot` - while empty, has `disable` and `enable` chat `Commands` . This is an example of the bot without any loaded modules
|
||||
- `simple_command_bot` - bot responds to a `test` `Command`. As the command was not loaded through a `Module`, `disable` & `enable` commands don't work on the `test` command. This could be a Global `Command`
|
||||
- `simple_debug_listener` - bot outputs all twitch `ServerMessages` received to terminal
|
||||
|
||||
|
||||
|
||||
# Example Bots
|
||||
|
||||
Use the following commands to build and run built-in bots. No coding required!
|
||||
Use the following to build and run built-in bots. No coding required!
|
||||
|
||||
## New Bot
|
||||
## New Empty Bot
|
||||
Run an empty simple bot that logs into chat and has minimum built in functions
|
||||
|
||||
```
|
||||
cargo run --bin new_bot
|
||||
cargo run -p new_empty_bot
|
||||
```
|
||||
|
||||
## WIP Customized Fun Bot
|
||||
## Full Featured Forcebot
|
||||
|
||||
Run a forcebot with fun catered customizations
|
||||
|
||||
*ongoing work in progress*
|
||||
|
||||
```
|
||||
cargo run --bin fun_bot
|
||||
cargo run -p forcebot_core
|
||||
```
|
||||
|
||||
|
||||
|
@ -51,28 +70,69 @@ cargo run --bin fun_bot
|
|||
Run a bot that listens to all messages and output to console
|
||||
|
||||
```
|
||||
cargo run --bin simple_debug_listener
|
||||
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 --bin simple_command_bot
|
||||
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 --bin moderator_reactor
|
||||
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 --bin simple_module
|
||||
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
|
||||
|
||||
1. Create a new package
|
||||
|
||||
For example, to create a new binary crate in the workspace
|
||||
|
||||
```
|
||||
cargo new my_new_bot
|
||||
```
|
||||
|
||||
2. 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"
|
||||
```
|
||||
|
||||
3. Copy `main.rs` from the `new_empty_bot` package into your package
|
||||
|
||||
4. Optionally, customize your `main()` to load modules before starting the bot
|
||||
|
||||
5. Build and run your package
|
||||
```
|
||||
cargo run -p my_new_bot
|
||||
```
|
||||
|
||||
|
||||
|
@ -83,7 +143,7 @@ cargo run --bin simple_module
|
|||
Uses Env defined variables to create and run the bot
|
||||
|
||||
```rust
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_core::Bot;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
|
@ -95,7 +155,6 @@ pub async fn main() {
|
|||
bot.run().await;
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Customize by Loading Custom Modules
|
||||
|
@ -105,7 +164,8 @@ A `Module` is a group of bot objects (eg `Command`) that elevated users can mana
|
|||
Custom `Modules` can be loaded into a new bot with minimum coding : just load the modules and run the bot
|
||||
|
||||
```rust
|
||||
use forcebot_rs_v2::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
use forcebot_core::{custom_mods::{guest_badge, pyramid}, Bot};
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
|
@ -134,7 +194,7 @@ Create a custom `Module` by :
|
|||
|
||||
|
||||
```rust
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_core::Bot;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
|
@ -153,7 +213,7 @@ pub async fn main() {
|
|||
pub mod custom_mod {
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::{execution_async, Badge, Bot, Command, Module};
|
||||
use forcebot_core::{execution_async, Badge, Bot, Command, Module};
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
|
||||
|
@ -193,7 +253,6 @@ pub mod custom_mod {
|
|||
cmd
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Simple Debug Listener
|
||||
|
@ -202,7 +261,7 @@ Bot with a simple listener that listens for all messages and prints in output
|
|||
```rust
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::{execution_async, Bot, Listener};
|
||||
use forcebot_core::{execution_async, Bot, Listener};
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -225,7 +284,7 @@ pub async fn main() {
|
|||
Result::Ok("Success".to_string())
|
||||
}
|
||||
|
||||
/* 2d. Set and Store the execution body using `async_box()` */
|
||||
/* 2d. Set and Store the execution body using `execution_async()` */
|
||||
listener.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 3. Load the listener into the bot */
|
||||
|
@ -235,7 +294,6 @@ pub async fn main() {
|
|||
bot.run().await;
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Moderator Reactor
|
||||
|
@ -243,12 +301,11 @@ pub async fn main() {
|
|||
Example listener listens for a moderator badge and reply in chat
|
||||
|
||||
```rust
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_rs_v2::execution_async;
|
||||
use forcebot_rs_v2::Listener;
|
||||
use forcebot_core::Bot;
|
||||
use forcebot_core::execution_async;
|
||||
use forcebot_core::Listener;
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
|
||||
|
@ -286,7 +343,7 @@ pub async fn main() {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 4. Set and Store the execution body using `async_box()` */
|
||||
/* 4. Set and Store the execution body using `execution_async()` */
|
||||
listener.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 5. Load the listener into the bot */
|
||||
|
@ -296,9 +353,6 @@ pub async fn main() {
|
|||
bot.run().await;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Simple Test Command
|
||||
|
@ -306,13 +360,12 @@ pub async fn main() {
|
|||
```rust
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::Badge;
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_rs_v2::execution_async;
|
||||
use forcebot_rs_v2::Command;
|
||||
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() {
|
||||
|
||||
|
@ -331,7 +384,7 @@ pub async fn main() {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 3. Set and Store the execution body using `execution_async()` */
|
||||
cmd.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 4. optionally, remove admin only default flag */
|
||||
|
@ -347,11 +400,9 @@ pub async fn main() {
|
|||
bot.run().await;
|
||||
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
# Crate Rust Documentation
|
||||
# Crate Rust API Documentation
|
||||
|
||||
Create `forcebot_rs_v2` Rust Crate documentation
|
||||
|
||||
|
|
11
simple_command_bot/Cargo.toml
Normal file
11
simple_command_bot/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "simple_command_bot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"
|
|
@ -15,10 +15,10 @@
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::Badge;
|
||||
use forcebot_rs_v2::Bot;
|
||||
use forcebot_rs_v2::execution_async;
|
||||
use forcebot_rs_v2::Command;
|
||||
use forcebot_core::Badge;
|
||||
use forcebot_core::Bot;
|
||||
use forcebot_core::execution_async;
|
||||
use forcebot_core::Command;
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ pub async fn main() {
|
|||
Result::Err("Not Valid message type".to_string())
|
||||
}
|
||||
|
||||
/* 3. Set and Store the execution body using `async_box()` */
|
||||
/* 3. Set and Store the execution body using `execution_async()` */
|
||||
cmd.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 4. optionally, remove admin only default flag */
|
11
simple_debug_listener/Cargo.toml
Normal file
11
simple_debug_listener/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "simple_debug_listener"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use forcebot_rs_v2::{execution_async, Bot, Listener};
|
||||
use forcebot_core::{execution_async, Bot, Listener};
|
||||
use twitch_irc::message::ServerMessage;
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -35,7 +35,7 @@ pub async fn main() {
|
|||
Result::Ok("Success".to_string())
|
||||
}
|
||||
|
||||
/* 2d. Set and Store the execution body using `async_box()` */
|
||||
/* 2d. Set and Store the execution body using `execution_async()` */
|
||||
listener.set_exec_fn(execution_async(execbody));
|
||||
|
||||
/* 3. Load the listener into the bot */
|
11
simple_module_example/Cargo.toml
Normal file
11
simple_module_example/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "simple_module_example"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"
|
79
simple_module_example/src/main.rs
Normal file
79
simple_module_example/src/main.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
//! Simple Module with a Command
|
||||
//!
|
||||
//! Adding objects through packages provides controls ,
|
||||
//! such as moderators, and brodcasters can disable or enable mods
|
||||
//!
|
||||
//! Here, moderators or above can enable or disable the `test`
|
||||
//! module with the command `<prefix> disable test`
|
||||
//!
|
||||
//! Be sure the followig is defined in `.env`
|
||||
//! - login_name
|
||||
//! - access_token
|
||||
//! - bot_channels
|
||||
//! - prefix
|
||||
//! - bot_admins
|
||||
//!
|
||||
//! Bot access tokens be generated here -
|
||||
//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
|
||||
//! - More Info - <https://dev.twitch.tv/docs/authentication>
|
||||
|
||||
use forcebot_core::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()).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.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(execution_async(execbody));
|
||||
cmd.set_admin_only(false);
|
||||
cmd.set_min_badge(Badge::Vip);
|
||||
|
||||
cmd
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue