Source code for point

# point/__init__.py
#
#

""" point package. """

__version__ = 12

## IMPORTS 

from point.utils import *
from point.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

## 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
[docs]class NotSet(Error): pass ## BOOT
homedir = os.path.expanduser("~")
[docs]def boot(*args, **kwargs): global kernel cfg = args[0] kernel.cfg.update(cfg) if cfg.shell: hello("POINT") if not kernel.cfg.workdir: kernel.cfg.workdir = j(homedir, "point.data", "") make_dir(kernel.cfg.workdir) if not kernel.cfg.loglevel: cfg.loglevel = "error" from point.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(" ") kernel.plugs.load_package("point.plugs") try: kernel.plugs.load_package("evidence.plugs") except: logging.warn("no evidence") kernel.plugs.init() if kernel.cfg.shell: print(" ") return kernel ## SHUTDOWN
[docs]def shutdown(): global kernel if kernel.cfg.shell: print("") logging.warn("shutdown is here !!") for obj in kernel.run.obj_iter(): if obj == None: continue try: obj.exit() except: error() kernel.cmnds.exit() kernel.plugs.exit() try: sys.stdout.flush() ; sys.stdout.close() except: pass os._exit(0) ## BASE
[docs]class Object(dict): def __getattribute__(p, *args, **kwargs): name = args[0] result = "" if name == "what": result = get_cls(p) if name == "modname": result = get_modname(p) if name == "plugname": result = get_plugname(3) if name == "func": result = get_func(5) if name == "kind": result = mj(p.modname, p.what, p.func) if name == "stdin": return sys.stdin if name == "stdout": return sys.stdout if result: return result return dict.__getattribute__(p, *args, **kwargs) def __getattr__(p, name): try: return p[name] except KeyError: if name == "timed": val = "" if "Date" in p: val = p.Date elif "date" in p: val = p.date elif "published" in p: val = p.published if val: val = short_date(val) elif "added" in p: val = to_time(p.added) #else: result = time_time(time.time()) if not val: raise NoDate() return val if name == "_result": p["_result"] = Object() if name == "_status": p["_status"] = Object() if name == "_ready": p["_ready"] = threading.Event() return p[name] def __setattr__(p, name, value): return dict.__setitem__(p, name, value) def __exists__(p, a): try: return p[a] except KeyError: False def __lt__(p, a): return time_stamp(p.ddate) < time_stamp(a.ddate) def __iter__(p): return p.clean_keys()
[docs] def obj_iter(p, *args, **kwargs): for key in p.clean_keys(): yield p[key] ## TOUCH
[docs] def touch(p, *args, **kwargs): try: res = getattr(p, args[0]) except (TypeError, AttributeError): res = None return res ## LOCATORS
[docs] def get_root(p, *args, **kwargs): return j(os.path.expanduser("~"), *args)
[docs] def get_roots(p, *args, **kwargs): result = [] return result
[docs] def get_target(p): if "_target" in p: return p._target return None ## OUTPUT
[docs] def to_json(p, *args, **kwargs): return json.dumps(p.clean(*args, **kwargs), default=smooth, *args, **kwargs)
[docs] def to_full(p, *args, **kwargs): return json.dumps(p, default=smooth, *args, **kwargs)
[docs] def make_signature(p, sig=None): if "data" in p: return str(hashlib.sha1(bytes(str(p.data), "utf-8")).hexdigest()) raise NotSet
[docs] def make_path(p, *args, **kwargs): path = p.get_path(*args, **kwargs) ; make_dir(path) ; return path ## INPUT
[docs] def exit(p, *args, **kwargs): pass
[docs] def load(p, *args, **kwargs): if args: path = p.make_path(*args, **kwargs) else: path = p.make_path() return p.load_file(path)
[docs] def load_file(p, *args, **kwargs): path = args[0] logging.debug("load_file %s" % " ".join(args)) ondisk = p.read(path) fromdisk = json.loads(ondisk) if "data" in fromdisk: p.update(fromdisk["data"]) return p
[docs] def load_json(p, *args, **kwargs): p.update(json.loads(args[0]))
[docs] def read(p, *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 "do_test" in p: 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(p, *args, **kwargs): # object attributes settins before save path = args[0] p.path = path todisk = Object() todisk.create_type = p.what todisk.stime = time.ctime(time.time()) todisk.modname = p.modname todisk.version = __version__ todisk.data = p.clean() todisk.signature = todisk.make_signature() try: todisk.data.timed = p.timed except NoDate: todisk.data.timed = to_time(time.ctime(time.time())) try: result = todisk.to_json(indent=2, ensure_ascii=False) except TypeError: raise NoJSON() return result
[docs] def save(p, *args, **kwargs): if not args: t = rtime() else: t = args[0] root = j(kernel.cfg.workdir, t) make_dir(root) p.sync(root)
[docs] def sync(p, *args, **kwargs): # syn the object to disk try: path = args[0] except IndexError: path = p.path logging.info("save %s" % " ".join(args)) fn = path.split(os.sep)[-1] todisk = p.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.info("saved %s" % path) return p ## STATE
[docs] def register(p, *args, **kwargs): name = args[0] obj = args[1] p[name] = obj
[docs] def clean_keys(p, *args, **kwargs): for key in p.keys(): k = str(key) if k.startswith("_"): continue if k == "format": continue if args and k in args[0]: continue yield key
[docs] def clean(p, *args, **kwargs): res = Object() for key in p.clean_keys(): res[key] = p[key] return res
[docs] def pretty(p): return json.dumps(p, indent=2) ## GETTIES
[docs] def get_rest(p, *args, **kwargs): try: cmnd, rest = p.txt.split(" ", 1) ; return rest except ValueError: return "" ## OBJECTORS
[docs] def objects(p, *args, **kwargs): path = p.get_root(kernel.cfg.workdir, *args, **kwargs) objs = [] for fnn in list_files(path, **kwargs): obj = Object().load_file(fnn) if "deleted" in obj: continue objs.append(obj) return objs
[docs] def has_obj(p, *args, **kwargs): key = args[0] value = args[1] for obj in p.objects(): if key not in obj: continue if value in obj[key]: return obj[key] return None
[docs] def check_wanted(p, *args, **kwargs): want = args[0] for key, value in want.items(): if key == "format": continue if key not in p: continue if value.startswith("-"): continue if value not in str(p[key]): return False return True
[docs] def check_notwanted(p, *args, **kwargs): not_want = args[0] for key, value in not_want.items(): if key == "format": continue if key not in p: continue if value in p[key]: return True return False
[docs] def selector(p, *args, **kwargs): wanted = args[0] keys = p.keys() for w in wanted: if w in keys: return True return False
[docs] def parse(p, *args, **kwargs): if "txt" not in p: logging.debug("txt not set: %s" % str(p)) ; return result = Object() result.update(p) splitted = p.txt.split() for word in splitted: if word.startswith("."): result["ucmnd"] = word[1:] if word.startswith("-"): result[word] = "knob" ; continue if splitted and "ucmnd" not in result: result["ucmnd"] = splitted[0] return result
[docs] def slice(p, *args, **kwargs): """ args: list of keywords to slice the dict. """ o = Object() arguments = args[0] for arg in arguments: try: o[arg] = p[arg] except KeyError: continue return o ## RESULT
[docs] def ready(p): p._ready.set()
[docs] def clear(p): p._ready.clear()
[docs] def wait(p, sec=180.0): try: p._ready.wait(sec) except: pass
[docs] def add(p, *args, **kwargs): p._result[time.time()] = args[0]
[docs] def reply(p, *args, **kwargs): if "outer" in p: p.outer.write(str(args[0]) + "\n") ; p.outer.flush() ; return if "format" in p and p.format == "timed": tijd = to_time(time.ctime(time.time())) txt = "%s " % tijd else: txt = "" txt += str(args[0]) if "channel" in p: p.say(p.channel, txt) else: p.say("", txt) # BHJTW: str() kan verkeert uitpakken ..
[docs] def say(p, *args, **kwargs): p._target.say(args[0], str(args[1]))
[docs] def show(p): return ["%s=%s" % (a, b) for a, b in p.items() if b]
[docs] def display(p, *args, **kwargs): for res in sorted(p._result.keys()): d = p._result[res] if "channel" in p: p.say(p.channel, d) else: p.say("", d) p.ready() ## first and last
[docs] def first(p, *args, **kwargs): key = args[0] try: value = args[1] except IndexError: value = None result = None for o in p.objects(): if key in o: continue if value and o[key] != value: continue if not result: result = o if o.timed < result.timed: result = o return result
[docs] def last(p, *args, **kwargs): key = args[0] try: value = args[1] except IndexError: value = None result = None for o in p.objects(): if key not in o: continue if value and o[key] != value: continue if not result: result = o if o.timed > result.timed: result = o return result ## TASKS
[docs]class Runner(threading.Thread): def __init__(p, *args, **kwargs): threading.Thread.__init__(p, None, p._loop, "thread.%s" % str(time.time()), args, kwargs) p.setDaemon(True) p._queue = queue.Queue() p._outqueue = queue.Queue() p._state = "mainloop" p.running = "waiting" p.time_start = time.time() def _loop(p): while p._state: p._state = "waiting" args, kwargs = p._queue.get() if not p._state: break func = args[0] try: obj = args[1] except: obj = Object() logging.info("run %s" % str(func)) p.running = get_funcname(str(func)) p._state = "running" p.time_start = time.time() try: func(*args[1:], **kwargs) except: error() time.sleep(0.01) try: obj.ready() except AttributeError: pass kernel.ready() _thread.interrupt_main()
[docs] def exit(p, *args, **kwargs): p._state = ""
[docs] def put(p, *args, **kwargs): p._queue.put((args, kwargs)) ## DISPATCH
[docs]class Dispatcher(Object): def __init__(p, *args, **kwargs): Object.__init__(p, *args, **kwargs) p._state = "running" p.runners = collections.deque() p.max = 50
[docs] def is_alive(p, *args, **kwargs): for runner in p.runners: if runner.is_alive(): return True return False
[docs] def register(p, cbtype, cb, *args, **kwargs): logging.debug("register %s" % cbtype) if cbtype not in p: p[cbtype] = [] p[cbtype].append(cb)
[docs] def dispatch(p, *args, **kwargs): event = args[0] parsed = event.parse() if not parsed: return if "ucmnd" in parsed: p.execute(parsed.ucmnd, event)
[docs] def execute(p, *args, **kwargs): cmnd = args[0] event = args[1] if cmnd not in p: event.ready() ; return for func in p[cmnd]: logging.info("exec %s" % str(func)) try: getattr(func, "threaded") ; kernel.workers.put(func, event) except AttributeError: func(event)
[docs] def do_func(p, *args, **kwargs): cmnd = args[0] event = args[1] if cmnd not in p: return for func in p[cmnd]: func(event)
[docs] def exit(p, name=None): for runner in p.runners: if name and name not in runner.name: continue runner.join(0.1) p.ready()
[docs] def put(p, *args, **kwargs): target = p.make_new() target.put(*args, **kwargs) return target
[docs] def make_new(p, *args, **kwargs): for runner in p.runners: if runner._state != "running": return runner if len(p._runners) < p.max: runner = Runner(*args, **kwargs) p.runners.append(runner) runner.start() else: runner = random.choice(p._runners) return runner
[docs] def cleanup(p, dojoin=False): todo = [] for runner in p.runners: if runner.stopped or not len(runner.queue): todo.append(runner) for runner in todo: runner.stop() ; p.runners.remove(runner) ## PLUGINS
[docs]class Plugins(Object): def __init__(p, *args, **kwargs): Object.__init__(p, *args, **kwargs) p.plugins = []
[docs] def get_names(p, plugsdir): return [x[:-3] for x in os.listdir(plugsdir) if x.endswith(".py")]
[docs] def load_plugs(p, path): logging.warn("load %s" % path) for plugname in p.get_names(path): if "__" in plugname: continue try: p[plugname] = p.load_mod(plugname, path, force=True) if plugname not in p.plugins: p.plugins.append(plugname) except: error() ; continue p.ready()
[docs] def load_package(p, modname): mod = __import__(modname) path, fn = os.path.split(mod.__file__) path += os.sep + "plugs" p.load_plugs(path)
[docs] def load_mod(p, plugname, pdir="", force=False): logging.info("load %s" % plugname) if plugname in p: if not force: return p[plugname] p[plugname] = imp.reload(p[plugname]) else: if not pdir: pdir = j(p.root, "plugs") search = imp.find_module(plugname, [pdir,]) p[plugname] = imp.load_module(plugname, *search) return p[plugname]
[docs] def plug_exec(p, plugname, item): logging.info("%s %s" % (item, plugname)) try: todo = getattr(p[plugname], item) todo() except AttributeError: pass
[docs] def exit(p, *args, **kwargs): for plugname in p.clean(): try: p.plug_exec(plugname, "shutdown") ; del p[plugname] except KeyError: pass p.ready()
[docs] def reload(p, plugname, force=False): p.unload(plugname) mod = p.load_mod(plugname, force) return mod
[docs] def init(p, *args, **kwargs): if args: target = args[0] else: target = kernel.cfg.init for plugname in p.plugins: if target and target != "all" and plugname != target: continue p.plug_exec(plugname, "init") ## BOTS
[docs]class Bot(Dispatcher): def __init__(p, *args, **kwargs): Dispatcher.__init__(p, *args, **kwargs) p.time_in = 0 p.time_out = 0 p.time_start = time.time()
[docs] def exit(p, *args, **kwargs): p._state = "" ; p.ready()
[docs] def stop(p, *args, **kwargs): p._state = ""
[docs] def status(p, *args, **kwargs): return p._state
[docs] def join_channels(p, *args, **kwargs): pass
[docs] def begin(p, *args, **kwargs): if p not in kernel.fleet: kernel.fleet.append(p) p.connect() while p._state: time.sleep(0.01) try: event = p.do_one() except RemoteDisconnect: time.sleep(2) ; p.connect() if p._state == "once": break kernel.ready() _thread.interrupt_main()
[docs] def do_one(p, *args, **kwargs): pass
[docs] def get_prompt(p, *args, **kwargs): return ""
[docs] def connect(p, *args, **kwargs): pass
[docs] def announce(p, *args, **kwargs): if "channels" in p: for channel in p.channels: p.say(channel, args[0], **kwargs) else: p.say(*args, **kwargs) ## CONSOLE
[docs]class ConsoleBot(Bot): def _raw(p, *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(p, *args, **kwargs): try: txt = args[1] except IndexError: txt = args[0] p._raw(txt)
[docs] def get_prompt(p, *args, **kwargs): return "%s %s%s<%s " % (to_time(time.ctime(time.time())), BOLD, YELLOW, ENDC)
[docs] def do_one(p, *args, **kwargs): o = Object() if not kernel.cfg.shell: in_txt = " ".join(kernel.cfg.runargs) ; p._state = "once" else: in_txt = input(p.get_prompt()) o.txt = in_txt o._target = p kernel.cmnds.dispatch(o) p.time_in = time.time() return o ## IRC
[docs]class IRCBot(Bot): marker = "\r\n" cc = "." def __init__(p, *args, **kwargs): Bot.__init__(p, *args, **kwargs) p.connected = threading.Event() p.register("004", p._onconnect) p.register("513", p.handle_513) p.register("433", p.handle_433) p.register("366", p.handle_366) p.register("PING", p.handle_ping) p.register("INVITE", p.handle_invite) p.register("PRIVMSG", p.handle_privmsg) p.register("NOTICE", p.handle_notice) p._lock = _thread.allocate_lock() p._buffer = [] p._lastline = "" p.encoding = "utf-8" if "realname" not in p: p.realname = "point" if "server" not in p: p.server = "localhost" if "port" not in p: p.port = 6667 if "nick" not in p: p.nick = "point" if "channels" not in p: p.channels = [] if "channel" in p and p["channel"] not in p.channels: p.channels.append(p.channel) def _raw(p, txt): logging.warn("> %s" % txt) if not txt.endswith(p.marker): txt += p.marker txt = bytes(txt, p.encoding) if 'ssl' in p and p.ssl: p.sock.write(txt) else: p.sock.send(txt[:512]) def _connect(p): p.stopped = False if "ipv6" in p: p.oldsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: p.oldsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) p.server = p.bind() logging.warn('connect %s - %s' % (p.server, p.port)) p.oldsock.settimeout(60) p.oldsock.connect((p.server, int(str(p.port or 6667)))) p.blocking = 1 p.oldsock.setblocking(p.blocking) logging.warn('connection made to %s' % p.server) p.fsock = p.oldsock.makefile("r") if "blocking" in p: p.oldsock.settimeout(301.0) if 'ssl' in p and p['ssl']: p.sock = socket.ssl(p.oldsock) else: p.sock = p.oldsock p.connecttime = time.time() p.ready() return True def _onconnect(p, *args, **kwargs): logging.warn("logged on !!") if "onconnect" in p: time.sleep(0.5) ; p._raw(p.onconnect) if "servermodes" in p: p._raw("MODE %s %s" % (p.nick, p.servermodes)) p.wait() p.join_channels() def _dodcc(p, event, s): s.send(bytes('Welcome to POINT ' + event.nick + " !!\n", p.encoding)) _thread.start_new_thread(p._dccloop, (event, s)) def _dccloop(p, 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=p, txt=res) o.outer = sockfile kernel.cmnds.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(p, event): try: rest = event.get_rest() parsed = txt_parse(rest) addr = parsed.args[2] ; port = parsed.args[3][:-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 p._dodcc(event, s)
[docs] def do_one(p, *args, **kwargs): if not p._buffer: p.read_some() try: line = p._buffer.pop(0) except IndexError: return Object() e = Object() e._target = p o = irc_parse(e, line.rstrip()) try: p.do_func(o.etype, o) except: error() p.time_in = time.time() return o
[docs] def read_some(p, *args, **kwargs): try: if "ssl" in p and p.ssl: inbytes = p.sock.read() else: inbytes = p.sock.recv(512) except socket.timeout: return except Exception as ex: error() ; return try: txt = str(inbytes, p.encoding) except UnicodeDecodeError: txt = " " if txt == "": raise RemoteDisconnect() p._lastline += txt splitted = p._lastline.split(p.marker) for s in splitted[:-1]: logging.warn("< %s" % s) ; p._buffer.append(s) p._lastline = splitted[-1]
[docs] def send(p, txt): p._raw(txt) ; time.sleep(3.0)
[docs] def bind(p): server = p.server try: p.oldsock.bind((server, 0)) except socket.error: if not server: try: socket.inet_pton(socket.AF_INET6, p.server) except socket.error: pass else: server = p.server if not server: try: socket.inet_pton(socket.AF_INET, p.server) except socket.error: pass else: server = p.server if not server: ips = [] try: for item in socket.getaddrinfo(p.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(p): if "password" in p: p._raw("PASS %s" % p.password) logging.warn('logging in on %s - this may take a while' % p.server) p._raw("NICK %s" % p.nick or "p") p._raw("USER %s localhost %s :%s" % (p.username or "p", p.server or "localhost", p.realname))
[docs] def say(p, *args, **kwargs): try: channel, txt = args except ValueError: channel = p.channel ; txt = args[0] p.privmsg(channel, txt)
[docs] def join_channels(p, *args, **kwargs): for channel in p.channels: p.join(channel)
[docs] def broadcast(p, txt): for i in p.channels: p.say(i, txt)
[docs] def connect(p, reconnect=True): try: res = p._connect() except: error() ; return if res: time.sleep(1) ; p.logon() return res
[docs] def close(p): if 'ssl' in p and p['ssl']: p.oldsock.shutdown(2) ; p.oldsock.close() else: p.sock.shutdown(2) ; p.sock.close() p.fsock.close()
[docs] def handle_notice(p, event): pass
[docs] def handle_ping(p, event): p.pongcheck = True ; p.pong()
[docs] def handle_433(p, event): p.donick(event.arguments[1] + "_")
[docs] def handle_invite(p, event): p.join(event.channel)
[docs] def handle_privmsg(p, event): if event.txt.startswith("\001DCC"): p._dccconnect(event) ; return if event.txt and event.txt[0] == p.cc: kernel.cmnds.dispatch(event)
[docs] def handle_513(p, event): p._raw("PONG %s" % event.arguments[6])
[docs] def handle_ctcp(p, event): if event.txt and event.txt[0] == p.cc: resolve(event)
[docs] def donick(p, nick, setorig=False, save=False, whois=False): p.send('NICK %s\n' % nick[:16])
[docs] def join(p, channel, password=None): if password: p._raw('JOIN %s %s' % (channel, password)) else: p._raw('JOIN %s' % channel)
[docs] def handle_366(p, *args, **kwargs): p.ready()
[docs] def part(p, channel): p.send('PART %s' % channel) if channel in p.channels: p.channels.remove(channel) ; p.save()
[docs] def who(p, who): p.send('WHO %s' % who.strip())
[docs] def names(p, channel): p.send('NAMES %s' % channel)
[docs] def whois(p, who): p.send('WHOIS %s' % who)
[docs] def privmsg(p, printto, what): p.send('PRIVMSG %s :%s' % (printto, what))
[docs] def voice(p, channel, who): p.send('MODE %s +v %s' % (channel, who))
[docs] def doop(p, channel, who): p.send('MODE %s +o %s' % (channel, who))
[docs] def delop(p, channel, who): p.send('MODE %s -o %s' % (channel, who))
[docs] def quit(p, reason='https://pikacode.com/bthate/point2'): p.send('QUIT :%s' % reason)
[docs] def notice(p, printto, what): p.send('NOTICE %s :%s' % (printto, what))
[docs] def ctcp(p, printto, what): p.send("PRIVMSG %s :\001%s\001" % (printto, what))
[docs] def ctcpreply(p, printto, what): p.send("NOTICE %s :\001%s\001" % (printto, what))
[docs] def action(p, printto, what, event=None, *args, **kwargs): p.send("PRIVMSG %s :\001ACTION %s\001" % (printto, what))
[docs] def getchannelmode(p, channel): p.send('MODE %s' % channel)
[docs] def settopic(p, channel, txt): p.send('TOPIC %s :%s' % (channel, txt))
[docs] def ping(p, *args, **kwargs): p.send('PING :%s' % p.server)
[docs] def pong(p, *args, **kwargs): p.send('PONG :%s' % p.server) ## irc_parse function
[docs]def irc_parse(obj, *args, **kwargs): rawstr = str(args[0]) p = obj p.servermsg = False splitted = re.split('\s+', rawstr) if not rawstr[0] == ':': p.servermsg = True p.prefix = splitted[0] if p.servermsg: p.etype = p.prefix else: p.etype = splitted[1] try: nickuser = p.prefix.split('!') p.origin = nickuser[1] p.nick = nickuser[0][1:] except IndexError: p.origin = p.prefix ; p.servermsg = True if p.etype in pfc: p.arguments = splitted[2:pfc[p.etype]+2] txtsplit = re.split('\s+', rawstr, pfc[p.etype]+2) p.txt = txtsplit[-1] else: p.arguments = splitted[2:] if p.arguments: p.target = p.arguments[0] p.postfix = ' '.join(p.arguments) if not "txt" in p: p.txt = rawstr.rsplit(":")[-1] if p.txt.startswith(":"): p.txt = p.txt[1:] if not "channel" in p: for c in p.arguments + [p.txt, ]: if c.startswith("#"): p.channel = c if p.servermsg: p.origin = p.origin[1:-1] p.channel = p.origin if not "origin" in p: p.origin = p.channel if not "target" in p: p.target = p.channel or p.origin return obj ## XMPP
[docs]class XMPPBot(Bot): def __init__(p, *args, **kwargs): import sleekxmpp from sleekxmpp import clientxmpp Bot.__init__(p, *args, **kwargs) if "port" not in p: p.port = 5222 p.queue = queue.Queue() p.xmpp = clientxmpp.ClientXMPP(p.user, getpass.getpass(stream=sys.stdout)) p.xmpp.add_event_handler("session_start", p.session_start) p.xmpp.add_event_handler("message", p.handle_message) p.xmpp.add_event_handler('disconnected', p.handle_disconnected) p.xmpp.add_event_handler('connected', p.handle_connected) p.xmpp.add_event_handler('presence_available', p.handle_presence) p.xmpp.add_event_handler('presence_dnd', p.handle_presence) p.xmpp.add_event_handler('presence_xa', p.handle_presence) p.xmpp.add_event_handler('presence_chat', p.handle_presence) p.xmpp.add_event_handler('presence_away', p.handle_presence) p.xmpp.add_event_handler('presence_unavailable', p.handle_presence) p.xmpp.add_event_handler('presence_subscribe', p.handle_presence) p.xmpp.add_event_handler('presence_subscribed', p.handle_presence) p.xmpp.add_event_handler('presence_unsubscribe', p.handle_presence) p.xmpp.add_event_handler('presence_unsubscribed', p.handle_presence) p.xmpp.add_event_handler('groupchat_message', p.handle_message) p.xmpp.add_event_handler('groupchat_presence', p.handle_presence) p.xmpp.add_event_handler('groupchat_subject', p.handle_presence) p.xmpp.add_event_handler('failed_auth', p.handle_failedauth) p.xmpp.exception = p.exception p.xmpp.use_signals() p.openfire = kernel.cfg.openfire if p.openfire: logging.warn("openfire used") import ssl p.xmpp.ssl_version = ssl.PROTOCOL_SSLv3 p._connected = threading.Event() p.channels = [] p.time_in = time.time() def _raw(p, txt): p.xmpp.send_raw(txt)
[docs] def connect(p): try: p.xmpp.connect((p.server, p.port), use_ssl=p.openfire) except: p.xmpp.connect((p.server, p.port))
[docs] def session_start(p, event): p.xmpp.send_presence()
[docs] def exception(p, ex): p._state = ex logging.error(str(ex)) p.stop()
[docs] def handle_failedauth(p, error, *args): #p._state = error logging.warn(error)
[docs] def handle_failure(p, ex, *args, **kwargs): p._state = ex logging.warn(ex)
[docs] def handle_disconnected(p, *args, **kwargs): p._connected.clear() p._state = "disconnected" logging.error("disconnected")
[docs] def handle_connected(p, *args, **kwargs): p._state = "connected" ; p._connected.set() ; logging.warn("connected!")
[docs] def loop(p, *args, **kwargs): p.xmpp.process()
[docs] def say(p, *args, **kwargs): try: channel, txt = args except ValueError: channel = p.origin ; txt = args[0] p.xmpp.send_message(channel, txt)
[docs] def do_one(p, *args, **kwargs): p.time_in = time.time() return p.queue.get()
[docs] def handle_message(p, 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.to_json()) ; return m.origin = stripped(str(m["from"])) if not m.origin in p.channels: p.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 = p kernel.cmnds.dispatch(m)
[docs] def handle_presence(p, data, *args, **kwargs): logging.info("< %s" % data) o = Object(**data) if "from" in p and p["from"]: o.origin = stripped(str(p["from"])) o.to = p.origin else: o.origin = "" ; p.to = "" o.element = "presence" if o.type == 'subscribe': pres = Object({'to': p["from"], 'type': 'subscribed'}) o.xmpp.send_presence(pres) pres = Object({'to': p["from"], 'type': 'subscribe'}) o.xmpp.send_presence(pres) else: try: p.channels.remove(p.origin) except (NotSet, ValueError): pass o.no_dispatch = True o._target = p kernel.cmnds.dispatch(o) ## VARS
kernel = Object(format="keys") kernel.cmnds = Dispatcher(format="keys") kernel.workers = Dispatcher(format="keys") kernel.direct = Dispatcher(format="keys") kernel.plugs = Plugins(format="keys") kernel.run = Object(format="keys") kernel.cfg = Object(format="show") kernel.fleet = []