Exemple #1
0
def com_evolve(client, arguments=None):
    """
    Dispatches a thread to:
    Evolves all of current char's enhancer cards
    """
    # Are we currently active?
    if client.robin["char"] is None:
        client.send("You need to activate a character first.\n")
        return

    # No arguments
    if arguments is None:
        """
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^cevolve start^~  - Start evolving all feeders")
        t.add("  ^cevolve cancel^~ - Cancel evolutions in progress")
        client.send_cc(t.get())
        return
        """
        arguments = "start"

    # Parse arg1: either 'start' or 'cancel'
    arg1list = ["start", "cancel"]
    candidates = expand(arguments, arg1list)[0]
    if len(candidates) == 0 or len(candidates) > 1:
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^cevolve start^~  - Start evolving all feeders")
        t.add("  ^cevolve cancel^~ - Cancel evolutions in progress")
        client.send_cc(t.get())
        return

    arg1 = candidates[0]
    if arg1 == "start":
        # Make sure we aren't already running a dispatcher
        if "dispatcher" in client.robin:
            if client.robin["dispatcher"].is_alive():
                client.send_cc(MenuStr("You need to ^ccancel^~ any running commands first.").get())
                return

        client.send_cc("\n[Evolving feeders]\n")

        # DispatcherThread config
        # Preamble strings
        pre_console = "[{}] Evolving feeders...".format(client.robin["char"].name)
        # Worker thread
        work_target = client.robin["char"].evolve
        work_extra_args = ()
        name = "[{}] Evolve".format(client.robin["char"].name)

        client.robin["dispatcher"] = DispatcherThread(client, pre_console, work_target, work_extra_args, name)
        client.robin["dispatcher"].start()
    elif arg1 == "cancel":
        client.robin["dispatcher"].queue.put("CANCEL")
        client.send("Cancelling...")
    return
Exemple #2
0
def com_update(client, arguments=None):
    """
    Update the active character
    """
    # Are we currently active?
    if client.robin["char"] is None:
        t = MenuStr()
        t.add("You need to activate a character to use this command.")
        t.add("To update a non-active character, use the ^cchar update^~ command.")
        client.send_cc(t.get())
        return

    client.robin["char"].update()
    client.send("Stats updated.\n")
Exemple #3
0
 def loadchars(self):
     '''
     Loads characters from file
     Characters loaded are automatically scheduled for an update between 0.5 and 10mins later
     '''
     console = ConsoleEngine()
     y = console.logtask("Loading character sessions from file...")
     t = MenuStr()
     
     with self.filelock:
         try:
             f = open(Config.charsave, 'r')
             tempchars = pickle.load(f)
             f.close()
         except IOError:
             console.logstatus(y, "[FAILED]")
             console.log("File '{}' not available for reading.".format(Config.charsave))
             return
         except:
             console.logstatus(y, "[FAILED]")
             console.log("Error reading '{}'".format(Config.charsave))
             return
         
     
     for x in tempchars.keys():
         tchar = tempchars[x]
         
         # Check last update time - we don't want anything too old
         currtime = datetime.datetime.now()
         sinceupdate = currtime - tchar.lastupdatetime
         maxage = Config.maxloadage
         if (maxage > 150):
             maxage = 150
         smaxage = maxage * 60
         if (sinceupdate.seconds > smaxage):
             # Too old
             console.log("Load: Skipped [{}] - Session too stale".format(tchar.name))
             t.add("Skipping [{}]: Session too stale.".format(tchar.name))
             continue
         
         # Check if same as existing character
         if (tchar.name in self.chars):
             # If so, see which has a fresher logon
             tsl = currtime - tchar.logontime
             sl = currtime - self.chars[tchar.name].logontime
             if (tsl < sl):
                 console.log("Load: Overrode [{}] - Fresher logon".format(tchar.name))
                 t.add("Overriding [{}]: Fresher logon.".format(tchar.name))
             else:
                 console.log("Load: Skipped [{}] - Not fresher than existing logon".format(tchar.name))
                 t.add("Skipping [{}]: Not fresher than existing logon.".format(tchar.name))
                 continue
         else:
             # New character
             console.log("Load: Added [{}]".format(tchar.name))
             t.add("Adding [{}]".format(tchar.name))
             
         # If we haven't continued by now, it's a valid character
         self.chars[tchar.name] = tchar
         self.chars[tchar.name].lock = threading.Lock()
         
         # Done. Let the other threads have at it
         self.chars[tchar.name].nextupdate = datetime.timedelta(seconds=(random.randint(30, 600))) 
         
     console.logstatus(y, "[OK]")
     return t.get()
