mirror of
https://github.com/DragonMinded/bemaniutils.git
synced 2026-08-02 08:12:51 -05:00
212 lines
8.8 KiB
Python
Executable File
212 lines
8.8 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
import argparse
|
|
import json
|
|
import requests
|
|
import sys
|
|
from typing import Dict, List, Any, Optional
|
|
|
|
|
|
class APIClient:
|
|
API_VERSION = 'v1'
|
|
|
|
def __init__(self, base_uri: str, token: str) -> None:
|
|
self.base_uri = base_uri
|
|
self.token = token
|
|
|
|
def exchange_data(self, request_uri: str, request_args: Dict[str, Any]) -> Dict[str, Any]:
|
|
if self.base_uri[-1:] != '/':
|
|
uri = '{}/{}'.format(self.base_uri, request_uri)
|
|
else:
|
|
uri = '{}{}'.format(self.base_uri, request_uri)
|
|
|
|
headers = {
|
|
'Authorization': 'Token {}'.format(self.token),
|
|
'Content-Type': 'application/json; charset=utf-8',
|
|
}
|
|
data = json.dumps(request_args).encode('utf8')
|
|
|
|
r = requests.request(
|
|
'GET',
|
|
uri,
|
|
headers=headers,
|
|
data=data,
|
|
allow_redirects=False,
|
|
)
|
|
|
|
if r.headers['content-type'] != 'application/json; charset=utf-8':
|
|
raise Exception('API returned invalid content type \'{}\'!'.format(r.headers['content-type']))
|
|
|
|
jsondata = r.json()
|
|
|
|
if r.status_code == 200:
|
|
return jsondata
|
|
|
|
if 'error' not in jsondata:
|
|
raise Exception('API returned error code {} but did not include \'error\' attribute in response JSON!'.format(r.status_code))
|
|
error = jsondata['error']
|
|
|
|
if r.status_code == 401:
|
|
raise Exception('The API token used is not authorized against the server!')
|
|
if r.status_code == 404:
|
|
raise Exception('The server does not support this game/version or request object and returned \'{}\''.format(error))
|
|
if r.status_code == 405:
|
|
raise Exception('The server did not recognize the request and returned \'{}\''.format(error))
|
|
if r.status_code == 500:
|
|
raise Exception('The server had an error processing the request and returned \'{}\''.format(error))
|
|
if r.status_code == 501:
|
|
raise Exception('The server does not support this version of the API!')
|
|
raise Exception('The server returned an invalid status code {}!'.format(r.status_code))
|
|
|
|
def info_exchange(self) -> None:
|
|
resp = self.exchange_data('', {})
|
|
print('Server name: {}'.format(resp['name']))
|
|
print('Server admin email: {}'.format(resp['email']))
|
|
print('Server supported versions: {}'.format(', '.join(resp['versions'])))
|
|
|
|
def __id_check(self, idtype: str, ids: List[str]) -> None:
|
|
if idtype not in ['card', 'song', 'instance', 'server']:
|
|
raise Exception('Invalid ID type provided!')
|
|
if idtype == 'card' and len(ids) == 0:
|
|
raise Exception('Invalid number of IDs given!')
|
|
if idtype == 'song' and len(ids) not in [1, 2]:
|
|
raise Exception('Invalid number of IDs given!')
|
|
if idtype == 'instance' and len(ids) != 3:
|
|
raise Exception('Invalid number of IDs given!')
|
|
if idtype == 'server' and len(ids) != 0:
|
|
raise Exception('Invalid number of IDs given!')
|
|
|
|
def records_exchange(self, game: str, version: str, idtype: str, ids: List[str], since: Optional[int], until: Optional[int]) -> None:
|
|
self.__id_check(idtype, ids)
|
|
params = {
|
|
'ids': ids,
|
|
'type': idtype,
|
|
'objects': ['records'],
|
|
} # type: Dict[str, Any]
|
|
if since is not None:
|
|
params['since'] = since
|
|
if until is not None:
|
|
params['until'] = until
|
|
resp = self.exchange_data(
|
|
'{}/{}/{}'.format(self.API_VERSION, game, version),
|
|
params,
|
|
)
|
|
print(json.dumps(resp['records'], indent=4))
|
|
|
|
def profile_exchange(self, game: str, version: str, idtype: str, ids: List[str]) -> None:
|
|
self.__id_check(idtype, ids)
|
|
resp = self.exchange_data(
|
|
'{}/{}/{}'.format(self.API_VERSION, game, version),
|
|
{
|
|
'ids': ids,
|
|
'type': idtype,
|
|
'objects': ['profile'],
|
|
},
|
|
)
|
|
print(json.dumps(resp['profile'], indent=4))
|
|
|
|
def statistics_exchange(self, game: str, version: str, idtype: str, ids: List[str]) -> None:
|
|
self.__id_check(idtype, ids)
|
|
resp = self.exchange_data(
|
|
'{}/{}/{}'.format(self.API_VERSION, game, version),
|
|
{
|
|
'ids': ids,
|
|
'type': idtype,
|
|
'objects': ['statistics'],
|
|
},
|
|
)
|
|
print(json.dumps(resp['statistics'], indent=4))
|
|
|
|
def catalog_exchange(self, game: str, version: str) -> None:
|
|
resp = self.exchange_data(
|
|
'{}/{}/{}'.format(self.API_VERSION, game, version),
|
|
{
|
|
'ids': [],
|
|
'type': 'server',
|
|
'objects': ['catalog'],
|
|
},
|
|
)
|
|
print(json.dumps(resp['catalog'], indent=4))
|
|
|
|
|
|
def main():
|
|
# Global arguments
|
|
parser = argparse.ArgumentParser(description='A sample API client for an e-AMUSEMENT API provider.')
|
|
parser.add_argument('-t', '--token', type=str, required=True, help='The authorization token for speaing to the API.')
|
|
parser.add_argument('-b', '--base', type=str, required=True, help='Base URI to connect to for all requests.')
|
|
subparser = parser.add_subparsers(dest='request')
|
|
|
|
# Info request
|
|
subparser.add_parser('info')
|
|
|
|
# Score request
|
|
record_parser = subparser.add_parser('records')
|
|
record_parser.add_argument('-g', '--game', type=str, required=True, help='The game we want to look records up for.')
|
|
record_parser.add_argument('-v', '--version', type=str, required=True, help='The version we want to look records up for.')
|
|
record_parser.add_argument('-t', '--type', type=str, required=True, choices=['card', 'song', 'instance', 'server'], help='The type of ID used to look up records.')
|
|
record_parser.add_argument('-s', '--since', metavar='TIMESTAMP', default=None, type=int, help='Only load records updated since TIMESTAMP')
|
|
record_parser.add_argument('-u', '--until', metavar='TIMESTAMP', default=None, type=int, help='Only load records updated before TIMESTAMP')
|
|
record_parser.add_argument('id', metavar='ID', nargs='*', type=str, help='The ID we will look up records for.')
|
|
|
|
# Profile request
|
|
profile_parser = subparser.add_parser('profile')
|
|
profile_parser.add_argument('-g', '--game', type=str, required=True, help='The game we want to look profiles up for.')
|
|
profile_parser.add_argument('-v', '--version', type=str, required=True, help='The version we want to look profiles up for.')
|
|
profile_parser.add_argument('-t', '--type', type=str, required=True, choices=['card', 'server'], help='The type of ID used to look up profiles.')
|
|
profile_parser.add_argument('id', metavar='ID', nargs='*', type=str, help='The ID we will look up profiles for.')
|
|
|
|
# Statistics request
|
|
statistic_parser = subparser.add_parser('statistics')
|
|
statistic_parser.add_argument('-g', '--game', type=str, required=True, help='The game we want to look statistics up for.')
|
|
statistic_parser.add_argument('-v', '--version', type=str, required=True, help='The version we want to look statistics up for.')
|
|
statistic_parser.add_argument('-t', '--type', type=str, required=True, choices=['card', 'song', 'instance', 'server'], help='The type of ID used to look up statistics.')
|
|
statistic_parser.add_argument('id', metavar='ID', nargs='*', type=str, help='The ID we will look up statistics for.')
|
|
|
|
# Catalog request
|
|
catalog_parser = subparser.add_parser('catalog')
|
|
catalog_parser.add_argument('-g', '--game', type=str, required=True, help='The game we want to look catalog entries up for.')
|
|
catalog_parser.add_argument('-v', '--version', type=str, required=True, help='The version we want to look catalog entries up for.')
|
|
|
|
# Grab args
|
|
args = parser.parse_args()
|
|
client = APIClient(args.base, args.token)
|
|
if args.request == 'info':
|
|
client.info_exchange()
|
|
elif args.request == 'records':
|
|
client.records_exchange(
|
|
args.game,
|
|
args.version,
|
|
args.type,
|
|
args.id,
|
|
args.since,
|
|
args.until,
|
|
)
|
|
elif args.request == 'profile':
|
|
client.profile_exchange(
|
|
args.game,
|
|
args.version,
|
|
args.type,
|
|
args.id,
|
|
)
|
|
elif args.request == 'statistics':
|
|
client.statistics_exchange(
|
|
args.game,
|
|
args.version,
|
|
args.type,
|
|
args.id,
|
|
)
|
|
elif args.request == 'catalog':
|
|
client.catalog_exchange(
|
|
args.game,
|
|
args.version,
|
|
)
|
|
else:
|
|
raise Exception('Invalid request type {}!'.format(args.request))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
main()
|
|
except Exception as e:
|
|
print(e, file=sys.stderr)
|
|
sys.exit(1)
|