#!/usr/bin/python3 import socket from os import _exit from random import randint class IRC: """A set of methods for basic IRC communication.""" def __init__(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def set_prefs(self, prefs): """Set environment variables from a dictionary of values.""" self.server = prefs["server"] self.channels = prefs["channels"] self.bot_nick = prefs["bot_nick"] self.admin_user = prefs["admin_user"] self.admin_code = prefs["admin_code"] self.req_prefix = prefs["req_prefix"] self.is_debug = prefs["is_debug"] def msg(self, command, text, *args, **kwargs): """Send messages given the IRC command and text. Optionally specify a message recipient with `recvr=user`.""" recvr = kwargs.get("recvr", "") if recvr != "": recvr += " :" self.sock.sendall(bytes(command + " " + recvr + text + "\n", "utf-8")) def pm(self, text, recipient): """Alias of msg() with the PRIVMSG IRC command and a recipient.""" self.msg("PRIVMSG", text, recvr=recipient) def connect(self): """Connect to the server and sends user/nick information.""" self.sock.connect(self.server) self.msg("USER", self.bot_nick + " " + self.bot_nick + " " + \ self.bot_nick + " ehlo") self.msg("NICK", self.bot_nick) def parse_line(self, line): """Extract the request, the nick and username of the requester, the channel where the request originated and returns a dictionary of values.""" data = {"req": "", "req_chan": "", "nick": "", "user": ""} if (":" + self.req_prefix) in self.line: data["req"] = line.split("PRIVMSG", 1)[1].split(":" + \ self.req_prefix, 1)[1].strip() data["req_chan"] = line.split("PRIVMSG ", 1)[1].split(" :", 1)[0] data["nick"] = line.split("!~", 1)[0][1:] data["user"] = line.split("!~", 2)[1][0:].split("@", 1)[0] return data def keep_alive(self): """Stay connected to a server by responding to server pings.""" self.line = self.sock.recv(2040).decode("utf-8").strip("\n\r") if "PING" in self.line: self.msg("PONG", ":" + self.server[0]) if self.is_debug: print(self.line) def join_chans(self): """Join channels from a list provided in environment settings.""" for c in self.channels: if c.strip() != "" or c.strip() != "#": self.msg("JOIN", c) def map_actions(self, channel): """Listen for bot requests in a channel and match responses.""" data = self.parse_line(self.line) # Respond only in the channel the request was made if channel == data["req_chan"]: # General commands if data["req"] == "rollcall" or data["req"] == "help": rollcall = ( "一、二、三、らーめん缶! " "Hello, I am a ramen vending machine. " "Please type a code to request service: " "!help " "Support: +81 012-700-1MIO " "どうぞめしあがれ。" ) self.pm(rollcall, data["req_chan"]) elif data["req"] == ("water " + self.bot_nick): resp = [ ("\x01ACTION happily pours the hot liquid into a bowl of " "noodles and offers it to ") + data["nick"] + "\x01", "( ^_^)o自自o(^_^ )Cheers!", "Water Level [/////////] 200% - Thanks! (^▽^)" ] self.pm(resp[randint(0, len(resp)-1)], data["req_chan"]) elif data["req"] == ("botsnack " + self.bot_nick): self.pm("Ramen time anytime! ヽ(´▽`)/", data["req_chan"]) # Respond to some commands only in private message if data["req_chan"] == self.bot_nick: if data["req"] == ("exit " + self.admin_code) and \ data["user"].lower() == self.admin_user.lower(): self.pm("Okay, okay, I'll leave. (´・ω・`)", self.admin_user) self.msg("QUIT", ":noodling off") _exit(0)