Source code for bot.__init__

# bot/__init__.py
#
#

""" bot package. """

__version__ = 19

## IMPORTS 

from bot.utils import *
from bot.log import datefmt

## BASIC IMPORTS

import collections
import threading
import logging
import getpass
import _thread
import socket
import queue
import types
import errno
import select
import fcntl
import uuid
import json
import time
import imp

import sys
import os
import re

try: import readline
except: error()

## ERRORS

[docs]class Error(BaseException): pass
[docs]class OverloadError(Error): pass
[docs]class MissingArgument(Error): pass
[docs]class MissingOutFunction(Error): pass
[docs]class NoText(Error): pass
[docs]class NoDate(Error): pass
[docs]class NoPath(Error): pass
[docs]class NoJSON(Error): pass
[docs]class NoFileName(Error): pass
[docs]class SignatureError(Error): pass
[docs]class NoSuchBotType(Error): pass
[docs]class NoEvent(Error): pass
[docs]class RemoteDisconnect(Error): pass
[docs]class NotOne(Error): pass
[docs]class TargetMissing(Error): pass ## BOOT
[docs]def boot(*args, **kwargs): global kernel cfg = args[0] kernel.cfg.update(cfg) if cfg.shell: hello("BOTJE") set_workdir(kernel.cfg.workdir) if not kernel.cfg.loglevel: cfg.loglevel = "error" from bot.log import log_config log_config(cfg.loglevel) if kernel.cfg.loglevel: logging.warn("E G G S") logging.warn("") show_eggs() if kernel.cfg.loglevel: logging.warn("") logging.warn("C O N F I G") logging.warn("") for line in kernel.cfg.show(): logging.warn(line) if kernel.cfg.loglevel: logging.warn("") logging.warn("B O O T") logging.warn("") return kernel ## WORKDIR
[docs]def set_workdir(*args, **kwargs): global kernel workdir = args[0] if not workdir: workdir = "bot.workdir" wd = workdir.split(os.sep)[-1] if not wd: wd = workdir.split(os.sep)[-2] if not kernel.cfg.workdir: kernel.cfg.workdir = j(os.getcwd(), wd) kernel.cfg.rootlist = [] kernel.cfg.rootlist.append(kernel.cfg.workdir) kernel.cfg.rootlist.append(j("backups", day(), "")) make_dir(kernel.cfg.workdir) ## BASE
[docs]class Object(dict): def __getattribute__(zelf, *args, **kwargs): name = args[0] result = "" if name == "date": return zelf.Date or zelf.added or "" if name == "what": result = get_cls(zelf) if name == "modname": result = get_modname(zelf) if name == "plugname": result = get_plugname(3) if name == "func": result = get_func(5) if name == "how": result = get_how(2) if name == "kind": result = mj(zelf.modname, zelf.what, zelf.func) if name == "stdin": return sys.stdin if name == "stdout": return sys.stdout if result: zelf[name] = result ; return zelf[name] return dict.__getattribute__(zelf, *args, **kwargs) def __getattr__(zelf, name): try: return zelf[name] except KeyError: if name == "timed": zelf["timed"] = short_date(zelf.Date or zelf.date or zelf.published) or to_time(zelf.added) if name == "_result": zelf["_result"] = Object() if name == "_status": zelf["_status"] = Object() if name == "_ready": zelf["_ready"] = threading.Event() try: return zelf[name] except KeyError: return "" def __setattr__(zelf, name, value): return dict.__setitem__(zelf, name, value) def __exists__(zelf, a): try: return zelf[a] except KeyError: False def __lt__(zelf, a): return time_stamp(zelf.ddate) < time_stamp(a.ddate) ## TOUCH
[docs] def touch(zelf, *args, **kwargs): try: res = getattr(zelf, args[0]) except (TypeError, AttributeError): res = None return res ## LOCATORS
[docs] def get_root(zelf, *args, **kwargs): return j(os.path.expanduser("~"), *args)
[docs] def get_roots(zelf, *args, **kwargs): result = [] return result
[docs] def get_target(zelf): if "_target" in zelf: return zelf._target return None
[docs] def get_all(zelf, *args, **kwargs): attr = args[0] result = [] for obj in zelf.objects(): if attr in obj and obj[attr]: result.append(obj) return result ## OUTPUT
[docs] def make_json(zelf, *args, **kwargs): return json.dumps(zelf.reduced(*args, **kwargs), default=smooth, *args, **kwargs)
[docs] def make_full(zelf, *args, **kwargs): return json.dumps(zelf, default=smooth, *args, **kwargs)
[docs] def make_signature(zelf, sig=None): return str(hashlib.sha1(bytes(str(sig or zelf), "utf-8")).hexdigest())
[docs] def make_path(zelf, *args, **kwargs): path = zelf.get_path(*args, **kwargs) ; make_dir(path) ; return path ## INPUT
[docs] def load(zelf, *args, **kwargs): if args: path = zelf.make_path(*args, **kwargs) else: path = zelf.make_path() return zelf.load_file(path)
[docs] def load_file(zelf, *args, **kwargs): path = args[0] logging.debug("load_file %s" % " ".join(args)) ondisk = zelf.read(path) fromdisk = json.loads(ondisk) if "data" in fromdisk: zelf.update(fromdisk["data"]) return zelf
[docs] def load_json(zelf, *args, **kwargs): zelf.update(json.loads(args[0]))
[docs] def read(zelf, *args, **kwargs): logging.debug("read %s" % " ".join(args)) path = args[0] try: f = open(path, "r") except IOError as ex: if ex.errno == errno.ENOENT: return "{}" raise if zelf.do_test: f.line_buffering = False res = "" for line in f: if not line.strip().startswith("#"): res += line if not res.strip(): return "{}" f.close() return res ## PERSISTENCE
[docs] def dump(zelf, *args, **kwargs): # object attributes settins before save path = args[0] zelf.path = path todisk = Object() todisk.data = zelf.reduced() todisk.how = zelf.how todisk.create_type = zelf.what todisk.stime = time.ctime(time.time()) todisk.modname = zelf.modname todisk.version = __version__ todisk.signature = zelf.make_signature() try: result = todisk.make_json(indent=2, ensure_ascii=False) except TypeError: raise NoJSON() return result
[docs] def save(zelf, *args, **kwargs): if not args: t = rtime() else: t = args[0] for path in kernel.cfg.rootlist: root = zelf.get_root(path, t) make_dir(root) zelf.sync(root)
[docs] def sync(zelf, *args, **kwargs): # syn the object to disk try: path = args[0] except IndexError: path = zelf.path logging.info("save %s" % " ".join(args)) fn = path.split(os.sep)[-1] todisk = zelf.dump(path, **kwargs) datafile = open(path + ".tmp", 'w') fcntl.flock(datafile, fcntl.LOCK_EX | fcntl.LOCK_NB) datafile.write(headertxt % (fn, __version__, "%s characters" % len(todisk))) datafile.write(todisk) datafile.write("\n") fcntl.flock(datafile, fcntl.LOCK_UN) datafile.close() os.rename(path + ".tmp", path) logging.warn("saved %s" % path) return zelf ## STATE
[docs] def register(zelf, *args, **kwargs): name = args[0] obj = args[1] zelf[name] = obj
[docs] def reduced(zelf, *args, **kwargs): res = Object() for key in zelf.keys(): k = str(key) if k.startswith("_"): continue if k in ["args", "rest", "first",]: continue if args and k in args[0]: continue res[k] = zelf[k] return res
[docs] def pretty(zelf): return json.dumps(zelf, indent=2) ## OBJECTORS
[docs] def objects(zelf, *args, **kwargs): path = zelf.get_root(kernel.cfg.workdir, *args, **kwargs) flist = list_files(path, **kwargs) res = [] for fnn in flist: try: obj = Object().load_file(fnn) except ValueError: logging.warn("no json in %s" % fnn) ; continue if "key" in kwargs and kwargs["key"] not in obj: continue res.append(obj) logging.debug("%s objects found" % len(res)) return res
[docs] def has_obj(zelf, *args, **kwargs): key, value = args for obj in zelf.objects(): if key in obj and value in obj[key]: return True return False ## RESULT
[docs] def parse(zelf, *args, **kwargs): try: zelf.ucmnd, zelf.rest = zelf.txt.split(" ", 1) except: zelf.ucmnd = zelf.txt ; zelf.rest = "" if zelf.ucmnd and zelf.ucmnd[0] == ".": zelf.ucmnd = zelf.ucmnd[1:] return zelf
[docs] def prepare(zelf, *args, **kwargs): zelf.opts = get_opts(zelf.txt) zelf.args = get_args(zelf.txt) zelf.knobs = get_knobs(zelf.txt) zelf.parse() return zelf
[docs] def ready(zelf): zelf._ready.set()
[docs] def wait(zelf, sec=180.0): try: zelf._ready.wait(sec) except: pass
[docs] def add(zelf, *args, **kwargs): zelf._result[time.time()] = args[0]
[docs] def reply(zelf, *args, **kwargs): if zelf.outer: zelf.outer.write(str(args[0]) + "\n") ; zelf.outer.flush() ; return zelf.say(zelf.channel, args[0])
[docs] def say(zelf, *args, **kwargs): zelf._target.say(args[0], args[1])
[docs] def show(zelf): return ["%s=%s" % (a, b) for a, b in zelf.items() if b]
[docs] def display(zelf, *args, **kwargs): for res in sorted(zelf._result.keys()): d = zelf._result[res] zelf.say(zelf.channel or "", d) ## TASKS
[docs]class Runner(threading.Thread): def __init__(zelf, *args, **kwargs): threading.Thread.__init__(zelf, None, zelf._loop, "thread.%s" % str(time.time()), args, kwargs) zelf.setDaemon(True) zelf._queue = queue.Queue() zelf._outqueue = queue.Queue() zelf._state = "idle" def _loop(zelf): logging.info("start %s" % str(zelf)) while zelf._state in ["running", "once", ]: args, kwargs = zelf._queue.get() if zelf._state == "stop": break func = args[0] try: func(*args[1:], **kwargs) except: error() time.sleep(0.001) logging.warn("stop %s" % str(zelf))
[docs] def stop(zelf, *args, **kwargs): zelf._state = "stop"
[docs] def put(zelf, *args, **kwargs): zelf._queue.put((args, kwargs)) ## DISPATCH
[docs]class Dispatcher(Object): max = 50 runners = collections.deque()
[docs] def register(zelf, cbtype, cb, *args, **kwargs): logging.debug("register %s" % cbtype) if cbtype not in zelf: zelf[cbtype] = [] zelf[cbtype].append(cb)
[docs] def dispatch(zelf, *args, **kwargs): event = args[0] event.prepare() logging.info("event %s" % str(event)) if event.etype: try: for func in zelf[event.etype]: func(event) except KeyError: pass if event.ucmnd: if event.ucmnd not in kernel: return try: for func in zelf[event.ucmnd]: func(event) except KeyError: pass except: error()
[docs] def stop(zelf, name=None): for runner in zelf.runners: if name and name not in runner.name: continue runner.stop()
[docs] def put(zelf, *args, **kwargs): target = zelf.make_new() target.put(*args, **kwargs) return target
[docs] def make_new(zelf, *args, **kwargs): if len(zelf._runners) < zelf.max: runner = Runner(*args, **kwargs) runner.start() zelf.runners.append(runner) else: runner = random.choice(zelf._runners) return runner
[docs] def cleanup(zelf, dojoin=False): todo = [] for runner in zelf.runners: if runner.stopped or not len(runner.queue): todo.append(runner) for runner in todo: runner.stop() ; zelf.runners.remove(runner) ## PLUGINS
[docs]class Plugins(Object):
[docs] def get_names(zelf, plugsdir): return [x[:-3] for x in os.listdir(plugsdir) if x.endswith(".py")]
[docs] def load_plugs(zelf, path): logging.warn("plugs %s" % path) for plugname in zelf.get_names(path): if "__" in plugname: continue try: zelf[plugname] = zelf.load_mod(plugname, path, force=True) except: error() ; continue
[docs] def load_package(zelf, modname): mod = __import__(modname) path, fn = os.path.split(mod.__file__) path += os.sep + "plugs" zelf.load_plugs(path)
[docs] def load_mod(zelf, plugname, pdir="", force=False): logging.info("load %s - %s" % (zelf.what.lower(), plugname)) if plugname in zelf: if not force: return zelf[plugname] zelf[plugname] = imp.reload(zelf[plugname]) else: if not pdir: pdir = j(zelf.root, "plugs") search = imp.find_module(plugname, [pdir,]) zelf[plugname] = imp.load_module(plugname, *search) zelf.plug_exec(plugname, "init") return zelf[plugname]
[docs] def plug_exec(zelf, plugname, item): try: todo = getattr(zelf[plugname], item) ; todo() ; logging.info("exec %s" % get_name(todo)) except AttributeError: pass
[docs] def exit(zelf, *args, **kwargs): for plugname in zelf.reduced(): try: zelf.plug_exec(plugname, "shutdown") ; del zelf[plugname] except KeyError: pass
[docs] def reload(zelf, plugname, force=False): zelf.unload(plugname) mod = zelf.load_mod(plugname, force) return mod ## BOTS
[docs]class Bot(Dispatcher):
[docs] def exit(zelf, *args, **kwargs): pass
[docs] def begin(zelf, *args, **kwargs): if zelf not in kernel.fleet: kernel.fleet.append(zelf) zelf.connect() if not zelf._state: zelf._state = "running" while zelf._state in ["running", "once"]: time.sleep(0.01) zelf.do_one() if zelf._state == "once": break
[docs] def do_one(zelf, *args, **kwargs): pass
[docs] def get_prompt(zelf, *args, **kwargs): return ""
[docs] def connect(zelf, *args, **kwargs): pass
[docs] def announce(zelf, *args, **kwargs): if zelf.channels: for channel in zelf.channels: zelf.say(channel, args[0], **kwargs) else: zelf.say(*args, **kwargs) ## CONSOLE
[docs]class ConsoleBot(Bot): def _raw(zelf, *args, **kwargs): txt = args[0] try: sys.stdout.write(txt) ; sys.stdout.write("\n") ; sys.stdout.flush() except Exception as ex: logging.warn(str(ex))
[docs] def say(zelf, *args, **kwargs): try: txt = args[1] except IndexError: txt = args[0] zelf._raw(txt)
[docs] def get_prompt(zelf, *args, **kwargs): return "%s -=- %s%s<%s " % (time.strftime(datefmt), BOLD, YELLOW, ENDC)
[docs] def do_one(zelf, *args, **kwargs): o = Object() if not kernel.cfg.shell: o.txt = " ".join(kernel.cfg.runargs) ; zelf._state = "once" else: o.txt = input(zelf.get_prompt()) o._target = zelf o.prepare() kernel.dispatch(o) return o ## IRC
[docs]class IRCBot(Bot): marker = "\r\n" cc = "." def __init__(zelf, *args, **kwargs): Bot.__init__(zelf, *args, **kwargs) zelf.connected = threading.Event() #zelf.register("250", zelf._onconnect) zelf.register("001", zelf._onconnect) zelf.register("513", zelf.handle_513) zelf.register("433", zelf.handle_433) zelf.register("PING", zelf.handle_ping) zelf.register("INVITE", zelf.handle_invite) zelf.register("PRIVMSG", zelf.handle_privmsg) zelf._lock = _thread.allocate_lock() zelf._buffer = [] zelf._lastline = "" zelf.encoding = "utf-8" zelf.server = zelf.server or "localhost" zelf.port = zelf.port or 6667 zelf.nick = zelf.nick or "bot" if not zelf.channels: zelf.channels = [] if zelf.channel and zelf.channel not in zelf.channels: zelf.channels.append(zelf.channel) def _raw(zelf, txt): logging.warn("> %s" % txt) if not txt.endswith(zelf.marker): txt += zelf.marker txt = bytes(txt, zelf.encoding) if 'ssl' in zelf and zelf.ssl: zelf.sock.write(txt) else: zelf.sock.send(txt[:512]) def _connect(zelf): zelf.stopped = False if zelf.ipv6: zelf.oldsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: zelf.oldsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) zelf.server = zelf.bind() logging.warn('connect %s - %s (%s)' % (zelf.server, zelf.port, zelf.name)) zelf.oldsock.settimeout(60) zelf.oldsock.connect((zelf.server, int(str(zelf.port or 6667)))) zelf.blocking = 1 zelf.oldsock.setblocking(zelf.blocking) logging.warn('connection made to %s (%s)' % (zelf.server, zelf.name)) zelf.fsock = zelf.oldsock.makefile("r") if zelf.blocking: zelf.oldsock.settimeout(301.0) if 'ssl' in zelf and zelf['ssl']: zelf.sock = socket.ssl(zelf.oldsock) else: zelf.sock = zelf.oldsock zelf.connecttime = time.time() return True def _onconnect(zelf, *args, **kwargs): logging.warn("logged on !!") if "onconnect" in zelf: time.sleep(2) ; zelf._raw(zelf.onconnect) if "servermodes" in zelf: zelf._raw("MODE %s %s" % (zelf.nick, zelf.servermodes)) zelf.join_channels(*args, **kwargs) zelf.ready() def _dodcc(zelf, event, s): s.send(bytes('Welcome to BOTJE ' + event.nick + " !!\n", zelf.encoding)) _thread.start_new_thread(zelf._dccloop, (event, s)) def _dccloop(zelf, event, s): sockfile = s.makefile('rw') s.setblocking(True) while 1: try: res = sockfile.readline() if not res: break res = res.rstrip() logging.warn("< DCC %s" % res) o = Object(_target=zelf, txt=res) o.outer = sockfile o.prepare() kernel.dispatch(o) except socket.timeout: time.sleep(0.01) except socket.error as ex: if ex.errno in [EAGAIN, ]: continue else: raise except Exception as ex: error() sockfile.close() def _dccconnect(zelf, event): try: addr = event.args[3] ; port = event.args[4][:-1] port = int(port) if re.search(':', addr): s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((addr, port)) except Exception as ex: error() ; return zelf._dodcc(event, s)
[docs] def do_one(zelf, *args, **kwargs): if not zelf._buffer: zelf.read_some() try: line = zelf._buffer.pop(0) except IndexError: return Object() e = Object() e._target = zelf o = irc_parse(e, line.rstrip()) o.prepare() zelf.dispatch(o)
[docs] def read_some(zelf, *args, **kwargs): try: if "ssl" in zelf and zelf.ssl: inbytes = zelf.sock.read() else: inbytes = zelf.sock.recv(512) except Exception as ex: error() try: txt = str(inbytes, zelf.encoding) except UnicodeDecodeError: txt = " " if txt == "": raise RemoteDisconnect() zelf._lastline += txt splitted = zelf._lastline.split(zelf.marker) for s in splitted[:-1]: logging.warn("< %s" % s) ; zelf._buffer.append(s) zelf._lastline = splitted[-1]
[docs] def send(zelf, txt): zelf._raw(txt) ; time.sleep(3.0)
[docs] def bind(zelf): server = zelf.server try: zelf.oldsock.bind((server, 0)) except socket.error: if not server: try: socket.inet_pton(socket.AF_INET6, zelf.server) except socket.error: pass else: server = zelf.server if not server: try: socket.inet_pton(socket.AF_INET, zelf.server) except socket.error: pass else: server = zelf.server if not server: ips = [] try: for item in socket.getaddrinfo(zelf.server, None): if item[0] in [socket.AF_INET, socket.AF_INET6] and item[1] == socket.SOCK_STREAM: ip = item[4][0] if ip not in ips: ips.append(ip) except socket.error: pass else: server = random.choice(ips) return server
[docs] def logon(zelf): if "password" in zelf: zelf._raw("PASS %s" % zelf.password) logging.warn('logging in on %s - this may take a while' % zelf.server) zelf._raw("NICK %s" % zelf.nick or "bot") zelf._raw("USER %s localhost %s :%s" % (zelf.username or "botje", zelf.server or "localhost", zelf.realname or "botje"))
[docs] def say(zelf, *args, **kwargs): try: channel, txt = args except ValueError: channel = zelf.channel ; txt = args[0] zelf.privmsg(channel, txt)
[docs] def join_channels(zelf, *args, **kwargs): for channel in zelf.channels: zelf.join(channel)
[docs] def broadcast(zelf, txt): for i in zelf.channels: zelf.say(i, txt)
[docs] def connect(zelf, reconnect=True): try: res = zelf._connect() except: error() ; return if res: time.sleep(1) ; zelf.logon() return res
[docs] def close(zelf): if 'ssl' in zelf and zelf['ssl']: zelf.oldsock.shutdown(2) ; zelf.oldsock.close() else: zelf.sock.shutdown(2) ; zelf.sock.close() zelf.fsock.close()
[docs] def handle_ping(zelf, event): zelf.pongcheck = True ; zelf.pong()
[docs] def handle_433(zelf, event): zelf.donick(event.arguments[1] + "_")
[docs] def handle_invite(zelf, event): zelf.join(event.channel)
[docs] def handle_privmsg(zelf, event): if event.txt.startswith("\001DCC"): zelf._dccconnect(event) ; return if event.txt and event.txt[0] == zelf.cc: event.prepare() kernel.dispatch(event)
[docs] def handle_513(zelf, event): zelf._raw("PONG %s" % event.arguments[6])
[docs] def handle_ctcp(zelf, event): if event.txt and event.txt[0] == zelf.cc: resolve(event)
[docs] def donick(zelf, nick, setorig=False, save=False, whois=False): zelf.send('NICK %s\n' % nick[:16])
[docs] def join(zelf, channel, password=None): if password: zelf._raw('JOIN %s %s' % (channel, password)) else: zelf._raw('JOIN %s' % channel)
[docs] def part(zelf, channel): zelf.send('PART %s' % channel) if channel in zelf.channels: zelf.channels.remove(channel) ; zelf.save()
[docs] def who(zelf, who): zelf.send('WHO %s' % who.strip())
[docs] def names(zelf, channel): zelf.send('NAMES %s' % channel)
[docs] def whois(zelf, who): zelf.send('WHOIS %s' % who)
[docs] def privmsg(zelf, printto, what): zelf.send('PRIVMSG %s :%s' % (printto, what))
[docs] def voice(zelf, channel, who): zelf.send('MODE %s +v %s' % (channel, who))
[docs] def doop(zelf, channel, who): zelf.send('MODE %s +o %s' % (channel, who))
[docs] def delop(zelf, channel, who): zelf.send('MODE %s -o %s' % (channel, who))
[docs] def quit(zelf, reason='https://pikacode.com/milla/botje'): zelf.send('QUIT :%s' % reason)
[docs] def notice(zelf, printto, what): zelf.send('NOTICE %s :%s' % (printto, what))
[docs] def ctcp(zelf, printto, what): zelf.send("PRIVMSG %s :\001%s\001" % (printto, what))
[docs] def ctcpreply(zelf, printto, what): zelf.send("NOTICE %s :\001%s\001" % (printto, what))
[docs] def action(zelf, printto, what, event=None, *args, **kwargs): zelf.send("PRIVMSG %s :\001ACTION %s\001" % (printto, what))
[docs] def getchannelmode(zelf, channel): zelf.send('MODE %s' % channel)
[docs] def settopic(zelf, channel, txt): zelf.send('TOPIC %s :%s' % (channel, txt))
[docs] def ping(zelf, *args, **kwargs): zelf.send('PING :%s' % zelf.server)
[docs] def pong(zelf, *args, **kwargs): zelf.send('PONG :%s' % zelf.server) ## irc_parse function
[docs]def irc_parse(obj, *args, **kwargs): rawstr = str(args[0]) zelf = obj zelf.servermsg = False splitted = re.split('\s+', rawstr) if not rawstr[0] == ':': zelf.servermsg = True zelf.prefix = splitted[0] if zelf.servermsg: zelf.etype = zelf.prefix else: zelf.etype = splitted[1] try: nickuser = zelf.prefix.split('!') zelf.origin = nickuser[1] zelf.nick = nickuser[0][1:] except IndexError: zelf.origin = zelf.prefix ; zelf.servermsg = True if zelf.etype in pfc: zelf.arguments = splitted[2:pfc[zelf.etype]+2] txtsplit = re.split('\s+', rawstr, pfc[zelf.etype]+2) zelf.txt = txtsplit[-1] else: zelf.arguments = splitted[2:] if zelf.arguments: zelf.target = zelf.arguments[0] zelf.postfix = ' '.join(zelf.arguments) if not "txt" in zelf: zelf.txt = rawstr.rsplit(":")[-1] if zelf.txt.startswith(":"): zelf.txt = zelf.txt[1:] if not "channel" in zelf: for c in zelf.arguments + [zelf.txt, ]: if c.startswith("#"): zelf.channel = c if zelf.servermsg: zelf.origin = zelf.origin[1:-1] zelf.channel = zelf.origin if not "origin" in zelf: zelf.origin = zelf.channel if not "target" in zelf: zelf.target = zelf.channel or zelf.origin return obj ## XMPP
[docs]class XMPPBot(Bot): def __init__(zelf, *args, **kwargs): import sleekxmpp from sleekxmpp import clientxmpp Bot.__init__(zelf, *args, **kwargs) zelf.port = zelf.port or 5222 logging.warn("creating xmpp %s" % str(zelf)) zelf.queue = queue.Queue() zelf.xmpp = clientxmpp.ClientXMPP(zelf.user, getpass.getpass()) zelf.xmpp.add_event_handler("session_start", zelf.session_start) zelf.xmpp.add_event_handler("message", zelf.handle_message) zelf.xmpp.add_event_handler('disconnected', zelf.handle_disconnected) zelf.xmpp.add_event_handler('connected', zelf.handle_connected) zelf.xmpp.add_event_handler('presence_available', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_dnd', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_xa', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_chat', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_away', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_unavailable', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_subscribe', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_subscribed', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_unsubscribe', zelf.handle_presence) zelf.xmpp.add_event_handler('presence_unsubscribed', zelf.handle_presence) zelf.xmpp.add_event_handler('groupchat_message', zelf.handle_message) zelf.xmpp.add_event_handler('groupchat_presence', zelf.handle_presence) zelf.xmpp.add_event_handler('groupchat_subject', zelf.handle_presence) zelf.xmpp.add_event_handler('failed_auth', zelf.handle_failedauth) zelf.xmpp.exception = zelf.exception zelf.xmpp.use_signals() zelf.openfire = False if zelf.openfire: import ssl zelf.xmpp.ssl_version = ssl.PROTOCOL_SSLv3 zelf._connected = threading.Event() zelf.channels = [] def _raw(zelf, txt): zelf.xmpp.send_raw(txt)
[docs] def connect(zelf): try: zelf.xmpp.connect((zelf.server, zelf.port or 5222), use_ssl=zelf.openfire) except: zelf.xmpp.connect((zelf.server, zelf.port or 5222), )
[docs] def session_start(zelf, event): zelf.xmpp.send_presence()
[docs] def exception(zelf, ex): logging.error(str(ex))
[docs] def handle_failedauth(zelf, error, *args): logging.warn(error)
[docs] def handle_failure(zelf, ex, *args, **kwargs): logging.error(str(ex))
[docs] def handle_disconnected(zelf, *args, **kwargs): zelf._connected.clear() ; logging.error("disconnected")
[docs] def handle_connected(zelf, *args, **kwargs): zelf._connected.set() ; logging.warn("connected!")
[docs] def loop(zelf, *args, **kwargs): zelf.xmpp.process()
[docs] def say(zelf, *args, **kwargs): try: channel, txt = args except ValueError: channel = zelf.jid ; txt = args[0] zelf.xmpp.send_message(channel, txt)
[docs] def get_one(zelf, *args, **kwargs): return zelf.queue.get()
[docs] def handle_message(zelf, data, *args, **kwargs): if '<delay xmlns="urn:xmpp:delay"' in str(data): logging.debug("ignoring delayed message") ; return logging.warn("< %s" % data) m = Object(**data) if m.type == "error": logging.warn("error %s" % m.make_json()) ; return m.origin = stripped(str(m["from"])) if not m.origin in zelf.channels: zelf.channels.append(m.origin) m.channel = m.origin m.to = m.origin m.element = "message" try: m.txt = m["body"] except KeyError: pass m._target = zelf kernel.dispatch(m)
[docs] def handle_presence(zelf, data, *args, **kwargs): logging.info("< %s" % data) p = Object(**data) if "from" in p and p["from"]: p.origin = stripped(str(p["from"])) p.to = p.origin else: p.origin = "" ; p.to = "" p.element = "presence" if p.type == 'subscribe': pres = Object({'to': p["from"], 'type': 'subscribed'}) zelf.send(pres) pres = Object({'to': p["from"], 'type': 'subscribe'}) zelf.send(pres) else: try: zelf.channels.remove(p.origin) except ValueError: pass p.no_dispatch = True p._target = zelf kernel.dispatch(p) ## VARS
kernel = Dispatcher() kernel.plugs = Plugins() kernel.run = Object() kernel.cfg = Object() kernel.fleet = []