Beispiel #1
0
class scannerhelp(loadable):
    """Help for scanners"""
    alias = "scanhelp"
    usage = " [nick]"
    access = "member"

    helptext = """When a request comes in, it looks like this...
[123] %s requested a Planet Scan of 1:1:1 Dists(i:17) https://game.planetarion.com/waves.pl?id=1&x=1&y=1&z=1
or...
[123] %s requested a Planet Scan of 1:1:1 Dists(i:17/r:35) https://game.planetarion.com/waves.pl?id=1&x=1&y=1&z=1
The "Dists(i:17)" is the number of distorters I think the planet has, based on blocked scanners or from dev scans. The real number may be higher, or possibly lower if some distorters have been destroyed.
The "r:35" in the second example means that the user requesting the scan thinks that the planet has at least 35 distorters.
If you don't have as many amplifiers as the planet has distorters, it's probably not worth wasting your resources trying.
The URL at the end will take you straight to the waves page in-game and will do the scan. You can then copy the URL of the scan (from the "Scan Link" on the page or from your address bar) and paste it in PM to me or in any channel where I can see it.
 
To list open requests, use ".req l" (.request list) for a list in an abbreviated format: [123: (17/35) P 1:1:1]
Alternatively, ".req links" will give a list of scan URLs to click on: [123 (17/35): http://game.planetarion.com/waves.pl?id=1&x=1&y=1&z=1]
If you get blocked, you can use the "blocks" subcommand. "!req 123 b 20" would indicate that you were blocked doing the example above (the request ID, 123, is in the square brackets) and you have 20 amplifiers.
 
If you have any problems, ask. Scanners are often idle, but usually helpful when they're around!
Thanks for scanning for %s!""" % ("Anon" if Config.getboolean(
        "Misc", "anonscans") else Config.items("Admins")[0][0], "Anon"
                                  if Config.getboolean("Misc", "anonscans")
                                  else Config.items("Admins")[0][0],
                                  Config.get("Alliance", "name"))

    @route(r"(.*)")
    def execute(self, message, user, params):
        if params.group(1):
            if not user.is_admin():
                message.alert("Insufficient access to send the help to %s." %
                              params.group(1))
                return
            from Hooks.scans.request import request
            tnick = params.group(1).strip()
            if not CUT.nick_in_chan(tnick, request().scanchan()):
                message.alert(
                    "%s does not appear to be in the scanner channel. Aborting."
                    % tnick)
                return
            if message.reply_type() == NOTICE_REPLY:
                message.notice(self.helptext, tnick, 2)
            else:
                message.privmsg(self.helptext, tnick, 2)
        elif message.reply_type() == PUBLIC_REPLY and not user.is_admin():
            message.alert(
                "Insufficient access to spam the channel. Try another prefix."
                % params.group(1))
        else:
            message.reply(self.helptext, 2)
Beispiel #2
0
    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())
Beispiel #3
0
    def execute(self, request, user, message=None, planet=None):
        tick = Updates.current_tick()

        Q = session.query(Request)
        Q = Q.filter(Request.user == user)
        Q = Q.filter(Request.tick > tick - 5)
        Q = Q.filter(Request.active == True)
        Q = Q.order_by(asc(Request.id))
        open = Q.all()

        Q = session.query(Scan)
        Q = Q.join(Request.scan)
        Q = Q.filter(Request.user == user)
        Q = Q.filter(Request.tick > tick - 24)
        Q = Q.filter(Request.scan != None)
        Q = Q.order_by(desc(Request.id))
        completed = Q.all()

        Q = session.query(Scan)
        Q = Q.filter(Scan.scanner == user)
        Q = Q.order_by(desc(Scan.id))
        scans = Q[:25]

        return render("scans/scans.tpl",
                      request,
                      anonscans=Config.getboolean("Misc", "anonscans"),
                      types=Request._requestable,
                      open=open,
                      completed=completed,
                      scans=scans,
                      message=message,
                      planet=planet)
Beispiel #4
0
    def request(self, message, user, planet, scan, dists, gal=False):
        request = Request(target=planet, scantype=scan, dists=dists)
        user.requests.append(request)
        session.commit()

        if not gal:
            requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon"
            dists_intel = planet.intel.dists if planet.intel else 0
            message.privmsg(
                "[%s] %s requested a %s Scan of %s:%s:%s Dists(i:%s%s) "
                % (
                    request.id,
                    requester,
                    request.type,
                    planet.x,
                    planet.y,
                    planet.z,
                    dists_intel,
                    "/r:%s" % request.dists if request.dists > 0 else "",
                )
                + request.link,
                self.scanchan(),
            )

        return request
Beispiel #5
0
    def robonotify(self, header, body):
        # Check for correct "From" address?
        if Config.getboolean("imap", "singleaddr"):
            uname_re = "%s\+(.+)@.+" % Config.get("imap", "user").split("@")[0].lower()
        else:
            uname_re = "<?(.+)@.+"
        uname = re.findall(uname_re, header['To'].lower())[0]

        dsuff = Config.get("imap", "defsuffix")
        if dsuff:
            if uname[-len(dsuff):] == dsuff:
                uname = uname[:-len(dsuff)]
            else:
                self.forwardMail(uname, header, body)
                return

        # Check for the main notificatino types
        tick = re.findall("events in tick (\d+)", body)[0]
        newfleets = re.findall("We have detected an open jumpgate from (.+), located at (\d{1,2}):(\d{1,2}):(\d{1,2}). ".replace(" ","\s+") +\
                               "The fleet will approach our system in tick (\d+) and appears to have (\d+) visible ships.".replace(" ","\s+"), body)
        recalls = re.findall("The (.+) fleet from (\d{1,2}):(\d{1,2}):(\d{1,2}) has been recalled.".replace(" ","\s+"), body)
        cons = len(re.findall("Our construction team reports that .+ has been finished".replace(" ","\s+"), body))
        res = len(re.findall("Our scientists report that .+ has been finished".replace(" ","\s+"), body))

        # Wrap it up in a bow
        for line in newfleets:
            push("defcall", etype="new", uname=uname, tick=tick, name=line[0], x=line[1], y=line[2], z=line[3], eta=line[4], size=line[5])
        for line in recalls:
            push("defcall", etype="rec", uname=uname, tick=tick, name=line[0], x=line[1], y=line[2], z=line[3])
        if res + cons > 0:
            push("defcall", etype="fin", uname=uname, tick=tick, res=res, cons=cons)

        if len(newfleets) + len(recalls) + cons + res == 0:
            self.forwardMail(uname, header, body)
