def load(name=None, id=None, passwd=None, exact=True, active=True, access=0): assert id or name Q = session.query(User) if active is True: if access in Config.options("Access"): access = Config.getint("Access", access) elif type(access) is int: pass else: raise LoadableError("Invalid access level") Q = Q.filter(User.active == True).filter(User.access >= access) if id is not None: user = Q.filter(User.id == id).first() if name is not None: for filter in ( User.name.ilike(name), User.name.ilike(name + "%"), User.alias.ilike(name), User.alias.ilike(name + "%"), User.name.ilike("%" + name + "%"), User.alias.ilike("%" + name + "%"), ): user = Q.filter(filter).first() if user is not None or exact is True: break if (user and passwd) is not None: user = user if user.passwd == User.hasher(passwd) else None return user
def ctcp(message): """Respond to CTCP queries (from admins)""" m = message.get_msg() if m[0] == '\001': from Core.config import Config try: if message.get_pnick() in Config.options("Admins"): if m[1:5] == 'PING': message.write("NOTICE %s :\001PING %s\001" % (message.get_nick(), m[6:])) elif m[1:8] == 'VERSION': import subprocess try: version = subprocess.check_output( ["git", "describe", "HEAD"]).strip() version += "/" + "/".join( subprocess.check_output([ "git", "describe", "origin/acl", "origin/master" ]).split()) except: pass message.write( "NOTICE %s :\001VERSION %s\001" % (message.get_nick(), "Merlin (%s)" % version)) except PNickParseError: pass
def execute(self, message, user, params): # do stuff here if params.group(1).lower() == Config.get("Connection","nick").lower(): message.reply("I'll peck your eyes out, c**t.") return idiot = User.load(name=params.group(1), access="member") if idiot is None: message.reply("That user isn't a member!") return if (not user.is_admin()) and user != idiot and idiot.sponsor != user.name: message.reply("You do not have sufficent access to demote this member.") return if "galmate" in Config.options("Access"): idiot.access = Config.getint("Access","galmate") else: idiot.access = 0 if idiot.planet is not None and idiot.planet.intel is not None: intel = idiot.planet.intel alliance = Alliance.load(Config.get("Alliance","name")) if intel.alliance == alliance: intel.alliance = None session.commit() message.privmsg("remuser %s %s"%(Config.get("Channels","home"), idiot.name,),'p') message.privmsg("remuser %s %s"%(Config.get("Channels","core"), idiot.name,),'p') if idiot.sponsor != user.name: # message.privmsg("note send %s You have been removed from private channels."%(idiot.name,),'p') message.reply("%s has been reduced to \"galmate\" level and removed from the channel. "%(idiot.name,)) else: # message.privmsg("note send %s You have been removed from private channels."%(idiot.name,),'p') message.reply("%s has been reduced to \"galmate\" level and removed from the channel."%(idiot.name,))
def updatenotifier(message): """Receive and parse update notifications""" m = message.get_msg() if m[0] == '@': try: if message.get_chan() == Config.get("Updates", "notify-channel") and message.get_pnick() in Config.get("Updates", "notify-allow").split(): params = m[1:].split("/", 3) if params[0] in Config.get("Updates", "notify-repo").split(): mtags = params[1].split(",") ctags = Config.get("Updates", "notify-branch").split() selected = False if "all" in mtags or "all" in ctags: selected = True else: for tag in mtags: if tag in ctags: selected = True break if tag == "unstable": mtags.extend(["acl", "master"]) elif tag == "stable": mtags.extend(["acl-stable", "legacy-stable"]) if selected == True: levels = Config.get("Updates", "notify-level").split() if params[2] in levels or ("all" in levels and params[2] != "forks"): nu = Config.get("Updates", "notify-users").split() message.privmsg("UPDATE (%s): %s in %s: %s" % (message.get_pnick(), params[2], "/".join(params[:1]), params[3]), ",".join(nu) if nu else Config.options("Admins")[0], priority=+5) except (ChanParseError, PNickParseError): pass
def __new__(cls): self = super(loadable, cls).__new__(cls) self.name = cls.__name__ self.doc = cls.__doc__ self.routes = self.routes or [] self.routes.extend([ ( name, route._ROUTE, route._ACCESS, ) for name, route in sorted(cls.__dict__.items()) if hasattr(route, "_ROUTE") and hasattr(route, "_ACCESS") ]) if cls.access in Config.options("Access"): self.access = Config.getint("Access", cls.access) elif type(cls.access) is int: self.access = cls.access else: self.access = min([ route._ACCESS for route in cls.__dict__.values() if hasattr(route, "_ROUTE") and hasattr(route, "_ACCESS") ]) return self
def execute(self, message, user, params): reply = "" tick = Updates.current_tick() opts = params.group(1).split() for o in reversed(Config.options("Access")): if ("galmates" not in opts) and (Config.getint("Access", o) == 0): continue Q = session.query(User) Q = Q.filter(User.access == Config.getint("Access", o)) Q = Q.order_by(asc(User.name)) result = Q.all() if len(result) < 1: continue printable = map( lambda (u): "%s%s%s%s%s" % (u.name, ' (' + u.alias + ')' if u.alias else '', " (%d:%d:%d)" % (u.planet.x, u.planet.y, u.planet.z) if "coords" in opts and u.planet is not None else '', " (%s)" % ((u.fleetupdated or 0) - tick) if "defage" in opts else '', " (%s)" % (u.fleetupdated or 0) if "mydef" in opts else ''), result) reply += "%s: " % (o) reply += ', '.join(printable) reply += '\n' message.reply(reply[:-1])
def execute(self, request, user, sort=None): levels = [] + User.levels if "galmate" in Config.options("Access"): levels.append(("Galaxy", Config.getint("Access","galmate"),)) else: levels.append(("Galaxy", 0,)) if sort is not None: levels = [("All", 0,),] order = {"name" : (asc(Channel.name),), "userlevel" : (desc(Channel.userlevel),), "maxlevel" : (desc(Channel.maxlevel),), } if sort not in order.keys(): sort = "name" order = order.get(sort) channels = [] for level in levels: Q = session.query(Channel.name, Channel.userlevel, Channel.maxlevel) Q = Q.filter(Channel.userlevel >= level[1]) Q = Q.filter(Channel.userlevel < levels[levels.index(level)-1][1]) if levels.index(level) > 0 else Q for o in order: Q = Q.order_by(o) channels.append((level[0], Q.all(),)) return render("channels.tpl", request, accesslist=channels)
def execute(self, message, user, params): # do stuff here if params.group(1).lower() == Config.get("Connection","nick").lower(): message.reply("I'll peck your eyes out, c**t.") return idiot = User.load(name=params.group(1), access="member") if idiot is None: message.reply("That idiot isn't a member!") return if (not user.is_admin()) and user != idiot and idiot.sponsor != user.name: message.reply("You are not %s's sponsor"%(idiot.name,)) return if "galmate" in Config.options("Access"): idiot.access = Config.getint("Access","galmate") else: idiot.access = 0 if idiot.planet is not None and idiot.planet.intel is not None: intel = idiot.planet.intel alliance = Alliance.load(Config.get("Alliance","name")) if intel.alliance == alliance: intel.alliance = None session.commit() message.privmsg("remuser %s %s"%(Config.get("Channels","home"), idiot.name,),Config.get("Services", "nick")) message.privmsg("ban %s *!*@%s.%s Your sponsor doesn't like you anymore"%(Config.get("Channels","home"), idiot.name, Config.get("Services", "usermask"),),Config.get("Services", "nick")) if idiot.sponsor != user.name: message.privmsg("note send %s Some admin has removed you for whatever reason. If you still wish to be a member, go ahead and find someone else to sponsor you back."%(idiot.name,),Config.get("Services", "nick")) message.reply("%s has been reduced to \"galmate\" level and removed from the channel. %s is no longer %s's sponsor. If anyone else would like to sponsor that person back, they may."%(idiot.name,idiot.sponsor,idiot.name)) else: message.privmsg("note send %s Your sponsor (%s) no longer wishes to be your sponsor. If you still wish to be a member, go ahead and find someone else to sponsor you back."%(idiot.name,user.name,),Config.get("Services", "nick")) message.reply("%s has been reduced to \"galmate\" level and removed from the channel. You are no longer %s's sponsor. If anyone else would like to sponsor that person back, they may."%(idiot.name,idiot.name))
def execute(self, message, user, params): # do stuff here if params.group(1).lower() == Config.get("Connection","nick").lower(): message.reply("I'll peck your eyes out, c**t.") return idiot = User.load(name=params.group(1), access="member") if idiot is None: message.reply("That idiot isn't a member!") return if (not user.is_admin()) and user != idiot and idiot.sponsor != user.name: message.reply("You are not %s's sponsor"%(idiot.name,)) return if "galmate" in Config.options("Access"): idiot.access = Config.getint("Access","galmate") else: idiot.access = 0 if idiot.planet is not None and idiot.planet.intel is not None: intel = idiot.planet.intel alliance = Alliance.load(Config.get("Alliance","name")) if intel.alliance == alliance: intel.alliance = None session.commit() message.privmsg("remuser %s %s"%(Config.get("Channels","home"), idiot.name,),'p') message.privmsg("ban %s *!*@%s.users.netgamers.org Your sponsor doesn't like you anymore"%(Config.get("Channels","home"), idiot.name,),'p') if idiot.sponsor != user.name: message.privmsg("note send %s Some admin has removed you for whatever reason. If you still wish to be a member, go ahead and find someone else to sponsor you back."%(idiot.name,),'p') message.reply("%s has been reduced to \"galmate\" level and removed from the channel. %s is no longer %s's sponsor. If anyone else would like to sponsor that person back, they may."%(idiot.name,idiot.sponsor,idiot.name)) else: message.privmsg("note send %s Your sponsor (%s) no longer wishes to be your sponsor. If you still wish to be a member, go ahead and find someone else to sponsor you back."%(idiot.name,user.name,),'p') message.reply("%s has been reduced to \"galmate\" level and removed from the channel. You are no longer %s's sponsor. If anyone else would like to sponsor that person back, they may."%(idiot.name,idiot.name))
def write(self, text, color=False, priority=0): # Write something to the server, the message will be split up by newlines and at 450chars max # Set Priority l = len(text) p = 5 + priority if l < 100: p -= 1 elif l > 150: p += min(l,400) // 100 + l // 450 ## n = False try: n = self.get_pnick() except: p += 2 if n: if n in Config.options("Admins"): p -= 2 try: u = User.load(n) if u: if u.is_admin(): p -= 1 elif u.is_galmate(): p += 1 else: p +=2 except: p += 2 # Split message and send colon = text.find(":") if colon != -1: while text[colon-1] != " " and colon != -1: colon = text.find(":",colon+1) if colon != -1: params = text[:colon+1] text = text[colon+1:] if colon == -1: params = text text = None if text: if color: params += "\x03"+Config.get("Connection", "color") for line in text.split("\n"): line while line: i = len(line) while len(line[:i]) > (450 - len(params)): i = line.rfind(" ", 0, i) if i == -1: Connection.write((params + line)[:450]) line = line[450 - len(params):] continue Connection.write(params + line[:i], p) line = line[i+1:] else: Connection.write(params, p)
def check_access(self, message, user=None, channel=None): if command is not True: return None if admin is not True: return True if message.get_pnick() in Config.options("Admins"): return True return None
def execute(self, request, user, message=None): tick = Updates.current_tick() Q = session.query(Attack) if user.access < ( Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000 ): # Hide attacks until they are active, unless the user has access Q = Q.filter( Attack.landtick <= tick + Config.getint("Misc", "attactive")) Q = Q.filter( Attack.landtick + Attack.waves >= tick) # Hide attacks one tick after the last wave has landed Q = Q.order_by(asc(Attack.id)) attacks = Q.all() Q = session.query(Planet, Target.tick) Q = Q.join(Target.planet) Q = Q.join(Target.user) Q = Q.filter(Planet.active == True) Q = Q.filter(Target.user == user) Q = Q.filter( Target.tick >= tick - 12) # We shouldn't need any bookings 12 ticks after landing Q = Q.order_by(asc(Target.tick), asc(Planet.x), asc(Planet.y), asc(Planet.z)) bookings = [] scans = [] for planet, tock in Q.all(): bookings.append(( planet, tock, [], )) if planet.scan("P"): bookings[-1][2].append(planet.scan("P")) scans.append(planet.scan("P")) if planet.scan("D"): bookings[-1][2].append(planet.scan("D")) scans.append(planet.scan("D")) if planet.scan("A") or planet.scan("U"): bookings[-1][2].append(planet.scan("A") or planet.scan("U")) scans.append(planet.scan("A") or planet.scan("U")) if tock <= tick + Config.getint("Misc", "attjgp") and planet.scan( "J"): bookings[-1][2].append(planet.scan("J")) scans.append(planet.scan("J")) return render("attacks.tpl", request, message=message, attacks=attacks, bookings=bookings, scans=scans)
def admin_msg(message, priority=2): # Import these here or Core/connection.py will get upset. from Core.chanusertracker import CUT from Core.config import Config from Core.connection import Connection for a in Config.options("Admins"): for nick in CUT.get_user_nicks(a.lower()): Connection.write("PRIVMSG %s :%s" % (nick, message), priority)
def user_in(chan): if not chan.find("#") == 0: if chan in Config.options("Channels"): chan = Config.get("Channels",chan) else: raise LoadableError("Invalid channel") def wrapper(execute): execute._USER_IN = chan return execute return wrapper
def channel(chan): if not chan.find("#") == 0: if chan in Config.options("Channels"): chan = Config.get("Channels",chan) elif chan == "PM": chan = Config.get("Connection","nick") else: raise LoadableError("Invalid channel") def wrapper(execute): execute._CHANNEL = chan return execute return wrapper
def check_access(loadable, message, access=None, user=None, channel=None): if command is not True: return None if admin is not True: return True if message.get_pnick() in Config.options("Admins"): return True return None
def check_access(self, message, access=None, user=None, channel=None): try: user = loadable.check_access(self, message, access, user, channel) if not self.is_user(user): raise UserError else: return user except UserError: if message.get_pnick() in Config.options("Admins"): return User(name=Config.get("Connection", "nick"), access=Config.getint("Access", "admin")) else: raise
def show(self, message, user, params): id = params.group(1) attack = Attack.load(id) if attack is None: message.alert("No attack exists with id %s" %(id)) return if user.access < (Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000) and attack.landtick > Updates.current_tick() + Config.getint("Misc", "attactive"): message.alert("Attack %s is not open yet" %(id)) return message.reply(str(attack))
def __new__(cls): self = super(loadable, cls).__new__(cls) self.name = cls.__name__ if cls.access in Config.options("Access"): self.access = Config.getint("Access", cls.access) elif type(cls.access) in (int, type(None),): self.access = cls.access else: raise LoadableError("Invalid access level") return self
def user_in(chan): if not chan.find("#") == 0: if chan in Config.options("Channels"): chan = Config.get("Channels", chan) else: raise LoadableError("Invalid channel") def wrapper(execute): execute._USER_IN = chan return execute return wrapper
def execute(self, message, user, params): reply = [] Q = session.query(Channel) if not params.group(1): Q = Q.filter(Channel.userlevel > ( Config.getint("Access", "galmate") if "galmate" in Config.options("Access") else 0)) for c in Q.all(): reply.append(c.name) message.reply("Stored channels: %s" % (", ".join(reply)))
def list(self, message, user, params): Q = session.query(Attack) if user.access < (Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000): # Hide attacks until they are active, unless the user has access Q = Q.filter(Attack.landtick <= Updates.current_tick() + Config.getint("Misc", "attactive")) Q = Q.filter(Attack.landtick + Attack.waves >= Updates.current_tick()) # Hide attacks one tick after the last wave has landed Q = Q.order_by(asc(Attack.id)) replies = [] for attack in Q: replies.append("(%d LT: %d %s)" %(attack.id,attack.landtick,attack.comment,)) reply = "Open attacks: " + " ".join(replies) message.reply(reply)
def channel(chan): if not chan.find("#") == 0: if chan in Config.options("Channels"): chan = Config.get("Channels", chan) elif chan == "PM": chan = Config.get("Connection", "nick") else: raise LoadableError("Invalid channel") def wrapper(execute): execute._CHANNEL = chan return execute return wrapper
def robocop(self, message, scantype, pa_id, x, y, z, names, scanner, reqs, old=False): nicks = [] reply = "Old " if old else "" reply += "%s on %s:%s:%s " % ( PA.get(scantype, "name"), x, y, z, ) if ("showscanner" in Config.options("Misc") and Config.getboolean("Misc", "showscanner") and scanner != 'None'): reply += "from %s " % (User.load(id=scanner).name) if User.load( id=scanner) not in (None, 'None') else "" reply += Config.get("URL", "viewscan") % (pa_id, ) if old: reply += " !request cancel %s if this is suitable." % (reqs) for name in names.split(","): user = User.load(name) for nick in CUT.get_user_nicks(name): nicks.append(nick) message.privmsg(self.url(reply, user), nick) if not old: reply = "[-%s] %s on %s:%s:%s " % ( reqs, PA.get(scantype, "name"), x, y, z, ) reply += "delivered to: " reply += ", ".join(nicks) if not Config.getboolean( "Misc", "anonscans") else "Anon" if Config.getboolean("Misc", "showurls"): reply += " (%s)" % (Config.get("URL", "viewscan") % (pa_id, )) from Hooks.scans.request import request message.privmsg(reply, request().scanchan())
def show(self, message, user, params): id = params.group(1) attack = Attack.load(id) if attack is None: message.alert("No attack exists with id %s" % (id)) return if user.access < (Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000) and attack.landtick > Updates.current_tick( ) + Config.getint("Misc", "attactive"): message.alert("Attack %s is not open yet" % (id)) return message.reply(str(attack))
def __new__(cls): self = super(loadable, cls).__new__(cls) self.name = cls.__name__ if cls.access in Config.options("Access"): self.access = Config.getint("Access", cls.access) elif type(cls.access) in ( int, type(None), ): self.access = cls.access else: raise LoadableError("Invalid access level") return self
def get_user(self, name, channel, pnick=None, pnickf=None): # Regular user check if (pnick is None) and (pnickf is None): # This shouldn't happen return None nick = self.Nicks.get(name) if (nick and nick.puser) is not None: # They already have a user associated pnick = nick.puser elif pnickf is not None: # Call the pnick function, might raise PNickParseError try: pnick = pnickf() except PNickParseError: return None user = User.load(name=pnick) if user is None and Config.getboolean("Misc", "autoreg"): if nick and not nick.puser: if "galmate" in Config.options("Access"): access = Config.getint("Access", "galmate") else: access = 0 user = User.load(name=pnick, active=False) if user is None: user = User(name=pnick, access=access) session.add(user) else: user.active = True user.access = access session.commit() if user is None: return None if (nick is not None) and self.mode_is("rapid", "join"): if self.Pusers.get(user.name) is None: # Add the user to the tracker self.Pusers[user.name] = Puser(user.name) if nick.puser is None: # Associate the user and nick nick.puser = user.name self.Pusers[user.name].nicks.add(nick.name) # Return the SQLA User return user
def __new__(cls): self = super(loadable, cls).__new__(cls) self.name = cls.__name__ self.doc = cls.__doc__ self.routes = self.routes or [] self.routes.extend([(name, route._ROUTE, route._ACCESS,) for name, route in sorted(cls.__dict__.items()) if hasattr(route, "_ROUTE") and hasattr(route, "_ACCESS")]) if cls.access in Config.options("Access"): self.access = Config.getint("Access", cls.access) elif type(cls.access) is int: self.access = cls.access else: self.access = min([route._ACCESS for route in cls.__dict__.values() if hasattr(route, "_ROUTE") and hasattr(route, "_ACCESS")]) return self
def execute(self, request, user, sort=None): levels = [] + User.levels if "galmate" in Config.options("Access"): levels.append(( "Galaxy", Config.getint("Access", "galmate"), )) else: levels.append(( "Galaxy", 0, )) if sort is not None: levels = [ ( "All", 0, ), ] order = { "name": (asc(Channel.name), ), "userlevel": (desc(Channel.userlevel), ), "maxlevel": (desc(Channel.maxlevel), ), } if sort not in order.keys(): sort = "name" order = order.get(sort) channels = [] for level in levels: Q = session.query(Channel.name, Channel.userlevel, Channel.maxlevel) Q = Q.filter(Channel.userlevel >= level[1]) Q = Q.filter(Channel.userlevel < levels[levels.index(level) - 1][1] ) if levels.index(level) > 0 else Q for o in order: Q = Q.order_by(o) channels.append(( level[0], Q.all(), )) return render("channels.tpl", request, accesslist=channels)
def execute(self, message, user, params): chan = params.group(1) if "galmate" in Config.options("Access"): access = Config.getint("Access","galmate") else: access = 0 try: session.add(Channel(name=chan, userlevel=access, maxlevel=access)) session.commit() message.reply("Added your galchannel as %s (if you didn't add me to the channel with at least access 24 first, I'm never going to bother joining)" % (chan,)) message.privmsg("set %s autoinvite on" %(chan,),'P'); message.privmsg("invite %s" %(chan,),'P'); except IntegrityError: session.rollback() message.reply("Channel %s already exists" % (chan,))
def channel(chan): if not chan.find("#") == 0: if chan in Config.options("Channels"): chan = Config.get("Channels",chan) elif chan == "PM": chan = Config.get("Connection","nick") else: raise LoadableError("Invalid channel") def wrapper(hook): def execute(self, message, user, params): if self.is_chan(message, chan): hook(self, message, user, params) return else: raise ChanParseError(chan) return execute return wrapper
def ctcp(message): """Respond to CTCP queries (from admins)""" m = message.get_msg() if m[0] == '\001': from Core.config import Config try: if message.get_pnick() in Config.options("Admins"): if m[1:5] == 'PING': message.write("NOTICE %s :\001PING %s\001" % (message.get_nick(), m[6:])) elif m[1:8] == 'VERSION': import subprocess try: version = subprocess.check_output(["git", "describe", "HEAD"]).strip() version += "/" + "/".join(subprocess.check_output(["git", "describe", "origin/acl", "origin/master"]).split()) except: pass message.write("NOTICE %s :\001VERSION %s\001" % (message.get_nick(), "Merlin (%s)" % version)) except PNickParseError: pass
def wrapper(hook): if access in Config.options("Access"): acc = Config.getint("Access",access) elif type(access) is int: acc = access else: raise LoadableError("Invalid access level") class callback(hook): name = hook.__name__ doc = hook.__doc__ trigger = "PRIVMSG" access = acc def isdecorated(self): pass def __call__(self, message): self.run(message) callback.__name__ = hook.__name__ return callback
def execute(self, message, user, params): reply = "" tick=Updates.current_tick() opts = params.group(1).split() for o in reversed(Config.options("Access")): if ("galmates" not in opts) and (Config.getint("Access", o) == 0): continue; Q = session.query(User) Q = Q.filter(User.access == Config.getint("Access", o)) Q = Q.order_by(asc(User.name)) result = Q.all() if len(result) < 1: continue printable=map(lambda (u): "%s%s%s%s%s" % (u.name,' ('+u.alias+')' if u.alias else '', " (%d:%d:%d)" % (u.planet.x, u.planet.y, u.planet.z) if "coords" in opts and u.planet is not None else '', " (%s)" % ((u.fleetupdated or 0)-tick) if "defage" in opts else '', " (%s)" % (u.fleetupdated or 0) if "mydef" in opts else ''),result) reply += "%s: " % (o) reply += ', '.join(printable) reply += '\n' message.reply(reply[:-1])
def execute(self, message, user, params): chan = params.group(1) if "galmate" in Config.options("Access"): access = Config.getint("Access", "galmate") else: access = 0 try: session.add(Channel(name=chan, userlevel=access, maxlevel=access)) session.commit() message.reply( "Added your galchannel as %s (if you didn't add me to the channel with at least access 24 first, I'm never going to bother joining)" % (chan, )) message.privmsg("set %s autoinvite on" % (chan, ), Config.get("Services", "nick")) message.privmsg("invite %s" % (chan, ), Config.get("Services", "nick")) except IntegrityError: session.rollback() message.reply("Channel %s already exists" % (chan, ))
def route(regex=None, access=0): if regex is None: param = re.compile(loadable.param, re.I) elif type(regex) is str: param = re.compile(r"\s*%s\s*$"%(regex,), re.I) else: raise LoadableError("Invalid route regex") if access in Config.options("Access"): access = Config.getint("Access",access) elif type(access) is int: access = access else: raise LoadableError("Invalid access level") def wrapper(execute): execute._ROUTE = param execute._ACCESS = access return execute return wrapper
def execute(self, request, user, message=None): tick = Updates.current_tick() Q = session.query(Attack) if user.access < (Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000): # Hide attacks until they are active, unless the user has access Q = Q.filter(Attack.landtick <= tick + Config.getint("Misc", "attactive")) Q = Q.filter(Attack.landtick + Attack.waves >= tick) # Hide attacks one tick after the last wave has landed Q = Q.order_by(asc(Attack.id)) attacks = Q.all() Q = session.query(Planet, Target.tick) Q = Q.join(Target.planet) Q = Q.join(Target.user) Q = Q.filter(Planet.active == True) Q = Q.filter(Target.user == user) Q = Q.filter(Target.tick >= tick - 12) # We shouldn't need any bookings 12 ticks after landing Q = Q.order_by(asc(Target.tick), asc(Planet.x), asc(Planet.y), asc(Planet.z)) bookings = [] scans = [] for planet, tock in Q.all(): bookings.append((planet, tock, [],)) if planet.scan("P"): bookings[-1][2].append(planet.scan("P")) scans.append(planet.scan("P")) if planet.scan("D"): bookings[-1][2].append(planet.scan("D")) scans.append(planet.scan("D")) if planet.scan("A") or planet.scan("U"): bookings[-1][2].append(planet.scan("A") or planet.scan("U")) scans.append(planet.scan("A") or planet.scan("U")) if tock <= tick + Config.getint("Misc", "attjgp") and planet.scan("J"): bookings[-1][2].append(planet.scan("J")) scans.append(planet.scan("J")) return render("attacks.tpl", request, message=message, attacks=attacks, bookings=bookings, scans=scans)
def route(regex=None, access=0): if regex is None: param = re.compile(loadable.param, re.I) elif type(regex) is str: param = re.compile(r"\s*%s\s*$" % (regex, ), re.I) else: raise LoadableError("Invalid route regex") if access in Config.options("Access"): access = Config.getint("Access", access) elif type(access) is int: access = access else: raise LoadableError("Invalid access level") def wrapper(execute): execute._ROUTE = param execute._ACCESS = access return execute return wrapper
def list(self, message, user, params): Q = session.query(Attack) if user.access < ( Config.getint("Access", "hc") if "hc" in Config.options("Access") else 1000 ): # Hide attacks until they are active, unless the user has access Q = Q.filter(Attack.landtick <= Updates.current_tick() + Config.getint("Misc", "attactive")) Q = Q.filter(Attack.landtick + Attack.waves >= Updates.current_tick() ) # Hide attacks one tick after the last wave has landed Q = Q.order_by(asc(Attack.id)) replies = [] for attack in Q: replies.append("(%d LT: %d %s)" % ( attack.id, attack.landtick, attack.comment, )) reply = "Open attacks: " + " ".join(replies) message.reply(reply)
def updatenotifier(message): """Receive and parse update notifications""" m = message.get_msg() if m[0] == '@': try: if message.get_chan() == Config.get( "Updates", "notify-channel") and message.get_pnick() in Config.get( "Updates", "notify-allow").split(): params = m[1:].split("/", 3) if params[0] in Config.get("Updates", "notify-repo").split(): mtags = params[1].split(",") ctags = Config.get("Updates", "notify-branch").split() selected = False if "all" in mtags or "all" in ctags: selected = True else: for tag in mtags: if tag in ctags: selected = True break if tag == "unstable": mtags.extend(["acl", "master"]) elif tag == "stable": mtags.extend(["acl-stable", "legacy-stable"]) if selected == True: levels = Config.get("Updates", "notify-level").split() if params[2] in levels or ("all" in levels and params[2] != "forks"): nu = Config.get("Updates", "notify-users").split() message.privmsg("UPDATE (%s): %s in %s: %s" % (message.get_pnick(), params[2], "/".join(params[:1]), params[3]), ",".join(nu) if nu else Config.options("Admins")[0], priority=+5) except (ChanParseError, PNickParseError): pass
def execute(self, message, user, params): pnick = params.group(1) if "galmate" in Config.options("Access"): access = Config.getint("Access","galmate") else: access = 0 member = User.load(name=pnick, active=False) if member is None: member = User(name=pnick, access=access) session.add(member) elif not member.active: member.active = True member.access = access elif member.access < access: member.access = access else: message.reply("User %s already exists" % (pnick,)) return session.commit() message.reply("Added user %s at level %s" % (pnick,access))
def execute(self, message, user, params): pnick = params.group(1) if "galmate" in Config.options("Access"): access = Config.getint("Access", "galmate") else: access = 0 member = User.load(name=pnick, active=False) if member is None: member = User(name=pnick, access=access) session.add(member) elif not member.active: member.active = True member.access = access elif member.access < access: member.access = access else: message.reply("User %s already exists" % (pnick, )) return session.commit() message.reply("Added user %s at level %s" % (pnick, access))
def robocop(self, message, scantype, pa_id, x, y, z, names, scanner, reqs, old=False): nicks = [] reply = "Old " if old else "" reply += "%s on %s:%s:%s " % (PA.get(scantype,"name"),x,y,z,) if ("showscanner" in Config.options("Misc") and Config.getboolean("Misc", "showscanner") and scanner != 'None'): reply+= "from %s " % (User.load(id=scanner).name) if User.load(id=scanner) not in (None, 'None') else "" reply += Config.get("URL","viewscan") % (pa_id,) if old: reply += " !request cancel %s if this is suitable." % (reqs) for name in names.split(","): user = User.load(name) for nick in CUT.get_user_nicks(name): nicks.append(nick) message.privmsg(self.url(reply, user), nick) if not old: reply = "[-%s] %s on %s:%s:%s " % (reqs,PA.get(scantype,"name"),x,y,z,) reply+= "delivered to: " reply+= ", ".join(nicks) if not Config.getboolean("Misc", "anonscans") else "Anon" if Config.getboolean("Misc", "showurls"): reply += " (%s)" % (Config.get("URL","viewscan") % (pa_id,)) from Hooks.scans.request import request message.privmsg(reply, request().scanchan())
def robocop(self, message, notice, target=None): if notice[:3] == "!#!": notice = " ".join(notice[3:].split("!#!")) if target: message.notice(notice, target) else: for chan in session.query(Channel).filter(Channel.userlevel > (Config.getint("Access", "galmate") if "galmate" in Config.options("Access") else 0)).all(): message.notice(notice, chan.name)
def scanchan(self): return Config.get("Channels", "scans") if "scans" in Config.options( "Channels") else Config.get("Channels", "home")
def expire(self, message, user, params): id = params.group(1) prop = self.load_prop(id) if prop is None: message.reply("No proposition number %s exists (idiot)." % (id, )) return if not prop.active: message.reply("You can't expire prop %d, it's already expired." % (prop.id, )) return if prop.proposer is not user and not user.is_admin(): message.reply("Only %s may expire proposition %d." % (prop.proposer.name, prop.id)) return if prop.type == "invite" and not self.member_count_below_limit(): message.reply( "You have tried to invite somebody, but we have too many losers and I can't be bothered dealing with more than %s of you." % (Config.getint("Alliance", "members"), )) return self.recalculate_carebears(prop) yes, no, veto = self.sum_votes(prop) passed = yes > no and veto <= 0 vote_result = ['no', 'yes'][passed] reply = self.text_result(vote_result, yes, no, veto) reply += self.text_summary(prop) message.reply(reply) if prop.type == "invite" and passed: pnick = prop.person access = Config.getint("Access", "member") member = User.load(name=pnick, active=False) if member is None: member = User(name=pnick, access=access, sponsor=prop.proposer.name) session.add(member) elif not member.active: member.active = True member.access = access member.sponsor = prop.proposer.name elif not member.is_member(): member.access = access member.sponsor = prop.proposer.name message.privmsg( "adduser %s %s 24" % ( Config.get("Channels", "home"), pnick, ), Config.get("Services", "nick")) message.reply( "%s has been added to %s and given member level access to me." % (pnick, Config.get("Channels", "home"))) if prop.type == "kick" and passed: idiot = prop.kicked if "galmate" in Config.options("Access"): idiot.access = Config.getint("Access", "galmate") else: idiot.access = 0 if idiot.planet is not None and idiot.planet.intel is not None: intel = idiot.planet.intel alliance = Alliance.load(Config.get("Alliance", "name")) if intel.alliance == alliance: intel.alliance = None message.privmsg( "remuser %s %s" % ( Config.get("Channels", "home"), idiot.name, ), Config.get("Services", "nick")) # message.privmsg("ban %s *!*@%s.%s Your sponsor doesn't like you anymore"%(Config.get("Channels","home"), idiot.name, Config.get("Services", "usermask"),),Config.get("Services", "nick")) message.privmsg( "note send %s A proposition to kick you from %s has been raised by %s with reason '%s' and passed by a vote of %s to %s." % (idiot.name, Config.get("Alliance", "name"), prop.proposer.name, prop.comment_text, yes, no), Config.get("Services", "nick")) message.reply( "%s has been reduced to \"galmate\" level and removed from the channel." % (idiot.name, )) if prop.type == "suggestion" and passed: message.reply("Suggestion \"%s\" has passed" % (prop.comment_text)) prop.active = False prop.closed = current_timestamp() prop.vote_result = vote_result session.commit()
def url(self, text, user): if self.is_user(user) and user.url in Config.options("alturls"): return text.replace(Config.get("URL", "game"), Config.get("alturls", user.url)) else: return text
def execute(self, message, user, params): if params.group(1)[-6:].lower() == "hideme": notice = "%s" % (params.group(1)[:-6]) else: notice = "(%s) %s" % (user.name, params.group(1)) for chan in session.query(Channel).filter(Channel.userlevel > (Config.getint("Access", "galmate") if "galmate" in Config.options("Access") else 0)).all(): message.notice(notice, chan.name)
def set_prefs(self, message, user, params): name=params.group(1) u = User.load(name=name, exact=False) if u is None: message.reply("No members matching %s found"%(name,)) return else: user=u params = self.split_opts(params.group(2)) reply = "" for opt, val in params.items(): if opt == "planet": m = self.planet_coordre.match(val) if m: planet = Planet.load(*m.group(1,3,5)) if planet is None: message.alert("No planet with coords %s:%s:%s" % m.group(1,3,5)) continue user.planet = planet reply += " planet=%s:%s:%s"%(planet.x,planet.y,planet.z) if user.is_member(): alliance = Alliance.load(Config.get("Alliance","name")) if planet.intel is None: planet.intel = Intel(nick=user.name, alliance=alliance) else: planet.intel.nick = user.name planet.intel.alliance = alliance elif val in self.nulls: user.planet = None reply += " planet=None" if opt == "password": if message.in_chan(): message.reply("Don't set passwords in public you shit") continue user.passwd = val reply += " password=%s"%(val) if opt == "tguser": user.tguser = val reply += " tguser=%s"%(val) if opt == "url": if val == "game" or val in self.nulls: user.url = None val = Config.get("URL", "game") elif val not in Config.options("alturls"): ret = "Valid URLs are: game: %s, " %(Config.get("URL", "game"),) ret+= ", ".join(["%s: %s" %(k,v,) for k, v in Config.items("alturls")]) message.reply(ret) continue else: user.url = val val = Config.get("alturls", val) reply += " url: %s"%(val) if opt == "email": if val in self.nulls: user.email = None reply += " email=None" else: try: user.email = val except AssertionError: reply += " email=%s"%(user.email) else: reply += " email=%s"%(val) if opt == "phone": if val in self.nulls: user.phone = "" reply += " phone=None" else: user.phone = val reply += " phone=%s"%(val) if opt == "pubphone": if val.lower() in self.true: user.pubphone = True reply += " pubphone=%s"%(True) elif val.lower() in self.false: user.pubphone = False reply += " pubphone=%s"%(False) if opt == "smsmode": if (val[:1] in ['C', 'G']) and (Config.get("Misc", "sms") != "combined"): message.alert("Your alliance doesn't support SMS mode switching") continue if val[:1].upper() in User._sms_modes: user.smsmode = val reply += " smsmode=%s" % (user.smsmode,) elif val[:1].lower() == "b" or val in self.nulls: user._smsmode = None reply += " smsmode=None" session.commit() if len(reply) > 0: message.reply("Updated preferences for %s:" % (user.name) + reply)
def pinvite(message): # P invites us to a channel if (message.get_hostmask().lower() == Config.get("Services", "host").lower() or message.get_pnick() in Config.options("Admins")) and Channel.load(message.get_msg()) is not None: message.join(message.get_msg())
def execute(self, message, user, params): rec = params.group(1) public_text = params.group(2) + ' - %s' % (user.name, ) text = encode(public_text + '/%s' % (user.phone, )) receiver = User.load(name=rec, exact=False, access="member") or User.load(name=rec) if not receiver: message.reply("Who exactly is %s?" % (rec, )) return if receiver.smsmode == "Retard": message.reply( "I refuse to talk to that incompetent retard. Check %s's mydef comment and use !phone show to try sending it using your own phone." % (receiver.name, )) return if not (receiver.pubphone or receiver.smsmode == "Email" ) and user not in receiver.phonefriends and user.access < ( Config.getint("Access", "SMSer") if "SMSer" in Config.options("Access") else 1000): message.reply( "%s's phone number is private or they have not chosen to share their number with you. Supersecret message not sent." % (receiver.name, )) return if receiver.smsmode == "Email": mode = "email" phone = receiver.email if not phone: message.reply( "That incompetent retard %s has set their sms mode to email but hasn't provided an address. Super secret message not sent." % (receiver.name, )) return else: mode = Config.get("Misc", "sms") phone = self.prepare_phone_number(receiver.phone) if not phone or len(phone) <= 7: message.reply( "%s has no phone number or their phone number is too short to be valid (under 6 digits). Super secret message not sent." % (receiver.name, )) return if (receiver.smsmode == "WhatsApp"): if Config.get("WhatsApp", "login"): mode = "whatsapp" elif (receiver.smsmode == "Twilio"): if Config.get("Twilio", "sid"): mode = "twilio" else: mode = receiver.smsmode or mode if mode == "combined" else mode mode = mode.lower() error = "" if len(text) >= 160: message.reply( "Max length for a text is 160 characters. Your text was %i characters long. Super secret message not sent." % (len(text), )) return if mode == "email": error = self.send_email(user, receiver, public_text, phone, text) elif mode == "whatsapp": if receiver.phone[0] == "g": phone = receiver.phone wa = WhatsappEchoClient(phone[1:], text, True) wa.login( Config.get("WhatsApp", "login"), Config.get("WhatsApp", "password").decode("string_escape")) if wa.gotReceipt: error = None self.log_message(user, receiver, phone, public_text, "whatsapp") else: error = "No receipt received from the WhatsApp server." elif mode == "twilio": client = Client(Config.get("Twilio", "sid"), Config.get("Twilio", "auth_token")) tw = client.messages.create(body=text, to=phone, from_=Config.get("Twilio", "number")) if tw.sid: error = None self.log_message(user, receiver, phone, public_text, "twilio") else: error = "Failed to get message ID from Twilio server." else: if mode == "googlevoice" or mode == "combined": if Config.get("googlevoice", "user"): error = self.send_googlevoice(user, receiver, public_text, phone, text) else: error = "smsmode set to Google Voice but no Google Voice account is available." if mode == "clickatell" or (mode == "combined" and error is not None): if Config.get("clickatell", "user"): error = self.send_clickatell(user, receiver, public_text, phone, text) else: if mode == "combined": error = "smsmode set to combined but no SMS account is available." else: error = "smsmode set to Clickatell but no Clickatell account is available." if error is None: message.reply("Successfully processed To: %s Message: %s" % (receiver.name, decode(text))) else: message.reply( error or "That wasn't supposed to happen. I don't really know what went wrong. Maybe your mother dropped you." )
def execute(self, message, user, params): tick = Updates.current_tick() # Galaxy Scan if params.group(5) is None: # Access Control: # Uncomment this and change "group" to the lowest group that can request galscans. # if not user.is_group(): # message.alert("Insufficient access for galaxy scans.") # return galaxy = Galaxy.load(*params.group(1, 3)) if galaxy is None: message.alert("No galaxy with coords %s:%s" % params.group(1, 3)) return planets = galaxy.planets galscan = Config.has_option("Misc", "galscans") and Config.getboolean("Misc", "galscans") else: planet = Planet.load(*params.group(1, 3, 5)) if planet is None: message.alert("No planet with coords %s:%s:%s" % params.group(1, 3, 5)) return planets = [planet] galscan = False # Scan Quota if Config.has_section("ScanQuota"): opts = Config.options("ScanQuota") q = [] for o in opts: if int(o) >= user.access: q.append(int(o)) if q: ScanQuota = Config.getint("ScanQuota", str(min(q))) reqs = ( session.query(Request.id) .filter(Request.requester_id == user.id) .filter(Request.tick == tick) .count() ) if (reqs + len(planets) * len(params.group(6).upper())) > ScanQuota: message.reply( "This request will exceed your scan quota for this tick (%d scans remaining). " % (ScanQuota - reqs) + "Try searching with !planet, !dev, !unit, !news, !jgp, !au." ) return dists = int(params.group(7) or 0) galdists = [] mergescans = (not galscan) and ( Config.has_option("Misc", "maxscans") and len(planets) * len(params.group(6)) > Config.getint("Misc", "maxscans") ) for planet in planets: if galscan or mergescans: galdists.append(planet.intel.dists if planet.intel else 0) if len(galdists) < len(planets): continue types = 0 for scantype in params.group(6).upper(): # Reject requests for incoming scans if not PA.getboolean(scantype, "request"): message.alert("%s scans cannot be requested." % (PA.get(scantype, "name"))) continue types += 1 if galscan or mergescans: # Request the scans for i in range(len(planets)): request = self.request(message, user, planets[i], scantype, galdists[i], galscan or mergescans) # Inform the requester if galscan and (message.get_chan() != self.scanchan()): message.reply( "Requested a Galaxy %s Scan of %s:%s. !request cancel %s:%s to cancel the request." % (request.type, planet.x, planet.y, request.id - len(planets) + 1, request.id) ) # Check for existing scans scan = planet.scan(scantype) if scan and request.tick - scan.tick < PA.getint(scantype, "expire"): message.reply( "%s Scan of %s:%s:%s is already available from %s ticks ago: %s. !request cancel %s if this is suitable." % (scantype, planet.x, planet.y, planet.z, request.tick - scan.tick, scan.link, request.id) ) # Cancel requests with a 0-tick old scan, if required if request.tick == scan.tick: req0age = ( Config.getint("Misc", "req0agej") if request.scantype == "J" else Config.getint("Misc", "req0age") ) if req0age == 1: Q = ( session.query(Request) .filter(Request.tick == request.tick) .filter(Request.planet_id == request.planet_id) ) Q = Q.filter(Request.scantype == request.scantype).filter( Request.requester_id == request.requester_id ) if Q.count() == 1: request.active = False message.reply( "Request %s cancelled due to an existing scan. If you really need a newer one, repeat your scan request." % (request.id) ) message.privmsg( "Cancelled scan request %s due to existing scan" % (request.id), self.scanchan() ) elif req0age == 0: request.active = False message.reply("Request %s cancelled due to an existing scan." % (request.id)) message.privmsg( "Cancelled scan request %s due to existing scan" % (request.id), self.scanchan() ) # Tell the scanners requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon" if galscan: message.privmsg( "[%s:%s] %s requested a Galaxy %s Scan of %s:%s Max Dists(i:%s%s) " % ( request.id - len(planets) + 1, request.id, requester, request.type, planet.x, planet.y, max(galdists), "/r:%s" % dists if dists > 0 else "", ) + Config.get("URL", "reqgscan") % (planet.x, planet.y), self.scanchan(), ) else: request = self.request(message, user, planet, scantype, dists) if message.get_chan() != self.scanchan(): message.reply( "Requested a %s Scan of %s:%s:%s. !request cancel %s to cancel the request." % (request.type, planet.x, planet.y, planet.z, request.id) ) # Check for existing scans scan = planet.scan(scantype) if scan and request.tick - scan.tick < PA.getint(scan.scantype, "expire"): message.reply( "%s Scan of %s:%s:%s is already available from %s ticks ago: %s. !request cancel %s if this is suitable." % (scantype, planet.x, planet.y, planet.z, request.tick - scan.tick, scan.link, request.id) ) # Cancel requests with a 0-tick old scan, if required if request.tick == scan.tick: req0age = ( Config.getint("Misc", "req0agej") if request.scantype == "J" else Config.getint("Misc", "req0age") ) if req0age == 1: Q = ( session.query(Request) .filter(Request.tick == request.tick) .filter(Request.planet_id == request.planet_id) ) Q = Q.filter(Request.scantype == request.scantype).filter( Request.requester_id == request.requester_id ) if Q.count() == 1: request.active = False message.reply( "Request %s cancelled due to an existing scan. If you really need a newer one, repeat your scan request." % (request.id) ) message.privmsg( "Cancelled scan request %s due to existing scan" % (request.id), self.scanchan() ) elif req0age == 0: request.active = False message.reply("Request %s cancelled due to an existing scan." % (request.id)) message.privmsg( "Cancelled scan request %s due to existing scan" % (request.id), self.scanchan() ) if mergescans: message.reply( "Requested %d scans. !request cancel %s:%s to cancel the request." % (len(planets) * types, request.id - len(planets) * types + 1, request.id) ) message.privmsg( "[%s:%s] %s requested %d scans (%s) Max Dists(i:%s%s). !request links for details " % ( request.id - len(planets) * types + 1, request.id, requester, len(planets) * types, params.group(6).upper(), max(galdists), "/r:%s" % dists if dists > 0 else "", ), self.scanchan(), ) session.commit()
def scanchan(self): return ( Config.get("Channels", "scans") if "scans" in Config.options("Channels") else Config.get("Channels", "home") )
def set_prefs(self, message, user, params): params = self.split_opts(params.group(1)) reply = "" for opt, val in params.items(): if opt == "planet": m = self.planet_coordre.match(val) if m: planet = Planet.load(*m.group(1, 3, 5)) if planet is None: message.alert("No planet with coords %s:%s:%s" % m.group(1, 3, 5)) continue user.planet = planet reply += " planet=%s:%s:%s" % (planet.x, planet.y, planet.z) if user.is_member(): alliance = Alliance.load(Config.get( "Alliance", "name")) if planet.intel is None: planet.intel = Intel(nick=user.name, alliance=alliance) else: planet.intel.nick = user.name planet.intel.alliance = alliance elif val in self.nulls: user.planet = None reply += " planet=None" if opt == "password": if message.in_chan(): message.reply("Don't set your password in public you shit") continue user.passwd = val reply += " password=%s" % (val) if opt == "url": if val == "game" or val in self.nulls: user.url = None val = Config.get("URL", "game") elif val not in Config.options("alturls"): ret = "Valid URLs are: game: %s, " % (Config.get( "URL", "game"), ) ret += ", ".join([ "%s: %s" % ( k, v, ) for k, v in Config.items("alturls") ]) message.reply(ret) continue else: user.url = val val = Config.get("alturls", val) reply += " url: %s" % (val) if opt == "email": if val in self.nulls: user.email = None reply += " email=None" else: try: user.email = val except AssertionError: reply += " email=%s" % (user.email) else: reply += " email=%s" % (val) if opt == "phone": if val in self.nulls: user.phone = "" reply += " phone=None" else: user.phone = val reply += " phone=%s" % (val) if opt == "pubphone": if val.lower() in self.true: user.pubphone = True reply += " pubphone=%s" % (True) elif val.lower() in self.false: user.pubphone = False reply += " pubphone=%s" % (False) if opt == "smsmode": if Config.get("Misc", "sms") != "combined": message.alert( "Your alliance doesn't support SMS mode switching") continue if val[:1].upper() in User._sms_modes: user.smsmode = val reply += " smsmode=%s" % (user.smsmode, ) elif val[:1].lower() == "b" or val in self.nulls: user._smsmode = None reply += " smsmode=None" session.commit() if len(reply) > 0: message.reply("Updated your preferences:" + reply)
def execute(self, message, user, params): tick = Updates.current_tick() # Galaxy Scan if params.group(5) is None: # Access Control: # Uncomment this and change "group" to the lowest group that can request galscans. # if not user.is_group(): # message.alert("Insufficient access for galaxy scans.") # return galaxy = Galaxy.load(*params.group(1,3)) if galaxy is None: message.alert("No galaxy with coords %s:%s" % params.group(1,3)) return planets = galaxy.planets galscan = Config.has_option("Misc", "galscans") and Config.getboolean("Misc", "galscans") else: planet = Planet.load(*params.group(1,3,5)) if planet is None: message.alert("No planet with coords %s:%s:%s" % params.group(1,3,5)) return planets = [planet] galscan = False # Scan Quota if Config.has_section("ScanQuota"): opts = Config.options("ScanQuota") q = [] for o in opts: if int(o) >= user.access: q.append(int(o)) if q: ScanQuota = Config.getint("ScanQuota", str(min(q))) reqs = session.query(Request.id).filter(Request.requester_id == user.id).filter(Request.tick == tick).count() if (reqs + len(planets) * len(params.group(6).upper())) > ScanQuota: message.reply("This request will exceed your scan quota for this tick (%d scans remaining). " % (ScanQuota - reqs) +\ "Try searching with !planet, !dev, !unit, !news, !jgp, !au.") return dists = int(params.group(7) or 0) galdists = [] mergescans = (not galscan) and (Config.has_option("Misc", "maxscans") and len(planets)*len(params.group(6)) > Config.getint("Misc", "maxscans")) for planet in planets: if galscan or mergescans: galdists.append(planet.intel.dists if planet.intel else 0) if len(galdists) < len(planets): continue types = 0 for scantype in params.group(6).upper(): # Reject requests for incoming scans if not PA.getboolean(scantype, "request"): message.alert("%s scans cannot be requested." % (PA.get(scantype, "name"))) continue types += 1 if galscan or mergescans: # Request the scans for i in range(len(planets)): request = self.request(message, user, planets[i], scantype, galdists[i], galscan or mergescans) # Inform the requester if galscan and (message.get_chan() != self.scanchan()): message.reply("Requested a Galaxy %s Scan of %s:%s. !request cancel %s:%s to cancel the request." % (request.type, planet.x, planet.y, request.id-len(planets)+1, request.id)) # Check for existing scans scan = planet.scan(scantype) if scan and request.tick - scan.tick < PA.getint(scantype,"expire"): message.reply("%s Scan of %s:%s:%s is already available from %s ticks ago: %s. !request cancel %s if this is suitable." % ( scantype, planet.x, planet.y, planet.z, request.tick - scan.tick, scan.link, request.id,)) # Cancel requests with a 0-tick old scan, if required if (request.tick == scan.tick): req0age = Config.getint("Misc", "req0agej") if request.scantype == "J" else Config.getint("Misc", "req0age") if req0age == 1: Q = session.query(Request).filter(Request.tick == request.tick).filter(Request.planet_id == request.planet_id) Q = Q.filter(Request.scantype == request.scantype).filter(Request.requester_id == request.requester_id) if Q.count() == 1: request.active = False message.reply("Request %s cancelled due to an existing scan. If you really need a newer one, repeat your scan request." % (request.id)) message.privmsg("Cancelled scan request %s due to existing scan" % (request.id), self.scanchan()) elif req0age == 0: request.active = False message.reply("Request %s cancelled due to an existing scan." % (request.id)) message.privmsg("Cancelled scan request %s due to existing scan" % (request.id), self.scanchan()) # Tell the scanners requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon" if galscan: message.privmsg("[%s:%s] %s requested a Galaxy %s Scan of %s:%s Max Dists(i:%s%s) " % (request.id-len(planets)+1, request.id, requester, request.type, planet.x, planet.y, max(galdists), "/r:%s" % dists if dists > 0 else "") + Config.get("URL", "reqgscan") % (planet.x, planet.y) , self.scanchan()) else: request = self.request(message, user, planet, scantype, dists) if message.get_chan() != self.scanchan(): message.reply("Requested a %s Scan of %s:%s:%s. !request cancel %s to cancel the request." % (request.type, planet.x, planet.y, planet.z, request.id,)) # Check for existing scans scan = planet.scan(scantype) if scan and request.tick - scan.tick < PA.getint(scan.scantype,"expire"): message.reply("%s Scan of %s:%s:%s is already available from %s ticks ago: %s. !request cancel %s if this is suitable." % ( scantype, planet.x, planet.y, planet.z, request.tick - scan.tick, scan.link, request.id,)) # Cancel requests with a 0-tick old scan, if required if (request.tick == scan.tick): req0age = Config.getint("Misc", "req0agej") if request.scantype == "J" else Config.getint("Misc", "req0age") if req0age == 1: Q = session.query(Request).filter(Request.tick == request.tick).filter(Request.planet_id == request.planet_id) Q = Q.filter(Request.scantype == request.scantype).filter(Request.requester_id == request.requester_id) if Q.count() == 1: request.active = False message.reply("Request %s cancelled due to an existing scan. If you really need a newer one, repeat your scan request." % (request.id)) message.privmsg("Cancelled scan request %s due to existing scan" % (request.id), self.scanchan()) elif req0age == 0: request.active = False message.reply("Request %s cancelled due to an existing scan." % (request.id)) message.privmsg("Cancelled scan request %s due to existing scan" % (request.id), self.scanchan()) if mergescans: message.reply("Requested %d scans. !request cancel %s:%s to cancel the request." % (len(planets) * types, request.id-len(planets)*types+1, request.id)) message.privmsg("[%s:%s] %s requested %d scans (%s) Max Dists(i:%s%s). !request links for details " % (request.id-len(planets)*types+1, request.id, requester, len(planets)*types, params.group(6).upper(), max(galdists), "/r:%s" % dists if dists > 0 else ""), self.scanchan()) session.commit()