Exemple #4
0
    def sell(self, outqueue, inqueue):
        '''
        Sell rupie cards
        Return output to user using queue
        @keyword outqueue: Queue to buffer output in. Sending "END" signals completion
        @keyword inqueue: Queue to listen for input. Receiving "CANCEL" signals cancellation.
        '''
        conn = ROBConn()
        
        # Emulate sale list presses
        t = MenuStr("\n\nEmulating sale list presses...")
        outqueue.put(t.get())
        conn.geturl('card_list', self.conn_session, send_session=self.session, send_viewer=self.viewer)
        
        # Scrape initial sales page
        soup = conn.geturl('card_sale/index', self.conn_session, send_viewer=self.viewer)
        
        # Check to see if 'All' is selected 
        if (soup.find("div", "tabArea").find("a", href=re.compile("http://bahamut-n.cygames.jp/bahamut_n/card_sale/index/0"))):
            url = soup.find("div", "tabArea").find("a", href=re.compile("http://bahamut-n.cygames.jp/bahamut_n/card_sale/index/0"))['href']
            url = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", url).group(1)
            # Add viewer ourselves to avoid confusing ROBConn
            if '?' not in url:
                raise RuntimeError
            url = url + "&viewer_id=" + self.viewer
            
            outqueue.put(MenuStr("Setting display filter to 'All'...").get())
            
            soup = conn.geturl(url, self.conn_session)
        
        # Now check to see if sort order is 'last obtained'
        orderform = soup.find("form")
        if (orderform.find("option", selected=True).get_text() != 'Last Obtained'):
            # Prepare to make it so
            vals = []
            vals.append(('sort_type', orderform.find(text=re.compile("Last Obtained")).find_parent("option")['value']))
            for x in orderform.find_all("input"):
                if (x["type"] == 'submit'):
                    continue
                vals.append((x["name"], x["value"]))
            query = urllib.urlencode(vals)
            headers = {'Cache-Control': 'max-age=0',
                 'Origin': 'http://bahamut-n.cygames.jp',
                 'Referer': conn.getreferer(self.viewer)}
            url = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", orderform['action']).group(1)
            
            outqueue.put(MenuStr("Setting sort order to 'last obtained'...").get())
            
            soup = conn.geturl(url, self.conn_session, postdata=query, extra_headers=headers)
        
        # Ready to scrape
        sell_list, form = self._sell_scrape(soup)
        
        # Prepare pagelist
        pagelist = soup.find_all("a", "a_link")
        pagelist = pagelist = [re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", y['href']).group(1) for y in pagelist]
        
        noDupes = []
        [noDupes.append(i) for i in pagelist if not noDupes.count(i)]
        pagelist = noDupes
        
        # If there is only the one page and we have no suitable sale candidates:
        if (len(pagelist) == 0 and len(sell_list) == 0):
            outqueue.put("\nNo more cards to sell.\n")
            outqueue.put("END")
            return
        
        # If we're still here, recurse over pagelist looking for sales
        pagecount = 0
        while (len(sell_list) == 0):
            if ((pagecount + 1) > len(pagelist)):
                # We reached the end of the pagelist
                outqueue.put("\nNo more cards to sell.\n")
                outqueue.put("END")
                return
        
            soup = conn.geturl(pagelist[pagecount], self.conn_session, send_viewer=self.viewer)
            sell_list, form = self._sell_scrape(soup)
            
            pagecount += 1
        
        # If we're still here, we found sale candidates.
        t = MenuStr()
        t.add("\nSelling:")
        t.add(pprint.pformat(sell_list))
        t.add()
        outqueue.put(t.get())

        # Get sale confirmation form
        vallist = []
        for x in sell_list:
            vallist.append(('sleeve[]', x[0]))
        vallist = urllib.urlencode(vallist)

        eurl = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", form['action']).group(1)
        
        ehead = {'Cache-Control': 'max-age=0',
                 'Origin': 'http://bahamut-n.cygames.jp',
                 'Referer': conn.getreferer(self.viewer)}
        
        # Go or no go?
        try:
            if (inqueue.get(False) == "CANCEL"):
                outqueue.put(MenuStr("Cancelled.").get())
                outqueue.put("END")
                return
        except Queue.Empty:
            pass
        
        # Getting
        soup = conn.geturl(eurl, self.conn_session, postdata=vallist, extra_headers=ehead)

        # Scrape the received confirmation form
        eform = soup.find("form")
        eurl = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", eform['action']).group(1)
        ehead = {'Cache-Control': 'max-age=0',
                 'Origin': 'http://bahamut-n.cygames.jp',
                 'Referer': conn.getreferer(self.viewer)}
        # Duplicate all form data
        evals = eform.find_all("input")
        equery = []
        for x in evals[:]:
            if (x["type"] == 'submit'): continue
            equery.append((x["name"], x["value"]))
        equery = urllib.urlencode(equery)
        
        # Last chance to cancel
        try:
            if (inqueue.get(False) == "CANCEL"):
                outqueue.put(MenuStr("Cancelled.").get())
                outqueue.put("END")
                return
        except Queue.Empty:
            pass
        
        # Push button
        soup = conn.geturl(eurl, self.conn_session, postdata=equery, extra_headers=ehead)
        
        # Done. Give a status update
        self.update()
        t = "Sold. [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                     self.stamina, self.maxstamina,
                                                     self.rupies)
        outqueue.put(t)
        
        #  Recurse? As long as this is the final call
        self.sell(outqueue, inqueue)