Beispiel #6
0
    def execute(self, message, user, params):
        if not Config.get("Twilio", "sid"):
            message.reply("Twilio support not configured. Tell the admin. If you are the admin, configure Twilio or disable !call to prevent this message.")
            return

        rec = params.group(1)
        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 user in receiver.phonefriends or user.is_admin()):
            message.reply("%s's phone number is private or they have not chosen to share their number with you. No call made." % (receiver.name,))
            return

        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). No call made." % (receiver.name,))
            return

        client = Client(Config.get("Twilio", "sid"), Config.get("Twilio", "auth_token"))
        if Config.getboolean("Twilio", "warn"):
            url="http://twimlets.com/echo?Twiml=%3CResponse%3E%3CSay%20voice%3D%22alice%22%20language%3D%22en-GB%22%20%3EHello.%20This%20is%20" +\
                Config.get("Connection", "nick") + ".%20Stop%20wasting%20our%20credit!%3C%2FSay%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        else:
            url="http://twimlets.com/echo?Twiml=%3CResponse%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        tw = client.api.account.calls.create(to=phone, from_=Config.get("Twilio", "number"), url=url, timeout=Config.getint("Twilio", "timeout"))

        if tw.sid:
            message.reply("Successfully called %s." % (receiver.name))
        else:
            message.reply("Error: Failed to get call ID from Twilio server.")
Beispiel #7
0
    def execute(self, message, user, params):
        if not Config.get("Twilio", "sid"):
            message.reply("Twilio support not configured. Tell the admin. If you are the admin, configure Twilio or disable !call to prevent this message.")
            return

        rec = params.group(1)



        phone = self.prepare_phone_number(rec)
        if not phone or len(phone) <= 7:
            message.reply("No phone number or phone number is too short to be valid (under 6 digits). No call made." % (rec,))
            return

        client = Client(Config.get("Twilio", "sid"), Config.get("Twilio", "auth_token"))
        if Config.getboolean("Twilio", "warn"):
            url="http://twimlets.com/echo?Twiml=%3CResponse%3E%3CSay%20voice%3D%22alice%22%20language%3D%22en-GB%22%20%3EHello.%20This%20is%20" +\
                Config.get("Connection", "nick") + ".%20Stop%20wasting%20our%20credit!%3C%2FSay%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        else:
            url="http://twimlets.com/echo?Twiml=%3CResponse%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        tw = client.api.account.calls.create(to=phone, from_=Config.get("Twilio", "number"), url=url, timeout=Config.getint("Twilio", "timeout"))

        if tw.sid:
            message.reply("Successfully called %s." % (rec))
        else:
            message.reply("Error: Failed to get call ID from Twilio server.")
Beispiel #8
0
    def robocop(self, message, scantype, pa_id, x, y, z, names):
        nicks = []
        reply = "%s on %s:%s:%s " % (
            PA.get(scantype, "name"),
            x,
            y,
            z,
        )
        reply += Config.get("URL", "viewscan") % (pa_id, )

        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)

        reply = "%s on %s:%s:%s " % (
            PA.get(scantype, "name"),
            x,
            y,
            z,
        )
        reply += "delivered to: "
        reply += ", ".join(nicks) if not Config.getboolean(
            "Misc", "anonscans") else "Anon"
        from Hooks.scans.request import request
        message.privmsg(reply, request().scanchan())
Beispiel #9
0
 def robocop(self, message, request_id, mode):
     request = Request.load(request_id, active=False)
     if request is None:
         return
     
     if mode == "cancel":
         reply = "Cancelled scan request %s" % (request.id,)
         message.privmsg(reply, self.scanchan())
         nicks = CUT.get_user_nicks(request.user.name)
         for nick in nicks:
             message.privmsg(reply, nick)
         return
     
     if mode == "block":
         reply = "Updated request %s dists to %s" % (request.id, request.dists,)
         message.privmsg(reply, self.scanchan())
         nicks = CUT.get_user_nicks(request.user.name)
         for nick in nicks:
             message.privmsg(reply, nick)
         return
     
     user = request.user
     planet = request.target
     
     requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon"
     dists_intel = planet.intel.dists if planet.intel else 0
     message.privmsg("[%s] %s requested a %s Scan of %s:%s:%s Dists(i:%s%s) " % (request.id, requester, request.type, planet.x,planet.y,planet.z, 
                                                     dists_intel, "/r:%s" % request.dists if request.dists > 0 else "") + request.link, self.scanchan())
Beispiel #10
0
 def robocop(self, message, request_id, mode):
     request = Request.load(request_id, active=False)
     if request is None:
         return
     
     if mode == "cancel":
         reply = "Cancelled scan request %s" % (request.id,)
         message.privmsg(reply, self.scanchan())
         nicks = CUT.get_user_nicks(request.user.name)
         for nick in nicks:
             message.privmsg(reply, nick)
         return
     
     if mode == "block":
         reply = "Updated request %s dists to %s" % (request.id, request.dists,)
         message.privmsg(reply, self.scanchan())
         nicks = CUT.get_user_nicks(request.user.name)
         for nick in nicks:
             message.privmsg(reply, nick)
         return
     
     user = request.user
     planet = request.target
     
     requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon"
     dists_intel = planet.intel.dists if planet.intel else 0
     message.privmsg("[%s] %s requested a %s Scan of %s:%s:%s Dists(i:%s%s) " % (request.id, requester, request.type, planet.x,planet.y,planet.z, 
                                                     dists_intel, "/r:%s" % request.dists if request.dists > 0 else "") + request.link, self.scanchan())
Beispiel #11
0
 def flux_passwd(self, user):
     if not Config.getboolean("FluxBB", "enabled"):
         return -1
     if session.execute("SELECT username FROM %susers WHERE LOWER(username) LIKE '%s';" % (Config.get("FluxBB", "prefix"), user.name.lower())).rowcount > 0:
         return session.execute("UPDATE %susers SET password='******' WHERE LOWER(username) LIKE '%s';" % (Config.get("FluxBB", "prefix"), user.passwd, user.name.lower())).rowcount
     else:
         group = Config.get("FluxBB", "memgroup") if user.is_member() else Config.get("FluxBB", "galgroup")
         if group == 0:
             return -1
         return session.execute("INSERT INTO %susers (group_id, username, password, email, title) VALUES ('%s', '%s', '%s', '%s', '%s');" % (
                                Config.get("FluxBB", "prefix"), group, user.name, user.passwd, user.email, user.level)).rowcount
Beispiel #12
0
 def flux_passwd(self, user):
     if not Config.getboolean("FluxBB", "enabled"):
         return -1
     if session.execute("SELECT username FROM %susers WHERE LOWER(username) LIKE '%s';" % (Config.get("FluxBB", "prefix"), user.name.lower())).rowcount > 0:
         return session.execute("UPDATE %susers SET password='******' WHERE LOWER(username) LIKE '%s';" % (Config.get("FluxBB", "prefix"), user.passwd, user.name.lower())).rowcount
     else:
         group = Config.get("FluxBB", "memgroup") if user.is_member() else Config.get("FluxBB", "galgroup")
         if group == 0:
             return -1
         return session.execute("INSERT INTO %susers (group_id, username, password, email, title) VALUES ('%s', '%s', '%s', '%s', '%s');" % (
                                Config.get("FluxBB", "prefix"), group, user.name, user.passwd, user.email, user.level)).rowcount
