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

View File

@ -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?
- `%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!
- `%%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.
- `%%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
@ -70,4 +70,5 @@ Pro tip: When you use the `%invade #channel` command, G.1.R will set up that cha
- [ ] DM commander: To control the bots from the shadows, like a true mastermind.
- [ ] 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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ struct Config {
pub struct 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 config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().unwrap();

View File

@ -15,7 +15,7 @@ struct Config {
pub struct AiCode;
// setup a prompt and respnse log for training other bots
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 config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().unwrap();

View File

@ -8,29 +8,31 @@ use toml::{Value, to_string};
use colored::*;
use leetspeak;
use regex::Regex;
//use anyhow::Result;
//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
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, mpsc, Mutex};
#[derive(Clone, Deserialize)]
struct Config {
//invaders: Vec<String>,
server: String,
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 {
fn handle(&self, message: &str) -> Vec<String> {
fn handle(&mut self, message: &str) -> Vec<String> {
let mut response = vec![];
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 channel = parts[2];
let invadechannel = parts[5];
let scream = if parts.len() > 6 { parts[6] } else { "" }; // read entire message
//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 scream = if parts.len() > 6 { parts[6] } else { "" };
let config_str = std::fs::read_to_string("config.toml").unwrap();
let config_value = config_str.parse::<Value>().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 config_clone = config.clone();
let screaming = scream.to_string();
let command_channel = channel.to_string();
let thread_invader = random_word::gen(); // change to leetspeak on nick collision
std::thread::spawn(move || {
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 || {
let stream = TcpStream::connect((config_clone.server.as_str(), config_clone.port)).unwrap();
let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
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();
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());
ssl_stream.write_all(response.as_bytes()).unwrap();
}
if message.starts_with("433") { // Numeric reply for nickname in use
let leet_nick = leetspeak::translate(&thread_invader);
if message.starts_with(":ircd.chat 433") { // Numeric reply for nickname in use
let leet_nick = leetspeak::translate_with_level(&thread_invader, &leetspeak::Level::One);
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(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
// 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));
} 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

View File

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

View File

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