bot base class. provides data/methods common to all bots.
Bases: object
Base class for all bots. Inherit from this.
do an action in a channel. .. overload this.
announce a message to all channels. .. overload this
connect the bot to the server. reconnects in the default case.
connect to the server and join channels.
dispatch an event.
execute a message on the bot.
change nick of the bot. .. overload this.
shutdown the bot. overload this.
pass fake txt input as if it was received by the bot. .. overload this.
get topic of a channel. .. overload this.
join a channel using optional password. .. overload this.
join all registered channels. .. overload this.
query names of a channel. .. overload this.
check whether an event originated from the bot owner.
leave a channel. .. overload this.
set ratelimit on a user.
write the event in json to the webservers, use the request that is passed in.
save bot state.
say txt onto the console. overload this for your bot.
send txt to the server. .. overload this
send raw txt to the server. overload this.
start the bots loops. will block until ctrl-c is received.
set topic of a channel. .. overload this.
close sockets of the bot. .. overload this
stop the bot.
send voice txt to the channel. BHJTW ?? nick option ??. overload this.
do a whois query on a nick. overload this.
# gozerbot/botbase.py # # """ bot base class. provides data/methods common to all bots. """ __status__ = "seen"
from threads.thr import start_new_thread from utils.log import rlog from less import Less from persist.pdol import Pdol from utils.dol import Dol from utils.lazydict import LazyDict from persist.persiststate import PersistState from channels import Channels from datadir import datadir from persist.pdod import Pdod from config import config, Config, fleetbotconfigtxt from runner import runners_start from monitor import Monitor from callbacks import callbacks, gn_callbacks from cache import userhosts from wait import Wait, Privwait from eventhandler import mainhandler from exit import globalshutdown from utils.exception import handle_exception from plugins import plugins
from gozerbot.plugs.throttle import state as throttlestate
import time import threading import os import types import sys import copy
cpy = copy.deepcopy
class BotBase(object): """ Base class for all bots. Inherit from this. """ def __init__(self, name, cfg={}): self.name = name self.encoding = sys.getdefaultencoding() if not cfg: cfg = Config(inittxt=fleetbotconfigtxt) if not cfg.has_key('dir'): cfg['dir'] = os.getcwd() if not cfg.has_key('user'): cfg['user'] = 'gozerbot' if not cfg.has_key('type'): cfg['type'] = 'gozernet' self.__dict__.update(cfg) if not cfg.has_key('name'): if 'fleet' in cfg['dir']: self.name = cfg.dir.split(os.sep)[-1] else: self.name = name if not cfg.has_key('nick'): self.nick = 'gozerbot' if not cfg.has_key('server'): self.server = 'server not set' try: self.host = cfg['host'] if not self.host: self.host = self.user.split('@')[1] except (KeyError, IndexError): try: self.host = self.user.split('@')[1] except (ValueError, IndexError): self.host = 'host not set' if not cfg.has_key('port'): self.port = 0 if not cfg.has_key('ipv6'): self.ipv6 = 0 else: self.ipv6 = cfg['ipv6'] if '..' in self.name or '/' in self.name: raise Exception('wrong bot name %s' % self.name) self.datadir = datadir + os.sep + 'fleet' + os.sep + self.name if not os.path.exists(self.datadir): os.mkdir(self.datadir) self.state = Pdod(self.datadir + os.sep + 'state') # bot state if not self.state.has_key('joinedchannels'): self.state['joinedchannels'] = [] if not self.state.has_key('allowed'): self.state['allowed'] = [] if not self.state.has_key('no-op'): self.state['no-op'] = [] if not self.state.has_key('opchan'): self.state['opchan'] = [] self.timejoined = {} self.type = self.type or 'gozernet' if self.type == 'jabber': self.type = 'xmpp' self.networkname = self.server self.jid = "%s@%s" % (self.nick, self.server) self.jids = {} self.shutloop = False self.cfg = cfg # the bots config self.orignick = "" # original nick self.blocking = 1 # use blocking sockets self.lastoutput = 0 # time of last output self.stopped = False # flag to set when bot is to be stopped self.connected = False # conencted flag self.connecting = False # connecting flag self.connectok = threading.Event() # event set when bot has connected self.waitingforconnect = False # flag to indicate we are waiting for connect self.starttime = time.time() # start time of the bot self.nrevents = 0 # number of events processed self.gcevents = 0 # number of garbage collected events self.less = Less(5) # output buffering self.userchannels = Dol() # list of channels a user is in self.channels = Channels(self.datadir + os.sep + 'channels') # channels self.userhosts = PersistState(self.datadir + os.sep + 'userhosts') # userhosts cache self.splitted = [] # list of splitted nicks self.throttle = [] # list of nicks that need to be throttled self.jabber = False # flag is set on jabber bots self.google = False self.callbacks = callbacks self.monitor = Monitor() self.wait = Wait() self.privwait = Privwait() self.error = None runners_start() def ownercheck(self, ievent, txt=None): """ check whether an event originated from the bot owner. """ owner = self.cfg['owner'] or config['owner'] if type(owner) == types.ListType: if ievent.userhost in owner: return 1 elif owner == ievent.userhost: return 1 else: rlog(100, self.name, 'failed owner check %s should be in %s' % (ievent.userhost, owner)) if not txt: ievent.reply("only owner (see config file) is allowed to perform this command") else: ievent.reply("only owner (see config file) %s" % txt) return 0 def save(self): """ save bot state. """ self.channels.save() self.userhosts.save() self.state.save() def stop(self): """ stop the bot. """ self.stopped = True rlog(10, self.name, 'stopped') def exit(self): """ shutdown the bot. overload this. """ pass def connect(self, reconnect=True): """ connect the bot to the server. reconnects in the default case. """ pass def say(self, printto, what, event=None, who=None, how='msg', fromm=None, speed=0, groupchat=False): """ say txt onto the console. overload this for your bot. """ print what def whois(self, nick): """ do a whois query on a nick. overload this. """ pass def sendraw(self, txt): """ send raw txt to the server. overload this. """ print txt def voice(self, channel, txt): """ send voice txt to the channel. BHJTW ?? nick option ??. overload this. """ pass def action(self, channel, txt): """ do an action in a channel. .. overload this. """ pass def _raw(self, txt): """ core method for sending txt. .. overload this. """ print txt def settopic(self, channel, txt): """ set topic of a channel. .. overload this. """ pass def names(self, channel): """ query names of a channel. .. overload this. """ pass def gettopic(self, channel): """ get topic of a channel. .. overload this. """ pass def _dcclisten(self, *args): """ listen for incoming DCC CHAT requests. .. overload this. """ pass def donick(self, nick, save=False, setorig=True): """ change nick of the bot. .. overload this. """ pass def fakein(self, txt): """ pass fake txt input as if it was received by the bot. .. overload this. """ pass def part(self, channel): """ leave a channel. .. overload this. """ pass def serveforever(self): """ start the bots loops. will block until ctrl-c is received. """ self.stopped = False self.shutloop = False while not self.stopped and not self.shutloop: try: import asyncore ; asyncore.poll(timeout=0.01) except ImportError: pass except Exception, ex: handle_exception() globalshutdown() os._exit(1) time.sleep(0.01) mainhandler.handle_one() def join(self, channel, password=""): """ join a channel using optional password. .. overload this. """ pass def joinchannels(self): """ join all registered channels. .. overload this. """ pass def connectwithjoin(self, reconnect=True): """ connect to the server and join channels. """ self.connect(reconnect) self.connectok.wait() start_new_thread(self.joinchannels, ()) def broadcast(self): """ announce a message to all channels. .. overload this""" pass def send(self, txt): """ send txt to the server. .. overload this""" pass def shutdown(self): """ close sockets of the bot. .. overload this""" pass def domsg(self, msg, response=False, wait=False): """ execute a message on the bot. """ if response: msg.reply('executing %s (%s) on %s bot' % (msg.txt, msg.userhost, self.name)) from gozerbot.plugins import plugins if wait: plugins.waitdispatch(self, msg) else: plugins.trydispatch(self, msg) def ratelimit(self, userhost, cpm=20): """ set ratelimit on a user. """ try: throttlestate['level'][userhost] = cpm throttlestate.save() rlog(10, self.name, '%s throttled to %s cpm' % (userhost, cpm)) except Exception, ex: rlog(100, self.name, "can't set throttle of %s" % userhost) handle_exception() def remoteout(self, request, event): """ write the event in json to the webservers, use the request that is passed in. """ request.wfile.write(event.tojson()) def doevent(self, event): """ dispatch an event. """ if not event: return e = cpy(event) if event.isremote: gn_callbacks.check(self, e) else: callbacks.check(self, e) if event.remotecmnd: plugins.trydispatch(self, event)