Beispiel #13
0
 def check_access(self, user):
     user = user or User(access=0)
     if not Config.getboolean("Arthur", "public") and not self.is_user(user):
         raise UserError("Hi! Please login below:")
     if getattr(self, "_USER", False) is True:
         if self.is_user(user) is False:
             raise UserError("You need to be logged in to use this feature")
     if user.access >= self.access:
         return user
     else:
         raise UserError("You don't have access to this page")
Beispiel #14
0
 def check_access(self, user):
     user = user or User(access=0)
     if not Config.getboolean("Arthur",
                              "public") and not self.is_user(user):
         raise UserError("Hi! Please login below:")
     if getattr(self, "_USER", False) is True:
         if self.is_user(user) is False:
             raise UserError("You need to be logged in to use this feature")
     if user.access >= self.access:
         return user
     else:
         raise UserError("You don't have access to this page")
Beispiel #15
0
 def forwardMail(self, uname, header, body):
     if not Config.getboolean("imap", "forwarding"):
         return
     body = "Original Message from %s\n\n" % (header['From']) + body
     user = User.load(uname)
     if user:
         addr = user.email
     else:
         addr = Config.get("imap", "bounce")
         body = "Bad username: %s\n\n" % (uname) + body
     if addr:
         self.send_email(header['Subject'], body, addr)
Beispiel #16
0
 def request(self, message, user, planet, scan, dists, gal=False):
     request = Request(target=planet, scantype=scan, dists=dists)
     user.requests.append(request)
     session.commit()
     
     if not gal:
         requester = user.name if not Config.getboolean("Misc", "anonscans") else "Anon"
         dists_intel = planet.intel.dists if planet.intel else 0
         message.privmsg("[%s] %s requested a %s Scan of %s:%s:%s Dists(i:%s%s) " % (request.id, requester, request.type, planet.x,planet.y,planet.z, 
                                                         dists_intel, "/r:%s" % request.dists if request.dists > 0 else "") + request.link, self.scanchan())
     
     return request
Beispiel #17
0
 def forwardMail(self, uname, header, body):
     if not Config.getboolean("imap", "forwarding"):
         return
     body = "Original Message from %s\n\n" % (header['From']) + body
     user = User.load(uname)
     if user:
         addr = user.email
     else:
         addr = Config.get("imap", "bounce")
         body = "Bad username: %s\n\n" % (uname) + body
     if addr:
         self.send_email(header['Subject'], body, addr)
Beispiel #18
0
 def execute(self, message, user, params):
     
     planet = Planet.load(*params.group(1,3,5))
     if planet is None:
         message.reply("No planet with coords %s:%s:%s found" % params.group(1,3,5))
         return
     
     notice = "DEFCALL: %s wants %s to %s:%s:%s eta %s" % (user.name, params.group(7), params.group(1), params.group(3), 
                                                           params.group(5), params.group(6))
     if Config.getboolean("Misc", "globaldef"):
         push("broadcast", notice="!#!"+notice.replace(" ","!#!"))
     else:
         message.notice(notice, Config.get("Channels", "home"))
Beispiel #19
0
    def execute(self, message, user, params):
        if not Config.get("Twilio", "sid"):
            message.reply(
                "Twilio support not configured. Tell the admin. If you are the admin, configure Twilio or disable !call to prevent this message."
            )
            return

        rec = params.group(1)
        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 user in receiver.phonefriends
                or user.is_admin()):
            message.reply(
                "%s's phone number is private or they have not chosen to share their number with you. No call made."
                % (receiver.name, ))
            return

        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). No call made."
                % (receiver.name, ))
            return

        client = Client(Config.get("Twilio", "sid"),
                        Config.get("Twilio", "auth_token"))
        if Config.getboolean("Twilio", "warn"):
            url="http://twimlets.com/echo?Twiml=%3CResponse%3E%3CSay%20voice%3D%22alice%22%20language%3D%22en-GB%22%20%3EHello.%20This%20is%20" +\
                Config.get("Connection", "nick") + ".%20Stop%20wasting%20our%20credit!%3C%2FSay%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        else:
            url = "http://twimlets.com/echo?Twiml=%3CResponse%3E%3CHangup%2F%3E%3C%2FResponse%3E&",
        tw = client.api.account.calls.create(
            to=phone,
            from_=Config.get("Twilio", "number"),
            url=url,
            timeout=Config.getint("Twilio", "timeout"))

        if tw.sid:
            message.reply("Successfully called %s." % (receiver.name))
        else:
            message.reply("Error: Failed to get call ID from Twilio server.")
Beispiel #20
0
def base_context(request):
    context = {"name"   : Config.get("Alliance", "name"),
               "slogan" : Config.get("Alliance", "name"),
               "tick"   : Updates.current_tick(),
               "update" : Updates.load(),
               "graphs" : Config.get("Misc", "graphing") != "disabled",
               }
    if getattr(request, "user", None) is not None:
        context["user"] = request.user
        context["menu"] = menu.generate(request.user)
    if getattr(request, "session", None) is not None:
        slogan, count = Slogan.search("")
        if slogan is not None:
            context["slogan"] = str(slogan)
    if Config.has_section("FluxBB") and Config.getboolean("FluxBB", "enabled"):
        context["fluxurl"] = "<br><br><a href=\"%s\">Forum</a>" % (Config.get("FluxBB", "url"))
    if Config.getboolean("Arthur", "showdumps"):
        if context.has_key("fluxurl"):
            context["dumpurl"] = "&nbsp;&nbsp;"
        else:
            context["dumpurl"] = "<br><br>"
        context["dumpurl"] += "<a href=\"/dumps/\">Dumps</a>"
    return context
Beispiel #21
0
def base_context(request):
    context = {"name"   : Config.get("Alliance", "name"),
               "slogan" : Config.get("Alliance", "name"),
               "tick"   : Updates.current_tick(),
               "update" : Updates.load(),
               "graphs" : Config.get("Misc", "graphing") != "disabled",
               }
    if getattr(request, "user", None) is not None:
        context["user"] = request.user
        context["menu"] = menu.generate(request.user)
    if getattr(request, "session", None) is not None:
        slogan, count = Slogan.search("")
        if slogan is not None:
            context["slogan"] = str(slogan)
    if Config.has_section("FluxBB") and Config.getboolean("FluxBB", "enabled"):
        context["fluxurl"] = "<br><br><a href=\"%s\">Forum</a>" % (Config.get("FluxBB", "url"))
    if Config.getboolean("Arthur", "showdumps"):
        if context["fluxurl"]:
            context["dumpurl"] = "&nbsp;&nbsp;"
        else:
            context["dumpurl"] = "<br><br>"
        context["dumpurl"] += "<a href=\"/dumps/\">Dumps</a>"
    return context