Exemple #5
0
 def evolve(self, outqueue, inqueue):
     '''
     Evolve feeders in inventory as much as possible
     Return output to user using queue
     @keyword outqueue: Queue to buffer output in. Sending "END" signals completion
     @keyword inqueue: Queue to listen for input. Receiving "CANCEL" signals cancellation.
     '''
     
     # Start by checking current rupies
     self.update()
     if (int(self.rupies) < 575):
         t = MenuStr("\n\n^RInsufficient Rupies.^~ [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                                                  self.stamina, self.maxstamina,
                                                                                  self.rupies))
         outqueue.put(t.get())
         outqueue.put("END")
         return
     
     conn = ROBConn()
     anti_infinite = []
     
     # 1. Scrape current evolve menu
     soup = conn.geturl('card_union', self.conn_session, send_session=self.session, send_viewer=self.viewer)
     if re.search('card_union/union_card', conn.getreferer(self.viewer)):
         # We were redirected to new base page
         # Send along cached new base data
         t = self._evo_newbase(soup)
         if not t:
             outqueue.put(MenuStr("\n\nNo available bases.").get())
             outqueue.put("END")
             return
         else:
             anti_infinite.append(t[0])
             soup = t[1]
     
     # Find card id tuple for current base
     base = soup.find(text=re.compile("Change card to evolve")).find_parent("div").div.get_text()
     base = [str.strip(str(x)) for x in base.split("\n")]
     while '' in base:
         base.remove('')
     base = tuple(base)
     
     # Make sure current base is in EvolveTable
     if base not in EvolveTable:
         t = self._evo_newbase()
         if not t:
             outqueue.put(MenuStr("\n\nNo available bases.").get())
             outqueue.put("END")
             return
         else:
             anti_infinite.append(t[0])
             soup = t[1]
             
             # Determine new base
             base = soup.find(text=re.compile("Change card to evolve")).find_parent("div").div.get_text()
             base = [str.strip(str(x)) for x in base.split("\n")]
             while '' in base:
                 base.remove('')
             base = tuple(base)
             
     t = MenuStr()
     basestr = pprint.pformat(base)
     t.add("\n\nUsing base: {}".format(basestr))
     outqueue.put(t.get())
     
     # Search for level 1 material in material list
     level1 = EvolveTable[base]['Material']
     matlink = self._evo_newmatlink(soup, level1)
     
     # Until we get a link to a proper level1 for a base, we'll keep recursing.
     while not matlink:
         outqueue.put(MenuStr("Could not find level 1 materials.  Looking for new base...").get())
         
         t = self._evo_newbase()
         if not t:
             outqueue.put(MenuStr("\n\nNo available bases.").get())
             outqueue.put("END")
             return
         else:
             if t[0] in anti_infinite:
                 y = MenuStr("\n\n** Infinite loop detected! **")
                 y.add("This probably means you have two or more feeder cards of the same kind that are higher than level 1.")
                 y.add("Please manually evolve your feeders so that for each card-type there is only one high level card and the rest are all level 1.")
                 outqueue.put(y.get())
                 outqueue.put("END")
                 return
             anti_infinite.append(t[0])
             soup = t[1]
             
         # Do we abort after finding the new base?
         try:
             if (inqueue.get(False) == "CANCEL"):
                 outqueue.put(MenuStr("Cancelled.").get())
                 outqueue.put("END")
                 return
         except Queue.Empty:
             pass
         
         # Find card id tuple for current base
         base = soup.find(text=re.compile("Change card to evolve")).find_parent("div").div.get_text()
         base = [str.strip(str(x)) for x in base.split("\n")]
         while '' in base:
             base.remove('')
         base = tuple(base)
         
         t = MenuStr()
         basestr = pprint.pformat(base)
         t.add("\n\nUsing base: {}".format(basestr))
         outqueue.put(t.get())
         
         # Search for level 1 material in material list
         level1 = EvolveTable[base]['Material']
         matlink = self._evo_newmatlink(soup, level1)
             
     outqueue.put(MenuStr("Evolving using {}...".format(pprint.pformat(level1))).get())
     
     # Go or no go?
     try:
         if (inqueue.get(False) == "CANCEL"):
             outqueue.put(MenuStr("Cancelled.").get())
             outqueue.put("END")
             return
     except Queue.Empty:
         pass
     
     # Evolve button form
     soup = conn.geturl(matlink, self.conn_session, send_viewer=self.viewer)
     eform = soup.find("form")
     eurl = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", eform['action']).group(1)
     evals = eform.find_all("input")
     equery = []
     
     # Copy all form values, make sure the submit button is there
     submitfound = False
     for x in evals[:]:
         if (x["type"] == 'submit'):
             submitfound = True
         else:
             equery.append((x["name"], x["value"]))
     
     if (not submitfound) or (re.match("(?i)Insufficient rupies", soup.encode(formatter=None))):
         t = MenuStr("\n^RInsufficient Rupies.^~ [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                                                  self.stamina, self.maxstamina,
                                                                                  self.rupies))
         outqueue.put(t.get())
         outqueue.put("END")
         return    
     
     equery = urllib.urlencode(equery)
     ehead = {'Cache-Control': 'max-age=0',
              'Origin': 'http://bahamut-n.cygames.jp',
              'Referer': conn.getreferer(self.viewer)}
     
     # Last chance to cancel
     try:
         if (inqueue.get(False) == "CANCEL"):
             outqueue.put(MenuStr("Cancelled.").get())
             outqueue.put("END")
             return
     except Queue.Empty:
         pass
     
     # Submit form and touch flash
     soup = conn.geturl(eurl, self.conn_session, postdata=equery, extra_headers=ehead)
     furl = re.findall(r"(?<=\"http://bahamut-n.cygames.jp/bahamut_n/)card_union.*?(?=\")", soup.encode(formatter=None))[0]
     #furl = re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", form['action']).group(1)
     conn.geturl(furl, self.conn_session, extra_headers={'Referer': conn.getreferer(self.viewer)}, flash=True, spammy=True)
     
     # Done one evolution
     self.update()
     t = "^GEvolved^~. [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                  self.stamina, self.maxstamina,
                                                  self.rupies)
     outqueue.put(t)
     
     #  Recurse? As long as this is the final call
     self.evolve(outqueue, inqueue)
