Compare commits

...

2 Commits

Author SHA1 Message Date
legitnull
6ef48be979
updated readme 2023-04-15 23:14:28 -06:00
legitnull
7806149daa fixed nick collision on invade 2023-03-28 21:26:56 -06:00
8 changed files with 77 additions and 37 deletions

@ -46,11 +46,11 @@ this is the dev branch
- `%ping`: Send this command to G.1.R and he'll respond back with "pong" and the time it took. Because why not? - `%ping`: Send this command to G.1.R and he'll respond back with "pong" and the time it took. Because why not?
- `%kill`: Do you hate your bot companion and want to end his miserable existence? Just type this command and he'll self-destruct, leaving you alone with your conscience (and your loneliness). - `%kill`: Do you hate your bot companion and want to end his miserable existence? Just type this command and he'll self-destruct, leaving you alone with your conscience (and your loneliness).
- `%invade 5 #channel SCREAM`: Do you want to summon the Invaders to a specific channel? This command will do just that, plus a chance to let out your deepest screams of despair. 5 being the number of invaders to join! - `%invade 5 #channel SCREAM`: Do you want to summon the Invaders to a specific channel? This command will do just that, plus a chance to let out your deepest screams of despair. 5 being the number of invaders to join!
- `%%scream #channel SCREAM`: In case the invaders weren't enough to scare off your enemies, use this command to make them hear your battle cry across the IRC lands. - `%%scream #channel "SCREAM"`: In case the invaders weren't enough to scare off your enemies, use this command to make them hear your battle cry across the IRC lands.
- `%%join #channel`: More bots, more fun! Tell G.1.R to join the party in a specific channel and watch the madness unfold. - `%%join #channel`: More bots, more fun! Tell G.1.R to join the party in a specific channel and watch the madness unfold.
- `%%leave #channel`: Tired of all the chaos? Use this command to make the bots leave the channel and leave you in peace (or in silence, at least). - `%%leave #channel`: Tired of all the chaos? Use this command to make the bots leave the channel and leave you in peace (or in silence, at least).
Pro tip: When you use the `%invade #channel` command, G.1.R will set up that channel to be the commander channel, so you can control all the bots from one place and only that place. Talk about efficient invasion tactics! Pro tip: When you use the `%invade 5 #channel` command, G.1.R will set up that channel to be the commander channel, so you can control all the bots from one place and only that place. Talk about efficient invasion tactics!
## TODO ## TODO
@ -71,3 +71,4 @@ Pro tip: When you use the `%invade #channel` command, G.1.R will set up that cha
- [ ] Key rotation: To avoid API attempts from stopping the invasion. - [ ] Key rotation: To avoid API attempts from stopping the invasion.
So what are you waiting for? Join us in our quest for world domination, and let's make Invader Zim proud! So what are you waiting for? Join us in our quest for world domination, and let's make Invader Zim proud!
t

@ -1,8 +1,8 @@
nick = "g1r" nick = "g1r"
server = "ircd.chat" server = "ircd.chat"
port = 6697 port = 6697
password = "mine" password = ""
channels = [ "#s4d", "wiki", "#emo", "#tcpdirect", "#macros", "#b0tsh0p" ] #add key access channels = [ "#sad", "#s4d", "wiki", "#emo", "#tcpdirect", "#macros", "#b0tsh0p" ] #add key access
admin_users = ["s4d", "sad", "g", "d", "h3x", "kayos", "moony"] # add host identification admin_users = ["s4d", "sad", "g", "d", "h3x", "kayos", "moony"] # add host identification
ignore_users = ["maple", "aibird", "professorOak", "van"] ignore_users = ["maple", "aibird", "professorOak", "van"]
openai = "sk-" openai = "sk-"