Beispiel #22
0
    def execute(self, message, user, params):

        planet = Planet.load(*params.group(1, 3, 5))
        if planet is None:
            message.reply("No planet with coords %s:%s:%s found" %
                          params.group(1, 3, 5))
            return

        notice = "DEFCALL: %s wants %s to %s:%s:%s eta %s" % (
            user.name, params.group(7), params.group(1), params.group(3),
            params.group(5), params.group(6))
        if Config.getboolean("Misc", "globaldef"):
            push("broadcast", notice="!#!" + notice.replace(" ", "!#!"))
        else:
            message.notice(notice, Config.get("Channels", "home"))
Beispiel #23
0
 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 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
Beispiel #25
0
    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
Beispiel #26
0
 def robocop(self, message, scantype, pa_id, x, y, z, names):
     nicks = []
     reply = "%s on %s:%s:%s " % (PA.get(scantype,"name"),x,y,z,)
     reply+= Config.get("URL","viewscan") % (pa_id,)
     
     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)
     
     reply = "%s on %s:%s:%s " % (PA.get(scantype,"name"),x,y,z,)
     reply+= "delivered to: "
     reply+= ", ".join(nicks) if not Config.getboolean("Misc", "anonscans") else "Anon"
     from Hooks.scans.request import request
     message.privmsg(reply, request().scanchan())
Beispiel #27
0
 def execute(self, request, user, message=None):
     tick = Updates.current_tick()
     
     Q = session.query(Request)
     Q = Q.filter(Request.user == user)
     Q = Q.filter(Request.tick > tick - 5)
     Q = Q.filter(Request.active == True)
     Q = Q.order_by(asc(Request.id))
     mine = Q.all()
     
     Q = session.query(Request)
     Q = Q.filter(Request.tick > tick - 5)
     Q = Q.filter(Request.active == True)
     Q = Q.order_by(asc(Request.id))
     everyone = Q.all()
     
     return render("scans/requests.tpl", request, anonscans=Config.getboolean("Misc", "anonscans"), types=Request._requestable, mine=mine, everyone=everyone, message=message)
Beispiel #28
0
    def parse_N(self, scan_id, scan, page):
        #incoming fleets
        #<td class=left valign=top>Incoming</td><td valign=top>851</td><td class=left valign=top>We have detected an open jumpgate from Tertiary, located at 18:5:11. The fleet will approach our system in tick 855 and appears to have roughly 95 ships.</td>
        for m in re.finditer(
                '<td class="left" valign="top">Incoming</td><td valign="top">(\d+)</td><td class="left" valign="top">We have detected an open jumpgate from ([^<]+), located at <a[^>]+>(\d+):(\d+):(\d+)</a>. The fleet will approach our system in tick (\d+) and appears to have (\d+) visible ships.</td>',
                page):
            fleetscan = FleetScan()

            newstick = m.group(1)
            fleetname = m.group(2)
            originx = m.group(3)
            originy = m.group(4)
            originz = m.group(5)
            arrivaltick = m.group(6)
            numships = m.group(7)

            fleetscan.mission = "Unknown"
            fleetscan.fleet_name = fleetname
            fleetscan.launch_tick = newstick
            fleetscan.landing_tick = int(arrivaltick)
            fleetscan.fleet_size = numships

            owner = PlanetHistory.load_planet(
                originx,
                originy,
                originz,
                newstick,
                closest=not Config.getboolean("Misc", "catchup"))
            if owner is None:
                continue
            fleetscan.owner = owner
            fleetscan.target = scan.planet
            fleetscan.in_cluster = fleetscan.owner.x == fleetscan.target.x
            fleetscan.in_galaxy = fleetscan.in_cluster and fleetscan.owner.y == fleetscan.target.y

            try:
                scan.fleets.append(fleetscan)
                session.commit()
            except Exception, e:
                session.rollback()
                scanlog("Exception in news: %s" % (str(e), ), traceback=True)
                continue

            scanlog('Incoming: ' + newstick + ':' + fleetname + '-' + originx +
                    ':' + originy + ':' + originz + '-' + arrivaltick + '|' +
                    numships)
Beispiel #29
0
def join(message):
    # Someone is joining a channel
    if message.get_nick() != Merlin.nick:
        # Someone is joining a channel we're in
        try:
            u = User.load(name=message.get_pnick())
            if u is None:
                return
            tells = u.newtells
            for tell in tells:
                if Config.getboolean("Misc", "tellmsg"):
                    message.privmsg("Message from %s: %s" % (tell.sender.name, tell.message), message.get_nick())
                else:
                    message.notice("Message from %s: %s" % (tell.sender.name, tell.message), message.get_nick())
                tell.read = True
            session.commit()
        except PNickParseError:
            return
Beispiel #30
0
def join(message):
    # Someone is joining a channel
    if message.get_nick() != Merlin.nick:
        # Someone is joining a channel we're in
        try:
            u = User.load(name=message.get_pnick())
            if u is None:
                return
            tells = u.newtells
            for tell in tells:
                if Config.getboolean("Misc", "tellmsg"):
                    message.privmsg(
                        "Message from %s: %s" %
                        (tell.sender.name, tell.message), message.get_nick())
                else:
                    message.notice(
                        "Message from %s: %s" %
                        (tell.sender.name, tell.message), message.get_nick())
                tell.read = True
            session.commit()
        except PNickParseError:
            return
Beispiel #31
0
    def execute(self, request, user, message=None):
        tick = Updates.current_tick()

        Q = session.query(Request)
        Q = Q.filter(Request.user == user)
        Q = Q.filter(Request.tick > tick - 5)
        Q = Q.filter(Request.active == True)
        Q = Q.order_by(asc(Request.id))
        mine = Q.all()

        Q = session.query(Request)
        Q = Q.filter(Request.tick > tick - 5)
        Q = Q.filter(Request.active == True)
        Q = Q.order_by(asc(Request.id))
        everyone = Q.all()

        return render("scans/requests.tpl",
                      request,
                      anonscans=Config.getboolean("Misc", "anonscans"),
                      types=Request._requestable,
                      mine=mine,
                      everyone=everyone,
                      message=message)
Beispiel #32
0
            originx = m.group(3)
            originy = m.group(4)
            originz = m.group(5)
            arrivaltick = m.group(6)

            fleetscan.mission = "Attack"
            fleetscan.fleet_name = fleetname
            fleetscan.launch_tick = newstick
            fleetscan.landing_tick = arrivaltick

            target = PlanetHistory.load_planet(
                originx,
                originy,
                originz,
                newstick,
                closest=not Config.getboolean("Misc", "catchup"))
            if target is None:
                continue
            fleetscan.owner = scan.planet
            fleetscan.target = target
            fleetscan.in_cluster = fleetscan.owner.x == fleetscan.target.x
            fleetscan.in_galaxy = fleetscan.in_cluster and fleetscan.owner.y == fleetscan.target.y

            try:
                scan.fleets.append(fleetscan)
                session.commit()
            except Exception, e:
                session.rollback()
                scanlog("Exception in news: %s" % (str(e), ), traceback=True)
                continue
