Skip to content

Commit

Permalink
feat: add getUserRecentAchievements function
Browse files Browse the repository at this point in the history
  • Loading branch information
wescopeland committed May 23, 2023
1 parent b08ab17 commit 2ccc039
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Click the function names to open their complete docs on the docs site.
- [`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.
- [`getUserPoints()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-points.html) - Get a user's total hardcore and softcore points.
- [`getUserProgress()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-progress.html) - Get a user's progress on a list of specified games.
- [`getUserRecentAchievements()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-recent-achievements.html) - Get a list of achievements recently earned by the user.
- [`getUserRecentlyPlayedGames()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-recently-played-games.html) - Get a list of games a user has recently played.
- [`getUserSummary()`](https://retroachievements-api-js.vercel.app/v1/users/get-user-summary.html) - Get a user's profile metadata.

Expand Down
60 changes: 60 additions & 0 deletions docs/v1/users/get-user-recent-achievements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# getUserRecentAchievements

A call to this function will retrieve a list of a target user's recently earned achievements, via their username. By default, it fetches achievements earned in the last hour.

## Examples

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

// This gets the user's achievements earned in the last hour.
const userRecentAchievements = await getUserRecentAchievements(authorization, {
userName: "xelnia"
});
```

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

// This gets the user's achievements earned in the last two hours.
const userRecentAchievements = await getUserRecentAchievements(authorization, {
userName: "xelnia",
recentMinutes: 120
});
```

## Returns

```json
[
{
"date": "2023-05-23 22:32:24",
"hardcoreMode": true,
"achievementId": 51214,
"title": "You're a special Champ!",
"description": "Win the Tournament as [You] on Hard with 1 attribute on max. and 1 attribute on min.",
"badgeName": "121991",
"points": 25,
"author": "Som1",
"gameTitle": "WWF King of the Ring",
"gameIcon": "/Images/062599.png",
"gameId": 6316,
"consoleName": "Game Boy",
"badgeUrl": "/Badge/121991.png",
"gameUrl": "/game/6316"
}
]
```

## 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 recently played games for. |
| `recentMinutes` | `number?` | Optional. Defaults to 60. How many minutes back to fetch for the given user. |

## Source

[@retroachievements/api, getUserRecentAchievements.ts](https://github.dev/RetroAchievements/retroachievements-api-js/blob/main/src/user/getUserRecentAchievements.ts)
[RAWeb, API_GetUserRecentAchievements.php](https://github.dev/RetroAchievements/RAWeb/blob/master/public/API/API_GetUserRecentAchievements.php)
82 changes: 82 additions & 0 deletions src/user/getUserRecentAchievements.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { rest } from "msw";
import { setupServer } from "msw/node";

import { apiBaseUrl } from "../utils/internal";
import { buildAuthorization } from "../utils/public";
import { getUserRecentAchievements } from "./getUserRecentAchievements";
import type { GetUserRecentAchievementsResponse } from "./models";

const server = setupServer();

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

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

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

const mockResponse: GetUserRecentAchievementsResponse = [
{
Date: "2023-05-23 22:32:24",
HardcoreMode: 1,
AchievementID: 51_214,
Title: "You're a special Champ!",
Description:
"Win the Tournament as [You] on Hard with 1 attribute on max. and 1 attribute on min.",
BadgeName: "121991",
Points: 25,
Author: "Som1",
GameTitle: "WWF King of the Ring",
GameIcon: "/Images/062599.png",
GameID: 6316,
ConsoleName: "Game Boy",
BadgeURL: "/Badge/121991.png",
GameURL: "/game/6316"
}
];

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

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

// ASSERT
expect(response).toEqual([
{
date: "2023-05-23 22:32:24",
hardcoreMode: true,
achievementId: 51_214,
title: "You're a special Champ!",
description:
"Win the Tournament as [You] on Hard with 1 attribute on max. and 1 attribute on min.",
badgeName: "121991",
points: 25,
author: "Som1",
gameTitle: "WWF King of the Ring",
gameIcon: "/Images/062599.png",
gameId: 6316,
consoleName: "Game Boy",
badgeUrl: "/Badge/121991.png",
gameUrl: "/game/6316"
}
]);
});
});
80 changes: 80 additions & 0 deletions src/user/getUserRecentAchievements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
apiBaseUrl,
buildRequestUrl,
call,
serializeProperties
} from "../utils/internal";
import type { AuthObject } from "../utils/public";
import type {
GetUserRecentAchievementsResponse,
UserRecentAchievement
} from "./models";

/**
* A call to this function will retrieve a list of a target user's
* recently earned achievements, via their username. By default, it
* fetches achievements earned in the last hour.
*
* @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.recentMinutes Optional. Defaults to 60. How many minutes
* back to fetch for the given user.
*
* @example
* ```
* const userRecentAchievements = await getUserRecentAchievements(
* authorization,
* { userName: "xelnia" }
* );
* ```
*
* @returns An array containing metadata about a user's recently earned achievements.
* ```json
* [
* {
* date: '2023-05-23 22:32:24',
* hardcoreMode: true,
* achievementId: 51214,
* title: "You're a special Champ!",
* description: 'Win the Tournament as [You] on Hard with 1 attribute on max. and 1 attribute on min.',
* badgeName: '121991',
* points: 25,
* author: 'Som1',
* gameTitle: 'WWF King of the Ring',
* gameIcon: '/Images/062599.png',
* gameId: 6316,
* consoleName: 'Game Boy',
* badgeUrl: '/Badge/121991.png',
* gameUrl: '/game/6316'
* }
* ]
* ```
*/
export const getUserRecentAchievements = async (
authorization: AuthObject,
payload: { userName: string; recentMinutes?: number }
): Promise<UserRecentAchievement[]> => {
const { userName, recentMinutes } = payload;

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

if (recentMinutes !== undefined) {
queryParams["m"] = recentMinutes;
}

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

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

return serializeProperties(rawResponse, {
shouldMapToBooleans: ["HardcoreMode"]
});
};
1 change: 1 addition & 0 deletions src/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from "./getUserCompletedGames";
export * from "./getUserGameRankAndScore";
export * from "./getUserPoints";
export * from "./getUserProgress";
export * from "./getUserRecentAchievements";
export * from "./getUserRecentlyPlayedGames";
export * from "./getUserSummary";
export * from "./models";
19 changes: 19 additions & 0 deletions src/user/models/get-user-recent-achievements-response.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
interface GetUserRecentAchievementsEntity {
Date: string;
HardcoreMode: 0 | 1;
AchievementID: number;
Title: string;
Description: string;
BadgeName: string;
Points: number;
Author: string;
GameTitle: string;
GameIcon: string;
GameID: number;
ConsoleName: string;
BadgeURL: string;
GameURL: string;
}

export type GetUserRecentAchievementsResponse =
GetUserRecentAchievementsEntity[];
2 changes: 2 additions & 0 deletions src/user/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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-claims.model";
Expand All @@ -14,5 +15,6 @@ export * from "./user-completed-games.model";
export * from "./user-game-rank-and-score.model";
export * from "./user-points.model";
export * from "./user-progress.model";
export * from "./user-recent-achievement.model";
export * from "./user-recently-played-games.model";
export * from "./user-summary.model";
16 changes: 16 additions & 0 deletions src/user/models/user-recent-achievement.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface UserRecentAchievement {
date: string;
hardcoreMode: boolean;
achievementId: number;
title: string;
description: string;
badgeName: string;
points: number;
author: string;
gameTitle: string;
gameIcon: string;
gameId: number;
consoleName: string;
badgeUrl: string;
gameUrl: string;
}

1 comment on commit 2ccc039

@vercel
Copy link

@vercel vercel bot commented on 2ccc039 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.