def fetch_list(self): """Queries the full list from the remote server. Returns the list if successful, False otherwise.""" self.check_credentials() self.msg.info(self.name, 'Downloading list...') try: # Get an XML list from MyAnimeList API data = self._request_gzip( "http://myanimelist.net/malappinfo.php?u=" + self.username + "&status=all&type=" + self.mediatype) # Parse the XML data and load it into a dictionary # using the proper function (anime or manga) root = ET.ElementTree().parse(data, parser=self._make_parser()) if self.mediatype == 'anime': self.msg.info(self.name, 'Parsing anime list...') return self._parse_anime(root) elif self.mediatype == 'manga': self.msg.info(self.name, 'Parsing manga list...') return self._parse_manga(root) else: raise utils.APIFatal( 'Attempted to parse unsupported media type.') except urllib2.HTTPError, e: raise utils.APIError("Error getting list.")
def _sendcmd(self, cmd, options=None): """Send a VNDB compatible command and return the response data""" msg = cmd if options: msg += " " + json.dumps(options, separators=(',', ':')) msg += "\x04" # EOT # Send message self.s.sendall(msg) # Construct response lines = [] while True: line = self.s.recv(65536) if line.endswith("\x04"): line = line.strip("\x04") lines.append(line) response = "".join(lines) break else: lines.append(line) # Separate into response name and JSON data _resp = response.split(' ', 1) name = _resp[0] try: data = json.loads(_resp[1]) except IndexError: data = None # Treat error as an exception if name == 'error': raise utils.APIError(data['msg']) return (name, data)
def _connect(self): """Create TCP socket and connect""" try: self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.connect(("api.vndb.org", 19534)) except socket.error: raise utils.APIError("Connection error.")
def delete_show(self, item): self.check_credentials() self.msg.info(self.name, 'Deleting VN %s...' % item['title']) (name, data) = self._sendcmd('set %s %d' % (self.mediatype, item['id'])) if name != 'ok': raise utils.APIError("Invalid response (%s)" % name)
def delete_show(self, item): """Sends a show delete to the server""" self.check_credentials() self.msg.info(self.name, "Deleting show %s..." % item['title']) try: self._request( 'DELETE', "http://mal-api.com/%slist/%s/%d" % (self.mediatype, self.mediatype, item['id'])) return True except urllib2.HTTPError, e: raise utils.APIError('Error deleting: ' + str(e.code))
def delete_show(self, item): """Sends a show delete to the server""" self.check_credentials() self.msg.info(self.name, "Deleting show %s..." % item['title']) try: response = self.opener.open("http://myanimelist.net/api/" + self.mediatype + "list/delete/" + str(item['id']) + ".xml") return True except urllib2.HTTPError, e: raise utils.APIError('Error deleting: ' + str(e.code))
def update_show(self, item): """Sends a show update to the server""" self.check_credentials() self.msg.info(self.name, "Updating show %s..." % item['title']) data = self._build_data(item) try: self._request( 'PUT', "http://mal-api.com/%slist/%s/%d" % (self.mediatype, self.mediatype, item['id']), data) return True except urllib2.HTTPError, e: raise utils.APIError('Error updating: ' + str(e.code))
def check_credentials(self): """Checks if credentials are correct; returns True or False.""" if self.logged_in: return True # Already logged in self.msg.info(self.name, 'Logging in...') try: response = self._request( "http://myanimelist.net/api/account/verify_credentials.xml") self.logged_in = True return True except urllib2.HTTPError, e: raise utils.APIError("Incorrect credentials.")
def _request_gzip(self, url): """ Requests the page as gzip and uncompresses it Returns a stream object """ try: request = urllib2.Request(url) request.add_header('Accept-encoding', 'gzip') compressed_data = self.opener.open(request).read() except urllib2.URLError, e: raise utils.APIError("Connection error: %s" % e)
def add_show(self, item): """Adds a new show in the server""" self.check_credentials() self.msg.info(self.name, "Adding show %s..." % item['title']) data = self._build_data(item, True) try: # POST request self.opener.open( "http://mal-api.com/%slist/%s" % (self.mediatype, self.mediatype), data) return True except urllib2.HTTPError, e: raise utils.APIError('Error adding: ' + str(e.code))
def update_show(self, item): self.check_credentials() # Update status with set vnlist if 'my_status' in item.keys(): self.msg.info(self.name, 'Updating VN %s (status)...' % item['title']) if self.mediatype == 'wishlist': values = {'priority': item['my_status']} else: values = {'status': item['my_status']} (name, data) = self._sendcmd('set %s %d' % (self.mediatype, item['id']), values) if name != 'ok': raise utils.APIError("Invalid response (%s)" % name) # Update vote with set votelist if 'my_score' in item.keys(): self.msg.info(self.name, 'Updating VN %s (vote)...' % item['title']) if item['my_score'] > 0: # Add or update vote values = {'vote': item['my_score'] * 10} else: # Delete vote if it's 0 values = None (name, data) = self._sendcmd('set votelist %d' % item['id'], values) if name != 'ok': raise utils.APIError("Invalid response (%s)" % name)
def check_credentials(self): self.msg.info(self.name, 'Logging in...') try: response = self.opener.open( "http://melative.com/api/account/verify_credentials.json") self.logged_in = True # Parse user information data = json.load(response) self.username = data['name'] self.userid = data['id'] return True except urllib2.HTTPError, e: raise utils.APIError("Incorrect credentials.")
def update_show(self, item): """Sends a show update to the server""" self.check_credentials() self.msg.info(self.name, "Updating show %s..." % item['title']) xml = self._build_xml(item) # Send the XML as POST data to the MyAnimeList API values = {'data': xml} data = self._urlencode(values) try: response = self.opener.open( "http://myanimelist.net/api/" + self.mediatype + "list/update/" + str(item['id']) + ".xml", data) return True except urllib2.HTTPError, e: raise utils.APIError('Error updating: ' + str(e.code))
def check_credentials(self): """Checks if credentials are correct; returns True or False.""" # This shit never works, let's just continue # If credentials are wrong it'll return an unauthorized error # later return True if self.logged_in: return True # Already logged in self.msg.info(self.name, 'Logging in...') try: response = self.opener.open( "http://mal-api.com/account/verify_credentials") self.logged_in = True return True except urllib2.HTTPError, e: raise utils.APIError("Incorrect credentials.")
def fetch_list(self): """Queries the full list from the remote server. Returns the list if successful, False otherwise.""" self.check_credentials() self.msg.info(self.name, 'Downloading list...') try: # Get an XML list from MyAnimeList API response = self.opener.open("http://mal-api.com/%slist/%s" % (self.mediatype, self.username)) data = json.load(response) if self.mediatype == 'anime': self.msg.info(self.name, 'Parsing anime list...') return self._parse_anime(data) elif self.mediatype == 'manga': self.msg.info(self.name, 'Parsing manga list...') return self._parse_manga(data) else: raise utils.APIFatal( 'Attempted to parse unsupported media type.') except urllib2.HTTPError, e: raise utils.APIError("Error getting list.")
def _request(self, url): try: return self.opener.open(url, timeout=10) except urllib2.URLError, e: raise utils.APIError("Connection error: %s" % e)