[pybot-commits] CVS: pybot/pybot/modules infopack.py,1.9,1.10 permission.py,1.11,1.12 remoteinfo.py,
Brought to you by:
niemeyer
From: Gustavo N. <nie...@us...> - 2003-08-27 17:08:35
|
Update of /cvsroot/pybot/pybot/pybot/modules In directory sc8-pr-cvs1:/tmp/cvs-serv23476/pybot/modules Modified Files: infopack.py permission.py remoteinfo.py Log Message: * modules/permissions.py: Implemented permission parameters. * modules/{remoteinfo.py,infopack.py}: Adapted to work with premission parameters. * modules/infopack.py: Implemented infopack searching. Index: infopack.py =================================================================== RCS file: /cvsroot/pybot/pybot/pybot/modules/infopack.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** infopack.py 25 Aug 2003 20:44:24 -0000 1.9 --- infopack.py 27 Aug 2003 17:08:14 -0000 1.10 *************** *** 29,35 **** [in memory]" (the "infopackadmin" permission is needed). """,""" ! To show which infopacks are loaded, send me "show infopacks". You ! can also ask for help about some specific infopack with "help infopack ! <name>". """ --- 29,38 ---- [in memory]" (the "infopackadmin" permission is needed). """,""" ! After you load some infopack, you must say explicitly which ! users/channels and servers will be able to obtain information from ! it. To do that give the permission "infopack(<name>)" for these you ! want to allow. To show which infopacks are loaded, send me ! "show infopacks". You can also ask for help about some specific ! infopack with "help infopack <name>". """ *************** *** 39,42 **** --- 42,53 ---- """ + PERM_INFOPACK = """ + Users will be able to access information in some infopack if + they have the "infopack(<name>)" permission. Check "help infopack" + for more information. + """ + + MAXSEARCHRESULTS = 3 + class Info: def __init__(self, phrase="", action=0, notice=0, tonick=0): *************** *** 79,85 **** if line and line[0] != "#": if line[0] == "K": ! if values != []: ! values = [] ! self._info[line[2:].rstrip()] = values elif line[0] == "V": value = line[2:].split(":", 1) --- 90,96 ---- if line and line[0] != "#": if line[0] == "K": ! values = [] ! self._info[line[2:].rstrip().lower()] = \ ! (line[2:].rstrip(), values) elif line[0] == "V": value = line[2:].split(":", 1) *************** *** 147,156 **** found = 0 file = open(self._filename) ! for line in file.xreadlines(): if line and line[0] != "#": if not found: if line[0] == "K": key = line[2:].rstrip() ! if key == findkey: found = 1 foundvalue = 0 --- 158,167 ---- found = 0 file = open(self._filename) ! for line in file.readlines(): if line and line[0] != "#": if not found: if line[0] == "K": key = line[2:].rstrip() ! if key.lower() == findkey: found = 1 foundvalue = 0 *************** *** 164,169 **** break file.close() ! return values ! def get(self, line): --- 175,179 ---- break file.close() ! return key, values def get(self, line): *************** *** 173,179 **** key = m.group(1).lower() if self._info: ! values = self._info.get(key) else: ! values = self.getinfo(key) if values: value = random.choice(values) --- 183,192 ---- key = m.group(1).lower() if self._info: ! try: ! key, values = self._info[key] ! except KeyError: ! values = None else: ! key, values = self.getinfo(key) if values: value = random.choice(values) *************** *** 189,197 **** if "m" in flags: mask = random.choice(self._masks) ! info.phrase = mask%value[1] else: info.phrase = value[1] return info class InfopackModule: def __init__(self): --- 202,251 ---- if "m" in flags: mask = random.choice(self._masks) ! info.phrase = mask % {"key": key, "value": value[1]} else: info.phrase = value[1] return info + def _search(self, pattern, key, values, results): + found = 0 + if pattern.match(key): + found = 1 + value = random.choice(values) + else: + if len(values) > 1: + random.shuffle(values) + for value in values: + if pattern.match(value[1]): + found = 1 + break + if found: + mask = random.choice(self._masks) + phrase = mask % {"key": key, "value": random.choice(values)[1]} + results.append(phrase) + + def search(self, pattern): + results = [] + if self._info: + for key, values in self._info.values(): + self._search(pattern, key, values, results) + else: + file = open(self._filename) + values = [] + for line in file.readlines(): + if line and line[0] != "#": + if line[0] == "K": + if values: + self._search(pattern, key, values, results) + key = line[2:].rstrip() + values = [] + elif line[0] == "V": + value = line[2:].split(":", 1) + value[1] = value[1].rstrip() + values.append(value) + if values: + self._search(pattern, key, values, results) + file.close() + return results + class InfopackModule: def __init__(self): *************** *** 214,218 **** pack.loadcore() ! # [load|reload|unload] infopack <name> [in memory] [.|!] self.re1 = regexp(r"(?P<action>re|un)?load infopack (?P<name>\w+)(?P<inmemory> in memory)?") --- 268,272 ---- pack.loadcore() ! # [load|reload|unload] infopack <name> [in memory] self.re1 = regexp(r"(?P<action>re|un)?load infopack (?P<name>\w+)(?P<inmemory> in memory)?") *************** *** 220,223 **** --- 274,280 ---- self.re2 = regexp(r"show infopacks") + # search infopack <name> for /<regexp>/ + self.re3 = regexp(r"search infopack (?P<name>\S+) for /(?P<regexp>.*)/") + # infopack[s] mm.register_help("infopacks?", HELP, "infopack") *************** *** 322,325 **** --- 379,383 ---- else: # Unload infopack + cursor = db.cursor() if not self.packs.has_key(name): msg.answer("%:", ["Oops!", "Sorry!"], *************** *** 328,331 **** --- 386,391 ---- else: del self.packs[name] + cursor.execute("delete from infopack where name=%s", + name) msg.answer("%:", ["Unloaded", "Done", "Ok"], [".", "!"]) *************** *** 349,354 **** return 0 found = 0 ! for pack in self.packs.values(): info = pack.get(msg.line) if info: --- 409,459 ---- return 0 + m = self.re3.match(msg.line) + if m: + name = m.group("name") + regexp = m.group("regexp") + try: + pack = self.packs[name] + except KeyError: + msg.answer("%:", ["Oops!", "Sorry!"], + "This infopack is not loaded", + [".", "!"]) + return 0 + try: + pattern = re.compile(regexp, re.I) + except re.error: + msg.answer("%:", "Invalid pattern", [".", "!"]) + return 0 + results = pack.search(pattern) + reslen = len(results) + if not results: + msg.answer("%:", ["Pattern not found", + "Couldn't find anything with that pattern", + "Nothing found"], [".", "!"]) + elif reslen > MAXSEARCHRESULTS: + msg.answer("%:", ["Found too many entries", + "There are many entries like this", + "There are many matches"], + ", here are the first %d:"%MAXSEARCHRESULTS) + elif reslen > 1: + msg.answer("%:", ["Found %d entries:" % reslen, + "Found %d matches:" % reslen]) + else: + msg.answer("%:", ["Found one entry:", + "Found one match:"]) + n = 0 + for result in results: + msg.answer("-", result) + n += 1 + if n == MAXSEARCHRESULTS: + break + return 0 + + allowed = mm.permparams(msg, "infopack") + found = 0 ! for name, pack in self.packs.items(): ! if name not in allowed: ! continue info = pack.get(msg.line) if info: Index: permission.py =================================================================== RCS file: /cvsroot/pybot/pybot/pybot/modules/permission.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** permission.py 24 Aug 2003 19:30:53 -0000 1.11 --- permission.py 27 Aug 2003 17:08:14 -0000 1.12 *************** *** 43,51 **** """ ! VALIDUSER = re.compile(".+!.+@.+") class Permission: def __init__(self): ! db.table("permission", "permission,servername,target,userstr,nick") self.help = options.get("Help.perm", {}) mm.register("hasperm", self.mm_hasperm) --- 43,54 ---- """ ! VALIDUSER = re.compile(r".+!.+@.+") ! ! PARAM = re.compile(r"(?P<perm>\S+)\((?P<param>.*)\)$") class Permission: def __init__(self): ! db.table("permission", "permission, param default '', " ! "servername, target, userstr, nick") self.help = options.get("Help.perm", {}) mm.register("hasperm", self.mm_hasperm) *************** *** 53,56 **** --- 56,61 ---- mm.register("setperm", self.mm_setperm) mm.register("unsetperm", self.mm_unsetperm) + mm.register("permparams", self.mm_permparams) + mm.register("permparams_raw", self.mm_permparams_raw) hooks.register("Message", self.message) *************** *** 64,68 **** # (give|remove|del|delete|take) perm[ission] <perm> [to|from] [everyone | [user <user>] [[and] nick <nick>] [on|at] [this channel|channel <channel>] [on|at|to] [this server|server <server>]] ! self.re1 = regexp("(?P<cmd>give|remove|del|delete|take) (?:perm(?:ission)? (?P<perm1>\S+)|(?P<perm2>\S+) perm(?:ission)?)(?: to| from)?(?:(?P<everyone> everyone)|(?: user (?P<user>\S+))?(?:(?: and)? nick (?P<nick>\S+))?(?: on| at)?(?: (?P<thischannel>this channel)| channel (?P<channel>\S+))?(?: on| at| to)?(?: (?P<thisserver>this server)| server (?P<server>\S+))?)?") # (show|list) perm[ission][s] [<perm>] --- 69,73 ---- # (give|remove|del|delete|take) perm[ission] <perm> [to|from] [everyone | [user <user>] [[and] nick <nick>] [on|at] [this channel|channel <channel>] [on|at|to] [this server|server <server>]] ! self.re1 = regexp("(?P<cmd>give|remove|del|delete|take) (?:perm(?:ission)? (?P<perm1>\S+)|(?P<perm2>\S+) perm(?:ission)?)(?: to| from| for)?(?:(?P<everyone> everyone)|(?: user (?P<user>\S+))?(?:(?: and)? nick (?P<nick>\S+))?(?: on| at| to| in| for)?(?: (?P<thischannel>this channel)| channel (?P<channel>\S+))?(?: on| at| to| in| for)?(?: (?P<thisserver>this server)| server (?P<server>\S+))?)?") # (show|list) perm[ission][s] [<perm>] *************** *** 124,131 **** nick = m.group("nick") perm = m.group("perm1") or m.group("perm2") # Everyone is handled transparently, since all # items will be None if m.group("cmd").lower() == "give": ! if not mm.setperm(servername, target, userstr, nick, perm): msg.answer("%:", ["I already have this permission", "This permission was given before", --- 129,142 ---- nick = m.group("nick") perm = m.group("perm1") or m.group("perm2") + _m = PARAM.match(perm) + if _m: + perm, param = _m.group("perm", "param") + else: + param = "" # Everyone is handled transparently, since all # items will be None if m.group("cmd").lower() == "give": ! if not mm.setperm(servername, target, ! userstr, nick, perm, param): msg.answer("%:", ["I already have this permission", "This permission was given before", *************** *** 134,138 **** return 0 else: ! if not mm.unsetperm(servername, target, userstr, nick, perm): msg.answer("%:", "No entries like this were found", [".", "!"]) --- 145,150 ---- return 0 else: ! if not mm.unsetperm(servername, target, ! userstr, nick, perm, param): msg.answer("%:", "No entries like this were found", [".", "!"]) *************** *** 191,194 **** --- 203,208 ---- if first: s += "everyone" + if row.param: + s += " (%s)" % row.param if i == numrows-1: s += "." *************** *** 227,231 **** return 0 ! def mm_hasperm_raw(self, servername, target, user, perm): if servername == "console": return 1 --- 241,245 ---- return 0 ! def mm_hasperm_raw(self, servername, target, user, perm, param=""): if servername == "console": return 1 *************** *** 235,239 **** cursor = db.cursor() cursor.execute("select * from permission where " ! "permission='admin' or permission=%s", perm) for row in cursor.fetchall(): if (not row.servername or row.servername == servername) and \ --- 249,254 ---- cursor = db.cursor() cursor.execute("select * from permission where " ! "permission='admin' or " ! "(permission=%s and param=%s)", (perm, param)) for row in cursor.fetchall(): if (not row.servername or row.servername == servername) and \ *************** *** 244,263 **** return 0 ! def mm_hasperm(self, msg, perm): return self.mm_hasperm_raw(msg.server.servername, ! msg.target, msg.user, perm) ! def mm_setperm(self, servername, target, userstr, nick, perm): if self.mm_unsetperm(servername, target, userstr, nick, ! perm, check=1): return 0 cursor = db.cursor() ! cursor.execute("insert into permission values (%s,%s,%s,%s,%s)", ! perm, servername, target, userstr, nick) return bool(cursor.rowcount) ! def mm_unsetperm(self, servername, target, userstr, nick, perm, check=0): ! where = ["permission=%s"] ! wargs = [perm] if servername: where.append("servername=%s") --- 259,279 ---- return 0 ! def mm_hasperm(self, msg, perm, param=""): return self.mm_hasperm_raw(msg.server.servername, ! msg.target, msg.user, perm, param) ! def mm_setperm(self, servername, target, userstr, nick, perm, param=""): if self.mm_unsetperm(servername, target, userstr, nick, ! perm, param, check=1): return 0 cursor = db.cursor() ! cursor.execute("insert into permission values (%s,%s,%s,%s,%s,%s)", ! (perm, param, servername, target, userstr, nick)) return bool(cursor.rowcount) ! def mm_unsetperm(self, servername, target, userstr, nick, ! perm, param="", check=0): ! where = ["permission=%s", "param=%s"] ! wargs = [perm, param] if servername: where.append("servername=%s") *************** *** 287,290 **** --- 303,324 ---- cursor.execute("select * from permission where "+wstr, *wargs) return bool(cursor.rowcount) + + def mm_permparams_raw(self, servername, target, user, perm): + loggednick = mm.loggednick(servername, user) + cursor = db.cursor() + cursor.execute("select * from permission where " + "permission=%s", (perm,)) + params = {} + for row in cursor.fetchall(): + if (not row.servername or row.servername == servername) and \ + (not row.target or row.target == target) and \ + (not row.userstr or user.matchstr(row.userstr)) and \ + (not row.nick or row.nick == loggednick): + params[row.param] = 1 + return params.keys() + + def mm_permparams(self, msg, perm): + return self.mm_permparams_raw(msg.server.servername, + msg.target, msg.user, perm) def __loadmodule__(): Index: remoteinfo.py =================================================================== RCS file: /cvsroot/pybot/pybot/pybot/modules/remoteinfo.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** remoteinfo.py 25 Aug 2003 21:49:05 -0000 1.7 --- remoteinfo.py 27 Aug 2003 17:08:14 -0000 1.8 *************** *** 28,43 **** and to unload or reload using "(re|un)load remote info [from] <url>". To check what is being remotely loaded, use "show remote[ ]info[s]". To ! load and unload remote infos you'll need the "remoteinfo" permission, ! and to show and reload you need either the "remoteinfo" or the ! "remoteinforeload" permission. """,""" After you setup some URL for remote loading, you must say explicitly which users/channels and servers will be able to obtain information from ! it. To do that use the command "[don't] allow remote info [from] <url> ! [(for|on|at) (user|channel) <target>] [(for|on|at) server <server>]". ! Notice that you may omit user/channel and/or server to give wider ! permissions. ! """,""" ! The default reload interval is 10 minutes. To understand how to build the regex for the remote info command or how to build the remote information check "help remote info syntax". --- 28,38 ---- and to unload or reload using "(re|un)load remote info [from] <url>". To check what is being remotely loaded, use "show remote[ ]info[s]". To ! load and unload remote infos you must be an admin, and to show and reload ! you need the "remoteinfoadmin" permission. """,""" After you setup some URL for remote loading, you must say explicitly which users/channels and servers will be able to obtain information from ! it. To do that give the permission "remoteinfo(<url>)" for these you ! want to allow. The default reload interval is 10 minutes. To understand how to build the regex for the remote info command or how to build the remote information check "help remote info syntax". *************** *** 67,78 **** PERM_REMOTEINFO = """ ! Users with the "remoteinfo" permission can work with remote ! information settings. Check "help remoteinfo" for more information. """ ! PERM_RELOADREMOTEINFO = """ ! Users with the "reloadremoteinfo" permission can ask me to reload ! information from remote URLs. Notice that the "remoteinfo" permission ! allows that as well. Check "help remoteinfo" for more information. """ --- 62,73 ---- PERM_REMOTEINFO = """ ! Users with the "remoteinfo(<url>)" permission will be able to use ! knowledge acquired from the given url. Check "help remoteinfo" for ! more information. """ ! PERM_REMOTEINFOADMIN = """ ! Users with the "remoteinfoadmin" permission can ask me to reload ! information from remote URLs, and to show which URLs are being loaded. """ *************** *** 91,103 **** def __init__(self): db.table("remoteinfo", "id integer primary key, url, regex, interval", ! constraints="unique (url)", ! triggers=[ ! "create trigger remoteinfo1 after delete on remoteinfo " ! "begin" ! " delete from remoteinfoallow where infoid=old.id;" ! "end" ! ]) ! db.table("remoteinfoallow", "infoid, servername, target", ! constraints="unique (infoid, servername, target)") self.info = options.get("RemoteInfo.info", {}) self.info_lock = options.get("RemoteInfo.info_lock", {}) --- 86,90 ---- def __init__(self): db.table("remoteinfo", "id integer primary key, url, regex, interval", ! constraints="unique (url)") self.info = options.get("RemoteInfo.info", {}) self.info_lock = options.get("RemoteInfo.info_lock", {}) *************** *** 113,121 **** self.re2 = regexp(r"(?P<cmd>un|re)load remote *info (?:from )?(?P<url>\S+)") - # [(don[']t|do not)] allow remote[ ]info [from] <url> [(to|for|on|at|in) (user|channel) <target>] [(to|for|on|at|in) server <server>] - self.re3 = regexp(r"(?P<dont>don'?t |do not )?allow remote *info (?:from )?(?P<url>\S+)(?: (?:to|for|on|at|in) (?:user|channel) (?P<target>\S+))?(?: (?:to|for|on|at|in) server (?P<server>\S+))?") - # show remote[ ]info[s] ! self.re4 = regexp(r"show remote *infos?") # remote[ ]info --- 100,105 ---- self.re2 = regexp(r"(?P<cmd>un|re)load remote *info (?:from )?(?P<url>\S+)") # show remote[ ]info[s] ! self.re3 = regexp(r"show remote *infos?") # remote[ ]info *************** *** 125,129 **** mm.register_perm("remoteinfo", PERM_REMOTEINFO) ! mm.register_perm("reloadremoteinfo", PERM_RELOADREMOTEINFO) mm.hooktimer(30, self.reload_all, ()) --- 109,113 ---- mm.register_perm("remoteinfo", PERM_REMOTEINFO) ! mm.register_perm("remoteinfoadmin", PERM_REMOTEINFOADMIN) mm.hooktimer(30, self.reload_all, ()) *************** *** 140,144 **** mm.unregister_help(HELP_SYNTAX) mm.unregister_perm("remoteinfo") ! mm.unregister_perm("reloadremoteinfo") def lock_url(self, url): --- 124,128 ---- mm.unregister_help(HELP_SYNTAX) mm.unregister_perm("remoteinfo") ! mm.unregister_perm("remoteinfoadmin") def lock_url(self, url): *************** *** 233,239 **** def message_remoteinfo(self, msg): ret = None ! allowed = self.get_allowed_urls(msg.server.servername, ! msg.answertarget) for url, info in self.info.items(): if url not in allowed: continue --- 217,226 ---- def message_remoteinfo(self, msg): ret = None ! #allowed = self.get_allowed_urls(msg.server.servername, ! # msg.answertarget) ! allowed = mm.permparams(msg, "remoteinfo") for url, info in self.info.items(): + #if not mm.hasperm(msg, "remoteinfo", url): + # continue if url not in allowed: continue *************** *** 274,278 **** m = self.re1.match(msg.line) if m: ! if mm.hasperm(msg, "remoteinfo"): url = m.group("url") regex = (m.group("regex") or DEFAULTREGEX).strip() --- 261,265 ---- m = self.re1.match(msg.line) if m: ! if mm.hasperm(msg, "admin"): url = m.group("url") regex = (m.group("regex") or DEFAULTREGEX).strip() *************** *** 334,395 **** m = self.re2.match(msg.line) if m: ! cmd = m.group("cmd") ! url = m.group("url") ! cursor = db.cursor() ! cursor.execute("select * from remoteinfo where url=%s", ! (url,)) ! if not cursor.rowcount: ! msg.answer("%:", ["I can't do that.", "Nope.", None], ! ["I'm not loading that url", ! "This url is not in my database"], ! [".", "!"]) ! elif cmd == "un": ! if mm.hasperm(msg, "remoteinfo"): ! if not self.lock_url(url): ! msg.answer("%:", "Can't do that now. URL is " ! "being loaded in this exact " ! "moment. Try again in a few " ! "seconds.") ! else: ! if url in self.info: ! del self.info[url] ! if url in self.info_lock: ! del self.info_lock[url] ! # Unlocking is not really necessary, but ! # politically right. ;-) ! self.unlock_url(url) ! cursor.execute("delete from remoteinfo where url=%s", ! (url,)) ! msg.answer("%:", ["Done", "Of course", "Ready"], ! [".", "!"]) ! else: ! msg.answer("%:", [("You're not", ! ["allowed to change " ! "remote info options", ! "that good", ! "allowed to do this"]), ! "Nope"], [".", "!"]) ! else: ! if mm.hasperm(msg, "remoteinfo") or \ ! mm.hasperm(msg, "reloadremoteinfo"): ! msg.answer("%:", ["Will do that", ! "In a moment", ! "Will be ready in a moment", ! "Starting right now"], [".", "!"]) ! self.reload(url) ! else: ! msg.answer("%:", [("You're not", ! ["allowed to reload remote infos", ! "that good", ! "allowed to do this"]), ! "Nope"], [".", "!"]) ! return 0 ! ! m = self.re3.match(msg.line) ! if m: ! if mm.hasperm(msg, "remoteinfo"): url = m.group("url") - target = m.group("target") or "" - server = m.group("server") or "" cursor = db.cursor() cursor.execute("select * from remoteinfo where url=%s", --- 321,327 ---- m = self.re2.match(msg.line) if m: ! if mm.hasperm(msg, "remoteinfoadmin"): ! cmd = m.group("cmd") url = m.group("url") cursor = db.cursor() cursor.execute("select * from remoteinfo where url=%s", *************** *** 400,441 **** "This url is not in my database"], [".", "!"]) ! return 0 ! if m.group("dont"): ! cursor.execute("delete from remoteinfoallow where " ! "infoid=(select id from remoteinfo where url=%s) " ! "and servername=%s and target=%s", ! (url, server, target)) ! if cursor.rowcount: ! msg.answer("%:", ["Sure", "Done", "Removed", "Ok"], ! [".", "!"]) ! else: ! msg.answer("%:", ["I can't do that.", "Nope.", None], ! ["This target doesn't exist", ! "I'm not allowing this target", ! "This target is not in my database"], ! [".", "!"]) else: ! try: ! cursor.execute("insert into remoteinfoallow values " ! "((select id from remoteinfo where url=%s)," ! " %s,%s)", (url, server, target)) ! except db.error: ! msg.answer("%:", ["I can't do that.", "Nope.", None], ! ["This target is already allowed", ! "I'm already allowing this target", ! "This target is already in my database"], ! [".", "!"]) ! else: ! msg.answer("%:", ["Sure", "Done", "Added", "Ok"], ! [".", "!"]) else: msg.answer("%:", [("You're not", ! ["allowed to change remote info options", "that good", "allowed to do this"]), "Nope"], [".", "!"]) return 0 ! ! m = self.re4.match(msg.line) if m: if mm.hasperm(msg, "remoteinfo") or \ --- 332,368 ---- "This url is not in my database"], [".", "!"]) ! elif cmd == "un": ! if not self.lock_url(url): ! msg.answer("%:", "Can't do that now. URL is " ! "being loaded in this exact " ! "moment. Try again in a few " ! "seconds.") ! else: ! if url in self.info: ! del self.info[url] ! if url in self.info_lock: ! del self.info_lock[url] ! # Unlocking is not really necessary, but ! # politically right. ;-) ! self.unlock_url(url) ! cursor.execute("delete from remoteinfo where url=%s", ! (url,)) ! msg.answer("%:", ["Done", "Of course", "Ready"], ! [".", "!"]) else: ! msg.answer("%:", ["Will do that", ! "In a moment", ! "Will be ready in a moment", ! "Starting right now"], [".", "!"]) ! self.reload(url) else: msg.answer("%:", [("You're not", ! ["allowed to touch remote infos", "that good", "allowed to do this"]), "Nope"], [".", "!"]) return 0 ! ! m = self.re3.match(msg.line) if m: if mm.hasperm(msg, "remoteinfo") or \ |