1
0
mirror of synced 2024-11-28 07:50:51 +01:00
bemaniutils/bemani/utils/sampleclient.py

363 lines
10 KiB
Python

#! /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() -> None:
# 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)