Exemple #6
0
    def fillcards(self, outqueue, inqueue, quest, minstamina):
        '''
        Given quest parameters, fill card storage with cards
        Return output to user using queue
        @keyword quest: String of the form "<chapter>/<quest>"
        @keyword minstamina: Minimum stamina at which to attempt quest
        @keyword outqueue: Queue to buffer output in. Sending "END" signals completion
        @keyword inqueue: Queue to listen for input. Receiving "CANCEL" signals cancellation.
        '''
        
        # Start by checking current cards/stamina
        self.update()
        if (self.cards == self.maxcards) or (int(self.stamina) < minstamina):
            t = MenuStr("\n\nNothing to do here. [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                                      self.stamina, self.maxstamina,
                                                                      self.rupies))
            outqueue.put(t.get())
            outqueue.put("END")
            return False
        
        conn = ROBConn()
        # soup = conn.geturl('mypage', self.conn_session, send_session=self.session, send_viewer=self.viewer)
        
        # Emulate quest list presses
        t = MenuStr("\n\nEmulating quest list presses...")
        outqueue.put(t.get())
        conn.geturl('quest', self.conn_session, send_session=self.session, send_viewer=self.viewer)
        conn.geturl('quest/quest_list', self.conn_session, send_viewer=self.viewer)
        conn.geturl('quest/mission_list/{}'.format(quest.split('/')[0]), self.conn_session, send_viewer=self.viewer)
        
        # Grab peripherals only the first time (emulating browser back presses)
        first = True
        
        while (self.cards != self.maxcards) and (int(self.stamina) >= minstamina):
            # Before hitting the server for the flash, check for cancel signal
            try:
                if (inqueue.get(False) == "CANCEL"):
                    outqueue.put(MenuStr("Cancelled.").get())
                    outqueue.put("END")
                    return False
            except Queue.Empty:
                pass
            
            # Force a post
            soup = conn.geturl('smart_phone_flash/questConvert/{}'.format(quest), self.conn_session, get_peripherals=first, postdata='')
            first = False
            
            # No Stamina (safety; should not get called)
            if re.match('http://bahamut-n.cygames.jp/bahamut_n/quest/life_empty', conn.getreferer(self.viewer)):
                t = MenuStr("")
                t.add("No more stamina.")
                outqueue.put(t.get())
                outqueue.put("END")
                return False
            
            # Touch the quest flash
            url = re.findall(r"quest/play/{}\?flashParam=[0-9]*".format(quest), soup.encode(formatter=None))[0]
            conn.geturl(url, self.conn_session, extra_headers={'Referer': conn.getreferer(self.viewer)}, flash=True, spammy=True)

            self.update()
        
            t = MenuStr("^GQuest run^~. [C:{}/{} S:{}/{} R:{}]".format(self.cards, self.maxcards,
                                                                   self.stamina, self.maxstamina,
                                                                   self.rupies))
            outqueue.put(t.get())

        # Done
        t = MenuStr("")
        if (int(self.stamina) < minstamina):
            t.add("No more stamina.")
        elif (self.cards == self.maxcards):
            t.add("Card list full.")
        outqueue.put(t.get())
        outqueue.put("END")
        return True
