From 4e09613908d896ff6d6f30ffdade8914a9272261 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Fri, 24 May 2024 16:13:52 -0400 Subject: [PATCH] feat(getRecentGameAwards): add function --- README.md | 1 + src/feed/getRecentGameAwards.test.ts | 73 ++++++++++++++++ src/feed/getRecentGameAwards.ts | 85 +++++++++++++++++++ src/feed/index.ts | 1 + .../get-recent-game-awards-response.model.ts | 15 ++++ src/feed/models/index.ts | 2 + src/feed/models/recent-game-awards.model.ts | 15 ++++ .../game-info-and-user-progress.model.ts | 8 +- ...e-info-and-user-progress-response.model.ts | 8 +- ...user-completion-progress-response.model.ts | 9 +- .../user-completion-progress-entity.model.ts | 9 +- src/utils/public/models/award-kind.model.ts | 5 ++ src/utils/public/models/index.ts | 1 + 13 files changed, 208 insertions(+), 24 deletions(-) create mode 100644 src/feed/getRecentGameAwards.test.ts create mode 100644 src/feed/getRecentGameAwards.ts create mode 100644 src/feed/models/get-recent-game-awards-response.model.ts create mode 100644 src/feed/models/recent-game-awards.model.ts create mode 100644 src/utils/public/models/award-kind.model.ts diff --git a/README.md b/README.md index 1447982..c1f8a94 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ Click the function names to open their complete docs on the docs site. - [`getActiveClaims()`](https://api-docs.retroachievements.org/v1/get-active-claims.html) - Get all active set claims on the site. - [`getClaims()`](https://api-docs.retroachievements.org/v1/get-claims.html) - Get all claims of other kinds on the site. +- [`getRecentGameAwards()`](https://api-docs.retroachievements.org/v1/get-recent-game-awards.html) - Get all recent mastery, completion, and beaten awards earned on the site. - [`getTopTenUsers()`](https://api-docs.retroachievements.org/v1/get-top-ten-users.html) - Get the list of top ten points earners. ### Event diff --git a/src/feed/getRecentGameAwards.test.ts b/src/feed/getRecentGameAwards.test.ts new file mode 100644 index 0000000..746738e --- /dev/null +++ b/src/feed/getRecentGameAwards.test.ts @@ -0,0 +1,73 @@ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; + +import { apiBaseUrl } from "../utils/internal"; +import { buildAuthorization } from "../utils/public"; +import { getRecentGameAwards } from "./getRecentGameAwards"; +import type { GetRecentGameAwardsResponse, RecentGameAwards } from "./models"; + +const server = setupServer(); + +describe("Function: getRecentGameAwards", () => { + // MSW Setup + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + + it("is defined #sanity", () => { + // ASSERT + expect(getRecentGameAwards).toBeDefined(); + }); + + it("retrieves metadata about all recently-earned game awards on the site", async () => { + // ARRANGE + const authorization = buildAuthorization({ + username: "mockUserName", + webApiKey: "mockWebApiKey", + }); + + const mockResponse: GetRecentGameAwardsResponse = { + Count: 1, + Total: 1, + Results: [ + { + User: "renanbrj", + AwardKind: "mastered", + AwardDate: "2022-01-01T23:48:04+00:00", + GameID: 14_284, + GameTitle: "Batman Returns", + ConsoleID: 15, + ConsoleName: "Game Gear", + }, + ], + }; + + server.use( + http.get(`${apiBaseUrl}/API_GetRecentGameAwards.php`, () => + HttpResponse.json(mockResponse) + ) + ); + + // ACT + const response = await getRecentGameAwards(authorization); + + const expectedResponse: RecentGameAwards = { + count: 1, + total: 1, + results: [ + { + user: "renanbrj", + awardKind: "mastered", + awardDate: "2022-01-01T23:48:04+00:00", + gameId: 14_284, + gameTitle: "Batman Returns", + consoleId: 15, + consoleName: "Game Gear", + }, + ], + }; + + // ASSERT + expect(response).toEqual(expectedResponse); + }); +}); diff --git a/src/feed/getRecentGameAwards.ts b/src/feed/getRecentGameAwards.ts new file mode 100644 index 0000000..01ee1f7 --- /dev/null +++ b/src/feed/getRecentGameAwards.ts @@ -0,0 +1,85 @@ +import { + apiBaseUrl, + buildRequestUrl, + call, + serializeProperties, +} from "../utils/internal"; +import type { AuthObject, AwardKind } from "../utils/public"; +import type { GetRecentGameAwardsResponse, RecentGameAwards } from "./models"; + +/** + * A call to this function will retrieve all recently granted game + * awards across the site's userbase. + * + * @param authorization An object containing your username and webApiKey. + * This can be constructed with `buildAuthorization()`. + * + * @param payload.startDate The date to fetch awards from. + * + * @param payload.offset Optional. Defaults to 0. + * + * @param payload.count Optional. Defaults to 25. + * + * @param payload.desiredAwardKinds Optional. Defaults to all. Accepts "beaten-softcore", "beaten-hardcore", "completed", and/or "mastered". + * + * @example + * ``` + * const recentGameAwards = await getRecentGameAwards( + * authorization, + * ); + * ``` + * + * @returns An object containing metadata about all recently granted game + * awards across the site's userbase + * ``` + * { + * count: 1, + * total: 1, + * results: [ + * { + * user: "renanbrj", + * awardKind: "mastered", + * awardDate: "2022-01-01T23:48:04+00:00", + * gameId: 14_284, + * gameTitle: "Batman Returns", + * consoleId: 15, + * consoleName: "Game Gear", + * }, + * ], + * } + * ``` + */ +export const getRecentGameAwards = async ( + authorization: AuthObject, + payload?: Partial<{ + startDate: string; + offset: number; + count: number; + desiredAwardKinds: AwardKind[]; + }> +): Promise => { + const queryParams: Record = {}; + if (payload?.startDate) { + queryParams.d = payload.startDate; + } + if (payload?.offset) { + queryParams.o = payload.offset; + } + if (payload?.count) { + queryParams.c = payload.count; + } + if (payload?.desiredAwardKinds) { + queryParams.k = payload.desiredAwardKinds.join(","); + } + + const url = buildRequestUrl( + apiBaseUrl, + "/API_GetRecentGameAwards.php", + authorization, + queryParams + ); + + const rawResponse = await call({ url }); + + return serializeProperties(rawResponse); +}; diff --git a/src/feed/index.ts b/src/feed/index.ts index a8d6aec..4d4c699 100644 --- a/src/feed/index.ts +++ b/src/feed/index.ts @@ -1,5 +1,6 @@ export * from "./getAchievementOfTheWeek"; export * from "./getActiveClaims"; export * from "./getClaims"; +export * from "./getRecentGameAwards"; export * from "./getTopTenUsers"; export * from "./models"; diff --git a/src/feed/models/get-recent-game-awards-response.model.ts b/src/feed/models/get-recent-game-awards-response.model.ts new file mode 100644 index 0000000..e388d25 --- /dev/null +++ b/src/feed/models/get-recent-game-awards-response.model.ts @@ -0,0 +1,15 @@ +import type { AwardKind } from "../../utils/public"; + +export interface GetRecentGameAwardsResponse { + Count: number; + Total: number; + Results: Array<{ + User: string; + AwardKind: AwardKind; + AwardDate: string; + GameID: number; + GameTitle: string; + ConsoleID: number; + ConsoleName: string; + }>; +} diff --git a/src/feed/models/index.ts b/src/feed/models/index.ts index 7c41b28..0ebb73c 100644 --- a/src/feed/models/index.ts +++ b/src/feed/models/index.ts @@ -3,8 +3,10 @@ export * from "./claim-set-type.enum"; export * from "./claim-status.enum"; export * from "./claim-type.enum"; export * from "./get-achievement-of-the-week-response.model"; +export * from "./get-recent-game-awards-response.model"; export * from "./get-set-claims-response.model"; export * from "./get-top-ten-users-response.model"; +export * from "./recent-game-awards.model"; export * from "./set-claim.model"; export * from "./top-ten-users.model"; export * from "./top-ten-users-entity.model"; diff --git a/src/feed/models/recent-game-awards.model.ts b/src/feed/models/recent-game-awards.model.ts new file mode 100644 index 0000000..7cf5035 --- /dev/null +++ b/src/feed/models/recent-game-awards.model.ts @@ -0,0 +1,15 @@ +import type { AwardKind } from "../../utils/public"; + +export interface RecentGameAwards { + count: number; + total: number; + results: Array<{ + user: string; + awardKind: AwardKind; + awardDate: string; + gameId: number; + gameTitle: string; + consoleId: number; + consoleName: string; + }>; +} diff --git a/src/user/models/game-info-and-user-progress.model.ts b/src/user/models/game-info-and-user-progress.model.ts index 7fbba87..45b1c9b 100644 --- a/src/user/models/game-info-and-user-progress.model.ts +++ b/src/user/models/game-info-and-user-progress.model.ts @@ -2,6 +2,7 @@ import type { GameExtended, GameExtendedAchievementEntity, } from "../../game/models"; +import type { AwardKind } from "../../utils/public"; export type GameExtendedAchievementEntityWithUserProgress = GameExtendedAchievementEntity & { @@ -17,11 +18,6 @@ export interface GameInfoAndUserProgress extends GameExtended { userCompletion: string; userCompletionHardcore: string; - highestAwardKind?: - | "mastered" - | "completed" - | "beaten-hardcore" - | "beaten-softcore" - | null; + highestAwardKind?: AwardKind | null; highestAwardDate?: string; } diff --git a/src/user/models/get-game-info-and-user-progress-response.model.ts b/src/user/models/get-game-info-and-user-progress-response.model.ts index 11a6ff8..238ca71 100644 --- a/src/user/models/get-game-info-and-user-progress-response.model.ts +++ b/src/user/models/get-game-info-and-user-progress-response.model.ts @@ -2,6 +2,7 @@ import type { GameExtendedRawAchievementEntity, GetGameExtendedResponse, } from "../../game/models"; +import type { AwardKind } from "../../utils/public"; type GetGameExtendedResponseWithoutClaims = Omit< GetGameExtendedResponse, @@ -26,11 +27,6 @@ export interface GetGameInfoAndUserProgressResponse UserCompletion: string; UserCompletionHardcore: string; - HighestAwardKind?: - | "mastered" - | "completed" - | "beaten-hardcore" - | "beaten-softcore" - | null; + HighestAwardKind?: AwardKind | null; HighestAwardDate?: string; } diff --git a/src/user/models/get-user-completion-progress-response.model.ts b/src/user/models/get-user-completion-progress-response.model.ts index a6387f6..bf49c65 100644 --- a/src/user/models/get-user-completion-progress-response.model.ts +++ b/src/user/models/get-user-completion-progress-response.model.ts @@ -1,3 +1,5 @@ +import type { AwardKind } from "../../utils/public"; + interface RawUserCompletionProgressEntity { GameID: number; Title: string; @@ -9,12 +11,7 @@ interface RawUserCompletionProgressEntity { NumAwardedHardcore: number; MostRecentAwardedDate?: string; - HighestAwardKind?: - | "mastered" - | "completed" - | "beaten-hardcore" - | "beaten-softcore" - | null; + HighestAwardKind?: AwardKind | null; HighestAwardDate?: string | null; } diff --git a/src/user/models/user-completion-progress-entity.model.ts b/src/user/models/user-completion-progress-entity.model.ts index 8896e9e..ffdcda2 100644 --- a/src/user/models/user-completion-progress-entity.model.ts +++ b/src/user/models/user-completion-progress-entity.model.ts @@ -1,3 +1,5 @@ +import type { AwardKind } from "../../utils/public"; + export interface UserCompletionProgressEntity { gameId: number; title: string; @@ -9,11 +11,6 @@ export interface UserCompletionProgressEntity { numAwardedHardcore: number; mostRecentAwardedDate?: string; - highestAwardKind?: - | "mastered" - | "completed" - | "beaten-hardcore" - | "beaten-softcore" - | null; + highestAwardKind?: AwardKind | null; highestAwardDate?: string; } diff --git a/src/utils/public/models/award-kind.model.ts b/src/utils/public/models/award-kind.model.ts new file mode 100644 index 0000000..f9c26b0 --- /dev/null +++ b/src/utils/public/models/award-kind.model.ts @@ -0,0 +1,5 @@ +export type AwardKind = + | "beaten-softcore" + | "beaten-hardcore" + | "completed" + | "mastered"; diff --git a/src/utils/public/models/index.ts b/src/utils/public/models/index.ts index 489852c..04c545d 100644 --- a/src/utils/public/models/index.ts +++ b/src/utils/public/models/index.ts @@ -1 +1,2 @@ export * from "./auth-object.model"; +export * from "./award-kind.model";