diff --git a/.gitignore b/.gitignore index 6a18ad4..35ff8b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# App-specific +settings.json + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app.py b/app.py new file mode 100644 index 0000000..6016e15 --- /dev/null +++ b/app.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +from bot import Bot + +bot = Bot("127.0.0.1", 6667, "BabiliBot|py", ["#bots"]) + +def processor(message): + if "PRIVMSG" in message: + name, source, response = parse(message) + bot.send_message(source, "Got response") + if "PING :" in message: + ping(message) + +if __name__ == "__main__": + bot.start(processor, "settings.json") \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100755 index 0000000..b608955 --- /dev/null +++ b/bot.py @@ -0,0 +1,92 @@ +import json +import socket + +class Bot: + def __init__(self, server, port, botnick, channels): + self.ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server = server + self.port = port + self.botnick = botnick + self.channels = channels + self.running = True + + self.recv_size = 2048 + + def send(self, message, *args): + response = message.format(*args) + "\n" + print("DEBUG: ", response) + self.ircsock.send(response.encode()) + + def send_message(target, message, *args): + msg = message.format(*args) + response = "PRIVMSG {0} :{1}".format(target, msg) + "\n" + print("DEBUG: ", response) + ircsock.send(response.encode()) + + def join(self, chan, confirmed=False): + self.send("JOIN {}", chan) + + message = "" + magic_string = "End of /NAMES list." + while magic_string not in message: + message = self.ircsock.recv(self.recv_size).decode() + message = message.strip("\n\r") + print(message) + + def ping(self, message): + response = message.split("PING :")[1] + self.send("PONG :{0}", response) + + def parse(self, message): + before, after = message.split("PRIVMSG ", 1) + name = before.split("!", 1)[0][1:] + source, response = after.split(" :", 1) + return name, source, response + + def load_settings(self, location): + with open(location, "r") as f: + self.settings = json.loads(f.read()) + + def start(self, callback, settings): + message = "" + registered = False + confirmed = True + + self.ircsock.connect((self.server, self.port)) + self.send("USER {0} {0} {0} {0}", self.botnick) + self.send("NICK {0}", self.botnick) + + self.load_settings(settings) + + password = self.settings["password"] or "" + confirm = self.settings["confirm"] or "" + email = self.settings["email"] or "" + + magic_string = "MODE {} +r".format(self.botnick) + while magic_string not in message: + message = self.ircsock.recv(self.recv_size).decode() + message = message.strip("\n\r") + print(message) + if not registered and "Password accepted" in message: + registered = True + if not registered and "choose a different nick" in message: + self.send_message("NickServ", "IDENTIFY {}", password) + if not confirmed and "Your account will expire" i message: + self.send_message("NickServ", "CONFIRM {}", self.confirm) + confirmed = True + + print("DEBUG: Joining") + + for channel in self.channels: + self.join(channel) + + print("DEBUG: Joined") + + while self.running: + message = self.ircsock.recv(self.recv_size).decode("UTF-8") + message = message.strip('\n\r') + print(message) + + callback() + + # = #channel : \ No newline at end of file diff --git a/settings.example.json b/settings.example.json new file mode 100644 index 0000000..e4faec4 --- /dev/null +++ b/settings.example.json @@ -0,0 +1,5 @@ +{ + "password": "", + "email": "", + "confirm": "" +} \ No newline at end of file