Beispiel #33
0
        session.execute(text("INSERT INTO %scookie_log (log_time,year,week,howmany,giver_id,receiver_id) SELECT log_time,year,week,howmany,giver_id,receiver_id FROM %s.%scookie_log;" % (prefix, round, old_prefix)))
        print "  - smslog"
        session.execute(text("INSERT INTO %ssms_log (sender_id,receiver_id,phone,sms_text,mode) SELECT sender_id,receiver_id,phone,sms_text,mode FROM %s.%ssms_log;" % (prefix, round, old_prefix)))
    except DBAPIError, e:
        print "An error occurred during migration: %s" %(str(e),)
        session.rollback()
        print "Reverting to previous schema"
        """session.execute(text("DROP SCHEMA public CASCADE;"))
        session.execute(text("ALTER SCHEMA %s RENAME TO public;" % (round,)))"""
        session.commit()
        sys.exit()
    else:
        session.commit()
    finally:
        session.close()
    if Config.has_section("FluxBB") and Config.getboolean("FluxBB", "enabled"):
        tables = session.execute(text("SELECT table_name FROM information_schema.tables WHERE table_schema='%s' AND table_name LIKE '%s%%';" % (round, Config.get("FluxBB", "prefix"))))
        for t in tables:
            session.execute(text("CREATE TABLE %s AS SELECT * FROM %s.%s;" % (t[0], round, t[0])))
        session.commit()
        session.close()

    if round == "temp":
        print "Deleting temporary schema"
        session.execute(text("DROP SCHEMA temp CASCADE;"))
        session.commit()
        session.close()

print "Inserting ship stats"
shipstats.main()
Beispiel #34
0
    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()
Beispiel #35
0
    def robocop(self, message, etype, uname="Unknown", tick=0, x=0, y=0, z=0, name="", eta=0, size=0, res=0, cons=0):
        notice = ""
        email = ""

        if name[:3] == "!#!":
            name = " ".join(name[3:].split("!#!"))

        user = User.load(uname)
        if user is None:
            errorlog("Defcall: Invalid user in email. Idiot.")
            uname = "%s (whoever that is??)" % (uname)
            ucoords = "x:x:x"
            addr = Config.get("imap", "bounce")
            email = "Bad username in notifications: %s\n\nOriginal notification:\n\n\n" % (uname)
        else:
            uname = "%s%s" % (user.name, ("(%s)" % (user.alias)) if user.alias else "")
            if user.planet:
                ucoords = "%d:%d:%d" % (user.planet.x, user.planet.y, user.planet.z)
            else:
                ucoords = "idiot"
            addr = user.email

        if etype != "fin":
            p = Planet.load(x,y,z)
            if p is None:
                errorlog("Defcall: Invalid planet in email. Probably an exile.")

        if etype == "new":
            # Message to DC channel / main channel. Request scans.
            if p is None:
                arace = "??"
                aally = "Unknown"
            else:
                arace = p.race
                i = p.intel
                if i and i.alliance:
                    aally = i.alliance.name
                else:
                    aally = "Unknown"
            
            notice = "DEFCALL: %s (%s) has incoming eta %s(%s) from %s:%s:%s (%s, %s) - Fleet: %s Visible Ships: %s" % (uname, ucoords, eta, int(eta)-int(tick),
                                                                                                                        x, y, z, arace, aally, name, size)
            email += "Notification from Planetarion in tick %s\n\n" % (tick) +\
                     "Incoming Fleet %s from %s:%s:%s with %s visible ships expected to land in tick %s." % (name, x, y, z, size, eta) +\
                    "\n\nThis has been reported to the %s DCs." % (Config.get("Alliance", "name"))
        elif etype == "rec":
            # Message to DC channel *and* main channel
            notice = "RECALL: %s (%s) has had a recall: Fleet: %s from %s:%s:%s" % (uname, ucoords, name, x, y, z)
            email += "Notification from Planetarion in tick %s\n\n" % (tick) +\
                     "Incoming Fleet %s from %s:%s:%s has recalled." % (name, x, y, z) +\
                    "\n\nThis has been reported to %s." % (Config.get("Alliance", "name"))
        elif etype == "fin":
            # Nothing to see here. Move along.
            notice = ""
            what = ""
            if int(res):
                what = "research"
                if int(cons):
                    what += " and construction"
            else:
                what = "construction"
            email += "Notification from Planetarion in tick %s\n\nAll %s has finished and none is queued." % (tick, what)
        else:
            return
        # Send email - pref?
        if notice:
            if Config.getboolean("Misc", "globaldef"):
                   push("broadcast", notice="!#!"+notice.replace(" ","!#!"))
            else:
                if etype == "new" and Config.has_option("Channels", "def"):
                    message.notice(notice, Config.get("Channels", "def"))
                else:
                    message.notice(notice, Config.get("Channels", "home"))
        
        if email and addr:
            self.send_email("Relayed PA Notifications from tick %s" % (tick), email, addr)
        
        # Check for scans
	if etype == "new" and p and user:
           if Config.has_option("Misc", "autoscans"):
               scantypes = Config.get("Misc", "autoscans")
           else:
               scantypes = "A"
           scanage = (Config.getint("Misc", "scanage") or 2)

           for stype in scantypes:
               scan = p.scan(stype)
               if scan and (int(tick) - scan.tick <= scanage):
                   return
               else:
                   req = Request(target=p, scantype=stype, dists=0)
                   user.requests.append(req)
                   session.commit()
                   push("request", request_id=req.id, mode="request")
Beispiel #36
0
    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()
Beispiel #37
0
        for m in re.finditer('<td class="left" valign="top">Launch</td><td valign="top">(\d+)</td><td class="left" valign="top">The ([^,]+) fleet has been launched, heading for <a[^>]+>(\d+):(\d+):(\d+)</a>, on a mission to Attack. Arrival tick: (\d+)</td>', page):
            fleetscan = FleetScan()

            newstick = m.group(1)
            fleetname = m.group(2)
            originx = m.group(3)
            originy = m.group(4)
            originz = m.group(5)
            arrivaltick = m.group(6)

            fleetscan.mission = "Attack"
            fleetscan.fleet_name = fleetname
            fleetscan.launch_tick = newstick
            fleetscan.landing_tick = arrivaltick

            target = PlanetHistory.load_planet(originx,originy,originz,newstick,closest=not Config.getboolean("Misc", "catchup"))
            if target is None:
                continue
            fleetscan.owner = scan.planet
            fleetscan.target = target
            fleetscan.in_cluster = fleetscan.owner.x == fleetscan.target.x
            fleetscan.in_galaxy = fleetscan.in_cluster and fleetscan.owner.y == fleetscan.target.y

            try:
                scan.fleets.append(fleetscan)
                session.commit()
            except Exception, e:
                session.rollback()
                scanlog("Exception in news: %s"%(str(e),), traceback=True)
                continue
