From 80199e6ca2c09b10d866de70fec3ed198aa184a7 Mon Sep 17 00:00:00 2001 From: drisc Date: Mon, 22 Apr 2024 16:23:45 +0100 Subject: [PATCH] feat(endpoints): initial endpoints (#1) --- README.md | 68 +++++++++++++++-- retroachievements/__init__.py | 14 ++++ retroachievements/client.py | 140 ++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 retroachievements/__init__.py create mode 100644 retroachievements/client.py diff --git a/README.md b/README.md index f84aa1c..3addc7c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,73 @@

RetroAchievements Logo

-

RetroAchievements Web API Client

+ +

retroachievements-api

+ +

+ A Python library that lets you get achievement, user, and game data from RetroAchievements. +

+

+ +

+ Documentation: Get Started +
+

+ +
+ +## Status +This library is currently a work in progress, endpoint and test coverage can be found below: + +ℹ️  Endpoint coverage: 8 of 30 +ℹ️  Test coverage: 0 of 30 + +## Features + +✅  Officially-supported, aligns 1:1 with the RAWeb API. +✅  Backwards-compatible, easy migration path to API v2. +✅  Supports Python 3.11+. + +
+ +## Documentation + +Learn how to authenticate and start pulling data from RetroAchievements on our documentation website. + +- [Get started](https://api-docs.retroachievements.org/getting-started.html) +- [Get a user's profile information](https://api-docs.retroachievements.org/v1/users/get-user-summary.html) +- [Look up games a user has completed](https://api-docs.retroachievements.org/v1/users/get-user-completed-games.html) +- [Get a game's metadata](https://api-docs.retroachievements.org/v1/games/get-game-extended.html) ## Installation -WIP +Coming Soon +## How to begin making API calls -## Usage +To use any endpoint function in the API, you must first be authorized by RetroAchievements. Fortunately, this is a fairly straightforward process. -WIP +1. Visit [your control panel](https://retroachievements.org/controlpanel.php) on the RA website. -## Testing +2. Find the "Keys" section on the page. Copy the web API key value. **Do not expose your API key anywhere publicly.** -WIP +3. You can now create your authorization object using your web API key. + +```python +from retroachievements import RAClient + +userName = '' +webApiKey = '' + +auth = RAClient(userName, webApiKey) +``` + +4. You now have all you need to use any function in the API. Each function takes this authorization object as its first argument. Here's an example: + +```python +from retroachievements import getGame + +// This returns basic metadata about the game on this page: +// https://retroachievements.org/game/14402 +game = auth.getGame(14402); +``` ## Contributing diff --git a/retroachievements/__init__.py b/retroachievements/__init__.py new file mode 100644 index 0000000..fdff482 --- /dev/null +++ b/retroachievements/__init__.py @@ -0,0 +1,14 @@ +""" + +RetroAchievements API Client +--- + +Official Python API client for RetroAchievements + +""" + +__title__ = "retroachievements-api" +__authors__ = "drisc" +__version__ = "1.0.0" + +from .client import RAClient diff --git a/retroachievements/client.py b/retroachievements/client.py new file mode 100644 index 0000000..c2e2718 --- /dev/null +++ b/retroachievements/client.py @@ -0,0 +1,140 @@ +import requests as request +from retroachievements import __version__ + + +_BASE_URL = "https://retroachievements.org/API/" + + +class RAClient: + """ + Main class for accessing the RetroAhievements Web API + """ + + headers = { + "User-Agent": "RetroAchievements-api-python/" + __version__} + + def __init__(self, username, api_key): + self.username = username + self.api_key = api_key + + def url_params(self, params=None): + """ + Inserts the auth and query params into the request + """ + if params is None: + params = {} + params.update({"z": self.username, "y": self.api_key}) + return params + + # URL construction + def _call_api(self, endpoint=None, params=None, timeout=30, headers=None): + if endpoint is None: + endpoint = {} + req = request.get( + f"{_BASE_URL}{endpoint}", + params=self.url_params(params), + timeout=timeout, + headers=headers, + ) + return req + + # User endpoints + + def get_user_points(self, user: str) -> dict: + """ + Get a user's total hardcore and softcore points + + Params: + u: Username to query + """ + result = self._call_api("API_GetUserPoints.php?", {"u": user}).json() + return result + + def get_user_summary(self, user: str, + recent_games=0, + recent_cheevos=10) -> dict: + """ + Get a user's exhaustive profile metadata + + Params: + u: Username to query + g: Number of recent games to fetch, default = 0 + a: Number of recent achievements to fetch, default = 10 + """ + result = self._call_api( + "API_GetUserSummary.php?", + {"u": user, "g": recent_games, "a": recent_cheevos}, + ).json() + return result + + # Game endpoints + + def get_game(self, game: int) -> dict: + """ + Get basic metadata about a game + + Params: + i: The game ID to query + """ + result = self._call_api("API_GetGame.php?", {"i": game}).json() + return result + + def get_game_extended(self, game: int) -> dict: + """ + Get extended metadata about a game + + Params: + i: The game ID to query + """ + result = self._call_api("API_GetGameExtended.php?", {"i": game}).json() + return result + + def get_achievement_count(self, game: int) -> dict: + """ + Get the list of achievement ID's for a game + + Params: + i: The game ID to query + """ + result = self._call_api( + "API_GetAchievementCount.php?", {"i": game}).json() + return result + + def get_achievement_distribution(self, game: int) -> dict: + """ + Get how many players have unlocked how many achievements for a game + + Params: + i: The game ID to query + """ + result = self._call_api( + "API_GetAchievementDistribution.php?", {"i": game} + ).json() + return result + + # System Endpoints + + def get_console_ids(self) -> list: + """ + Get the complete list of console ID and name pairs on the site + + Params: + None + """ + result = self._call_api("API_GetConsoleIDs.php?", {}).json() + return result + + def get_game_list(self, system: int, has_cheevos=0, hashes=0) -> dict: + """ + Get the complete list of games for a console + + Params: + i: The system ID to query + f: If 1, only returns games that have achievements (default = 0) + h: If 1, also return the supported hashes for games (default = 0) + """ + result = self._call_api( + "API_GetGameList.php?", { + "i": system, "f": has_cheevos, "h": hashes} + ).json() + return result