Ejemplo n.º 1
0
 def savechars(self):
     '''
     Saves current characters to file
     '''
     console = ConsoleEngine()
     t = console.logtask("Saving character sessions to file...")
     
     with self.filelock:
         # Locks cannot be pickled, so prepare a lockless (shallow) copy
         charcopy = {}
         for x in self.getchars():
             char = self.chars[x]
             # Acquire all char locks while we rig up conn_session
             char.lock.acquire()
             charcopy[char.name] = copy.copy(char)
             charcopy[char.name].lock = None
             # Hack conn_session into existence
             charcopy[char.name].conn_session.__attrs__.append('robin')
         if (os.path.exists(Config.charsave)):
             # Make a backup of previous save
             shutil.copy(Config.charsave, Config.charsave + ".bak")
         f = open(Config.charsave, 'w')
         pickle.dump(charcopy, f)
         f.close()
         
         # Undo our conn_session rigging so that it can be used properly again
         for x in self.getchars():
             self.chars[x].conn_session.__attrs__.remove('robin')
             self.chars[x].lock.release()
         console.logstatus(t, "[OK]")
Ejemplo n.º 2
0
    def addchar(self, option, agent):
        if (option.lower() == "adb"):
            console = ConsoleEngine()
            t = console.logtask("Character add from ADB requested... (Ctrl-C cancels)")
            
            try :
                f = os.popen("adb -d logcat -d")
                d = f.read()
                c = re.findall(r"session_id=[a-z0-9]*&viewer_id=[0-9]*", d)
                c.reverse()
            except KeyboardInterrupt:
                console.logstatus(t, "[CANCELLED]")
                return "CANCELLED"

            if (len(c) == 0):
                console.logstatus(t, "[FAILED]")
                return "FAILED"
            else:
                rawsess = c[0]
                console.logstatus(t, "[OK]")
        else:
            rawsess = option
            
        rawsess = rawsess.split("&")
        session = rawsess[0].split("=")[1].strip()
        viewer = rawsess[1].split("=")[1].strip()
        
        char = ROBChar(session, viewer, agent)
        
        # If under maintenance
        if self.conn.maintenance:
            return "MAINTENANCE"
        else:
            self.chars[char.name] = char
            return char.name
Ejemplo n.º 3
0
 def update(self):
     with self.lock:            
         conn = ROBConn()
         console = ConsoleEngine()
         
         t = console.logtask("Updating stats for [{}]".format(self.name))
         self.updating = True
         
         # When doing arbitrary updates, emulate navbar press (i.e. send session)
         soup = conn.geturl('mypage', self.conn_session, send_session=self.session, send_viewer=self.viewer)
         soup = self.handlewelcome(soup)
         
         # Hmm. We only need to do this once, really.
         self.name = soup.find("div", "area_name").get_text().strip()
         self.conn_session.robin['name'] = self.name
         
         # Stats
         rawcards = soup.find("a", text="Cards").parent.find_next_sibling().get_text().split("/")
         self.cards = int(rawcards[0])
         self.maxcards = int(rawcards[1])
         
         self.rupies = soup.find('span', text=re.compile("Rupies:")).parent.find_next_sibling().get_text()
         self.rupies = int(self.rupies)
 
         rawstam = soup.find(text=re.compile("STAMINA:")).parent.span.get_text().strip().split("/")
         self.stamina = int(rawstam[0])
         self.maxstamina = int(rawstam[1])
         
         # Level and attribute points
         rawlevel = soup.find(text=re.compile("LVL:")).find_parent().span.get_text().strip()
         rawlevel = re.match("([0-9]*)(\(([0-9]*)\))?", rawlevel)
         self.level = int(rawlevel.group(1))
         if (rawlevel.group(3) is not None):
             self.points = int(rawlevel.group(3))
         else:
             self.points = 0
         
         # Scrape Inbox
         inboxlinks = soup.find(text=re.compile(r'Inbox(?! \()')).parent.find_next_sibling().find_all("a")
         self.inbox = [(re.match("http://bahamut-n.cygames.jp/bahamut_n/(.*)", x['href']).group(1), x.get_text()) for x in inboxlinks]
         
         self.updating = False
         self.lastupdatetime = datetime.datetime.now()
         # Set next update anywhere between 10mins and 90mins
         self.nextupdate = datetime.timedelta(seconds=(random.randint(10, 90) * 60))
         
         console.logstatus(t, "[OK]")
Ejemplo n.º 4
0
    def _dispatcher_run(self, pre_console, work_target, work_extra_args):
        # Preamble
        console = ConsoleEngine()
        console.log("== Started: " + pre_console)

        # Start the actual worker thread
        work_args = (self.queue, self.workerqueue)
        work_args += work_extra_args
        self.worker = threading.Thread(target=work_target, args=work_args)
        self.worker.start()

        # Process output
        t = self.queue.get(True)
        while t != "END":
            if t == "CANCEL":
                self.workerqueue.put("CANCEL")
                t = self.queue.get(True)
                console.log("-- Cancelled: " + pre_console)
                self.cancelled = True
                continue

            self.client.send_cc(t)
            t = self.queue.get(True)

        # We made it
        if not self.cancelled:
            console.log("== Done: " + pre_console)
        # Hackity hack up a sendprompt()
        from telnet import TelnetEngine

        telnet = TelnetEngine()
        telnet.sendprompt(self.client)