Beispiel #38
0
    def parse_N(self, scan_id, scan, page):
        #incoming fleets
        #<td class=left valign=top>Incoming</td><td valign=top>851</td><td class=left valign=top>We have detected an open jumpgate from Tertiary, located at 18:5:11. The fleet will approach our system in tick 855 and appears to have roughly 95 ships.</td>
        for m in re.finditer('<td class="left" valign="top">Incoming</td><td valign="top">(\d+)</td><td class="left" valign="top">We have detected an open jumpgate from ([^<]+), located at <a[^>]+>(\d+):(\d+):(\d+)</a>. The fleet will approach our system in tick (\d+) and appears to have (\d+) visible ships.</td>', page):
            fleetscan = FleetScan()

            newstick = m.group(1)
            fleetname = m.group(2)
            originx = m.group(3)
            originy = m.group(4)
            originz = m.group(5)
            arrivaltick = m.group(6)
            numships = m.group(7)

            fleetscan.mission = "Unknown"
            fleetscan.fleet_name = fleetname
            fleetscan.launch_tick = newstick
            fleetscan.landing_tick = int(arrivaltick)
            fleetscan.fleet_size = numships

            owner = PlanetHistory.load_planet(originx,originy,originz,newstick,closest=not Config.getboolean("Misc", "catchup"))
            if owner is None:
                continue
            fleetscan.owner = owner
            fleetscan.target = scan.planet
            fleetscan.in_cluster = fleetscan.owner.x == fleetscan.target.x
            fleetscan.in_galaxy = fleetscan.in_cluster and fleetscan.owner.y == fleetscan.target.y

            try:
                scan.fleets.append(fleetscan)
                session.commit()
            except Exception, e:
                session.rollback()
                scanlog("Exception in news: %s"%(str(e),), traceback=True)
                continue

            scanlog('Incoming: ' + newstick + ':' + fleetname + '-' + originx + ':' + originy + ':' + originz + '-' + arrivaltick + '|' + numships)
Beispiel #39
0
            text(
                "INSERT INTO %ssms_log (sender_id,receiver_id,phone,sms_text,mode) SELECT sender_id,receiver_id,phone,sms_text,mode FROM %s.%ssms_log;"
                % (prefix, round, old_prefix)))
    except DBAPIError, e:
        print "An error occurred during migration: %s" % (str(e), )
        session.rollback()
        print "Reverting to previous schema"
        """session.execute(text("DROP SCHEMA public CASCADE;"))
        session.execute(text("ALTER SCHEMA %s RENAME TO public;" % (round,)))"""
        session.commit()
        sys.exit()
    else:
        session.commit()
    finally:
        session.close()
    if Config.has_section("FluxBB") and Config.getboolean("FluxBB", "enabled"):
        tables = session.execute(
            text(
                "SELECT table_name FROM information_schema.tables WHERE table_schema='%s' AND table_name LIKE '%s%%';"
                % (round, Config.get("FluxBB", "prefix"))))
        for t in tables:
            session.execute(
                text("CREATE TABLE %s AS SELECT * FROM %s.%s;" %
                     (t[0], round, t[0])))
        session.commit()
        session.close()

    if round == "temp":
        print "Deleting temporary schema"
        session.execute(text("DROP SCHEMA temp CASCADE;"))
        session.commit()
Beispiel #40
0
    def robocop(self,
                message,
                etype,
                uname="Unknown",
                tick=0,
                x=0,
                y=0,
                z=0,
                name="",
                eta=0,
                size=0,
                res=0,
                cons=0):
        notice = ""
        email = ""

        if name[:3] == "!#!":
            name = " ".join(name[3:].split("!#!"))

        user = User.load(uname)
        if user is None:
            errorlog("Defcall: Invalid user in email. Idiot.")
            uname = "%s (whoever that is??)" % (uname)
            ucoords = "x:x:x"
            addr = Config.get("imap", "bounce")
            email = "Bad username in notifications: %s\n\nOriginal notification:\n\n\n" % (
                uname)
        else:
            uname = "%s%s" % (user.name,
                              ("(%s)" % (user.alias)) if user.alias else "")
            if user.planet:
                ucoords = "%d:%d:%d" % (user.planet.x, user.planet.y,
                                        user.planet.z)
            else:
                ucoords = "idiot"
            addr = user.email

        if etype != "fin":
            p = Planet.load(x, y, z)
            if p is None:
                errorlog(
                    "Defcall: Invalid planet in email. Probably an exile.")

        if etype == "new":
            # Message to DC channel / main channel. Request scans.
            if p is None:
                arace = "??"
                aally = "Unknown"
            else:
                arace = p.race
                i = p.intel
                if i and i.alliance:
                    aally = i.alliance.name
                else:
                    aally = "Unknown"

            notice = "DEFCALL: %s (%s) has incoming eta %s(%s) from %s:%s:%s (%s, %s) - Fleet: %s Visible Ships: %s" % (
                uname, ucoords, eta, int(eta) - int(tick), x, y, z, arace,
                aally, name, size)
            email += "Notification from Planetarion in tick %s\n\n" % (tick) +\
                     "Incoming Fleet %s from %s:%s:%s with %s visible ships expected to land in tick %s." % (name, x, y, z, size, eta) +\
                    "\n\nThis has been reported to the %s DCs." % (Config.get("Alliance", "name"))
        elif etype == "rec":
            # Message to DC channel *and* main channel
            notice = "RECALL: %s (%s) has had a recall: Fleet: %s from %s:%s:%s" % (
                uname, ucoords, name, x, y, z)
            email += "Notification from Planetarion in tick %s\n\n" % (tick) +\
                     "Incoming Fleet %s from %s:%s:%s has recalled." % (name, x, y, z) +\
                    "\n\nThis has been reported to %s." % (Config.get("Alliance", "name"))
        elif etype == "fin":
            # Nothing to see here. Move along.
            notice = ""
            what = ""
            if int(res):
                what = "research"
                if int(cons):
                    what += " and construction"
            else:
                what = "construction"
            email += "Notification from Planetarion in tick %s\n\nAll %s has finished and none is queued." % (
                tick, what)
        else:
            return
        # Send email - pref?
        if notice:
            if Config.getboolean("Misc", "globaldef"):
                push("broadcast", notice="!#!" + notice.replace(" ", "!#!"))
            else:
                if etype == "new" and Config.has_option("Channels", "def"):
                    message.notice(notice, Config.get("Channels", "def"))
                else:
                    message.notice(notice, Config.get("Channels", "home"))

        if email and addr:
            self.send_email("Relayed PA Notifications from tick %s" % (tick),
                            email, addr)

        # Check for scans
        if etype == "new" and p and user:
            if Config.has_option("Misc", "autoscans"):
                scantypes = Config.get("Misc", "autoscans")
            else:
                scantypes = "A"
            scanage = (Config.getint("Misc", "scanage") or 2)

            for stype in scantypes:
                scan = p.scan(stype)
                if scan and (int(tick) - scan.tick <= scanage):
                    return
                else:
                    req = Request(target=p, scantype=stype, dists=0)
                    user.requests.append(req)
                    session.commit()
                    push("request", request_id=req.id, mode="request")