Exemple #7
0
def com_char(client, arguments=None):
    engine = ROBEngine()

    # No arguments - show available characters
    if arguments is None:
        t = MenuStr()
        t.add("  Currently Available Characters:")
        t.add("  -------------------------------")
        chars = engine.getchars()
        if len(chars) == 0:
            t.add("    None")
            t.add()
        else:
            for x in chars:
                char = engine.getchar(x)
                if char.updating:
                    updating = "[Updating]"
                else:
                    updating = ""
                t.add("  ^G{:15}^~ ^R[^C{}^R]^~".format(char.name, char.agent))
                t.add(
                    "  ^gC:{:8} S:{:10} R:{:10}^~ ^r{}^~".format(
                        "{}/{}".format(char.cards, char.maxcards),
                        "{}/{}".format(char.stamina, char.maxstamina),
                        char.rupies,
                        updating,
                    )
                )
                t.add("  ^K?session_id={}&viewer_id={}^~".format(char.session, char.viewer))
                currtime = datetime.datetime.now()
                sincelogon = currtime - char.logontime
                slmin, slsec = divmod(sincelogon.seconds, 60)
                slhr, slmin = divmod(slmin, 60)
                slhr += sincelogon.days * 24
                slstr = "Logon: {:02d}:{:02d}:{:02d} ago".format(slhr, slmin, slsec)
                sinceupdate = currtime - char.lastupdatetime
                sumin, susec = divmod(sinceupdate.seconds, 60)
                suhr, sumin = divmod(sumin, 60)
                suhr += sinceupdate.days * 24
                sustr = "Updated: {:02d}:{:02d}:{:02d} ago".format(suhr, sumin, susec)
                t.add("  {:29}{}".format(slstr, sustr))
                numin, nusec = divmod(char.nextupdate.seconds, 60)
                nustr = "Auto-refresh in: {:02d}:{:02d}".format(numin, nusec)
                t.add("  {:29}".format(nustr))
                t.add()
        t.add("  ^cchar add [adb|<sessionstring>] [sensation|desire]^~ to add characters")
        t.add("  ^cchar delete <name>^~ to remove characters")
        t.add("  ^cchar update [all|<name>]^~ to update character stats")
        t.add("  ^cchar use <name>^~ to take control of a character")
        t.add("  ^cchar [save|load]^~ to save or load characters to/from disk")
        client.send_cc(t.get())
        return

    # Arguments passed. Expand
    # e.g. 'char add sensation adb'
    # 'char': command; 'add': arg1; 'sensation': arg2; etc.
    arg1list = ["add", "delete", "update", "use", "save", "load"]
    candidates, rawarg2 = expand(arguments, arg1list)
    if len(candidates) == 0:
        t = MenuStr()
        t.add("Possible options are:")
        t.add()
        t.add("  ^cchar add [adb|<sessionstring>] [sensation|desire]^~ to add characters")
        t.add("  ^cchar delete <name>^~ to remove characters")
        t.add("  ^cchar update [all|<name>]^~ to update character stats")
        t.add("  ^cchar use <name>^~ to take control of a character")
        t.add("  ^cchar [save|load]^~ to save or load characters to/from disk")
        client.send_cc(t.get())
        return
    elif len(candidates) > 1:
        t = MenuStr()
        t.add("The command ^cchar {}^~ was not specific enough. Did you mean:".format(arguments.split(None, 1)[0]))
        for x in candidates:
            t.add("  ^cchar {}^~".format(x))
        client.send_cc(t.get())
        return
    elif len(candidates) == 1:
        arg1 = candidates[0]

    # Got arg1

    # Add
    if arg1 == "add":
        # Need to parse for arg2(method) and arg3(device)
        # arg2 is taken without modification: it either matches 'adb' exactly, or is treated as a session string
        if rawarg2 is None:
            # No arg2 passed
            t = MenuStr()
            t.add("Possible options are:")
            t.add()
            t.add("  ^cchar add adb [sensation|desire]^~")
            t.add("  Look for recent sessions over ADB, use [sensation|desire] headers.")
            t.add()
            t.add("  ^cchar add <sessionstring> [sensation|desire]^~")
            t.add("  Add a character using <sessionstring>, use [sensation|desire] headers.")
            t.add("  (?session_id=<session>&viewer_id=<viewer>)")
            t.add()
            t.add("You must ensure the headers chosen match the device used to start the session.")
            client.send_cc(t.get())
            return

        rawarg2 = rawarg2.split(None, 1)
        arg2 = rawarg2[0]

        # Parse rawarg3
        if len(rawarg2) == 1:
            # No arg3 passed
            t = MenuStr()
            t.add("Possible options are:")
            t.add()
            if arg2 == "adb":
                t.add("  ^cchar add adb [sensation|desire]^~")
                t.add("  Look for recent sessions over ADB, use [sensation|desire] headers.")
            else:
                t.add("  ^cchar add <sessionstring> [sensation|desire]^~")
                t.add("  Add a character using <sessionstring>, use [sensation|desire] headers.")
                t.add("  (^K?session_id=<session>&viewer_id=<viewer>^~)")
            t.add()
            t.add("You must ensure the headers chosen match the device used to start the session.")
            client.send_cc(t.get())
            return

        rawarg3 = rawarg2[1]
        arg3list = ["sensation", "desire"]
        candidates = expand(rawarg3, arg3list)[0]
        if len(candidates) == 0 or len(candidates) > 1:
            t = MenuStr()
            t.add("Possible options are:")
            t.add()
            if arg2 == "adb":
                t.add("  ^cchar add adb [sensation|desire]^~")
                t.add("  Look for recent sessions over ADB, use [sensation|desire] headers.")
            else:
                t.add("  ^cchar add <sessionstring> [sensation|desire]^~")
                t.add("  Add a character using <sessionstring>, use [sensation|desire] headers.")
                t.add("  (^K?session_id=<session>&viewer_id=<viewer>^~)")
            t.add()
            t.add("You must ensure the headers chosen match the device used to start the session.")
            client.send_cc(t.get())
            return
        else:
            arg3 = candidates[0]

        # If we're still here, add a character using the options given
        t = engine.addchar(arg2, arg3)
        if t == "CANCELLED":
            client.send("Character add cancelled by server.\n")
        elif t == "FAILED":
            client.send("No recent sessions found over ADB.\n")
        elif t == "MAINTENANCE":
            client.send("ROB Servers undergoing maintenance.\n")
        else:
            client.send_cc("Successfully added [^G{}^~] with ^R[^C{}^R]^~ headers\n".format(t, arg3))
        return

    # Delete char
    if arg1 == "delete":
        if rawarg2 is None:
            # No arg2
            t = MenuStr()
            t.add("Possible options are:")
            t.add("  ^cchar delete <name>^~    - Remove a character from the character list")
            t.add()
            t.add("Available characters:")
            for x in engine.getchars():
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return

        # Parse arg2: a character name
        arg2list = []
        for x in engine.getchars():
            arg2list.append(x)
        candidates = expand(rawarg2, arg2list)[0]
        if len(candidates) == 0:
            t = MenuStr()
            t.add("No such character.  Choices are:")
            for x in arg2list:
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return
        else:
            arg2 = candidates[0]
            char = engine.getchar(arg2)
            if client.robin["char"] == char:
                client.robin["char"] = None
            engine.delchar(arg2)
            client.send_cc("Removed ^G{}^~ from character list.\n".format(char.name))
            return

    if arg1 == "update":
        # Parse arg2: either 'all' or a character name
        if rawarg2 is None:
            # No arg2
            t = MenuStr()
            t.add("Possible options are:")
            t.add("  ^cchar update all^~    - Manually update all characters (SLOW)")
            t.add("  ^cchar update <name>^~ - Manually update a character")
            t.add()
            t.add("Available characters:")
            for x in engine.getchars():
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return

        arg2list = ["all"]
        for x in engine.getchars():
            arg2list.append(x)
        candidates = expand(rawarg2, arg2list)[0]
        if len(candidates) == 0:
            t = MenuStr()
            """
            t.add("Possible options are:")
            t.add("  ^cchar update all^~    - Manually update all characters (SLOW)")
            t.add("  ^cchar update <name>^~ - Manually update a character")
            """
            t.add("No such character.  Choices are:")
            t.add("  ^call^~")
            for x in engine.getchars():
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return
        elif len(candidates) > 1:
            t = MenuStr()
            t.add(
                "The command ^cchar update {}^~ was not specific enough. Did you mean:".format(
                    rawarg2.split(None, 1)[0]
                )
            )
            for x in candidates:
                t.add("  ^cchar update {}^~".format(x))
            client.send_cc(t.get())
            return
        else:
            arg2 = candidates[0]
            if arg2 == "all":
                client.send("Not implemented. Please specify a character name.\n")
                return
            else:
                char = engine.getchar(arg2)
                char.update()
            client.send("Stats updated.\n")
            return

    if arg1 == "use":
        if rawarg2 is None:
            # No arg2
            t = MenuStr()
            t.add("Possible options are:")
            t.add("  ^cchar use <name>^~ - Take control of a character")
            t.add()
            t.add("Available characters:")
            for x in engine.getchars():
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return

        # Parse arg2: a character name
        arg2list = []
        for x in engine.getchars():
            arg2list.append(x)
        candidates = expand(rawarg2, arg2list)[0]
        if len(candidates) == 0:
            t = MenuStr()
            t.add("No such character.  Choices are:")
            for x in arg2list:
                t.add("  ^G{}^~".format(x))
            client.send_cc(t.get())
            return
        else:
            arg2 = candidates[0]
            char = engine.getchar(arg2)
            client.robin["char"] = char
            client.send_cc("Now controlling ^G{}^~.\n".format(char.name))
            return

    # Save/Load
    if arg1 == "save":
        engine.savechars()
        client.send("Characters saved.\n")
        return
    if arg1 == "load":
        t = engine.loadchars()
        client.send_cc(t)
        return