@ -12,7 +12,7 @@ use crate::modules::Command;
mod modules { mod modules {
pub trait Command { pub trait Command {
fn handle(&self, message: &str) -> Vec<String>; fn handle(&mut self, message: &str) -> Vec<String>;
} }
pub mod ping; pub mod ping;
pub mod kill; pub mod kill;
@ -56,6 +56,7 @@ fn main() {
let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
let mut ssl_stream = connector.connect(&config.server, stream).unwrap(); let mut ssl_stream = connector.connect(&config.server, stream).unwrap();
let nick_command = format!("NICK {}_\r\n", config.nick); //setup passwords let nick_command = format!("NICK {}_\r\n", config.nick); //setup passwords
let user_command = format!("USER {} 0 * :{}\r\n", config.nick, config.nick); let user_command = format!("USER {} 0 * :{}\r\n", config.nick, config.nick);
ssl_stream.write_all(nick_command.as_bytes()).unwrap(); ssl_stream.write_all(nick_command.as_bytes()).unwrap();
ssl_stream.write_all(user_command.as_bytes()).unwrap(); ssl_stream.write_all(user_command.as_bytes()).unwrap();
@ -88,14 +89,15 @@ fn main() {
continue; // skip processing the PING message further continue; // skip processing the PING message further
} }
// MODULES // MODULES
let ping_command = PingCommand; let mut ping_command = PingCommand;
let kill_command = KillCommand; let mut kill_command = KillCommand;
let invade_command = InvadeCommand; let mut invade_command = InvadeCommand::new();
let aicode = AiCode; let mut aicode = AiCode;
//let test_command = TestCommand; //let test_command = TestCommand;
let ai = Ai; let mut ai = Ai;
// ADMIN MODULES // ADMIN MODULES
if message.starts_with(":") && message.contains(" :%") { if message.starts_with(":") && message.contains(" :%") {
@ -117,6 +119,10 @@ fn main() {
for response in invade_command.handle(message) { for response in invade_command.handle(message) {
ssl_stream.write_all(response.as_bytes()).unwrap(); ssl_stream.write_all(response.as_bytes()).unwrap();
} }
} else if message.contains(":%%kill") {
for response in invade_command.handle(message) {
ssl_stream.write_all(response.as_bytes()).unwrap();
}
} }
} }

@ -16,7 +16,7 @@ struct Config {
pub struct Ai; pub struct Ai;
impl Command for Ai { impl Command for Ai {
fn handle(&self, message: &str) -> Vec<String> { fn handle(&mut self, message: &str) -> Vec<String> {
let mut responses = Vec::new(); let mut responses = Vec::new();
let config_str = std::fs::read_to_string("config.toml").unwrap(); let config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().unwrap(); let config_value = config_str.parse::<Value>().unwrap();

@ -15,7 +15,7 @@ struct Config {
pub struct AiCode; pub struct AiCode;
// setup a prompt and respnse log for training other bots // setup a prompt and respnse log for training other bots
impl Command for AiCode { impl Command for AiCode {
fn handle(&self, message: &str) -> Vec<String> { fn handle(&mut self, message: &str) -> Vec<String> {
let mut responses = Vec::new(); let mut responses = Vec::new();
let config_str = std::fs::read_to_string("config.toml").unwrap(); let config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().unwrap(); let config_value = config_str.parse::<Value>().unwrap();

@ -8,29 +8,31 @@ use toml::{Value, to_string};
use colored::*; use colored::*;
use leetspeak; use leetspeak;
use regex::Regex; use regex::Regex;
use std::sync::atomic::{AtomicBool, Ordering};
//use anyhow::Result; use std::sync::{Arc, mpsc, Mutex};
//use socks5_proxy::{client, Addr};
// use tokio::net::TcpStream;
use tokio_native_tls::{TlsConnector, TlsStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
// add better error handling
// add ai invasion
// add proxy support
#[derive(Clone, Deserialize)] #[derive(Clone, Deserialize)]
struct Config { struct Config {
//invaders: Vec<String>,
server: String, server: String,
port: u16, port: u16,
} }
pub struct InvadeCommand; pub struct InvadeCommand {
kill_flag: Arc<AtomicBool>,
kill_sender: Option<mpsc::Sender<()>>,
}
impl InvadeCommand {
pub fn new() -> Self {
Self {
kill_flag: Arc::new(AtomicBool::new(false)),
kill_sender: None,
}
}
}
impl Command for InvadeCommand { impl Command for InvadeCommand {
fn handle(&self, message: &str) -> Vec<String> { fn handle(&mut self, message: &str) -> Vec<String> {
let mut response = vec![]; let mut response = vec![];
if message.contains("PRIVMSG") && message.contains(":%invade") { if message.contains("PRIVMSG") && message.contains(":%invade") {
@ -39,24 +41,28 @@ impl Command for InvadeCommand {
let num_invaders = parts[4].parse::<u32>().unwrap_or(1) as usize; let num_invaders = parts[4].parse::<u32>().unwrap_or(1) as usize;
let channel = parts[2]; let channel = parts[2];
let invadechannel = parts[5]; let invadechannel = parts[5];
let scream = if parts.len() > 6 { parts[6] } else { "" }; // read entire message let scream = if parts.len() > 6 { parts[6] } else { "" };
//message.split(&format!("PRIVMSG {} :", channel.to_string())).nth(1).unwrap(),
//let channel = message.split("PRIVMSG ").nth(1).and_then(|s| s.splitn(2, ' ').next()).unwrap();
let config_str = std::fs::read_to_string("config.toml").unwrap(); let config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().unwrap(); let config_value = config_str.parse::<Value>().unwrap();
let config: Config = config_value.try_into().unwrap(); let config: Config = config_value.try_into().unwrap();
let (kill_sender, kill_receiver) = mpsc::channel();
self.kill_sender = Some(kill_sender);
let kill_receiver = Arc::new(Mutex::new(kill_receiver));
for _invader in 1..=num_invaders {//&config.invaders[1..num_invaders] { //1..=20 { for _invader in 1..=num_invaders {
let thread_channel = invadechannel.to_string(); let thread_channel = invadechannel.to_string();
let config_clone = config.clone(); let config_clone = config.clone();
let screaming = scream.to_string(); let screaming = scream.to_string();
let command_channel = channel.to_string(); let command_channel = channel.to_string();
let thread_invader = random_word::gen(); // change to leetspeak on nick collision let thread_invader = random_word::gen();
let kill_flag_clone = Arc::clone(&self.kill_flag);
let kill_receiver = Arc::clone(&kill_receiver);
std::thread::spawn(move || { std::thread::spawn(move || {
let stream = TcpStream::connect((config_clone.server.as_str(), config_clone.port)).unwrap(); let stream = TcpStream::connect((config_clone.server.as_str(), config_clone.port)).unwrap();
let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
let mut ssl_stream = connector.connect(config_clone.server.as_str(), stream).unwrap(); let mut ssl_stream = connector.connect(config_clone.server.as_str(), stream).unwrap();
@ -73,6 +79,15 @@ impl Command for InvadeCommand {
ssl_stream.write_all(msg.as_bytes()).unwrap(); ssl_stream.write_all(msg.as_bytes()).unwrap();
loop { loop {
if kill_flag_clone.load(Ordering::SeqCst) {
break;
}
if let Ok(_) = kill_receiver.lock().unwrap().try_recv() {
break;
}
@ -91,10 +106,21 @@ impl Command for InvadeCommand {
println!("{} {}","[%] PONG:".bold().green(), thread_invader.blue()); println!("{} {}","[%] PONG:".bold().green(), thread_invader.blue());
ssl_stream.write_all(response.as_bytes()).unwrap(); ssl_stream.write_all(response.as_bytes()).unwrap();
} }
if message.starts_with("433") { // Numeric reply for nickname in use if message.starts_with(":ircd.chat 433") { // Numeric reply for nickname in use
let leet_nick = leetspeak::translate(&thread_invader); let leet_nick = leetspeak::translate_with_level(&thread_invader, &leetspeak::Level::One);
let nick_command = format!("NICK {}\r\n", leet_nick); let nick_command = format!("NICK {}\r\n", leet_nick);
let user_command = format!("USER {} 0 * :{}\r\n", thread_invader, thread_invader);
ssl_stream.write_all(nick_command.as_bytes()).unwrap(); ssl_stream.write_all(nick_command.as_bytes()).unwrap();
ssl_stream.write_all(user_command.as_bytes()).unwrap();
let join_command = format!("JOIN {} \r\n", thread_channel);
let commander = format!("JOIN {} \r\n", command_channel);
ssl_stream.write_all(commander.as_bytes()).unwrap();
ssl_stream.write_all(join_command.as_bytes()).unwrap();
ssl_stream.write_all(msg.as_bytes()).unwrap();
//break;
} }
// turn to mods // turn to mods
// setup so these will only run from the server admin to avoid handle/host conflicts // setup so these will only run from the server admin to avoid handle/host conflicts
@ -135,6 +161,13 @@ impl Command for InvadeCommand {
} }
response.push(format!("PRIVMSG {} :\x0304,01[!] INVADING {} WITH {} INVADERS...\x0f\r\n", channel, invadechannel, num_invaders)); response.push(format!("PRIVMSG {} :\x0304,01[!] INVADING {} WITH {} INVADERS...\x0f\r\n", channel, invadechannel, num_invaders));
} else if message.contains("PRIVMSG") && message.contains(":%%kill") {
let channel = message.split("PRIVMSG ").nth(1).and_then(|s| s.splitn(2, ' ').next()).unwrap();
if let Some(kill_sender) = &self.kill_sender {
let _ = kill_sender.send(());
}
self.kill_flag.store(true, Ordering::SeqCst);
response.push(format!("PRIVMSG {} :\x0304,01[!] TERMINATING ALL INVADERS...\x0f\r\n", channel));
} }
response response

@ -3,7 +3,7 @@ use crate::modules::Command;
pub struct KillCommand; pub struct KillCommand;
impl Command for KillCommand { impl Command for KillCommand {
fn handle(&self, message: &str) -> Vec<String> { fn handle(&mut self, message: &str) -> Vec<String> {
let mut response = vec![]; let mut response = vec![];
if message.contains("PRIVMSG") && message.contains(":%kill") { if message.contains("PRIVMSG") && message.contains(":%kill") {

@ -3,7 +3,7 @@ use std::time::{Instant};
use crate::modules::Command; use crate::modules::Command;
pub struct PingCommand; pub struct PingCommand;
impl Command for PingCommand { impl Command for PingCommand {
fn handle(&self, message: &str) -> Vec<String> { fn handle(&mut self, message: &str) -> Vec<String> {
let mut response = vec![]; let mut response = vec![];
if message.contains("PRIVMSG") && message.contains(":%ping") { if message.contains("PRIVMSG") && message.contains(":%ping") {