@retroachievements/api 0.0.0-development
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +103 -0
- package/dist/__playground.d.ts +7 -0
- package/dist/achievement/getAchievementUnlocks.d.ts +45 -0
- package/dist/achievement/index.d.ts +2 -0
- package/dist/achievement/models/achievement-unlock-entity.model.d.ts +6 -0
- package/dist/achievement/models/get-achievement-unlocks-response.model.d.ts +8 -0
- package/dist/achievement/models/index.d.ts +2 -0
- package/dist/api.cjs.development.js +2363 -0
- package/dist/api.cjs.development.js.map +1 -0
- package/dist/api.cjs.production.min.js +2 -0
- package/dist/api.cjs.production.min.js.map +1 -0
- package/dist/api.esm.js +2333 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/console/getConsoleIds.d.ts +22 -0
- package/dist/console/getGameList.d.ts +52 -0
- package/dist/console/index.d.ts +3 -0
- package/dist/console/models/console-id.model.d.ts +4 -0
- package/dist/console/models/game-list.model.d.ts +15 -0
- package/dist/console/models/get-console-ids-response.model.d.ts +4 -0
- package/dist/console/models/get-game-list-response.model.d.ts +15 -0
- package/dist/console/models/index.d.ts +4 -0
- package/dist/feed/getAchievementOfTheWeek.d.ts +48 -0
- package/dist/feed/getActiveClaims.d.ts +38 -0
- package/dist/feed/getTicketData.d.ts +158 -0
- package/dist/feed/getTopTenUsers.d.ts +24 -0
- package/dist/feed/index.d.ts +5 -0
- package/dist/feed/models/achievement-of-the-week.model.d.ts +32 -0
- package/dist/feed/models/achievement-ticket-stats-response.model.d.ts +7 -0
- package/dist/feed/models/achievement-ticket-stats.model.d.ts +7 -0
- package/dist/feed/models/active-claim.model.d.ts +49 -0
- package/dist/feed/models/game-ticket-stats.model.d.ts +9 -0
- package/dist/feed/models/game-tickets-response.model.d.ts +7 -0
- package/dist/feed/models/get-achievement-of-the-week-response.model.d.ts +32 -0
- package/dist/feed/models/get-active-claims-response.model.d.ts +19 -0
- package/dist/feed/models/get-top-ten-users-response.model.d.ts +10 -0
- package/dist/feed/models/index.d.ts +19 -0
- package/dist/feed/models/most-ticketed-games-response.model.d.ts +12 -0
- package/dist/feed/models/most-ticketed-games.model.d.ts +12 -0
- package/dist/feed/models/recent-tickets-response.model.d.ts +6 -0
- package/dist/feed/models/recent-tickets.model.d.ts +6 -0
- package/dist/feed/models/response-ticket-entity.model.d.ts +24 -0
- package/dist/feed/models/ticket-entity.model.d.ts +24 -0
- package/dist/feed/models/tickets-by-user-response.model.d.ts +8 -0
- package/dist/feed/models/top-ten-users-entity.model.d.ts +5 -0
- package/dist/feed/models/top-ten-users.model.d.ts +2 -0
- package/dist/feed/models/user-ticket-stats.model.d.ts +8 -0
- package/dist/game/getAchievementCount.d.ts +31 -0
- package/dist/game/getAchievementDistribution.d.ts +57 -0
- package/dist/game/getGame.d.ts +48 -0
- package/dist/game/getGameExtended.d.ts +68 -0
- package/dist/game/getGameRankAndScore.d.ts +38 -0
- package/dist/game/getGameRating.d.ts +38 -0
- package/dist/game/index.d.ts +7 -0
- package/dist/game/models/achievement-count.model.d.ts +4 -0
- package/dist/game/models/achievement-distribution-flags.model.d.ts +4 -0
- package/dist/game/models/game-extended-achievement-entity.model.d.ts +15 -0
- package/dist/game/models/game-extended-claim-entity.model.d.ts +7 -0
- package/dist/game/models/game-extended.model.d.ts +25 -0
- package/dist/game/models/game-rank-and-score-entity.model.d.ts +6 -0
- package/dist/game/models/game-rating.model.d.ts +9 -0
- package/dist/game/models/game.model.d.ts +19 -0
- package/dist/game/models/get-achievement-count-response.model.d.ts +4 -0
- package/dist/game/models/get-achievement-distribution-response.model.d.ts +1 -0
- package/dist/game/models/get-game-extended-response.model.d.ts +50 -0
- package/dist/game/models/get-game-rank-and-score-response.model.d.ts +8 -0
- package/dist/game/models/get-game-rating-response.model.d.ts +9 -0
- package/dist/game/models/get-game-response.model.d.ts +19 -0
- package/dist/game/models/index.d.ts +14 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/user/getAchievementsEarnedBetween.d.ts +59 -0
- package/dist/user/getAchievementsEarnedOnDay.d.ts +57 -0
- package/dist/user/getGameInfoAndUserProgress.d.ts +80 -0
- package/dist/user/getUserGameRankAndScore.d.ts +44 -0
- package/dist/user/getUserPoints.d.ts +30 -0
- package/dist/user/getUserProgress.d.ts +49 -0
- package/dist/user/getUserRecentlyPlayedGames.d.ts +50 -0
- package/dist/user/getUserSummary.d.ts +32 -0
- package/dist/user/index.d.ts +9 -0
- package/dist/user/models/dated-user-achievement.model.d.ts +17 -0
- package/dist/user/models/dated-user-achievements-response.model.d.ts +19 -0
- package/dist/user/models/game-info-and-user-progress.model.d.ts +12 -0
- package/dist/user/models/get-game-info-and-user-progress-response.model.d.ts +14 -0
- package/dist/user/models/get-user-game-rank-and-score-response.model.d.ts +8 -0
- package/dist/user/models/get-user-points-response.model.d.ts +4 -0
- package/dist/user/models/get-user-progress-response.model.d.ts +10 -0
- package/dist/user/models/get-user-recently-played-games-response.model.d.ts +16 -0
- package/dist/user/models/get-user-summary-response.model.d.ts +82 -0
- package/dist/user/models/index.d.ts +14 -0
- package/dist/user/models/user-game-rank-and-score.model.d.ts +8 -0
- package/dist/user/models/user-points.model.d.ts +4 -0
- package/dist/user/models/user-progress.model.d.ts +10 -0
- package/dist/user/models/user-recently-played-games.model.d.ts +16 -0
- package/dist/user/models/user-summary.model.d.ts +83 -0
- package/dist/utils/internal/apiBaseUrl.d.ts +1 -0
- package/dist/utils/internal/buildRequestUrl.d.ts +2 -0
- package/dist/utils/internal/call.d.ts +20 -0
- package/dist/utils/internal/index.d.ts +4 -0
- package/dist/utils/internal/serializeProperties.d.ts +4 -0
- package/dist/utils/public/buildAuthorization.d.ts +22 -0
- package/dist/utils/public/index.d.ts +3 -0
- package/dist/utils/public/models/auth-object.model.d.ts +19 -0
- package/dist/utils/public/models/index.d.ts +1 -0
- package/package.json +117 -0
- package/src/__playground.ts +27 -0
- package/src/achievement/getAchievementUnlocks.test.ts +71 -0
- package/src/achievement/getAchievementUnlocks.ts +80 -0
- package/src/achievement/index.ts +2 -0
- package/src/achievement/models/achievement-unlock-entity.model.ts +6 -0
- package/src/achievement/models/get-achievement-unlocks-response.model.ts +8 -0
- package/src/achievement/models/index.ts +2 -0
- package/src/console/getConsoleIds.test.ts +53 -0
- package/src/console/getConsoleIds.ts +43 -0
- package/src/console/getGameList.test.ts +82 -0
- package/src/console/getGameList.ts +94 -0
- package/src/console/index.ts +3 -0
- package/src/console/models/console-id.model.ts +4 -0
- package/src/console/models/game-list.model.ts +16 -0
- package/src/console/models/get-console-ids-response.model.ts +1 -0
- package/src/console/models/get-game-list-response.model.ts +16 -0
- package/src/console/models/index.ts +4 -0
- package/src/feed/getAchievementOfTheWeek.test.ts +167 -0
- package/src/feed/getAchievementOfTheWeek.ts +80 -0
- package/src/feed/getActiveClaims.test.ts +81 -0
- package/src/feed/getActiveClaims.ts +68 -0
- package/src/feed/getTicketData.test.ts +349 -0
- package/src/feed/getTicketData.ts +286 -0
- package/src/feed/getTopTenUsers.test.ts +101 -0
- package/src/feed/getTopTenUsers.ts +51 -0
- package/src/feed/index.ts +5 -0
- package/src/feed/models/achievement-of-the-week.model.ts +27 -0
- package/src/feed/models/achievement-ticket-stats-response.model.ts +7 -0
- package/src/feed/models/achievement-ticket-stats.model.ts +7 -0
- package/src/feed/models/active-claim.model.ts +66 -0
- package/src/feed/models/game-ticket-stats.model.ts +11 -0
- package/src/feed/models/game-tickets-response.model.ts +7 -0
- package/src/feed/models/get-achievement-of-the-week-response.model.ts +27 -0
- package/src/feed/models/get-active-claims-response.model.ts +19 -0
- package/src/feed/models/get-top-ten-users-response.model.ts +12 -0
- package/src/feed/models/index.ts +19 -0
- package/src/feed/models/most-ticketed-games-response.model.ts +12 -0
- package/src/feed/models/most-ticketed-games.model.ts +12 -0
- package/src/feed/models/recent-tickets-response.model.ts +7 -0
- package/src/feed/models/recent-tickets.model.ts +7 -0
- package/src/feed/models/response-ticket-entity.model.ts +25 -0
- package/src/feed/models/ticket-entity.model.ts +24 -0
- package/src/feed/models/tickets-by-user-response.model.ts +8 -0
- package/src/feed/models/top-ten-users-entity.model.ts +5 -0
- package/src/feed/models/top-ten-users.model.ts +3 -0
- package/src/feed/models/user-ticket-stats.model.ts +8 -0
- package/src/game/getAchievementCount.test.ts +49 -0
- package/src/game/getAchievementCount.ts +52 -0
- package/src/game/getAchievementDistribution.test.ts +187 -0
- package/src/game/getAchievementDistribution.ts +88 -0
- package/src/game/getGame.test.ts +81 -0
- package/src/game/getGame.ts +74 -0
- package/src/game/getGameExtended.test.ts +121 -0
- package/src/game/getGameExtended.ts +103 -0
- package/src/game/getGameRankAndScore.test.ts +62 -0
- package/src/game/getGameRankAndScore.ts +66 -0
- package/src/game/getGameRating.test.ts +59 -0
- package/src/game/getGameRating.ts +59 -0
- package/src/game/index.ts +7 -0
- package/src/game/models/achievement-count.model.ts +4 -0
- package/src/game/models/achievement-distribution-flags.model.ts +4 -0
- package/src/game/models/game-extended-achievement-entity.model.ts +15 -0
- package/src/game/models/game-extended-claim-entity.model.ts +7 -0
- package/src/game/models/game-extended.model.ts +26 -0
- package/src/game/models/game-rank-and-score-entity.model.ts +6 -0
- package/src/game/models/game-rating.model.ts +9 -0
- package/src/game/models/game.model.ts +19 -0
- package/src/game/models/get-achievement-count-response.model.ts +4 -0
- package/src/game/models/get-achievement-distribution-response.model.ts +1 -0
- package/src/game/models/get-game-extended-response.model.ts +56 -0
- package/src/game/models/get-game-rank-and-score-response.model.ts +8 -0
- package/src/game/models/get-game-rating-response.model.ts +9 -0
- package/src/game/models/get-game-response.model.ts +19 -0
- package/src/game/models/index.ts +14 -0
- package/src/index.ts +8 -0
- package/src/user/getAchievementsEarnedBetween.test.ts +84 -0
- package/src/user/getAchievementsEarnedBetween.ts +88 -0
- package/src/user/getAchievementsEarnedOnDay.test.ts +83 -0
- package/src/user/getAchievementsEarnedOnDay.ts +87 -0
- package/src/user/getGameInfoAndUserProgress.test.ts +135 -0
- package/src/user/getGameInfoAndUserProgress.ts +118 -0
- package/src/user/getUserGameRankAndScore.test.ts +60 -0
- package/src/user/getUserGameRankAndScore.ts +69 -0
- package/src/user/getUserPoints.test.ts +49 -0
- package/src/user/getUserPoints.ts +51 -0
- package/src/user/getUserProgress.test.ts +80 -0
- package/src/user/getUserProgress.ts +78 -0
- package/src/user/getUserRecentlyPlayedGames.test.ts +76 -0
- package/src/user/getUserRecentlyPlayedGames.ts +93 -0
- package/src/user/getUserSummary.test.ts +251 -0
- package/src/user/getUserSummary.ts +96 -0
- package/src/user/index.ts +9 -0
- package/src/user/models/dated-user-achievement.model.ts +17 -0
- package/src/user/models/dated-user-achievements-response.model.ts +20 -0
- package/src/user/models/game-info-and-user-progress.model.ts +19 -0
- package/src/user/models/get-game-info-and-user-progress-response.model.ts +28 -0
- package/src/user/models/get-user-game-rank-and-score-response.model.ts +9 -0
- package/src/user/models/get-user-points-response.model.ts +4 -0
- package/src/user/models/get-user-progress-response.model.ts +13 -0
- package/src/user/models/get-user-recently-played-games-response.model.ts +17 -0
- package/src/user/models/get-user-summary-response.model.ts +92 -0
- package/src/user/models/index.ts +14 -0
- package/src/user/models/user-game-rank-and-score.model.ts +8 -0
- package/src/user/models/user-points.model.ts +4 -0
- package/src/user/models/user-progress.model.ts +10 -0
- package/src/user/models/user-recently-played-games.model.ts +16 -0
- package/src/user/models/user-summary.model.ts +92 -0
- package/src/utils/internal/apiBaseUrl.ts +1 -0
- package/src/utils/internal/buildRequestUrl.test.ts +51 -0
- package/src/utils/internal/buildRequestUrl.ts +32 -0
- package/src/utils/internal/call.test.ts +39 -0
- package/src/utils/internal/call.ts +29 -0
- package/src/utils/internal/index.ts +4 -0
- package/src/utils/internal/serializeProperties.test.ts +141 -0
- package/src/utils/internal/serializeProperties.ts +75 -0
- package/src/utils/public/buildAuthorization.test.ts +36 -0
- package/src/utils/public/buildAuthorization.ts +40 -0
- package/src/utils/public/index.ts +3 -0
- package/src/utils/public/models/auth-object.model.ts +20 -0
- package/src/utils/public/models/index.ts +1 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* eslint-disable sonarjs/no-duplicate-string */
|
|
2
|
+
|
|
3
|
+
import { rest } from "msw";
|
|
4
|
+
import { setupServer } from "msw/node";
|
|
5
|
+
|
|
6
|
+
import { apiBaseUrl } from "../utils/internal";
|
|
7
|
+
import { buildAuthorization } from "../utils/public";
|
|
8
|
+
import { getGameRankAndScore } from "./getGameRankAndScore";
|
|
9
|
+
import type { GetGameRankAndScoreResponse } from "./models";
|
|
10
|
+
|
|
11
|
+
const server = setupServer();
|
|
12
|
+
|
|
13
|
+
describe("Function: getGameRankAndScore", () => {
|
|
14
|
+
// MSW Setup
|
|
15
|
+
beforeAll(() => server.listen());
|
|
16
|
+
afterEach(() => server.resetHandlers());
|
|
17
|
+
afterAll(() => server.close());
|
|
18
|
+
|
|
19
|
+
it("is defined #sanity", () => {
|
|
20
|
+
// ASSERT
|
|
21
|
+
expect(getGameRankAndScore).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("given a game ID, retrieves metadata about latest masteries for a game", async () => {
|
|
25
|
+
// ARRANGE
|
|
26
|
+
const authorization = buildAuthorization({
|
|
27
|
+
userName: "mockUserName",
|
|
28
|
+
webApiKey: "mockWebApiKey"
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const mockResponse: GetGameRankAndScoreResponse = [
|
|
32
|
+
{
|
|
33
|
+
User: "Arekdias",
|
|
34
|
+
TotalScore: "189",
|
|
35
|
+
LastAward: "2020-10-10 22:43:32",
|
|
36
|
+
Rank: 1
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
server.use(
|
|
41
|
+
rest.get(`${apiBaseUrl}/API_GetGameRankAndScore.php`, (_, res, ctx) =>
|
|
42
|
+
res(ctx.json(mockResponse))
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// ACT
|
|
47
|
+
const response = await getGameRankAndScore(authorization, {
|
|
48
|
+
gameId: 14_402,
|
|
49
|
+
type: "high-scores"
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// ASSERT
|
|
53
|
+
expect(response).toEqual([
|
|
54
|
+
{
|
|
55
|
+
user: "Arekdias",
|
|
56
|
+
totalScore: 189,
|
|
57
|
+
lastAward: "2020-10-10 22:43:32",
|
|
58
|
+
rank: 1
|
|
59
|
+
}
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
apiBaseUrl,
|
|
3
|
+
buildRequestUrl,
|
|
4
|
+
call,
|
|
5
|
+
serializeProperties
|
|
6
|
+
} from "../utils/internal";
|
|
7
|
+
import type { AuthObject } from "../utils/public";
|
|
8
|
+
import type {
|
|
9
|
+
GameRankAndScoreEntity,
|
|
10
|
+
GetGameRankAndScoreResponse
|
|
11
|
+
} from "./models";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A call to this function will retrieve metadata about
|
|
15
|
+
* either the latest masters for a game, or the highest
|
|
16
|
+
* points earners for a game. The game is targeted via
|
|
17
|
+
* its unique ID.
|
|
18
|
+
*
|
|
19
|
+
* @param authorization An object containing your userName and webApiKey.
|
|
20
|
+
* This can be constructed with `buildAuthorization()`.
|
|
21
|
+
*
|
|
22
|
+
* @param payload.gameId The unique game ID. If you are unsure, open the
|
|
23
|
+
* game's page on the RetroAchievements.org website. For example, Dragster's
|
|
24
|
+
* URL is https://retroachievements.org/game/14402. We can see from the
|
|
25
|
+
* URL that the game ID is "14402".
|
|
26
|
+
*
|
|
27
|
+
* @param payload.type Can either be "latest-masters" or "high-scores".
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```
|
|
31
|
+
* const gameRankAndScore = await getGameRankAndScore(
|
|
32
|
+
* authorization,
|
|
33
|
+
* { gameId: 14402, type: "latest-masters" }
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @returns An array containing a list of latest masters or
|
|
38
|
+
* high score earners for a given game ID.
|
|
39
|
+
* ```json
|
|
40
|
+
* [
|
|
41
|
+
* { user: 'Arekdias', totalScore: 189, lastAward: '2020-10-10 22:43:32' }
|
|
42
|
+
* ]
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export const getGameRankAndScore = async (
|
|
46
|
+
authorization: AuthObject,
|
|
47
|
+
payload: { gameId: number; type: "latest-masters" | "high-scores" }
|
|
48
|
+
): Promise<GameRankAndScoreEntity[]> => {
|
|
49
|
+
const { gameId, type } = payload;
|
|
50
|
+
|
|
51
|
+
const url = buildRequestUrl(
|
|
52
|
+
apiBaseUrl,
|
|
53
|
+
"/API_GetGameRankAndScore.php",
|
|
54
|
+
authorization,
|
|
55
|
+
{
|
|
56
|
+
g: gameId,
|
|
57
|
+
t: type === "latest-masters" ? 1 : 0
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const rawResponse = await call<GetGameRankAndScoreResponse>({ url });
|
|
62
|
+
|
|
63
|
+
return serializeProperties(rawResponse, {
|
|
64
|
+
shouldCastToNumbers: ["TotalScore"]
|
|
65
|
+
});
|
|
66
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { setupServer } from "msw/node";
|
|
3
|
+
|
|
4
|
+
import { apiBaseUrl } from "../utils/internal";
|
|
5
|
+
import { buildAuthorization } from "../utils/public";
|
|
6
|
+
import { getGameRating } from "./getGameRating";
|
|
7
|
+
import type { GetGameRatingResponse } from "./models";
|
|
8
|
+
|
|
9
|
+
const server = setupServer();
|
|
10
|
+
|
|
11
|
+
describe("Function: getGameRating", () => {
|
|
12
|
+
// MSW Setup
|
|
13
|
+
beforeAll(() => server.listen());
|
|
14
|
+
afterEach(() => server.resetHandlers());
|
|
15
|
+
afterAll(() => server.close());
|
|
16
|
+
|
|
17
|
+
it("is defined #sanity", () => {
|
|
18
|
+
// ASSERT
|
|
19
|
+
expect(getGameRating).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("given a game ID, retrieves metadata about how users have rated it", async () => {
|
|
23
|
+
// ARRANGE
|
|
24
|
+
const authorization = buildAuthorization({
|
|
25
|
+
userName: "mockUserName",
|
|
26
|
+
webApiKey: "mockWebApiKey"
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const mockResponse: GetGameRatingResponse = {
|
|
30
|
+
GameID: 14_402,
|
|
31
|
+
Ratings: {
|
|
32
|
+
Game: 3.1875,
|
|
33
|
+
Achievements: 0,
|
|
34
|
+
GameNumVotes: 16,
|
|
35
|
+
AchievementsNumVotes: 0
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
server.use(
|
|
40
|
+
rest.get(`${apiBaseUrl}/API_GetGameRating.php`, (_, res, ctx) =>
|
|
41
|
+
res(ctx.json(mockResponse))
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// ACT
|
|
46
|
+
const response = await getGameRating(authorization, { gameId: 14_402 });
|
|
47
|
+
|
|
48
|
+
// ASSERT
|
|
49
|
+
expect(response).toEqual({
|
|
50
|
+
gameId: 14_402,
|
|
51
|
+
ratings: {
|
|
52
|
+
game: 3.1875,
|
|
53
|
+
achievements: 0,
|
|
54
|
+
gameNumVotes: 16,
|
|
55
|
+
achievementsNumVotes: 0
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
apiBaseUrl,
|
|
3
|
+
buildRequestUrl,
|
|
4
|
+
call,
|
|
5
|
+
serializeProperties
|
|
6
|
+
} from "../utils/internal";
|
|
7
|
+
import type { AuthObject } from "../utils/public";
|
|
8
|
+
import type { GameRating, GetGameRatingResponse } from "./models";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A call to this function will retrieve metadata about
|
|
12
|
+
* how users have rated the game and its set.
|
|
13
|
+
*
|
|
14
|
+
* @param authorization An object containing your userName and webApiKey.
|
|
15
|
+
* This can be constructed with `buildAuthorization()`.
|
|
16
|
+
*
|
|
17
|
+
* @param payload.gameId The unique game ID. If you are unsure, open the
|
|
18
|
+
* game's page on the RetroAchievements.org website. For example, Dragster's
|
|
19
|
+
* URL is https://retroachievements.org/game/14402. We can see from the
|
|
20
|
+
* URL that the game ID is "14402".
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```
|
|
24
|
+
* const gameRating = await getGameRating(
|
|
25
|
+
* authorization,
|
|
26
|
+
* { gameId: 14402 }
|
|
27
|
+
* );
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @returns An object with game rating metadata.
|
|
31
|
+
* ```json
|
|
32
|
+
* {
|
|
33
|
+
* gameId: 14402,
|
|
34
|
+
* ratings: {
|
|
35
|
+
* game: 3.1875,
|
|
36
|
+
* achievements: 0,
|
|
37
|
+
* gameNumVotes: 16,
|
|
38
|
+
* achievementsNumVotes: 0
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const getGameRating = async (
|
|
44
|
+
authorization: AuthObject,
|
|
45
|
+
payload: { gameId: number }
|
|
46
|
+
): Promise<GameRating> => {
|
|
47
|
+
const { gameId } = payload;
|
|
48
|
+
|
|
49
|
+
const url = buildRequestUrl(
|
|
50
|
+
apiBaseUrl,
|
|
51
|
+
"/API_GetGameRating.php",
|
|
52
|
+
authorization,
|
|
53
|
+
{ i: gameId }
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const rawResponse = await call<GetGameRatingResponse>({ url });
|
|
57
|
+
|
|
58
|
+
return serializeProperties(rawResponse);
|
|
59
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface GameExtendedAchievementEntity {
|
|
2
|
+
id: number;
|
|
3
|
+
numAwarded: number;
|
|
4
|
+
numAwardedHardcore: number;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
points: number;
|
|
8
|
+
trueRatio: number;
|
|
9
|
+
author: string;
|
|
10
|
+
dateModified: string;
|
|
11
|
+
dateCreated: string;
|
|
12
|
+
badgeName: string;
|
|
13
|
+
displayOrder: number;
|
|
14
|
+
memAddr: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GameExtendedAchievementEntity } from "./game-extended-achievement-entity.model";
|
|
2
|
+
import type { GameExtendedClaimEntity } from "./game-extended-claim-entity.model";
|
|
3
|
+
|
|
4
|
+
export interface GameExtended {
|
|
5
|
+
id: number;
|
|
6
|
+
title: string;
|
|
7
|
+
consoleId: number;
|
|
8
|
+
forumTopicId: number;
|
|
9
|
+
flags: number;
|
|
10
|
+
imageIcon: string;
|
|
11
|
+
imageTitle: string;
|
|
12
|
+
imageIngame: string;
|
|
13
|
+
imageBoxArt: string;
|
|
14
|
+
publisher: string;
|
|
15
|
+
developer: string;
|
|
16
|
+
genre: string;
|
|
17
|
+
released: number;
|
|
18
|
+
isFinal: boolean;
|
|
19
|
+
consoleName: string;
|
|
20
|
+
richPresencePatch: string;
|
|
21
|
+
numAchievements: number;
|
|
22
|
+
numDistinctPlayersCasual: number;
|
|
23
|
+
numDistinctPlayersHardcore: number;
|
|
24
|
+
claims: GameExtendedClaimEntity[];
|
|
25
|
+
achievements: Record<number, GameExtendedAchievementEntity>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface Game {
|
|
2
|
+
id: number;
|
|
3
|
+
title: string;
|
|
4
|
+
forumTopicId: number;
|
|
5
|
+
consoleId: number;
|
|
6
|
+
consoleName: string;
|
|
7
|
+
flags: number;
|
|
8
|
+
imageIcon: string;
|
|
9
|
+
gameIcon: string;
|
|
10
|
+
imageTitle: string;
|
|
11
|
+
imageIngame: string;
|
|
12
|
+
imageBoxArt: string;
|
|
13
|
+
publisher: string;
|
|
14
|
+
developer: string;
|
|
15
|
+
genre: string;
|
|
16
|
+
released: number;
|
|
17
|
+
gameTitle: string;
|
|
18
|
+
console: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type GetAchievementDistributionResponse = Record<`${number}`, number>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// NOTE: This cannot be a true extension of the `GetGameResponse`
|
|
2
|
+
// interface because the return types for many of these fields
|
|
3
|
+
// are different from the actual RA API.
|
|
4
|
+
|
|
5
|
+
enum GameExtendedClaimType {
|
|
6
|
+
Primary = "0",
|
|
7
|
+
Collaboration = "1"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface GameExtendedRawAchievementEntity {
|
|
11
|
+
ID: string;
|
|
12
|
+
NumAwarded: string;
|
|
13
|
+
NumAwardedHardcore: string;
|
|
14
|
+
Title: string;
|
|
15
|
+
Description: string;
|
|
16
|
+
Points: string;
|
|
17
|
+
TrueRatio: string;
|
|
18
|
+
Author: string;
|
|
19
|
+
DateModified: string;
|
|
20
|
+
DateCreated: string;
|
|
21
|
+
BadgeName: string;
|
|
22
|
+
DisplayOrder: string;
|
|
23
|
+
MemAddr: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface GameExtendedRawClaimEntity {
|
|
27
|
+
User: string;
|
|
28
|
+
SetType: string;
|
|
29
|
+
ClaimType: GameExtendedClaimType;
|
|
30
|
+
Created: string;
|
|
31
|
+
Expiration: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface GetGameExtendedResponse {
|
|
35
|
+
ID: number;
|
|
36
|
+
Title: string;
|
|
37
|
+
ConsoleID: number;
|
|
38
|
+
ForumTopicID: number;
|
|
39
|
+
Flags: number;
|
|
40
|
+
ImageIcon: string;
|
|
41
|
+
ImageTitle: string;
|
|
42
|
+
ImageIngame: string;
|
|
43
|
+
ImageBoxArt: string;
|
|
44
|
+
Publisher: string;
|
|
45
|
+
Developer: string;
|
|
46
|
+
Genre: string;
|
|
47
|
+
Released: string;
|
|
48
|
+
IsFinal: boolean;
|
|
49
|
+
ConsoleName: string;
|
|
50
|
+
RichPresencePatch: string;
|
|
51
|
+
NumAchievements: number;
|
|
52
|
+
NumDistinctPlayersCasual: string;
|
|
53
|
+
NumDistinctPlayersHardcore: string;
|
|
54
|
+
Claims: GameExtendedRawClaimEntity[];
|
|
55
|
+
Achievements: Record<number, GameExtendedRawAchievementEntity> | [];
|
|
56
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface GetGameResponse {
|
|
2
|
+
ID: string;
|
|
3
|
+
Title: string;
|
|
4
|
+
ForumTopicID: string;
|
|
5
|
+
ConsoleID: string;
|
|
6
|
+
ConsoleName: string;
|
|
7
|
+
Flags: string;
|
|
8
|
+
ImageIcon: string;
|
|
9
|
+
GameIcon: string;
|
|
10
|
+
ImageTitle: string;
|
|
11
|
+
ImageIngame: string;
|
|
12
|
+
ImageBoxArt: string;
|
|
13
|
+
Publisher: string;
|
|
14
|
+
Developer: string;
|
|
15
|
+
Genre: string;
|
|
16
|
+
Released: string;
|
|
17
|
+
GameTitle: string;
|
|
18
|
+
Console: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./achievement-count.model";
|
|
2
|
+
export * from "./achievement-distribution-flags.model";
|
|
3
|
+
export * from "./game.model";
|
|
4
|
+
export * from "./game-extended.model";
|
|
5
|
+
export * from "./game-extended-achievement-entity.model";
|
|
6
|
+
export * from "./game-extended-claim-entity.model";
|
|
7
|
+
export * from "./game-rank-and-score-entity.model";
|
|
8
|
+
export * from "./game-rating.model";
|
|
9
|
+
export * from "./get-achievement-count-response.model";
|
|
10
|
+
export * from "./get-achievement-distribution-response.model";
|
|
11
|
+
export * from "./get-game-extended-response.model";
|
|
12
|
+
export * from "./get-game-rank-and-score-response.model";
|
|
13
|
+
export * from "./get-game-rating-response.model";
|
|
14
|
+
export * from "./get-game-response.model";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { setupServer } from "msw/node";
|
|
3
|
+
|
|
4
|
+
import { apiBaseUrl } from "../utils/internal";
|
|
5
|
+
import { buildAuthorization } from "../utils/public";
|
|
6
|
+
import { getAchievementsEarnedBetween } from "./getAchievementsEarnedBetween";
|
|
7
|
+
import type { DatedUserAchievementsResponse } from "./models";
|
|
8
|
+
|
|
9
|
+
const server = setupServer();
|
|
10
|
+
|
|
11
|
+
describe("Function: getAchievementsEarnedBetween", () => {
|
|
12
|
+
// MSW Setup
|
|
13
|
+
beforeAll(() => server.listen());
|
|
14
|
+
afterEach(() => server.resetHandlers());
|
|
15
|
+
afterAll(() => server.close());
|
|
16
|
+
|
|
17
|
+
it("is defined #sanity", () => {
|
|
18
|
+
// ASSERT
|
|
19
|
+
expect(getAchievementsEarnedBetween).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("retrieves a list of user achievements earned between a set of dates", async () => {
|
|
23
|
+
// ARRANGE
|
|
24
|
+
const authorization = buildAuthorization({
|
|
25
|
+
userName: "mockUserName",
|
|
26
|
+
webApiKey: "mockWebApiKey"
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const mockResponse: DatedUserAchievementsResponse = [
|
|
30
|
+
{
|
|
31
|
+
Date: "2022-10-12 07:36:31",
|
|
32
|
+
HardcoreMode: "1",
|
|
33
|
+
AchievementID: "173356",
|
|
34
|
+
Title: "Wind Beneath My Wings",
|
|
35
|
+
Description: "Collect all objects in the Wings Category.",
|
|
36
|
+
BadgeName: "193797",
|
|
37
|
+
Points: "10",
|
|
38
|
+
Author: "blendedsea",
|
|
39
|
+
GameTitle: "Me & My Katamari",
|
|
40
|
+
GameIcon: "/Images/047357.png",
|
|
41
|
+
GameID: "3571",
|
|
42
|
+
ConsoleName: "PlayStation Portable",
|
|
43
|
+
CumulScore: 40,
|
|
44
|
+
BadgeURL: "/Badge/193797.png",
|
|
45
|
+
GameURL: "/game/3571"
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
server.use(
|
|
50
|
+
rest.get(
|
|
51
|
+
`${apiBaseUrl}/API_GetAchievementsEarnedBetween.php`,
|
|
52
|
+
(_, res, ctx) => res(ctx.json(mockResponse))
|
|
53
|
+
)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// ACT
|
|
57
|
+
const response = await getAchievementsEarnedBetween(authorization, {
|
|
58
|
+
userName: "xelnia",
|
|
59
|
+
fromDate: new Date("2022-10-12"),
|
|
60
|
+
toDate: new Date("2022-10-13")
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ASSERT
|
|
64
|
+
expect(response).toEqual([
|
|
65
|
+
{
|
|
66
|
+
date: "2022-10-12 07:36:31",
|
|
67
|
+
hardcoreMode: true,
|
|
68
|
+
achievementId: 173_356,
|
|
69
|
+
title: "Wind Beneath My Wings",
|
|
70
|
+
description: "Collect all objects in the Wings Category.",
|
|
71
|
+
badgeName: "193797",
|
|
72
|
+
points: 10,
|
|
73
|
+
author: "blendedsea",
|
|
74
|
+
gameTitle: "Me & My Katamari",
|
|
75
|
+
gameIcon: "/Images/047357.png",
|
|
76
|
+
gameId: 3571,
|
|
77
|
+
consoleName: "PlayStation Portable",
|
|
78
|
+
cumulScore: 40,
|
|
79
|
+
badgeUrl: "/Badge/193797.png",
|
|
80
|
+
gameUrl: "/game/3571"
|
|
81
|
+
}
|
|
82
|
+
]);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
apiBaseUrl,
|
|
3
|
+
buildRequestUrl,
|
|
4
|
+
call,
|
|
5
|
+
serializeProperties
|
|
6
|
+
} from "../utils/internal";
|
|
7
|
+
import type { AuthObject } from "../utils/public";
|
|
8
|
+
import type {
|
|
9
|
+
DatedUserAchievement,
|
|
10
|
+
DatedUserAchievementsResponse
|
|
11
|
+
} from "./models";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A call to this function will retrieve a list of achievements
|
|
15
|
+
* earned by a given user between two provided dates.
|
|
16
|
+
*
|
|
17
|
+
* @param authorization An object containing your userName and webApiKey.
|
|
18
|
+
* This can be constructed with `buildAuthorization()`.
|
|
19
|
+
*
|
|
20
|
+
* @param payload.userName The user for which to retrieve the
|
|
21
|
+
* list of achievements for.
|
|
22
|
+
*
|
|
23
|
+
* @param payload.fromDate A Date object specifying when
|
|
24
|
+
* the list itself should begin.
|
|
25
|
+
*
|
|
26
|
+
* @param payload.toDate A Date object specifying when
|
|
27
|
+
* the list itself should end.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```
|
|
31
|
+
* const achievementsEarnedBetween = await getAchievementsEarnedBetween(
|
|
32
|
+
* authorization,
|
|
33
|
+
* {
|
|
34
|
+
* userName: "xelnia",
|
|
35
|
+
* fromDate: new Date("2022-10-12"),
|
|
36
|
+
* toDate: new Date("2022-10-13")
|
|
37
|
+
* }
|
|
38
|
+
* );
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @returns An array containing metadata about the user
|
|
42
|
+
* achievements earned during the specified date range.
|
|
43
|
+
* ```
|
|
44
|
+
* [
|
|
45
|
+
* {
|
|
46
|
+
* date: '2022-10-12 07:58:05',
|
|
47
|
+
* hardcoreMode: true,
|
|
48
|
+
* achievementId: 173315,
|
|
49
|
+
* title: 'Your Puny Human Weapons',
|
|
50
|
+
* description: 'Collect all objects in the Weapons Category.',
|
|
51
|
+
* badgeName: '193756',
|
|
52
|
+
* points: 10,
|
|
53
|
+
* author: 'blendedsea',
|
|
54
|
+
* gameTitle: 'Me & My Katamari',
|
|
55
|
+
* gameIcon: '/Images/047357.png',
|
|
56
|
+
* gameId: 3571,
|
|
57
|
+
* consoleName: 'PlayStation Portable',
|
|
58
|
+
* cumulScore: 120,
|
|
59
|
+
* badgeUrl: '/Badge/193756.png',
|
|
60
|
+
* gameUrl: '/game/3571'
|
|
61
|
+
* }
|
|
62
|
+
* ]
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export const getAchievementsEarnedBetween = async (
|
|
66
|
+
authorization: AuthObject,
|
|
67
|
+
payload: { userName: string; fromDate: Date; toDate: Date }
|
|
68
|
+
): Promise<DatedUserAchievement[]> => {
|
|
69
|
+
const { userName, fromDate, toDate } = payload;
|
|
70
|
+
|
|
71
|
+
const url = buildRequestUrl(
|
|
72
|
+
apiBaseUrl,
|
|
73
|
+
"/API_GetAchievementsEarnedBetween.php",
|
|
74
|
+
authorization,
|
|
75
|
+
{
|
|
76
|
+
u: userName,
|
|
77
|
+
f: (fromDate.getTime() / 1000).toFixed(0),
|
|
78
|
+
t: (toDate.getTime() / 1000).toFixed(0)
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const rawResponse = await call<DatedUserAchievementsResponse>({ url });
|
|
83
|
+
|
|
84
|
+
return serializeProperties(rawResponse, {
|
|
85
|
+
shouldCastToNumbers: ["AchievementID", "Points", "GameID"],
|
|
86
|
+
shouldMapToBooleans: ["HardcoreMode"]
|
|
87
|
+
});
|
|
88
|
+
};
|