Exemple #8
0
def com_use(client, arguments=None):
    # No arguments
    if arguments is None:
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^cuse <name>^~ - Take control of a character")
        client.send_cc(t.get())
        return

    # Parse arg1: a character name
    engine = ROBEngine()
    arg1list = []
    for x in engine.getchars():
        arg1list.append(x)
    candidates = expand(arguments, arg1list)[0]
    if len(candidates) == 0:
        t = MenuStr()
        t.add("No such character.  Choices are:")
        for x in arg1list:
            t.add("  ^G{}^~".format(x))
        client.send_cc(t.get())
        return
    else:
        arg1 = candidates[0]
        char = engine.getchar(arg1)
        client.robin["char"] = char
        client.send_cc("Now controlling ^G{}^~.\n".format(char.name))
        return
Exemple #9
0
def com_sell(client, arguments=None):
    """
    Dispatches a thread to:
    Sell all farmed rupie cards
    """
    # Are we currently active?
    if client.robin["char"] is None:
        client.send("You need to activate a character first.\n")
        return

    # No arguments
    if arguments is None:
        """
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^csell start^~  - Start selling all rupie cards")
        t.add("  ^csell cancel^~ - Cancel current sale operation")
        client.send_cc(t.get())
        return
        """
        arguments = "start"

    # Parse arg1: either 'start' or 'cancel'
    arg1list = ["start", "cancel", "loop"]
    candidates = expand(arguments, arg1list)[0]
    if len(candidates) == 0 or len(candidates) > 1:
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^csell start^~  - Start selling all rupie cards")
        t.add("  ^csell cancel^~ - Cancel current sale operation")
        t.add("  ^csell loop^~   - Start Fill-Sell loop")
        client.send_cc(t.get())
        return

    arg1 = candidates[0]
    if arg1 == "start":
        # Make sure we aren't already running a dispatcher
        if "dispatcher" in client.robin:
            if client.robin["dispatcher"].is_alive():
                client.send_cc(MenuStr("You need to ^ccancel^~ any running commands first.").get())
                return

        client.send_cc("\n[Selling cards]\n")

        # DispatcherThread config
        # Preamble strings
        pre_console = "[{}] Selling cards...".format(client.robin["char"].name)
        # Worker thread
        work_target = client.robin["char"].sell
        work_extra_args = ()
        name = "[{}] Sell".format(client.robin["char"].name)

        client.robin["dispatcher"] = DispatcherThread(client, pre_console, work_target, work_extra_args, name)
        client.robin["dispatcher"].start()
    elif arg1 == "cancel":
        client.robin["dispatcher"].queue.put("CANCEL")
        client.send("Cancelling...")
    elif arg1 == "loop":
        # Make sure we aren't already running a dispatcher
        if "dispatcher" in client.robin:
            if client.robin["dispatcher"].is_alive():
                client.send_cc(MenuStr("You need to ^ccancel^~ any running commands first.").get())
                return

        client.send_cc("\n[Starting Fill-Sell Loop]\n")

        # DispatcherThread config
        # Preamble strings
        pre_console = "[{}] Fill-Sell loop...".format(client.robin["char"].name)
        # Worker thread
        work_target = client.robin["char"].loop_sell
        work_extra_args = ()
        name = "[{}] Fill-Sell".format(client.robin["char"].name)

        client.robin["dispatcher"] = DispatcherThread(client, pre_console, work_target, work_extra_args, name)
        client.robin["dispatcher"].start()
    return