Ejemplo n.º 5
0
    def geturl(self, url, conn_session, send_session=None, send_viewer=None, get_peripherals=True, 
               postdata=None, extra_headers={}, flash=False, spammy=False):
        '''
        Makes a request to the ROB servers.
        Will not honour requests that have no user-agent, or are made with an expired session
        
        @keyword url: The url to request, relative to the ROB host
        @keyword conn_session: The requests session associated with a character
        @keyword send_session: The character session string to send, None if not needed
        @keyword send_viewer: The character viewer string to send, None if not needed
        @keyword get_peripherals: Should we parse for and request CSS and images? 
        @keyword postdata: Data to send with POST requests
        @keyword extra_headers: Dictionary of extra headers to send
        @keyword flash: Is the target a flash file?
        @keyword spammy: Is the request a spammy one?
        '''
        console = ConsoleEngine()
        
        # Extract viewer from conn_session for our internal use even if send_viewer is None
        id_viewer = conn_session.robin['viewer']
        
        # Make sure that unclean shutdowns etc don't interfere with our request
        if 'robin' in conn_session.__attrs__:
            conn_session.__attrs__.remove('robin')
        
        # Prepare url
        finalurl = StringIO()
        finalurl.write('http://bahamut-n.cygames.jp/bahamut_n/')
        finalurl.write(url)
        if (send_session or send_viewer):
            finalurl.write('?')
        if (send_session):
            finalurl.write('session_id={}'.format(send_session))
            if (send_viewer):
                finalurl.write('&')
        if (send_viewer):
            finalurl.write('viewer_id={}'.format(send_viewer))
        url = finalurl.getvalue()
        
        if (flash):
            extra_headers['Accept'] = None
            
        # Check if user-agent is set
        uafound = False
        for x in conn_session.headers.keys():
            if (x.lower() == "user-agent"):
                uafound = True
        for x in extra_headers.keys():
            if (x.lower() == "user-agent"):
                uafound = True
        if not uafound:
            console.log("** ERROR: User-Agent not set properly for [{}]!".format(conn_session.robin['name']))
            return -1
        
        # Check if session has expired
        if conn_session.robin['expired']:
            console.log("** ERROR: Session for [{}] is expired!".format(conn_session.robin['name']))
            return -2
        
        # Perform actual request
        # Get spamlock first
        self.spamlock.acquire()
        
        # allow_redirects=False cannot be included with session so must be included here 
        if (postdata is not None):
            if (postdata == ''):
                # No form data, but we need to add headers
                extra_headers['Content-Length'] = '0'
                extra_headers['Content-Type'] = "application/x-www-form-urlencoded"
            self.lastresponse[id_viewer] = conn_session.post(url,
                                                               headers=extra_headers,
                                                               allow_redirects=False,
                                                               data=postdata)
        else:
            self.lastresponse[id_viewer] = conn_session.get(url,
                                                              headers=extra_headers,
                                                              allow_redirects=False)
        
        # Handle redirects properly, stripping custom headers etc
        while(self.lastresponse[id_viewer].status_code == 302):
            self.lastresponse[id_viewer] = conn_session.get(self.lastresponse[id_viewer].headers['Location'],
                                                              allow_redirects=False,
                                                              params={'viewer_id': id_viewer})
        
        # If spammy, set time-release. If not, release now
        if spammy:
            t = threading.Timer(Config.spaminterval, self._spamrelease)
            t.name = "SpamLock"
            t.daemon = True
            t.start()
        else:
            self.spamlock.release() 
            
        # Is ROB under maintenance
        if "/maintenance" in self.lastresponse[id_viewer].url:
            self.maintenance = True
        else:
            self.maintenance = False
            
        # Is the current session expired
        if "_reauthorize" in self.lastresponse[id_viewer].url:
            conn_session.robin['expired'] = True
            console.log("** ERROR: Session for [{}] is expired!".format(conn_session.robin['name']))
            return -2
        
        # If touching a flash file, we're done
        if (flash):
            return
        
        # Read server response and grab peripherals if needed
        soup = BeautifulSoup(self.lastresponse[id_viewer].text,'lxml')

        # Parse for peripheral items to retrieve
        if (get_peripherals):
            self.getperipherals(conn_session, soup, referer=self.lastresponse[id_viewer].url)

        return soup
Ejemplo n.º 6
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()
Ejemplo n.º 7
0
 def __init__(self, session, viewer, agent):
     '''
     Initializes cookies, auto-refresh
     '''
     conn = ROBConn()
     console = ConsoleEngine()
     
     self.conn_session = conn.getnewsession(agent)
     self.agent = agent
     self.session = session
     self.viewer = viewer
     self.name = "<new>"
     
     # Ride on conn_session with some of our own data
     self.conn_session.robin = {}
     self.conn_session.robin['name'] = self.name
     self.conn_session.robin['expired'] = False
     self.conn_session.robin['viewer'] = self.viewer
     
     # Lock whenever modifications are being made
     self.lock = threading.Lock()
     
     # 1. Call ROB homepage to initialize cookies
     t = console.logtask("Initializing cookies for new character...")
     conn.geturl('', self.conn_session, send_session=self.session, send_viewer=self.viewer)
     self.logontime = datetime.datetime.now()
     
     if conn.maintenance:
         console.logstatus(t, "[MAINTENANCE]")
         return
     else:
         console.logstatus(t, "[OK]")
     
     # 2. Scrape 'My Page', check for welcome event
     t = console.logtask("Retrieving character stats...")
     self.update()
     console.logstatus(t, "[OK]")
     console.log("== New character: [{}] ({})".format(self.name, self.agent))