Add received/sent friend requests to API proxy

This commit is contained in:
Samuel Elliott
2025-07-25 19:33:45 +01:00
parent cd96ed7960
commit e9137a41c6
2 changed files with 60 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
import { fetch, Response } from 'undici';
import { ActiveEvent, CurrentUser, Event, Friend, Presence, PresencePermissions, User, WebServiceToken, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, WebService_4, Media, Announcements_4, Friend_4, PresenceOnline_4, PresenceOnline, PresenceOffline, GetActiveEventResult } from './coral-types.js';
import { ActiveEvent, CurrentUser, Event, Friend, PresencePermissions, User, WebServiceToken, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, WebService_4, Media, Announcements_4, Friend_4, PresenceOnline_4, PresenceOnline, PresenceOffline, GetActiveEventResult, ReceivedFriendRequest, SentFriendRequest } from './coral-types.js';
import { defineResponse, ErrorResponse, ResponseSymbol } from './util.js';
import { AbstractCoralApi, CoralApiInterface, CoralAuthData, CorrelationIdSymbol, PartialCoralAuthData, RequestFlagAddPlatformSymbol, RequestFlagAddProductVersionSymbol, RequestFlagNoParameterSymbol, RequestFlagRequestIdSymbol, RequestFlags, ResponseDataSymbol, ResponseEncryptionSymbol, Result } from './coral.js';
import { NintendoAccountToken, NintendoAccountUser } from './na.js';
@@ -139,6 +139,16 @@ export default class ZncProxyApi extends AbstractCoralApi implements CoralApiInt
return createResult(result, result.user);
}
async getReceivedFriendRequests() {
const result = await this.fetchProxyApi<{friend_requests: ReceivedFriendRequest[]}>('friends/requests/received');
return createResult(result, {friendRequests: result.friend_requests});
}
async getSentFriendRequests() {
const result = await this.fetchProxyApi<{friend_requests: SentFriendRequest[]}>('friends/requests/sent');
return createResult(result, {friendRequests: result.friend_requests});
}
async getFriendCodeUrl() {
const result = await this.fetchProxyApi<{friendcode: FriendCodeUrl}>('friendcode');
return createResult(result, result.friendcode);
@@ -233,6 +243,7 @@ export interface AuthPolicy {
list_friends_presence?: boolean;
friend?: boolean;
friend_presence?: boolean;
list_friend_requests?: boolean;
webservices?: boolean;
activeevent?: boolean;
chats?: boolean;

View File

@@ -164,6 +164,11 @@ class Server extends HttpServer {
app.get('/api/znc/friend/:nsaid/presence', this.authTokenMiddleware, this.localAuthMiddleware,
this.createProxyRequestHandler(r => this.handleFriendPresenceRequest(r, r.req.params.nsaid)));
app.get('/api/znc/friends/requests/received', this.authTokenMiddleware, this.localAuthMiddleware,
this.createProxyRequestHandler(r => this.handleReceivedFriendRequestsRequest(r)));
app.get('/api/znc/friends/requests/sent', this.authTokenMiddleware, this.localAuthMiddleware,
this.createProxyRequestHandler(r => this.handleSentFriendRequestsRequest(r)));
app.get('/api/znc/webservices', this.authTokenMiddleware, this.localAuthMiddleware,
this.createProxyRequestHandler(r => this.handleWebServicesRequest(r)));
app.get('/api/znc/webservice/:id/token',
@@ -665,6 +670,34 @@ class Server extends HttpServer {
return friend.presence;
}
async handleReceivedFriendRequestsRequest({req, res, policy}: RequestData) {
if (policy && !policy.list_friend_requests) {
throw new ResponseError(403, 'insufficient_scope');
}
const user = await this.getCoralUser(req);
const friend_requests = await user.getReceivedFriendRequests();
const updated = user.updated.fr_received!;
res.setHeader('Cache-Control', 'private, immutable, max-age=' + cacheMaxAge(updated, this.update_interval));
return {friend_requests, updated};
}
async handleSentFriendRequestsRequest({req, res, policy}: RequestData) {
if (policy && !policy.list_friend_requests) {
throw new ResponseError(403, 'insufficient_scope');
}
const user = await this.getCoralUser(req);
const friend_requests = await user.getSentFriendRequests();
const updated = user.updated.fr_sent!;
res.setHeader('Cache-Control', 'private, immutable, max-age=' + cacheMaxAge(updated, this.update_interval));
return {friend_requests, updated};
}
async handleWebServicesRequest({req, res, policy}: RequestData) {
if (policy && !policy.webservices) {
throw new ResponseError(403, 'insufficient_scope');
@@ -766,6 +799,12 @@ class Server extends HttpServer {
try {
return await this._cache(friendcode, async (): Promise<[FriendCodeUser | null, string]> => {
try {
// Always requested on the add friend page
Promise.all([
coral.getReceivedFriendRequests(),
coral.getSentFriendRequests(),
]);
const user = await coral.getUserByFriendCode(friendcode);
return [user, id];
} catch (err) {
@@ -800,8 +839,15 @@ class Server extends HttpServer {
private cached_friendcodeurl = new Map</** NA ID */ string, [number, FriendCodeUrl]>();
getFriendCodeUrl(id: string, coral: CoralApiInterface) {
return this._cache(id, () => coral.getFriendCodeUrl(),
this.user_friendcodeurl_promise, this.cached_friendcodeurl);
return this._cache(id, async () => {
// Always requested on the add friend page
Promise.all([
coral.getReceivedFriendRequests(),
coral.getSentFriendRequests(),
]);
return coral.getFriendCodeUrl();
}, this.user_friendcodeurl_promise, this.cached_friendcodeurl);
}
async handleFriendCodeUrlRequest({res, user}: RequestDataWithUser) {