Exemple #10
0
def com_score(client, arguments=None):
    char = client.robin["char"]

    # Prepare segments
    # Note that caret codes are counted as characters for format strings
    namestr = "[^G{}^~]".format(char.name)
    cardstr = "^C{}^~/^C{}^~".format(char.cards, char.maxcards)
    staminastr = "^R{}^~/^R{}^~".format(char.stamina, char.maxstamina)
    rupiesstr = "^Y{}^~".format(char.rupies)

    currtime = datetime.datetime.now()

    sincelogon = currtime - char.logontime
    slmin, slsec = divmod(sincelogon.seconds, 60)
    slhr, slmin = divmod(slmin, 60)
    slstr = "^K{:02d}^~:^K{:02d}^~:^K{:02d}^~ ago".format(slhr, slmin, slsec)

    sinceupdate = currtime - char.lastupdatetime
    sumin, susec = divmod(sinceupdate.seconds, 60)
    suhr, sumin = divmod(sumin, 60)
    sustr = "^K{:02d}^~:^K{:02d}^~:^K{:02d}^~ ago".format(suhr, sumin, susec)

    numin, nusec = divmod(char.nextupdate.seconds, 60)
    nustr = "   ^K{:02d}^~:^K{:02d}^~ min".format(numin, nusec)

    t = MenuStr()
    t.add("=" * 70)
    t.add()
    t.add("   [^KLv. {:>3}^~] ".format(char.level))
    t.add("   {:24} Device:       ^R[^C{}^R]^~".format(namestr, char.agent))
    t.add("   ^c?session_id={}&viewer_id={}^~".format(char.session, char.viewer))
    t.add()
    t.add("=" * 70)
    t.add()
    t.add("   Cards:    {:18} First logged on:   {}".format(cardstr, slstr))
    t.add("   Stamina:  {:18} Last updated:      {}".format(staminastr, sustr))
    t.add("   Rupies:   {:14} Auto-refresh in:   {}".format(rupiesstr, nustr))
    t.add()
    t.add("=" * 70)
    t.add()
    t.add("   ^GInbox^~:")
    t.add()
    for x in char.inbox:
        t.add("   {}".format(x[1]))
        t.add("   ^c{}^~".format(x[0]))
        t.add()

    client.send_cc(t.get())
