Skip to content

Commit

Permalink
feat: add getUserAwards function
Browse files Browse the repository at this point in the history
  • Loading branch information
wescopeland committed May 23, 2023
1 parent 2ccc039 commit f70e048
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Click the function names to open their complete docs on the docs site.
- [`getAchievementsEarnedBetween()`](https://retroachievements-api-js.vercel.app/v1/users/get-achievements-earned-between.html) - Get a list of achievements earned by a user between two dates.
- [`getAchievementsEarnedOnDay()`](https://retroachievements-api-js.vercel.app/v1/users/get-achievements-earned-on-day.html) - Get a list of achievements earned by a user on a given date.
- [`getGameInfoAndUserProgress()`](https://retroachievements-api-js.vercel.app/v1/users/get-game-info-and-user-progress.html) - Get metadata about a game as well as a user's progress on that game.
- [`getUserAwards()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-awards.html) - Get a list of a user's site awards/badges.
- [`getUserClaims()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-claims.html) - Get a list of set claims made over the lifetime of a user.
- [`getUserCompletedGames()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-completed-games.html) - Get hardcore and softcore completion metadata about games a user has played.
- [`getUserGameRankAndScore()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-game-rank-and-score.html) - Get metadata about how a user has performed on a given game.
Expand Down
8 changes: 8 additions & 0 deletions docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export default {
text: "Users",
collapsible: true,
items: [
{
text: "Recent Achievements",
link: "/v1/users/get-user-recent-achievements"
},
{
text: "Achievements Earned Between Days",
link: "/v1/users/get-achievements-earned-between"
Expand All @@ -73,6 +77,10 @@ export default {
text: "Progress for Game with Game Info",
link: "/v1/users/get-game-info-and-user-progress"
},
{
text: "Awards / Badges",
link: "/v1/users/get-user-awards"
},
{
text: "Set Claims",
link: "/v1/users/get-user-claims"
Expand Down
49 changes: 49 additions & 0 deletions docs/v1/users/get-user-awards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# getUserAwards

A call to this function will retrieve metadata about the target user's site awards, via their username.

## Examples

```ts
import { getUserAwards } from "@retroachievements/api";

const userAwards = await getUserAwards(authorization, { userName: "xelnia" });
```

## Returns

```json
{
"totalAwardsCount": 10,
"hiddenAwardsCount": 2,
"masteryAwardsCount": 6,
"completionAwardsCount": 0,
"eventAwardsCount": 0,
"siteAwardsCount": 2,
"visibleUserAwards": [
{
"awardedAt": "2022-08-26T19:34:43+00:00",
"awardType": "Mastery/Completion",
"awardData": 802,
"awardDataExtra": 1,
"displayOrder": 114,
"title": "WarioWare, Inc.: Mega Microgames!",
"consoleName": "Game Boy Advance",
"flags": null,
"imageIcon": "/Images/034678.png"
}
]
}
```

## Parameters

| Name | Type | Description |
| :-------------- | :------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------- |
| `authorization` | [`AuthObject`](/v1/data-models/auth-object) | An object that must contain a `userName` and a `webApiKey`. See [this page](/getting-started) for how to create this object. |
| `userName` | `string` | The user for which to retrieve the site awards for. |

## Source

[@retroachievements/api, getUserAwards.ts](https://github.dev/RetroAchievements/retroachievements-api-js/blob/main/src/user/getUserAwards.ts)
[RAWeb, API_GetUserAwards.php](https://github.dev/RetroAchievements/RAWeb/blob/master/public/API/API_GetUserAwards.php)
2 changes: 1 addition & 1 deletion docs/v1/users/get-user-recent-achievements.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const userRecentAchievements = await getUserRecentAchievements(authorization, {
| Name | Type | Description |
| :-------------- | :------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------- |
| `authorization` | [`AuthObject`](/v1/data-models/auth-object) | An object that must contain a `userName` and a `webApiKey`. See [this page](/getting-started) for how to create this object. |
| `userName` | `string` | The user for which to retrieve the recently played games for. |
| `userName` | `string` | The user for which to retrieve the recently earned achievements for. |
| `recentMinutes` | `number?` | Optional. Defaults to 60. How many minutes back to fetch for the given user. |

## Source
Expand Down
83 changes: 83 additions & 0 deletions src/user/getUserAwards.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { rest } from "msw";
import { setupServer } from "msw/node";

import { apiBaseUrl } from "../utils/internal";
import { buildAuthorization } from "../utils/public";
import { getUserAwards } from "./getUserAwards";
import type { GetUserAwardsResponse } from "./models";

const server = setupServer();

describe("Function: getUserAwards", () => {
// MSW Setup
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("is defined #sanity", () => {
// ASSERT
expect(getUserAwards).toBeDefined();
});

it("retrieves a list of a target user awards", async () => {
// ARRANGE
const authorization = buildAuthorization({
userName: "mockUserName",
webApiKey: "mockWebApiKey"
});

const mockResponse: GetUserAwardsResponse = {
TotalAwardsCount: 10,
HiddenAwardsCount: 5,
MasteryAwardsCount: 5,
CompletionAwardsCount: 0,
EventAwardsCount: 0,
SiteAwardsCount: 0,
VisibleUserAwards: [
{
AwardedAt: "2022-08-26T19:34:43+00:00",
AwardType: "Mastery/Completion",
AwardData: 802,
AwardDataExtra: 1,
DisplayOrder: 114,
Title: "WarioWare, Inc.: Mega Microgames!",
ConsoleName: "Game Boy Advance",
Flags: null,
ImageIcon: "/Images/034678.png"
}
]
};

server.use(
rest.get(`${apiBaseUrl}/API_GetUserAwards.php`, (_, res, ctx) =>
res(ctx.json(mockResponse))
)
);

// ACT
const response = await getUserAwards(authorization, { userName: "xelnia" });

// ASSERT
expect(response).toEqual({
totalAwardsCount: 10,
hiddenAwardsCount: 5,
masteryAwardsCount: 5,
completionAwardsCount: 0,
eventAwardsCount: 0,
siteAwardsCount: 0,
visibleUserAwards: [
{
awardedAt: "2022-08-26T19:34:43+00:00",
awardType: "Mastery/Completion",
awardData: 802,
awardDataExtra: 1,
displayOrder: 114,
title: "WarioWare, Inc.: Mega Microgames!",
consoleName: "Game Boy Advance",
flags: null,
imageIcon: "/Images/034678.png"
}
]
});
});
});
70 changes: 70 additions & 0 deletions src/user/getUserAwards.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
apiBaseUrl,
buildRequestUrl,
call,
serializeProperties
} from "../utils/internal";
import type { AuthObject } from "../utils/public";
import type { GetUserAwardsResponse, UserAwards } from "./models";

/**
* A call to this function will retrieve metadata about the target user's
* site awards, via their username.
*
* @param authorization An object containing your userName and webApiKey.
* This can be constructed with `buildAuthorization()`.
*
* @param payload.userName The user for which to retrieve the site awards for.
*
* @example
* ```
* const userAwards = await getUserAwards(
* authorization,
* { userName: "xelnia" }
* )
* ```
*
* @returns
* ```json
* {
* totalAwardsCount: 10,
* hiddenAwardsCount: 2,
* masteryAwardsCount: 6,
* completionAwardsCount: 0,
* eventAwardsCount: 0,
* siteAwardsCount: 2,
* visibleUserAwards: [
* {
* awardedAt: "2022-08-26T19:34:43+00:00",
* awardType: "Mastery/Completion",
* awardData: 802,
* awardDataExtra: 1,
* displayOrder: 114,
* title: "WarioWare, Inc.: Mega Microgames!",
* consoleName: "Game Boy Advance",
* flags: null,
* imageIcon: "/Images/034678.png"
* }
* ]
* }
* ```
*/
export const getUserAwards = async (
authorization: AuthObject,
payload: { userName: string }
): Promise<UserAwards> => {
const { userName } = payload;

const queryParams: Record<string, string> = { u: userName };

const url = buildRequestUrl(
apiBaseUrl,
"/API_GetUserAwards.php",
authorization,
queryParams
);

const rawResponse = await call<GetUserAwardsResponse>({ url });

return serializeProperties(rawResponse);
};
2 changes: 1 addition & 1 deletion src/user/getUserRecentAchievements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {
* @param authorization An object containing your userName and webApiKey.
* This can be constructed with `buildAuthorization()`.
*
* @param payload.userName The user for which to retrieve the summary for.
* @param payload.userName The user for which to retrieve the recent achievements for.
*
* @param payload.recentMinutes Optional. Defaults to 60. How many minutes
* back to fetch for the given user.
Expand Down
1 change: 1 addition & 0 deletions src/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./getAchievementsEarnedBetween";
export * from "./getAchievementsEarnedOnDay";
export * from "./getGameInfoAndUserProgress";
export * from "./getUserAwards";
export * from "./getUserClaims";
export * from "./getUserCompletedGames";
export * from "./getUserGameRankAndScore";
Expand Down
7 changes: 7 additions & 0 deletions src/user/models/award-type.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type AwardType =
| "Mastery/Completion"
| "Achievement Unlocks Yield"
| "Achievement Points Yield"
| "Patreon Supporter"
| "Certified Legend"
| "Invalid or deprecated award type";
23 changes: 23 additions & 0 deletions src/user/models/get-user-awards-response.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AwardType } from "./award-type.model";

interface GetUserAwardsEntity {
AwardedAt: string;
AwardType: AwardType;
AwardData: number;
AwardDataExtra: number;
DisplayOrder: number;
Title: string;
ConsoleName: string;
Flags: number | null;
ImageIcon: string;
}

export interface GetUserAwardsResponse {
TotalAwardsCount: number;
HiddenAwardsCount: number;
MasteryAwardsCount: number;
CompletionAwardsCount: number;
EventAwardsCount: number;
SiteAwardsCount: number;
VisibleUserAwards: GetUserAwardsEntity[];
}
3 changes: 3 additions & 0 deletions src/user/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
export * from "./award-type.model";
export * from "./dated-user-achievement.model";
export * from "./dated-user-achievements-response.model";
export * from "./game-info-and-user-progress.model";
export * from "./get-game-info-and-user-progress-response.model";
export * from "./get-user-awards-response.model";
export * from "./get-user-completed-games-response.model";
export * from "./get-user-game-rank-and-score-response.model";
export * from "./get-user-points-response.model";
export * from "./get-user-progress-response.model";
export * from "./get-user-recent-achievements-response.model";
export * from "./get-user-recently-played-games-response.model";
export * from "./get-user-summary-response.model";
export * from "./user-awards.model";
export * from "./user-claims.model";
export * from "./user-claims-response.model";
export * from "./user-completed-games.model";
Expand Down
23 changes: 23 additions & 0 deletions src/user/models/user-awards.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AwardType } from "./award-type.model";

interface UserAward {
awardedAt: string;
awardType: AwardType;
awardData: number;
awardDataExtra: number;
displayOrder: number;
title: string;
consoleName: string;
flags: number | null;
imageIcon: string;
}

export interface UserAwards {
totalAwardsCount: number;
hiddenAwardsCount: number;
masteryAwardsCount: number;
completionAwardsCount: number;
eventAwardsCount: number;
siteAwardsCount: number;
visibleUserAwards: UserAward[];
}
3 changes: 3 additions & 0 deletions src/utils/internal/serializeProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,8 @@ const naiveCamelCase = (originalValue: string) => {
// "rAPoints" -> "raPoints"
camelCased = camelCased.replace(/rA/g, "ra");

// "visibleUserawards" -> "visibleUserAwards"
camelCased = camelCased.replace(/visibleUserawards/g, "visibleUserAwards");

return camelCased;
};

1 comment on commit f70e048

@vercel
Copy link

@vercel vercel bot commented on f70e048 May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.