Beispiel #41
0
    def robonotify(self, header, body):
        if Config.getboolean("imap", "singleaddr"):
            uname_re = "%s\+(.+)@.+" % Config.get(
                "imap", "user").split("@")[0].lower()
            try:
                uname = re.findall(uname_re, header['To'].lower())[0]
            except IndexError:
                uname = "Unknown"
        else:
            uname_re = "<?(.+)@.+"
            uname = re.findall(uname_re, header['To'].lower())[0]

        dsuff = Config.get("imap", "defsuffix")
        if dsuff:
            if uname[-len(dsuff):] == dsuff:
                uname = uname[:-len(dsuff)]
            else:
                self.forwardMail(uname, header, body)
                return

        # Check the email "From" header says it's from Planetarion.
        if not "@planetarion.com" in header['From'].lower():
            self.forwardMail(uname, header, body)
            return

        # Get the tick number (if this is a notification email).
        try:
            tick = re.findall("events in tick (\d+)", body)[0]
        except IndexError:
            self.forwardMail(uname, header, body)
            return

        # Check for the main notificatino types
        newfleets = re.findall("We have detected an open jumpgate from (.+), located at (\d{1,2}):(\d{1,2}):(\d{1,2}). ".replace(" ","\s+") +\
                               "The fleet will approach our system in tick (\d+) and appears to have (\d+) visible ships.".replace(" ","\s+"), body)
        recalls = re.findall(
            "The (.+) fleet from (\d{1,2}):(\d{1,2}):(\d{1,2}) has been recalled."
            .replace(" ", "\s+"), body)
        cons = len(
            re.findall(
                "Our construction team reports that .+ has been finished".
                replace(" ", "\s+"), body))
        res = len(
            re.findall(
                "Our scientists report that .+ has been finished".replace(
                    " ", "\s+"), body))

        # Wrap it up in a bow
        for line in newfleets:
            push("defcall",
                 etype="new",
                 uname=uname,
                 tick=tick,
                 name=("!#!" + line[0].replace(" ", "!#!")),
                 x=line[1],
                 y=line[2],
                 z=line[3],
                 eta=line[4],
                 size=line[5])
        for line in recalls:
            push("defcall",
                 etype="rec",
                 uname=uname,
                 tick=tick,
                 name=("!#!" + line[0].replace(" ", "!#!")),
                 x=line[1],
                 y=line[2],
                 z=line[3])
        if res + cons > 0:
            push("defcall",
                 etype="fin",
                 uname=uname,
                 tick=tick,
                 res=res,
                 cons=cons)

        if len(newfleets) + len(recalls) + cons + res == 0:
            self.forwardMail(uname, header, body)
