firebot/contrib/arsenic.py

176 lines
5.6 KiB
Python
Raw Normal View History

2007-08-24 10:57:29 -06:00
#! /usr/bin/env python
import firebot
from finger import Finger
from procbot import ProcBot, Runner
import shorturl
import asyncore
import irc
import re
import os
import time
import socket
2008-03-27 16:57:17 -06:00
import rp
2008-09-05 09:30:00 -06:00
import random
import webretriever
webretriever.proxy = ('proxyout.lanl.gov', 8080)
2007-08-24 10:57:29 -06:00
2007-10-04 15:15:41 -06:00
def esc(arg):
return "'" + arg.replace("'", r"'\''") + "'"
def lesc(args):
return [esc(arg) for arg in args]
2007-08-24 10:57:29 -06:00
class Arsenic(firebot.FireBot, ProcBot):
2007-10-04 15:15:41 -06:00
debug = False
2007-08-24 10:57:29 -06:00
bindings = []
ping_interval = 120
2008-03-27 16:57:17 -06:00
chatty = True # Maybe #x can play nice now
2007-08-24 10:57:29 -06:00
def __init__(self, *args, **kwargs):
firebot.FireBot.__init__(self, *args, **kwargs)
self.seen = {}
self.lusers = {}
2007-10-04 15:15:41 -06:00
self.heartbeat_interval=0.01
2007-08-24 10:57:29 -06:00
self.lag = 0
self.whinecount = 0
2007-10-04 15:15:41 -06:00
def runcmd(self, sender, forum, addl, match):
command = match.group('command')
2007-12-12 13:43:11 -07:00
args = lesc(lesc(match.group('args').split(' ')))
2007-10-04 15:15:41 -06:00
argstr = ' '.join(args)
2007-12-12 13:43:11 -07:00
print argstr
2007-10-04 15:15:41 -06:00
Runner('%s %s' % (command, argstr),
lambda l,r: self.proc_cb('%s: ' % command, sender, forum, l, r))
bindings.append((re.compile(r"^(?P<command>whois) +(?P<args>.*)$"),
runcmd))
bindings.append((re.compile(r"^(?P<command>host) +(?P<args>.*)$"),
runcmd))
2007-08-24 10:57:29 -06:00
def rp(self, sender, forum, addl, match):
2008-03-27 16:57:17 -06:00
long = match.group('long') and True
conn = rp.make_connection()
rows = rp.rp(match.group('args').strip(), conn=conn)
ret = rp.format(rows, long=long)
if long:
forum.msg('[Sending privately]')
self.despool(sender, ret)
else:
self.despool(forum, ret)
bindings.append((re.compile(r"^rp +(?P<long>(-l|--long) +)?(?P<args>.*)$"),
2007-08-24 10:57:29 -06:00
rp))
def finger(self, sender, forum, addl, match):
command = 'finger'
argstr = match.group('args')
Finger(('finger.lanl.gov', 79),
argstr,
lambda l: self.proc_cb('%s: ' % command, sender, forum, l, 0))
bindings.append((re.compile(r"^(?P<command>finger) +(?P<args>.*)$"),
finger))
def lag(self, sender, forum, addl, match):
forum.msg("My server lag is %.3f seconds." % self.lag)
bindings.append((re.compile(r"^\008[,: ]+ (what is the )?(server )?lag"),
lag))
2008-09-05 09:30:00 -06:00
def pii(self, sender, forum, addl, match):
ssns = []
for i in range(10):
ssns.append('%03d-%02d-%04d' % (random.randint(1, 999),
random.randint(1, 99),
random.randint(1, 9999)))
forum.msg('Security incident! %s' % ' '.join(ssns))
bindings.append((re.compile(r'^pii$'),
pii))
2007-08-24 10:57:29 -06:00
bindings.extend(firebot.FireBot.bindings)
##
## IRC protocol-level extensions
##
def add_luser(self, luser, channel):
# Keeps track of what users have been on what channels, and
# sends an invite to luser for every channel in which they're
# listed. If they're already in the channel, the server just
# sends back an error. This has the effect of letting people
# get back into invite-only channels after a disconnect.
who = luser.name()
self.lusers[channel.name()][who] = luser
2007-10-04 15:15:41 -06:00
for chan, l in self.lusers.iteritems():
2007-08-24 10:57:29 -06:00
if chan == channel.name():
continue
2007-10-04 15:15:41 -06:00
t = l.get(who)
2007-08-24 10:57:29 -06:00
if t and t.host == luser.host:
2007-10-04 15:15:41 -06:00
self.write(['INVITE', who, chan])
2007-08-24 10:57:29 -06:00
def cmd_join(self, sender, forum, addl):
if sender.name() == self.nick:
# If it was me, get a channel listing and beg for ops
2007-10-04 15:15:41 -06:00
self.write(['WHO', forum.name()])
2007-08-24 10:57:29 -06:00
forum.notice('If you op me, I will op everyone who joins this channel.')
self.lusers[forum.name()] = {}
else:
# Otherwise, add the user
self.add_luser(sender, forum)
forum.write(['MODE', forum.name(), '+o'], sender.name())
def cmd_352(self, sender, forum, addl):
# Response to WHO
forum = irc.Channel(self, addl[0])
who = irc.User(self, addl[4], addl[1], addl[2])
self.add_luser(who, forum)
def cmd_invite(self, sender, forum, addl):
# Join any channel to which we're invited
self.write('JOIN', forum.name())
def cmd_pong(self, sender, forum, addl):
now = time.time()
self.lag = now - float(addl[0])
def cmd_482(self, sender, forum, addl):
2007-10-04 15:15:41 -06:00
forum = self.recipient(addl[0])
2007-08-24 10:57:29 -06:00
self.whinecount += 1
if (self.whinecount == 2 or
self.whinecount == 4 or
self.whinecount == 8):
forum.notice("Just a reminder: I can't op anyone unless I'm opped myself.")
elif (self.whinecount == 16):
forum.notice("This is the last time I'm going to beg for ops. Puh-leaze?")
if __name__ == '__main__':
2007-10-04 15:15:41 -06:00
import daemon
2008-03-27 16:57:17 -06:00
import sys
2007-10-04 15:15:41 -06:00
2008-03-27 16:57:17 -06:00
debug = False
if "-d" in sys.argv:
debug = True
2007-10-04 15:15:41 -06:00
if not debug:
# Become a daemon
log = file('arsenic.log', 'a')
daemon.daemon('arsenic.pid', log, log)
2007-08-24 10:57:29 -06:00
# Short URL server
us = shorturl.start(('', 0))
firebot.URLSERVER = (socket.gethostbyaddr(socket.gethostname())[0],
us.getsockname()[1])
NICK = ['arsenic']
INFO = "I'm a little printf, short and stdout"
2007-10-04 15:15:41 -06:00
l1 = Arsenic(('irc.lanl.gov', 6667),
2007-08-24 10:57:29 -06:00
NICK,
INFO,
2007-12-12 13:43:59 -07:00
["#x", "#csirt"],
2007-10-04 15:15:41 -06:00
ssl=False)
l1.debug = debug
2007-08-24 10:57:29 -06:00
2007-10-04 15:15:41 -06:00
irc.run_forever(0.01)