Created
December 8, 2013 14:06
-
-
Save joepie91/7858004 to your computer and use it in GitHub Desktop.
Basic IRC bot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
import socket, yaml, random, time | |
import cPickle as pickle | |
ctx = zmq.Context() | |
with open("config.yaml", "r") as cfile: | |
config = yaml.safe_load(cfile) | |
class Bot(object): | |
def __init__(self, hosts, port, nickname, realname, channels, admins): | |
self.hosts = hosts | |
self.port = port | |
self.nickname = nickname | |
self.realname = realname | |
self.channels = channels | |
self.admins = admins | |
self.connected = False | |
self.command_map = { | |
"422": self.join_all_channels, | |
"376": self.join_all_channels, | |
"PRIVMSG": self.receive_message | |
} | |
def split_irc(self, message): | |
if message[0] == ":": | |
prefix = ":" | |
message = message[1:] | |
else: | |
prefix = "" | |
if ":" in message: | |
rest, last = message.split(":", 1) | |
parts = rest.strip().split() + [last] | |
else: | |
parts = message.split() | |
parts[0] = prefix + parts[0] | |
return parts | |
def run(self): | |
while True: # Connect loop | |
host = random.choice(self.hosts) | |
self.sock = socket.socket() | |
try: | |
self.sock.connect((host, self.port)) | |
except socket.error, e: | |
continue # Reconnect | |
self.send_raw("NICK %s" % self.nickname) | |
self.sock.send("USER %s 0 0 :%s\r\n" % (self.nickname, self.realname)) | |
buff = "" | |
while True: # Read loop | |
try: | |
recvdata = self.sock.recv(1024) | |
except socket.error, e: | |
break # Something went wrong, reconnect... | |
if len(recvdata) == 0: | |
break # We have disconnected... | |
buff += recvdata | |
messages = buff.split("\n") | |
buff = messages.pop() | |
for message in messages: | |
self.process_message(self.split_irc(message.strip("\r"))) | |
def send_raw(self, message): | |
self.sock.send("%s\r\n" % message) | |
def send_message(self, recipient, message): | |
if self.connected == True: | |
self.send_raw("PRIVMSG %s :%s" % (recipient, message)) | |
def send_all(self, message): | |
for channel in self.channels: | |
self.send_message(channel, message) | |
def join(self, channel): | |
self.send_raw("JOIN %s" % channel) | |
def join_all_channels(self, message): | |
self.connected = True | |
for channel in self.channels: | |
self.join(channel) | |
def receive_message(self, message): | |
args = message[3].split() | |
sender = message[0][1:].split("!", 1)[0] | |
channel = message[2] # Does NOT deal with PMs yet! | |
try: | |
if sender in self.admins: | |
if args[0] == "!example": | |
# args[1:] will contain all parameters | |
self.send_message(channel, "This is an example command.") | |
except Exception, e: | |
self.send_message(channel, str(e)) | |
def format_time_duration(self, seconds): | |
# http://stackoverflow.com/a/20222351/1332715 | |
days, rem = divmod(seconds, 86400) | |
hours, rem = divmod(rem, 3600) | |
minutes, seconds = divmod(rem, 60) | |
if seconds < 1: | |
seconds = 1 | |
locals_ = locals() | |
magnitudes_str = ("{n} {magnitude}".format(n=int(locals_[magnitude]), magnitude=magnitude) for magnitude in ("days", "hours", "minutes", "seconds") if locals_[magnitude]) | |
return ", ".join(magnitudes_str) | |
def process_message(self, message): | |
if message[0].upper() == "PING": | |
self.send_raw("PONG %s" % message[1]) | |
else: | |
try: | |
self.command_map[message[1].upper()](message) | |
except KeyError, e: | |
pass | |
bot = Bot(config["irc"]["hosts"], config["irc"]["port"], config["irc"]["nickname"], config["irc"]["realname"], config["irc"]["channels"], config["irc"]["admins"]) | |
bot.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
irc: | |
hosts: | |
- kerpia.cryto.net | |
- box.cryto.net | |
- arvel.cryto.net | |
port: 6667 | |
nickname: StatusBot | |
realname: Cryto System Monitoring Service | |
admins: | |
- joepie91 | |
channels: | |
- "#test" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment