def write(self): with self.writelock: s = json.dumps(self.mem) f = open(self.path, "w") f.write(s) f.close() log.out("wrote memory, %d bytes" % len(s))
def cmd_submem(self, info): chatmem = info["chatmem"] submemid = info["args"]["submem"] if submemid == None: if (not chatmem.has_key("submems")) or not len(chatmem["submems"]): msg = "no active submems" else: msg = ("active submems: %s" % ", ".join(chatmem["submems"].keys())) elif not self.defaultsubmems.has_key(submemid): msg = "unknown submem '%s'" % submemid elif "delete" in info["switches"]: if (not chatmem.has_key("submems")) or (not chatmem["submems"].has_key(submemid)): msg = ("submem '%s' has not been initialized" % submemid) else: del chatmem["submems"][submemid] msg = ("submem '%s' deleted" % submemid) elif chatmem.has_key("submems") and chatmem["submems"].has_key(submemid) and not "reset" in info["switches"]: msg = ("submem '%s' already initialized" % submemid) else: if not chatmem.has_key("submems"): chatmem["submems"] = {} chatmem["submems"][submemid] = copy.deepcopy(self.defaultsubmems[submemid]) msg = ("submem '%s' initialized" % submemid) log.out(msg) return msg
def cmd_echo(self, info): text = info["args"]["text"] if "upper" in info["switches"]: text = text.upper() elif "lower" in info["switches"]: text = text.lower() log.out("echoing message text %s (from %s)" % (repr(text), repr(info["args"]["text"]))) return "echo: %s" % text
def exc(instance=None): with debug.PRINT_LOCK: #print("%s: %s" % (str(instance), str(sys.exc_info()))) log.out("[%s] EXCEPTION: %d kept messages:" % (time.strftime("%a, %d.%m.%Y (%b), %H:%M:%S"), len(debug.RECMSG))) debug.outrecordedmessages() log.out(traceback.format_exc())
def msg(tag, s): with debug.PRINT_LOCK: msg = "[%s] %s: %s" % ( time.strftime("%a, %d.%m.%Y (%b), %H:%M:%S"), (str(tag) if (type(tag) == types.StringType) else "MAIN"), str(s)) debug.record(msg) if (tag == True) or debug.tagenabled(tag): log.out(msg)
def trigger_hashtags(self, submem, msginfo): text = msginfo["message"]["text"] for match in re.finditer(r"#(\w+)", text, re.UNICODE): hashtag = match.group(1) log.out("got hashtag: " + hashtag) if not submem["hashtags"].has_key(hashtag): submem["hashtags"][hashtag] = 1 else: submem["hashtags"][hashtag] += 1
def outrecordedmessages(): with debug.RECORD_LOCK: l = len(debug.RECMSG) n = 0 i = debug.RECPOS while n < l: if not (i < l): i = 0 log.out("\t%s" % debug.RECMSG[i]) i += 1 n += 1
def __init__(self, path): self.path = path try: f = open(self.path, "r") s = f.read() f.close() self.mem = json.loads(s) except: log.out("could not load memory") self.mem = {} self.writelock = threading.Lock() self.writethread = threading.Thread(target=self.writeloop) self.writethread.daemon = True self.writethread.start()
def getme(self): err = 0 while True: try: r = self.session.get(self.getmeurl) response = r.json() except: err += 1 log.exc("fail #%d: error getting initial information" % err) if err >= 80: log.out("fail #%d: waiting 30 minutes, then retrying" % err) time.sleep(30 * 60) elif err >= 20: log.out("fail #%d: waiting 60 seconds, then retrying" % err) time.sleep(60) if err >= 10: log.out("renewing session") self.newsession() continue if not response["ok"]: log.out("response not ok, ignoring") continue break return response["result"]
def main(): debug.msg(True, "--- gamemod masterserver %s starting up ---" % gamemod.VERSION) g = gamemod() try: while True: time.sleep(1) # TODO except KeyboardInterrupt: msg = "exiting (KeyboardInterrupt) ..."; try: debug.msg(True, msg) except: try: log.out("(debug.msg failed, using log.out) " + msg) except: print("(debug.msg and log.out failed, using print) " + msg) sys.exit()
def main(): debug.msg(True, "--- gamemod masterserver %s starting up ---" % gamemod.VERSION) g = gamemod() try: while True: time.sleep(1) # TODO except KeyboardInterrupt: msg = "exiting (KeyboardInterrupt) ..." try: debug.msg(True, msg) except: try: log.out("(debug.msg failed, using log.out) " + msg) except: print("(debug.msg and log.out failed, using print) " + msg) sys.exit()
def process(self, msginfo): if (time.time() - START_TIME) < 2: log.out("not processing message, started less than 2 seconds ago") return iscommand = msginfo["type"] == "text" and msginfo["message"]["text"].startswith("/") for triginfo in TRIGGERS: if iscommand and not (triginfo.has_key("commands") and triginfo["commands"]): continue if triginfo["message"].has_key(msginfo["type"]): func = triginfo["message"][msginfo["type"]] elif triginfo["message"].has_key("*"): func = triginfo["message"]["*"] else: continue info = { "logic": self, "fromuser": msginfo["from"], "inchat": msginfo["chat"], "msginfo": msginfo } if triginfo.has_key("require") and not self.addrequirements(triginfo["require"], info): continue try: returnmsg = func(info) except: log.exc("exception in trigger function") return if returnmsg: if returnmsg == True: log.exc("ignoring message, trigger '%s' returned True" % (triginfo["id"] if triginfo.has_key("id") else "")) return self.returnmsg(msginfo, returnmsg) if iscommand: cmdstr = msginfo["message"]["text"][1:] try: returnmsg = self.quickexeccmd(cmdstr, msginfo["from"], msginfo["chat"]) except: log.exc("exception in command function") return if returnmsg: self.returnmsg(msginfo, returnmsg)
def permitaccess(self, fromuser, inchat, accessinfo): info = { "fromuser": fromuser, "inchat": inchat, "logic": self } if not self.addrequirements(accessinfo["require"], info): # couldn't add requirements return False for key, func in accessinfo["cond"].iteritems(): memval = info for k in key.split("."): if not memval.has_key(k): # access denied log.out("access denied, required field does not exist") return False memval = memval[k] if not func(info, memval): # access denied log.out("access denied by access function") return False return True
def execcmd(self, cmdstr, fromuser, inchat): if cmdstr.startswith("/"): cmdstr = cmdstr[1:] parts = cmdstr.split(" ", 1) cmd = parts[0] argstr = parts[1] if len(parts) > 1 else "" if self.commands.has_key(cmd): cmdinfo = self.commands[cmd] switches, args, errormsg = self.parseparams(cmdinfo, argstr) if args == None: # TODO if errormsg: log.out("failed parsing command: %s" % errormsg) # TODO pass error message on to user? else: log.out("failed parsing command") return False, None # access control if cmdinfo.has_key("access"): if not self.permitaccess(fromuser, inchat, cmdinfo["access"]): return False, None # TODO # info info = { "fromuser": fromuser, "inchat": inchat, "args": args, "switches": switches } # require if cmdinfo.has_key("require") and not self.addrequirements(cmdinfo["require"], info): # something went wrong return False, None # TODO # exec if cmdinfo.has_key("func"): return True, cmdinfo["func"](info) else: return True, eval("self.cmd_" + cmd)(info)
def addrequirements(self, req, info): if req.has_key("cmdmem"): cmdmem = self.cmdmem(req["cmdmem"]["id"], create = req["cmdmem"].has_key("create") and req["cmdmem"]["create"]) if cmdmem == None and not (req["cmdmem"].has_key("permitnone") and req["cmdmem"]["permitnone"]): log.out("no cmdmem") return False info["cmdmem"] = cmdmem if req.has_key("chatinfo") or req.has_key("chatmem") or req.has_key("submem"): create = req.has_key("chatinfo") or (req.has_key("chatmem") and req["chatmem"].has_key("create") and req["chatmem"]["create"]) or (req.has_key("submem") and req["submem"].has_key("create") and req["submem"]["create"]) info["chatinfo"] = self.botservice.getchatinfo(info["inchat"], create = create) if req.has_key("chatmem") or req.has_key("submem"): chatmem = info["chatinfo"] permitnone = (req.has_key("chatmem") and req["chatmem"].has_key("permitnone") and req["chatmem"]["permitnone"]) or (req.has_key("submem") and req["submem"].has_key("permitnone") and req["submem"]["permitnone"]) if chatmem == None and not permitnone: log.out("no chatmem") return False info["chatmem"] = chatmem if req.has_key("submem"): submemid = req["submem"]["id"] if not self.defaultsubmems.has_key(submemid): return False if chatmem and chatmem.has_key("submems") and chatmem["submems"].has_key(submemid): submem = chatmem["submems"][submemid] elif req["submem"].has_key("create") and req["submem"]["create"]: if not chatmem.has_key("submems"): chatmem["submems"] = {} submem = chatmem["submems"][submemid] = copy.deepcopy(self.defaultsubmems[submemid]) elif req["submem"].has_key("permitnone") and req["submem"]["permitnone"]: submem = None else: log.out("no submem") return False info["submem"] = submem if req.has_key("modules"): info["modules"] = {} for modulename in req["modules"]: if not self.modules.has_key(modulename): log.out("no module named '%s'" % modulename) return False info["modules"][modulename] = self.modules[modulename]["instance"] return True
def importmodulestats(self): for statid, statinfo in self.stats.iteritems(): if statinfo.has_key("import"): if not self.modules.has_key(statinfo["import"]["module"]): log.out("couldn't import stats '%s' as '%s': no module '%s'" % (statinfo["import"]["command"], statid, statinfo["import"]["module"])) del self.stats[statid] continue module = self.modules[statinfo["import"]["module"]]["info"] if not module["stats"].has_key(statinfo["import"]["stats"]): log.out("couldn't import stats '%s' from module '%s' as '%s': module doesn't define those stats" % (statinfo["import"]["stats"], statinfo["import"]["module"], statid)) del self.stats[statid] continue for k, v in module["stats"][statinfo["import"]["stats"]].iteritems(): statinfo[k] = v log.out("successfully imported stats '%s' from module '%s' as '%s'" % (statinfo["import"]["stats"], statinfo["import"]["module"], statid))
def importmodulecommands(self): todel = [] for cmdid, cmdinfo in self.commands.iteritems(): if cmdinfo.has_key("import"): if not self.modules.has_key(cmdinfo["import"]["module"]): log.out("couldn't import command '%s' as '%s': no module '%s'" % (cmdinfo["import"]["command"], cmdid, cmdinfo["import"]["module"])) todel.append(self.commands[cmdid]) continue module = self.modules[cmdinfo["import"]["module"]]["info"] if not module["commands"].has_key(cmdinfo["import"]["command"]): log.out("couldn't import command '%s' from module '%s' as '%s': module doesn't define that command" % (cmdinfo["import"]["command"], cmdinfo["import"]["module"], cmdid)) todel.append(self.commands[cmdid]) continue for k, v in module["commands"][cmdinfo["import"]["command"]].iteritems(): cmdinfo[k] = v log.out("successfully imported command '%s' from module '%s' as '%s'" % (cmdinfo["import"]["command"], cmdinfo["import"]["module"], cmdid)) for cmdid in todel: del self.commands[cmdid]
def __init__(self, botservice, mem): self.botservice = botservice self.mem = mem self.startcodes = {} if not self.mem.has_key("cmdmems"): self.mem["cmdmems"] = {} self.defaultsubmems = copy.deepcopy(SUBMEMS) self.defaultcmdmems = copy.deepcopy(CMDMEMS) self.modules = {} for moduleclass in MODULES: moduleinfo = moduleclass.MODULEINFO modulename = moduleinfo["name"] info = { "logic": self } if moduleinfo.has_key("submem"): if self.defaultsubmems.has_key(modulename): log.out("couldn't load module '%s': submem id collision" % modulename) continue self.defaultsubmems[modulename] = moduleinfo["submem"] if moduleinfo.has_key("cmdmem"): if self.defaultcmdmems.has_key(modulename): log.out("couldn't load module '%s': cmdmem id collision" % modulename) continue self.defaultcmdmems[modulename] = moduleinfo["cmdmem"] if not self.addrequirements(moduleinfo["instance"]["require"], info): log.out("couldn't load module '%s': requirements couldn't be added" % modulename) continue self.modules[modulename] = { "info": moduleinfo, "instance": moduleinfo["instance"]["func"](info) } self.commands = copy.deepcopy(COMMANDS) self.importmodulecommands() self.stats = copy.deepcopy(STATS) self.importmodulestats() self.uno = botuno.uno(self, self.cmdmem("uno", create = True)) self.urban = boturban.urban(self) self.outputloadedcommands()
def receive(self): cnt = 0 err = 0 while True: try: r = self.session.get(self.recvurl, params={"offset": self.offset, "timeout": 60}) response = r.json() cnt += 1 except: err += 1 log.exc("fail #%d: error receiving messages" % err) if err >= 80: log.out("fail #%d: waiting 30 minutes, then retrying" % err) time.sleep(30 * 60) elif err >= 20: log.out("fail #%d: waiting 60 seconds, then retrying" % err) time.sleep(60) if err >= 10: log.out("renewing session") self.newsession() cnt = 0 continue err = 0 log.out("receive: %s" % (json.dumps(response, indent=4),)) if not response["ok"]: log.out("response not ok, ignoring") else: for result in response["result"]: update_id = result["update_id"] message = result["message"] yield message self.offset = update_id + 1 if cnt >= 8192: log.out("cnt is %d, renewing session") self.newsession() cnt = 0
def close(*args): log.out("exiting...") m["offset"] = session.offset mem.write() log.close() sys.exit(0)
def getuserprofilephotos(self, user): log.out(json.dumps(self.session.get(self.userprofilephotosurl, params={"user_id": user}).json(), indent=4))
def exc(instance = None): with debug.PRINT_LOCK: #print("%s: %s" % (str(instance), str(sys.exc_info()))) log.out("[%s] EXCEPTION: %d kept messages:" % (time.strftime("%a, %d.%m.%Y (%b), %H:%M:%S"), len(debug.RECMSG))) debug.outrecordedmessages() log.out(traceback.format_exc())
def msg(tag, s): with debug.PRINT_LOCK: msg = "[%s] %s: %s" % (time.strftime("%a, %d.%m.%Y (%b), %H:%M:%S"), (str(tag) if (type(tag) == types.StringType) else "MAIN"), str(s)) debug.record(msg) if (tag == True) or debug.tagenabled(tag): log.out(msg)
def cmd_todo(self, info): log.out("todo works: %s" % json.dumps(info, indent=4))
def outputloadedcommands(self): log.out("loaded commands:\n%s" % self.makecmdliststring())
import time import signal import sys import memory import botapi import botservice from log import log import tokens log.open("verbot.log") log.out("starting...") MEMORY = "memory.json" mem = memory.memory(MEMORY) m = mem.get() if not m.has_key("offset"): m["offset"] = 0 if not m.has_key("bot"): m["bot"] = {} offset = m["offset"] log.out("offset is %d" % (offset,)) session = botapi.session(tokens.BOT_TOKEN, offset) bot = botservice.bot(m["bot"], session)
def parseargs(self, parseargs, vals, switches, args): for arg in parseargs: if arg.has_key("ifswitch") and not next((True for switch in arg["ifswitch"] if switches.count(switch) > 0), None): args[arg["name"]] = None continue if arg.has_key("ifnotswitch") and next((True for switch in arg["ifnotswitch"] if switches.count(switch) > 0), None): args[arg["name"]] = None continue if len(vals) <= 0: if arg.has_key("optional") and arg["optional"]: args[arg["name"]] = None continue else: return False, "missing arguments" parsinghints = arg["parsinghints"] if arg.has_key("parsinghints") else [] consumeall = parsinghints.count("consumeall") > 0 repeat = parsinghints.count("repeat") > 0 while len(vals): val = vals.pop(0) quotes = val.startswith('"') if quotes or consumeall: if quotes: val = val[1:] while len(vals): if quotes and val.endswith('"') and not val.endswith('\\"'): val = val[:-1] quotes = False if consumeall: continue else: break val += " " + vals.pop(0) if arg["type"] == "string": pass elif arg["type"] == "int": try: val = int(val) except: return False, "couldn't parse int argument '%s'" % arg["name"] # TODO elif arg["type"] == "user": user = self.finduser(val) if not user: return False, ("unknown user '%s'" % val) val = user elif arg["type"] == "chat": chat = self.findchat(val) if not chat: return False, ("unknown chat '%s'" % val) val = chat elif arg["type"] == "cmdid": if val.startswith("/"): val = val[1:] if not self.commands.has_key(val): return False, ("unknown command '%s'" % val) else: # unknown data type msg = "unknown argument data type: %s" % arg["type"] log.out(msg) return False, msg if repeat: if not args.has_key(arg["name"]): args[arg["name"]] = [] args[arg["name"]].append(val) else: args[arg["name"]] = val break return True, None