async def get_pack_ids(self, pack_id, token): if self.site == 'tmnext': url = '{base}/api/mappack/get_mappack_tracks/{id}?token={token}'.format( base=self.base_url(), id=pack_id, token=token) else: url = '{base}/api/mappack/get_tracks/{id}?token={token}'.format( base=self.base_url(), id=pack_id, token=token) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map pack not found!') if response.status < 200 or response.status > 399: raise MXInvalidResponse( 'Got invalid response status from ManiaExchange: {}'.format( response.status)) maps = list() if response.content_length > 0: for info in await response.json(): # Parse some differences between the api game endpoints. mx_id = info['TrackID'] maps.append((mx_id, info)) return maps else: raise MXMapNotFound("Mx returned with empty response.")
async def search_pack(self, options, **kwargs): if options is None: options = dict() if self.key: options['key'] = self.key options['api'] = 'on' url = '{}/mappacksearch/search'.format(self.base_url()) response = await self.session.get(url, params=options) if response.status == 404: raise MXMapNotFound('Got not found status from ManiaExchange: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) maps = list() json = await response.json() if not 'results' in json: return list() for info in json['results']: # Parse some differences between the api game endpoints. maps.append(info) return maps
async def search(self, options, **kwargs): if options is None: options = { "api": "on", "mode": 0, "style": 0, "order": -1, "length": -1, "page": 0, "gv": 1, "limit": 150 } if self.key: options['key'] = self.key url = '{}/tracksearch2/search'.format(self.base_url()) response = await self.session.get(url, params=options) if response.status == 404: raise MXMapNotFound('Got not found status from ManiaExchange: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) maps = [] json = await response.json() for info in json['results']: # Parse some differences between the api game endpoints. mx_id = info['TrackID'] if 'TrackID' in info else info['MapID'] info['MapID'] = mx_id info['MapUID'] = info['TrackUID'] if 'TrackUID' in info else info['MapUID'] maps.append(info) return maps
async def map_info_page(self, *ids): if self.site != 'sm': url = '{base}/maps/get_map_info/multi/{ids}'.format( base=self.base_url(True), ids=','.join(str(i) for i in ids[0]) ) else: url = '{base}/maps/{ids}'.format( base=self.base_url(True), ids=','.join(str(i) for i in ids[0]) ) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status == 302: raise MXInvalidResponse('Map author has declined info for the map. Status code: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) maps = [] for info in await response.json(): # Parse some differences between the api game endpoints. mx_id = info['TrackID'] if 'TrackID' in info else info['MapID'] info['MapID'] = mx_id info['MapUID'] = info['TrackUID'] if 'TrackUID' in info else info['MapUID'] maps.append((mx_id, info)) return maps
async def do_search(self, trackname=None, authorname=None, refresh=True, **terms): try: options = { "api": "on", "mode": 0, "gv": 1, "limit": 100, "tpack": self.app.instance.game.dedicated_title.split("@", 1)[0] } if trackname is not None: options['trackname'] = trackname if authorname is not None: options['anyauthor'] = authorname infos = await self.api.search(options) if len(infos) == 0: raise MXMapNotFound("No results for search") except MXMapNotFound as e: message = '$f00Error requesting {}-API: Map not found!'.format(self.app.site_short_name) await self.app.instance.chat(message, self.player) logger.debug('{}-API: Map not found: {}'.format(self.app.site_short_name, str(e))) return None except MXInvalidResponse as e: message = '$f00Error requesting {}-API: Got an invalid response!'.format(self.app.site_short_name) await self.app.instance.chat(message, self.player) logger.warning('{}-API: Invalid response: {}'.format(self.app.site_short_name, str(e))) return None if self.app.instance.game.game in ['tm', 'tmnext']: self.cache = [dict( mxid=_map['TrackID'], name=_map['Name'], gbxname=_map['GbxMapName'] if _map['GbxMapName'] != '?' else _map['Name'], author=_map['Username'], envir=_map['EnvironmentName'], awards='$fff🏆 {}'.format(_map['AwardCount']) if _map['AwardCount'] > 0 else "", length=_map['LengthName'], difficulty=_map['DifficultyName'], maptype=_map['MapType'], style=_map['StyleName'] ) for _map in infos] else: self.cache = [dict( mxid=_map['TrackID'], name=_map['Name'], gbxname=_map['GbxMapName'] if _map['GbxMapName'] != '?' else _map['Name'], author=_map['Username'], envir=_map['EnvironmentName'], awards='$fff🏆 {}'.format(_map['AwardCount']) if _map['AwardCount'] > 0 else "", difficulty=_map['DifficultyName'], maptype=_map['MapType'], style=_map['StyleName'] ) for _map in infos] if refresh: await self.refresh(self.player)
async def map_offline_record(self, trackid): url = '{base}/replays/get_replays/{id}/1'.format(base=self.base_url(True), id=trackid) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status == 302: raise MXInvalidResponse('Map author has declined info for the map. Status code: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) return [info for info in await response.json()]
async def download(self, mx_id): url = 'https://{site}.mania-exchange.com/tracks/download/{id}'.format( site=self.site, id=mx_id, ) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) return response
async def map_offline_records(self, trackid): url = '{base}/replays/get_replays/{id}/10'.format(base=self.base_url(True), id=trackid) response = await self.session.get(url) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status == 302: raise MXInvalidResponse('Map author has declined info for the map. Status code: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) record = [] for info in await response.json(): print(info) record.append((info)) return record
async def download(self, mx_id): url = '{base}/maps/download/{id}'.format( base=self.base_url(), id=mx_id, ) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status == 302: raise MXInvalidResponse( 'Map author has declined download of the map. Status code: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) return response
async def do_search(self, name=None, username=None, refresh=True, **terms): try: options = { "api": "on", "mode": 0, "limit": 100, } if name is not None: options['name'] = name if username is not None: options['username'] = username infos = await self.api.search_pack(options) if len(infos) == 0: raise MXMapNotFound("No results for search") except MXMapNotFound as e: message = '$f00Error requesting {}-API: Map not found!'.format( self.app.site_short_name) await self.app.instance.chat(message, self.player) logger.debug('{}-API: Map not found: {}'.format( self.app.site_short_name, str(e))) return None except MXInvalidResponse as e: message = '$f00Error requesting {}-API: Got an invalid response!'.format( self.app.site_short_name) await self.app.instance.chat(message, self.player) logger.warning('{}-API: Invalid response: {}'.format( self.app.site_short_name, str(e))) return None self.cache = [ dict(mxid=_map['ID'], name=_map['Name'], author=_map['Username'], mapcount=_map['TrackCount'], typename=_map['TypeName'], style=_map['StyleName'], videourl="$l[{video}]Video$l".format(video=_map['VideoURL']) if len(_map['VideoURL']) > 0 else "", unreleased='{}'.format(_map['Unreleased']), request='{}'.format(_map['Request'])) for _map in infos ] if refresh: await self.refresh(self.player)
async def pack_info(self, id, token): url = '{base}/api/mappack/get_info/{id}?token={token}&secret={token}'.format( base=self.base_url(), id=id, token=token ) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status == 302: raise MXInvalidResponse('Map author has declined info for the map. Status code: {}'.format(response.status)) if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) return response.json()
async def map_info(self, *ids): url = 'https://api.mania-exchange.com/{site}/maps/{ids}'.format( site=self.site, ids=','.join(ids) ) params = {'key': self.key} if self.key else {} response = await self.session.get(url, params=params) if response.status == 404: raise MXMapNotFound('Map has not been found!') if response.status < 200 or response.status > 399: raise MXInvalidResponse('Got invalid response status from ManiaExchange: {}'.format(response.status)) maps = list() for info in await response.json(): # Parse some differences between the api game endpoints. mx_id = info['TrackID'] if 'TrackID' in info else info['MapID'] info['MapID'] = mx_id info['MapUID'] = info['TrackUID'] if 'TrackUID' in info else info['MapUID'] maps.append((mx_id, info)) return maps
async def add_mx_map(self, player, data, **kwargs): # Make sure we update the key in the api. self.api.key = await self.setting_mx_key.get_value() # Prepare and fetch information about the maps from MX. mx_ids = data.maps try: infos = await self.api.map_info(*mx_ids) if len(infos) == 0: raise MXMapNotFound() except MXMapNotFound: message = '$f00Error: Can\'t add map from MX. Map not found on ManiaExchange!' await self.instance.chat(message, player) return except MXInvalidResponse as e: message = '$f00Error: Got invalid response from ManiaExchange: {}'.format( str(e)) await self.instance.chat(message, player.login) return try: if not await self.instance.storage.driver.exists( os.path.join('UserData', 'Maps', 'PyPlanet-MX')): await self.instance.storage.driver.mkdir( os.path.join('UserData', 'Maps', 'PyPlanet-MX')) except Exception as e: message = '$f00Error: Can\'t check or create folder: {}'.format( str(e)) await self.instance.chat(message, player.login) return # Fetch setting if juke after adding is enabled. juke_after_adding = await self.instance.setting_manager.get_setting( 'admin', 'juke_after_adding', prefetch_values=True) juke_maps = await juke_after_adding.get_value() if 'jukebox' not in self.instance.apps.apps: juke_maps = False juke_list = list() for mx_id, mx_info in infos: if 'Name' not in mx_info: continue try: # Test if map isn't yet in our current map list. if self.instance.map_manager.playlist_has_map( mx_info['MapUID']): raise Exception( 'Map already in playlist! Update? remove it first!') # Download file + save resp = await self.api.download(mx_id) map_filename = os.path.join( 'PyPlanet-MX', '{}-{}.Map.Gbx'.format(self.instance.game.game.upper(), mx_id)) async with self.instance.storage.open_map(map_filename, 'wb+') as map_file: await map_file.write(await resp.read()) await map_file.close() # Insert map to server. result = await self.instance.map_manager.add_map( map_filename, save_matchsettings=False) if result: # Juke if setting has been provided. if juke_maps: juke_list.append(mx_info['MapUID']) message = '$ff0Admin $fff{}$z$s$ff0 has added{} the map $fff{}$z$s$ff0 by $fff{}$z$s$ff0 from MX..'.format( player.nickname, ' and juked' if juke_maps else '', mx_info['Name'], mx_info['Username']) await self.instance.chat(message) else: raise Exception('Unknown error while adding the map!') except Exception as e: logger.warning( 'Error when player {} was adding map from mx: {}'.format( player.login, str(e))) message = '$ff0Error: Can\'t add map {}, Error: {}'.format( mx_info['Name'], str(e)) await self.instance.chat(message, player.login) # Save match settings after inserting maps. try: await self.instance.map_manager.save_matchsettings() except: pass # Reindex and create maps in database. try: await self.instance.map_manager.update_list(full_update=True) except: pass # Jukebox all the maps requested, in order. if juke_maps and len(juke_list) > 0: # Fetch map objects. for juke_uid in juke_list: map_instance = await self.instance.map_manager.get_map( uid=juke_uid) if map_instance: self.instance.apps.apps['jukebox'].insert_map( player, map_instance)
async def add_mx_map(self, player, data, **kwargs): # Make sure we update the key in the api. self.api.key = await self.setting_mx_key.get_value() # Prepare and fetch information about the maps from MX. mx_ids = data.maps try: infos = await self.api.map_info(*mx_ids) if len(infos) == 0: raise MXMapNotFound() except MXMapNotFound: message = '$ff0Error: Can\'t add map from MX. Map not found on ManiaExchange!' await self.instance.chat(message, player) return except MXInvalidResponse as e: message = '$ff0Error: Got invalid response from ManiaExchange: {}'.format( str(e)) await self.instance.chat(message, player.login) return try: if not await self.instance.storage.driver.exists( os.path.join('UserData', 'Maps', 'PyPlanet-MX')): await self.instance.storage.driver.mkdir( os.path.join('UserData', 'Maps', 'PyPlanet-MX')) except Exception as e: message = '$ff0Error: Can\'t check or create folder: {}'.format( str(e)) await self.instance.chat(message, player.login) return for mx_id, mx_info in infos: if 'Name' not in mx_info: continue try: # Test if map isn't yet in our current map list. if self.instance.map_manager.playlist_has_map( mx_info['MapUID']): raise Exception( 'Map already in playlist! Update? remove it first!') # Download file + save resp = await self.api.download(mx_id) map_filename = os.path.join( 'PyPlanet-MX', '{}-{}.Map.Gbx'.format(self.instance.game.game.upper(), mx_id)) async with self.instance.storage.open_map(map_filename, 'wb+') as map_file: await map_file.write(await resp.read()) await map_file.close() # Insert map to server. result = await self.instance.map_manager.add_map(map_filename) if result: message = '$ff0Admin $fff{}$z$s$ff0 has added the map $fff{}$z$s$ff0 by $fff{}$z$s$ff0 from MX..'.format( player.nickname, mx_info['Name'], mx_info['Username']) await self.instance.chat(message) else: raise Exception('Unknown error while adding the map!') except Exception as e: logger.warning( 'Error when player {} was adding map from mx: {}'.format( player.login, str(e))) message = '$ff0Error: Can\'t add map {}, Error: {}'.format( mx_info['Name'], str(e)) await self.instance.chat(message, player.login)