Beispiel #42
0
class Idler(threading.Thread):

    if Config.getboolean("imap", "ssl"):
        imap = imaplib2.IMAP4_SSL(Config.get("imap", "host"))
    else:
        imap = imaplib2.IMAP4(Config.get("imap", "host"))

    stopWaitingEvent = threading.Event()
    #Now, this stopWaitingEvent thing -- it really does make the whole thing work. Basically,
    #it holds a boolean value which is set and cleared using, oddly enough, the methods set() and
    #clear(). But, the good thing about it is that it has another method, wait(), which holds
    #execution until it has been set(). I cannot thank threading.Event() enough, I really couldn't
    #have done it without you!

    knownAboutMail = []  # will be a list of IDs of messages in the inbox
    killNow = False  # stops execution of thread to allow propper closing of conns.
    """
    Initialise (sorry, I'm from the UK) everything to get ready for PUSHed mail.
    """
    def __init__(self, GMailUsername, GMailPassword):

        os.system('clear')
        debugMsg('DEBUG is ENABLED')
        debugMsg('__init__() entered')

        try:
            #establish connection to IMAP Server
            self.imap.LOGIN(GMailUsername, GMailPassword)
            self.imap.SELECT("INBOX")

            #get the IDs of all messages in the inbox and put in knowAboutMail
            typ, data = self.imap.SEARCH(None, 'ALL')
            self.knownAboutMail = data[0].split()

            #now run the inherited __init__ method to create thread
            threading.Thread.__init__(self)

        except:  #Uh Oh, something went wrong
            print 'ERROR: IMAP Issue. It could be one (or more) of the following:'
            print '- The imaplib2.py file needs to be in the same directory as this file'
            print '- You\'re not connected to the internet'
            print '- Google\'s mail server(s) is/are down'
            print '- Your username and/or password is incorrect'
            sys.exit(1)

        debugMsg('__init__() exited')

    """
    The method invoked when the thread id start()ed. Enter a loop executing waitForServer()
    untill kill()ed. waitForServer() can, and should, be continuously executed to be alerted
    of new mail.
    """

    def run(self):
        debugMsg('run() entered')

        #loop until killNow is set by kill() method
        while not self.killNow:
            self.waitForServer()

        debugMsg('run() exited')

    """
    Relay email contents to merlin via robocop.
    """

    def robonotify(self, header, body):
        # Check for correct "From" address?
        uname = re.findall("(.+)@.+", header['To'])[0].split()[1]
        dsuff = Config.get("imap", "defsuffix")
        if dsuff:
            if uname[-len(dsuff):] == dsuff:
                uname = uname[:-len(dsuff)]
            else:
                self.forwardMail(uname, header, body)
                return

        tick = re.findall("events in tick (\d+)", body)[0]
        newfleets = re.findall("We have detected an open jumpgate from (.+), located at (\d{1,2}):(\d{1,2}):(\d{1,2}). " +\
                               "The fleet will approach our system in tick (\d+) and appears to have (\d+) visible ships.", body)
        recalls = re.findall(
            "The (.+) fleet from (\d{1,2}):(\d{1,2}):(\d{1,2}) has been recalled.",
            body)
        cons = len(
            re.findall(
                "Our construction team reports that .+ has been finished",
                body))
        res = len(
            re.findall("Our scientists report that .+ has been finished",
                       body))

        # Wrap it up in a bow
        for line in newfleets:
            push("defcall",
                 etype="new",
                 uname=uname,
                 tick=tick,
                 name=line[0],
                 x=line[1],
                 y=line[2],
                 z=line[3],
                 eta=line[4],
                 size=line[5])
        for line in recalls:
            push("defcall",
                 etype="rec",
                 uname=uname,
                 tick=tick,
                 name=line[0],
                 x=line[1],
                 y=line[2],
                 z=line[3])
        if res + cons > 0:
            push("defcall",
                 etype="fin",
                 uname=uname,
                 tick=tick,
                 res=res,
                 cons=cons)

        if len(newfleets) + len(recalls) + cons + res == 0:
            self.forwardMail(uname, header, body)

    """
    Decide whether to forward mail.
    """

    def forwardMail(self, uname, header, body):
        if not Config.getboolean("imap", "forwarding"):
            return
        body = "Original Message from %s\n\n" % (header['From']) + body
        user = User.load(uname)
        if user:
            addr = user.email
        else:
            addr = Config.get("imap", "bounce")
            body = "Bad username: %s\n\n" % (uname) + body
        if addr:
            self.send_email(header['Subject'], body, addr)

    """
    Send an email using smtplib.
    """

    def send_email(self, subject, message, addr):
        try:
            if (Config.get("smtp", "port") == "0"):
                smtp = SMTP("localhost")
            else:
                smtp = SMTP(Config.get("smtp", "host"),
                            Config.get("smtp", "port"))

            if not ((Config.get("smtp", "host") == "localhost") or
                    (Config.get("smtp", "host") == "127.0.0.1")):
                try:
                    smtp.starttls()
                except SMTPException as e:
                    raise SMSError("unable to shift connection into TLS: %s" %
                                   (str(e), ))

                try:
                    smtp.login(Config.get("smtp", "user"),
                               Config.get("smtp", "pass"))
                except SMTPException as e:
                    raise SMSError("unable to authenticate: %s" % (str(e), ))

            try:
                smtp.sendmail(
                    Config.get("smtp", "frommail"), addr,
                    "To:%s\nFrom:%s\nSubject:%s\n%s\n" %
                    (addr, "\"%s\" <%s>" %
                     (Config.get("Alliance", "name"),
                      Config.get("smtp", "frommail")), subject, message))
            except SMTPSenderRefused as e:
                raise SMSError("sender refused: %s" % (str(e), ))
            except SMTPRecipientsRefused as e:
                raise SMSError("unable to send: %s" % (str(e), ))

            smtp.quit()

        except (socket.error, SSLError, SMTPException, SMSError) as e:
            return "Error sending message: %s" % (str(e), )

    """
    Name says it all really: get (just) the specified header fields from the server for the 
    specified message ID.
    """

    def getMessageHeaderFieldsById(self, id, fields_tuple):
        debugMsg('getMessageHeaderFieldsById() entered')

        #get the entire header
        typ, header = self.imap.FETCH(id, '(RFC822.HEADER)')

        #get individual lines
        headerlines = header[0][1].splitlines()

        #get the lines that start with the values in fields_tuple
        results = {}
        for field in fields_tuple:
            results[field] = ''
            for line in headerlines:
                if line.startswith(field):
                    results[field] = line

        debugMsg('getMessageHeaderFieldsById() exited')
        return results  #which is a dictionary containing the the requested fields

    """
    The main def for displaying messages. It draws on getMessageHeaderFieldsById() and growlnotify()
    to do so.
    """

    def showNewMailMessages(self):
        debugMsg('showNewMailMessages() entered')

        #get IDs of all UNSEEN messages
        typ, data = self.imap.SEARCH(None, 'UNSEEN')

        debugMsg('data - new mail IDs:')
        debugMsg(data, 0)

        for id in data[0].split():
            if not id in self.knownAboutMail:

                #get From and Subject fields from header
                headerFields = self.getMessageHeaderFieldsById(
                    id, ('From', 'To', 'Subject'))
                print self.imap.fetch(id, '(BODY[TEXT])')[1][0][1]

                debugMsg('headerFields dict. (from showNewMailMessage()):')
                debugMsg(headerFields, 0)

                #notify
                self.robonotify(headerFields,
                                self.imap.fetch(id, '(BODY[TEXT])')[1][0][1])

                #add this message to the list of known messages
                self.knownAboutMail.append(id)

        debugMsg('showNewMailMessages() exited')

    """
    Called to stop the script. It stops the continuous while loop in run() and therefore
    stops the thread's execution.
    """

    def kill(self):
        self.killNow = True  # to stop while loop in run()
        self.timeout = True  # keeps waitForServer() nice
        self.stopWaitingEvent.set(
        )  # to let wait() to return and let execution continue

    """
    This is the block of code called by the run() method of the therad. It is what does all 
    the waiting for new mail (well, and timeouts).
    """

    def waitForServer(self):
        debugMsg('waitForServer() entered')

        #init
        self.newMail = False
        self.timeout = False
        self.IDLEArgs = ''
        self.stopWaitingEvent.clear()

        def _IDLECallback(args):
            self.IDLEArgs = args
            self.stopWaitingEvent.set()
            #_IDLECallack() is entered when the IMAP server responds to the IDLE command when new
            #mail is received. The self.stopWaitingEvent.set() allows the .wait() to return and
            #therefore the rest of waitForServer().

        #attach callback function, and let server know it should tell us when new mail arrives
        self.imap.idle(timeout=60 * ServerTimeout, callback=_IDLECallback)

        #execution will stay here until either:
        # - a new message is received; or
        # - the timeout has happened
        #       - we set the timout -- the RFC says the server has the right to forget about
        #            us after 30 mins of inactivity (i.e. not communicating with server for 30 mins).
        #            By sending the IDLE command every 29 mins, we won't be forgotten.
        # - Alternatively, the kill() method has been invoked.
        self.stopWaitingEvent.wait()

        #self.IDLEArgs has now been filled (if not kill()ed)

        if not self.killNow:  # skips a chunk of code to sys.exit() more quickly.

            try:
                b = bool(
                    self.IDLEArgs[0][1][0] == ('IDLE terminated (Success)'))
            except TypeError:
                b = False
                self.timeout = True
            if b:
                # This (above) is sent when either: there has been a timeout (server sends); or, there
                # is new mail. We have to check manually to see if there is new mail.

                typ, data = self.imap.SEARCH(
                    None, 'UNSEEN')  # like before, get UNSEEN message IDs

                debugMsg('Data: ')
                debugMsg(data, 0)

                #see if each ID is new, and, if it is, make newMail True
                for id in data[0].split():
                    if not id in self.knownAboutMail:
                        self.newMail = self.newMail or True
                    else:
                        self.timeout = True
                        # gets executed if there are UNSEEN messages that we have been notified of,
                        # but we haven't yet read. In this case, it response was just a timeout.

                if data[0] == '':  # no IDs, so it was a timeout (but no notified but UNSEEN mail)
                    self.timeout = True

            #now there has either been a timeout or a new message -- Do something...
            if self.newMail:
                debugMsg('INFO: New Mail Received')
                self.showNewMailMessages()

            elif self.timeout:
                debugMsg('INFO: A Timeout Occurred')

        debugMsg('waitForServer() exited')