fleet is a list of bots.
Bases: object
a fleet contains multiple bots (list of bots). used the datadir set in gozerbot/datadir.py
the locked function.
show available fleet bots.
broadcast txt to all bots.
return bot by name.
do command on a bot.
do a command on all bots.
connect bot to the server.
the locked function.
call exit on all bots. if jabber=True only jabberbots will exit.
return the main bot of the fleet.
return the first jabber bot of the fleet.
initialise a bot.
return list of bot names.
create a bot .. use configuration if provided.
delete bot by object.
replace bot with a new bot.
resume bot from session file.
resume individual bot.
save fleet data and call save on all the bots.
return number of bots in fleet.
start the bots.
call stop() on all fleet bots.
Bases: exceptions.Exception
# gozerbot/fleet.py # # """ fleet is a list of bots. """ __status__ = "seen"
from gozerbot.datadir import datadir from utils.exception import handle_exception from utils.generic import waitforqueue from utils.log import rlog from utils.locking import lockdec from threads.thr import start_new_thread, threaded from config import Config, fleetbotconfigtxt, config from users import users from plugins import plugins from simplejson import load
import Queue import os import types import threading import time import pickle import glob import logging import shutil import thread
fleetlock = thread.allocate_lock() fleetlocked = lockdec(fleetlock)
class FleetBotAlreadyExists(Exception): pass
class Fleet(object): """ a fleet contains multiple bots (list of bots). used the datadir set in gozerbot/datadir.py """ def __init__(self): self.datadir = datadir + os.sep + 'fleet' if not os.path.exists(self.datadir): os.mkdir(self.datadir) self.startok = threading.Event() self.bots = [] def getfirstbot(self): """ return the main bot of the fleet. """ self.startok.wait() return self.bots[0] def getfirstjabber(self): """ return the first jabber bot of the fleet. """ self.startok.wait() for bot in self.bots: if bot.type == 'xmpp': return bot def size(self): """ return number of bots in fleet. """ return len(self.bots) def resume(self, sessionfile): """ resume bot from session file. """ session = load(open(sessionfile)) for name in session['bots'].keys(): reto = None if name == session['name']: reto = session['channel'] start_new_thread(self.resumebot, (name, session['bots'][name], reto)) time.sleep(5) self.startok.set() def makebot(self, name, cfg=None): """ create a bot .. use configuration if provided. """ if self.byname(name): raise FleetBotAlreadyExists("there is already a %s bot in the fleet" % name) rlog(10, 'fleet', 'making bot') bot = None if not cfg: cfg = Config(self.datadir + os.sep + name, 'config', inittxt=fleetbotconfigtxt) cfg.save() if cfg['type'] == 'irc': from gozerbot.irc.bot import Bot bot = Bot(name, cfg) elif cfg['type'] == 'xmpp' or cfg['type'] == 'jabber': from gozerbot.xmpp.bot import Bot bot = Bot(name, cfg) elif cfg['type'] == 'gozernet': from gozerbot.gozernet.bot import GozerNetBot bot = GozerNetBot(name, cfg) else: rlog(10, 'fleet', '%s .. unproper type: %s' % (cfg['name'], cfg['type'])) if bot: cfg['name'] = bot.name = name self.initbot(bot) return bot raise Exception("can't make %s bot" % name) def resumebot(self, botname, data={}, printto=None): """ resume individual bot. """ oldbot = self.byname(botname) if oldbot: oldbot.exit() cfg = Config(datadir + os.sep + 'fleet' + os.sep + botname, 'config') bot = self.makebot(botname, cfg) rlog(100, 'fleet', 'bot made: %s' % str(bot)) if bot: if oldbot: self.replace(oldbot, bot) else: self.bots.append(bot) if not bot.jabber: bot._resume(data, printto) else: start_new_thread(bot.connectwithjoin, ()) def start(self, botlist=[], enable=False): """ start the bots. """ dirs = [] got = [] for bot in botlist: dirs.append(self.datadir + os.sep + bot) if not dirs: dirs = glob.glob(self.datadir + os.sep + "*") for fleetdir in dirs: if fleetdir.endswith('fleet'): continue rlog(10, 'fleet', 'found bot: ' + fleetdir) cfg = Config(fleetdir, 'config') if not cfg: rlog(10, 'fleet', "can't read %s config file" % fleetdir) ; continue name = fleetdir.split(os.sep)[-1] if not name: rlog(10, 'fleet', "can't read botname from %s config file" % fleetdir) ; continue if not enable and not cfg['enable']: rlog(10, 'fleet', '%s bot is disabled' % name) ; continue else: rlog(10, 'fleet', '%s bot is enabled' % name) if not name in fleetdir: rlog(10, 'fleet', 'bot name in config file doesnt match dir name') ; continue try: bot = self.makebot(name, cfg) except FleetBotAlreadyExists: rlog(10, 'fleet', 'there is already a fleetbot with the name %s' % name) ; continue if bot: self.addbot(bot) start_new_thread(bot.connectwithjoin, ()) got.append(bot) self.startok.set() return got def save(self): """ save fleet data and call save on all the bots. """ for i in self.bots: try: i.save() except Exception, ex: handle_exception() def avail(self): """ show available fleet bots. """ return os.listdir(self.datadir) def list(self): """ return list of bot names. """ result = [] for i in self.bots: result.append(i.name) return result def stopall(self): """ call stop() on all fleet bots. """ for i in self.bots: try: i.stop() except: pass def byname(self, name): """ return bot by name. """ for i in self.bots: if name == i.name: return i def replace(self, name, bot): """ replace bot with a new bot. """ for i in range(len(self.bots)): if name == self.bots[i].name: self.bots[i] = bot ; return def initbot(self, bot): """ initialise a bot. """ if bot not in self.bots: if not os.path.exists(self.datadir + os.sep + bot.name): os.mkdir(self.datadir + os.sep + bot.name) if type(bot.cfg['owner']) == types.StringType or type(bot.cfg['owner']) == types.UnicodeType: bot.cfg['owner'] = [bot.cfg['owner'], ] bot.cfg.save() users.make_owner(config['owner'] + bot.cfg['owner']) rlog(10, 'fleet', 'added bot: ' + bot.name) @fleetlocked def addbot(self, bot): """ add a bot to the fleet .. remove all existing bots with the same name. """ if not bot: return False for i in range(len(self.bots)-1, -1, -1): if self.bots[i].name == bot.name: rlog(10, 'fleet', 'removing %s from fleet' % bot.name) ; del self.bots[i] rlog(10, 'fleet', 'adding %s' % bot.name) self.bots.append(bot) return True def connect(self, name): """ connect bot to the server. """ for i in self.bots: if i.name == name: got = i.connect() if got: start_new_thread(i.joinchannels, ()) ; return True else: return False @fleetlocked def delete(self, name): """ delete bot with name from fleet. """ for i in self.bots: if i.name == name: i.exit() self.remove(i) i.cfg['enable'] = 0 i.cfg.save() rlog(10, 'fleet', '%s disabled' % i.name) return True return False def remove(self, bot): """ delete bot by object. """ try: self.bots.remove(bot) ; return True except ValueError: return False def exit(self, name=None, jabber=False): """ call exit on all bots. if jabber=True only jabberbots will exit. """ if not name: threads = [] for i in self.bots: if jabber and not i.jabber: pass else: threads.append(start_new_thread(i.exit, ())) for thr in threads: thr.join() return for i in self.bots: if i.name == name: try: i.exit() except: handle_exception() self.remove(i) return True return False def cmnd(self, event, name, cmnd): """ do command on a bot. """ bot = self.byname(name) if not bot: return 0 from gozerbot.eventbase import EventBase j = plugins.clonedevent(bot, event) j.onlyqueues = True j.txt = cmnd q = Queue.Queue() j.queues = [q] j.speed = 3 start_new_thread(plugins.trydispatch, (bot, j)) result = waitforqueue(q) if not result: return res = ["<%s>" % bot.name, ] res += result event.reply(res) def cmndall(self, event, cmnd): """ do a command on all bots. """ threads = [] for i in self.bots: thread = start_new_thread(self.cmnd, (event, i.name, cmnd)) threads.append(thread) for i in threads: i.join() def broadcast(self, txt): """ broadcast txt to all bots. """ for i in self.bots: i.broadcast(txt)
fleet = Fleet()