Exemple #11
0
def com_look(client, arguments=None):
    t = MenuStr()
    t.add("[^CThe Core^~]")
    t.add()
    t.add("You are standing in a large, white room, empty save for a")
    t.add("small computer terminal that flickers to life as you approach,")
    t.add("as if beckoning you to give it a command.")
    client.send_cc(t.get())
    return
Exemple #12
0
def com_fill(client, arguments=None):
    """
    Dispatches a thread to:
    Fill current char's card storage with feeders, either rupies or enhancers
    """
    # Are we currently active?
    if client.robin["char"] is None:
        client.send("You need to activate a character first.\n")
        return

    # No arguments
    if arguments is None:
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^cfill enhancers^~ - Fill with cards from quest 2-5 (Best for enhancing)")
        t.add("  ^cfill rupies^~    - Fill with cards from quest 2-2 (Best for rupie farming)")
        t.add("  ^cfill cancel^~    - Cancel a fill in progress")
        client.send_cc(t.get())
        return

    # Parse arg1: either 'enhancers' or 'rupies' or 'cancel'
    arg1list = ["enhancers", "rupies", "cancel"]
    candidates = expand(arguments, arg1list)[0]
    if len(candidates) == 0 or len(candidates) > 1:
        t = MenuStr()
        t.add("Possible options are:")
        t.add("  ^cfill enhancers^~ - Fill with cards from quest 2-5 (Best for enhancing)")
        t.add("  ^cfill rupies^~    - Fill with cards from quest 2-2 (Best for rupie farming)")
        client.send_cc(t.get())
        return

    arg1 = candidates[0]
    if (arg1 == "enhancers") or (arg1 == "rupies"):
        if arg1 == "enhancers":
            quest = "2/5"
            minstamina = 3
        elif arg1 == "rupies":
            quest = "2/2"
            minstamina = 3

        # Make sure we aren't already running a dispatcher
        if "dispatcher" in client.robin:
            if client.robin["dispatcher"].is_alive():
                client.send_cc(MenuStr("You need to ^ccancel^~ any running commands first.").get())
                return

        client.send_cc("\n[Farming quest {}]\n".format(quest))

        # DispatcherThread config
        # Preamble strings
        pre_console = "[{}] Filling with {}...".format(client.robin["char"].name, quest)
        # Worker thread
        work_target = client.robin["char"].fillcards
        work_extra_args = (quest, minstamina)
        name = "[{}] Fill {}".format(client.robin["char"].name, quest)

        client.robin["dispatcher"] = DispatcherThread(client, pre_console, work_target, work_extra_args, name)
        client.robin["dispatcher"].start()
    elif arg1 == "cancel":
        client.robin["dispatcher"].queue.put("CANCEL")
        client.send("Cancelling...")
    return
Exemple #13
0
def com_colour(client, arguments=None):
    """
    Send sample colour table to client
    """
    t = MenuStr()
    t.add("Colours:")
    t.add("  ^^k   = ^kblack^~")
    t.add("  ^^K   = ^Kbold black (grey)^~")
    t.add("  ^^r   = ^rred^~")
    t.add("  ^^R   = ^Rbold red^~")
    t.add("  ^^g   = ^ggreen^~")
    t.add("  ^^G   = ^Gbold green^~")
    t.add("  ^^y   = ^yyellow^~")
    t.add("  ^^Y   = ^Ybold yellow^~")
    t.add("  ^^b   = ^bblue^~")
    t.add("  ^^B   = ^Bbold blue^~")
    t.add("  ^^m   = ^mmagenta^~")
    t.add("  ^^M   = ^Mbold magenta^~")
    t.add("  ^^c   = ^ccyan^~")
    t.add("  ^^C   = ^Cbold cyan^~")
    t.add("  ^^w   = ^wwhite^~")
    t.add("  ^^W   = ^Wbold white^~")
    t.add("  ^^!   = ^!bold on (use within a block of non-bright text)^~")
    t.add("  ^^.   = ^.bold off^~")
    t.add("  ^^d   = ^ddefault text colors, varies by client^~")
    t.add("  ^^0   = ^0black background^~")
    t.add("  ^^1   = ^1red background^~")
    t.add("  ^^2   = ^2green background^~")
    t.add("  ^^3   = ^3yellow background^~")
    t.add("  ^^4   = ^4blue background^~")
    t.add("  ^^5   = ^5magenta background^~")
    t.add("  ^^6   = ^6cyan background^~")
    t.add("  ^^I   = ^Iinverse text on^~")
    t.add("  ^^i   = ^iinverse text off^~")
    t.add("  ^^~   = ^~reset all^~")
    t.add("  ^^U   = ^Uunderline on^~")
    t.add("  ^^u   = ^uunderline off^~")
    t.add("  ^^^^   = escape a caret, ^^^^r = ^^r^~")
    client.send_cc(t.get())
    return