friends-backend

This commit is contained in:
Maieul BOYER 2026-01-16 16:18:54 +01:00 committed by Nigel
parent df79bc5a80
commit 590604b385
22 changed files with 1826 additions and 29 deletions

View file

@ -1,6 +1,8 @@
apis/OpenapiOtherApi.ts
apis/index.ts
index.ts
models/AddFriend200Response.ts
models/AddFriend404Response.ts
models/AllowGuestMessage200Response.ts
models/AllowGuestMessage403Response.ts
models/ChangeDesc200Response.ts
@ -38,6 +40,9 @@ models/GuestLogin200ResponsePayload.ts
models/GuestLogin400Response.ts
models/GuestLogin500Response.ts
models/GuestLoginRequest.ts
models/ListFriend200Response.ts
models/ListFriend200ResponsePayload.ts
models/ListFriend200ResponsePayloadFriendsInner.ts
models/Login200Response.ts
models/Login202Response.ts
models/Login202ResponsePayload.ts
@ -60,6 +65,8 @@ models/ProviderList200Response.ts
models/ProviderList200ResponsePayload.ts
models/ProviderList200ResponsePayloadListInner.ts
models/ProviderList200ResponsePayloadListInnerColors.ts
models/RemoveFriend200Response.ts
models/RemoveFriend404Response.ts
models/Signin200Response.ts
models/Signin200ResponsePayload.ts
models/Signin400Response.ts
@ -82,7 +89,6 @@ models/TournamentList404Response.ts
models/TttHistory200Response.ts
models/TttHistory200ResponsePayload.ts
models/TttHistory200ResponsePayloadDataInner.ts
models/TttHistory200ResponsePayloadDataInnerPlayerX.ts
models/TttHistory404Response.ts
models/index.ts
runtime.ts

View file

@ -15,6 +15,8 @@
import * as runtime from '../runtime';
import type {
AddFriend200Response,
AddFriend404Response,
AllowGuestMessage200Response,
AllowGuestMessage403Response,
ChangeDesc200Response,
@ -46,6 +48,7 @@ import type {
GuestLogin400Response,
GuestLogin500Response,
GuestLoginRequest,
ListFriend200Response,
Login200Response,
Login202Response,
Login400Response,
@ -60,6 +63,8 @@ import type {
PongHistory200Response,
PongHistory404Response,
ProviderList200Response,
RemoveFriend200Response,
RemoveFriend404Response,
Signin200Response,
Signin400Response,
Signin500Response,
@ -74,6 +79,10 @@ import type {
TttHistory404Response,
} from '../models/index';
import {
AddFriend200ResponseFromJSON,
AddFriend200ResponseToJSON,
AddFriend404ResponseFromJSON,
AddFriend404ResponseToJSON,
AllowGuestMessage200ResponseFromJSON,
AllowGuestMessage200ResponseToJSON,
AllowGuestMessage403ResponseFromJSON,
@ -136,6 +145,8 @@ import {
GuestLogin500ResponseToJSON,
GuestLoginRequestFromJSON,
GuestLoginRequestToJSON,
ListFriend200ResponseFromJSON,
ListFriend200ResponseToJSON,
Login200ResponseFromJSON,
Login200ResponseToJSON,
Login202ResponseFromJSON,
@ -164,6 +175,10 @@ import {
PongHistory404ResponseToJSON,
ProviderList200ResponseFromJSON,
ProviderList200ResponseToJSON,
RemoveFriend200ResponseFromJSON,
RemoveFriend200ResponseToJSON,
RemoveFriend404ResponseFromJSON,
RemoveFriend404ResponseToJSON,
Signin200ResponseFromJSON,
Signin200ResponseToJSON,
Signin400ResponseFromJSON,
@ -190,6 +205,10 @@ import {
TttHistory404ResponseToJSON,
} from '../models/index';
export interface AddFriendRequest {
user: string;
}
export interface ChangeDescOperationRequest {
changeDescRequest: ChangeDescRequest;
}
@ -226,6 +245,10 @@ export interface PongHistoryRequest {
user: string;
}
export interface RemoveFriendRequest {
user: string;
}
export interface SigninRequest {
loginRequest: LoginRequest;
}
@ -243,6 +266,60 @@ export interface TttHistoryRequest {
*/
export class OpenapiOtherApi extends runtime.BaseAPI {
/**
*/
async addFriendRaw(requestParameters: AddFriendRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AddFriend200Response | ChangePassword401Response | AddFriend404Response>> {
if (requestParameters['user'] == null) {
throw new runtime.RequiredError(
'user',
'Required parameter "user" was null or undefined when calling addFriend().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
let urlPath = `/api/user/friend/add/{user}`;
urlPath = urlPath.replace(`{${"user"}}`, encodeURIComponent(String(requestParameters['user'])));
const response = await this.request({
path: urlPath,
method: 'PUT',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => AddFriend200ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => ChangePassword401ResponseFromJSON(jsonValue));
}
if (response.status === 404) {
// Object response for status 404
return new runtime.JSONApiResponse(response, (jsonValue) => AddFriend404ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401, 404`);
}
/**
*/
async addFriend(requestParameters: AddFriendRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AddFriend200Response | ChangePassword401Response | AddFriend404Response> {
const response = await this.addFriendRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async allowGuestMessageRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AllowGuestMessage200Response | StatusOtp401Response | AllowGuestMessage403Response>> {
@ -766,6 +843,48 @@ export class OpenapiOtherApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async listFriendRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ListFriend200Response | StatusOtp401Response>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
let urlPath = `/api/user/friend/list`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => ListFriend200ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => StatusOtp401ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401`);
}
/**
*/
async listFriend(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ListFriend200Response | StatusOtp401Response> {
const response = await this.listFriendRaw(initOverrides);
return await response.value();
}
/**
*/
async loginRaw(requestParameters: LoginOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Login200Response | Login202Response | Login400Response>> {
@ -1016,6 +1135,60 @@ export class OpenapiOtherApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async removeFriendRaw(requestParameters: RemoveFriendRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RemoveFriend200Response | ChangePassword401Response | RemoveFriend404Response>> {
if (requestParameters['user'] == null) {
throw new runtime.RequiredError(
'user',
'Required parameter "user" was null or undefined when calling removeFriend().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
let urlPath = `/api/user/friend/remove/{user}`;
urlPath = urlPath.replace(`{${"user"}}`, encodeURIComponent(String(requestParameters['user'])));
const response = await this.request({
path: urlPath,
method: 'PUT',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => RemoveFriend200ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => ChangePassword401ResponseFromJSON(jsonValue));
}
if (response.status === 404) {
// Object response for status 404
return new runtime.JSONApiResponse(response, (jsonValue) => RemoveFriend404ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401, 404`);
}
/**
*/
async removeFriend(requestParameters: RemoveFriendRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RemoveFriend200Response | ChangePassword401Response | RemoveFriend404Response> {
const response = await this.removeFriendRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async signinRaw(requestParameters: SigninRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Signin200Response | Signin400Response | Signin500Response>> {

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface AddFriend200Response
*/
export interface AddFriend200Response {
/**
*
* @type {string}
* @memberof AddFriend200Response
*/
kind: AddFriend200ResponseKindEnum;
/**
*
* @type {string}
* @memberof AddFriend200Response
*/
msg: AddFriend200ResponseMsgEnum;
}
/**
* @export
*/
export const AddFriend200ResponseKindEnum = {
Success: 'success'
} as const;
export type AddFriend200ResponseKindEnum = typeof AddFriend200ResponseKindEnum[keyof typeof AddFriend200ResponseKindEnum];
/**
* @export
*/
export const AddFriend200ResponseMsgEnum = {
AddFriendSuccess: 'addFriend.success'
} as const;
export type AddFriend200ResponseMsgEnum = typeof AddFriend200ResponseMsgEnum[keyof typeof AddFriend200ResponseMsgEnum];
/**
* Check if a given object implements the AddFriend200Response interface.
*/
export function instanceOfAddFriend200Response(value: object): value is AddFriend200Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function AddFriend200ResponseFromJSON(json: any): AddFriend200Response {
return AddFriend200ResponseFromJSONTyped(json, false);
}
export function AddFriend200ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddFriend200Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function AddFriend200ResponseToJSON(json: any): AddFriend200Response {
return AddFriend200ResponseToJSONTyped(json, false);
}
export function AddFriend200ResponseToJSONTyped(value?: AddFriend200Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface AddFriend404Response
*/
export interface AddFriend404Response {
/**
*
* @type {string}
* @memberof AddFriend404Response
*/
kind: AddFriend404ResponseKindEnum;
/**
*
* @type {string}
* @memberof AddFriend404Response
*/
msg: AddFriend404ResponseMsgEnum;
}
/**
* @export
*/
export const AddFriend404ResponseKindEnum = {
Failure: 'failure'
} as const;
export type AddFriend404ResponseKindEnum = typeof AddFriend404ResponseKindEnum[keyof typeof AddFriend404ResponseKindEnum];
/**
* @export
*/
export const AddFriend404ResponseMsgEnum = {
AddFriendFailureUnknownUser: 'addFriend.failure.unknownUser'
} as const;
export type AddFriend404ResponseMsgEnum = typeof AddFriend404ResponseMsgEnum[keyof typeof AddFriend404ResponseMsgEnum];
/**
* Check if a given object implements the AddFriend404Response interface.
*/
export function instanceOfAddFriend404Response(value: object): value is AddFriend404Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function AddFriend404ResponseFromJSON(json: any): AddFriend404Response {
return AddFriend404ResponseFromJSONTyped(json, false);
}
export function AddFriend404ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddFriend404Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function AddFriend404ResponseToJSON(json: any): AddFriend404Response {
return AddFriend404ResponseToJSONTyped(json, false);
}
export function AddFriend404ResponseToJSONTyped(value?: AddFriend404Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,110 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { ListFriend200ResponsePayload } from './ListFriend200ResponsePayload';
import {
ListFriend200ResponsePayloadFromJSON,
ListFriend200ResponsePayloadFromJSONTyped,
ListFriend200ResponsePayloadToJSON,
ListFriend200ResponsePayloadToJSONTyped,
} from './ListFriend200ResponsePayload';
/**
*
* @export
* @interface ListFriend200Response
*/
export interface ListFriend200Response {
/**
*
* @type {string}
* @memberof ListFriend200Response
*/
kind: ListFriend200ResponseKindEnum;
/**
*
* @type {string}
* @memberof ListFriend200Response
*/
msg: ListFriend200ResponseMsgEnum;
/**
*
* @type {ListFriend200ResponsePayload}
* @memberof ListFriend200Response
*/
payload: ListFriend200ResponsePayload;
}
/**
* @export
*/
export const ListFriend200ResponseKindEnum = {
Success: 'success'
} as const;
export type ListFriend200ResponseKindEnum = typeof ListFriend200ResponseKindEnum[keyof typeof ListFriend200ResponseKindEnum];
/**
* @export
*/
export const ListFriend200ResponseMsgEnum = {
ListFriendSuccess: 'listFriend.success'
} as const;
export type ListFriend200ResponseMsgEnum = typeof ListFriend200ResponseMsgEnum[keyof typeof ListFriend200ResponseMsgEnum];
/**
* Check if a given object implements the ListFriend200Response interface.
*/
export function instanceOfListFriend200Response(value: object): value is ListFriend200Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
if (!('payload' in value) || value['payload'] === undefined) return false;
return true;
}
export function ListFriend200ResponseFromJSON(json: any): ListFriend200Response {
return ListFriend200ResponseFromJSONTyped(json, false);
}
export function ListFriend200ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ListFriend200Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
'payload': ListFriend200ResponsePayloadFromJSON(json['payload']),
};
}
export function ListFriend200ResponseToJSON(json: any): ListFriend200Response {
return ListFriend200ResponseToJSONTyped(json, false);
}
export function ListFriend200ResponseToJSONTyped(value?: ListFriend200Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
'payload': ListFriend200ResponsePayloadToJSON(value['payload']),
};
}

View file

@ -0,0 +1,74 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { ListFriend200ResponsePayloadFriendsInner } from './ListFriend200ResponsePayloadFriendsInner';
import {
ListFriend200ResponsePayloadFriendsInnerFromJSON,
ListFriend200ResponsePayloadFriendsInnerFromJSONTyped,
ListFriend200ResponsePayloadFriendsInnerToJSON,
ListFriend200ResponsePayloadFriendsInnerToJSONTyped,
} from './ListFriend200ResponsePayloadFriendsInner';
/**
*
* @export
* @interface ListFriend200ResponsePayload
*/
export interface ListFriend200ResponsePayload {
/**
*
* @type {Array<ListFriend200ResponsePayloadFriendsInner>}
* @memberof ListFriend200ResponsePayload
*/
friends: Array<ListFriend200ResponsePayloadFriendsInner>;
}
/**
* Check if a given object implements the ListFriend200ResponsePayload interface.
*/
export function instanceOfListFriend200ResponsePayload(value: object): value is ListFriend200ResponsePayload {
if (!('friends' in value) || value['friends'] === undefined) return false;
return true;
}
export function ListFriend200ResponsePayloadFromJSON(json: any): ListFriend200ResponsePayload {
return ListFriend200ResponsePayloadFromJSONTyped(json, false);
}
export function ListFriend200ResponsePayloadFromJSONTyped(json: any, ignoreDiscriminator: boolean): ListFriend200ResponsePayload {
if (json == null) {
return json;
}
return {
'friends': ((json['friends'] as Array<any>).map(ListFriend200ResponsePayloadFriendsInnerFromJSON)),
};
}
export function ListFriend200ResponsePayloadToJSON(json: any): ListFriend200ResponsePayload {
return ListFriend200ResponsePayloadToJSONTyped(json, false);
}
export function ListFriend200ResponsePayloadToJSONTyped(value?: ListFriend200ResponsePayload | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'friends': ((value['friends'] as Array<any>).map(ListFriend200ResponsePayloadFriendsInnerToJSON)),
};
}

View file

@ -0,0 +1,75 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ListFriend200ResponsePayloadFriendsInner
*/
export interface ListFriend200ResponsePayloadFriendsInner {
/**
*
* @type {string}
* @memberof ListFriend200ResponsePayloadFriendsInner
*/
id: string;
/**
*
* @type {string}
* @memberof ListFriend200ResponsePayloadFriendsInner
*/
name: string;
}
/**
* Check if a given object implements the ListFriend200ResponsePayloadFriendsInner interface.
*/
export function instanceOfListFriend200ResponsePayloadFriendsInner(value: object): value is ListFriend200ResponsePayloadFriendsInner {
if (!('id' in value) || value['id'] === undefined) return false;
if (!('name' in value) || value['name'] === undefined) return false;
return true;
}
export function ListFriend200ResponsePayloadFriendsInnerFromJSON(json: any): ListFriend200ResponsePayloadFriendsInner {
return ListFriend200ResponsePayloadFriendsInnerFromJSONTyped(json, false);
}
export function ListFriend200ResponsePayloadFriendsInnerFromJSONTyped(json: any, ignoreDiscriminator: boolean): ListFriend200ResponsePayloadFriendsInner {
if (json == null) {
return json;
}
return {
'id': json['id'],
'name': json['name'],
};
}
export function ListFriend200ResponsePayloadFriendsInnerToJSON(json: any): ListFriend200ResponsePayloadFriendsInner {
return ListFriend200ResponsePayloadFriendsInnerToJSONTyped(json, false);
}
export function ListFriend200ResponsePayloadFriendsInnerToJSONTyped(value?: ListFriend200ResponsePayloadFriendsInner | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'id': value['id'],
'name': value['name'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ListFriend404Response
*/
export interface ListFriend404Response {
/**
*
* @type {string}
* @memberof ListFriend404Response
*/
kind: ListFriend404ResponseKindEnum;
/**
*
* @type {string}
* @memberof ListFriend404Response
*/
msg: ListFriend404ResponseMsgEnum;
}
/**
* @export
*/
export const ListFriend404ResponseKindEnum = {
Failure: 'failure'
} as const;
export type ListFriend404ResponseKindEnum = typeof ListFriend404ResponseKindEnum[keyof typeof ListFriend404ResponseKindEnum];
/**
* @export
*/
export const ListFriend404ResponseMsgEnum = {
RemoveFriendFailureUnknownUser: 'removeFriend.failure.unknownUser'
} as const;
export type ListFriend404ResponseMsgEnum = typeof ListFriend404ResponseMsgEnum[keyof typeof ListFriend404ResponseMsgEnum];
/**
* Check if a given object implements the ListFriend404Response interface.
*/
export function instanceOfListFriend404Response(value: object): value is ListFriend404Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function ListFriend404ResponseFromJSON(json: any): ListFriend404Response {
return ListFriend404ResponseFromJSONTyped(json, false);
}
export function ListFriend404ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ListFriend404Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function ListFriend404ResponseToJSON(json: any): ListFriend404Response {
return ListFriend404ResponseToJSONTyped(json, false);
}
export function ListFriend404ResponseToJSONTyped(value?: ListFriend404Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface RemoveFriend200Response
*/
export interface RemoveFriend200Response {
/**
*
* @type {string}
* @memberof RemoveFriend200Response
*/
kind: RemoveFriend200ResponseKindEnum;
/**
*
* @type {string}
* @memberof RemoveFriend200Response
*/
msg: RemoveFriend200ResponseMsgEnum;
}
/**
* @export
*/
export const RemoveFriend200ResponseKindEnum = {
Success: 'success'
} as const;
export type RemoveFriend200ResponseKindEnum = typeof RemoveFriend200ResponseKindEnum[keyof typeof RemoveFriend200ResponseKindEnum];
/**
* @export
*/
export const RemoveFriend200ResponseMsgEnum = {
RemoveFriendSuccess: 'removeFriend.success'
} as const;
export type RemoveFriend200ResponseMsgEnum = typeof RemoveFriend200ResponseMsgEnum[keyof typeof RemoveFriend200ResponseMsgEnum];
/**
* Check if a given object implements the RemoveFriend200Response interface.
*/
export function instanceOfRemoveFriend200Response(value: object): value is RemoveFriend200Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function RemoveFriend200ResponseFromJSON(json: any): RemoveFriend200Response {
return RemoveFriend200ResponseFromJSONTyped(json, false);
}
export function RemoveFriend200ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): RemoveFriend200Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function RemoveFriend200ResponseToJSON(json: any): RemoveFriend200Response {
return RemoveFriend200ResponseToJSONTyped(json, false);
}
export function RemoveFriend200ResponseToJSONTyped(value?: RemoveFriend200Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface RemoveFriend404Response
*/
export interface RemoveFriend404Response {
/**
*
* @type {string}
* @memberof RemoveFriend404Response
*/
kind: RemoveFriend404ResponseKindEnum;
/**
*
* @type {string}
* @memberof RemoveFriend404Response
*/
msg: RemoveFriend404ResponseMsgEnum;
}
/**
* @export
*/
export const RemoveFriend404ResponseKindEnum = {
Failure: 'failure'
} as const;
export type RemoveFriend404ResponseKindEnum = typeof RemoveFriend404ResponseKindEnum[keyof typeof RemoveFriend404ResponseKindEnum];
/**
* @export
*/
export const RemoveFriend404ResponseMsgEnum = {
RemoveFriendFailureUnknownUser: 'removeFriend.failure.unknownUser'
} as const;
export type RemoveFriend404ResponseMsgEnum = typeof RemoveFriend404ResponseMsgEnum[keyof typeof RemoveFriend404ResponseMsgEnum];
/**
* Check if a given object implements the RemoveFriend404Response interface.
*/
export function instanceOfRemoveFriend404Response(value: object): value is RemoveFriend404Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function RemoveFriend404ResponseFromJSON(json: any): RemoveFriend404Response {
return RemoveFriend404ResponseFromJSONTyped(json, false);
}
export function RemoveFriend404ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): RemoveFriend404Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function RemoveFriend404ResponseToJSON(json: any): RemoveFriend404Response {
return RemoveFriend404ResponseToJSONTyped(json, false);
}
export function RemoveFriend404ResponseToJSONTyped(value?: RemoveFriend404Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -13,13 +13,13 @@
*/
import { mapValues } from '../runtime';
import type { TttHistory200ResponsePayloadDataInnerPlayerX } from './TttHistory200ResponsePayloadDataInnerPlayerX';
import type { ListFriend200ResponsePayloadFriendsInner } from './ListFriend200ResponsePayloadFriendsInner';
import {
TttHistory200ResponsePayloadDataInnerPlayerXFromJSON,
TttHistory200ResponsePayloadDataInnerPlayerXFromJSONTyped,
TttHistory200ResponsePayloadDataInnerPlayerXToJSON,
TttHistory200ResponsePayloadDataInnerPlayerXToJSONTyped,
} from './TttHistory200ResponsePayloadDataInnerPlayerX';
ListFriend200ResponsePayloadFriendsInnerFromJSON,
ListFriend200ResponsePayloadFriendsInnerFromJSONTyped,
ListFriend200ResponsePayloadFriendsInnerToJSON,
ListFriend200ResponsePayloadFriendsInnerToJSONTyped,
} from './ListFriend200ResponsePayloadFriendsInner';
/**
*
@ -35,16 +35,16 @@ export interface TttHistory200ResponsePayloadDataInner {
gameId: string;
/**
*
* @type {TttHistory200ResponsePayloadDataInnerPlayerX}
* @type {ListFriend200ResponsePayloadFriendsInner}
* @memberof TttHistory200ResponsePayloadDataInner
*/
playerX: TttHistory200ResponsePayloadDataInnerPlayerX;
playerX: ListFriend200ResponsePayloadFriendsInner;
/**
*
* @type {TttHistory200ResponsePayloadDataInnerPlayerX}
* @type {ListFriend200ResponsePayloadFriendsInner}
* @memberof TttHistory200ResponsePayloadDataInner
*/
playerO: TttHistory200ResponsePayloadDataInnerPlayerX;
playerO: ListFriend200ResponsePayloadFriendsInner;
/**
*
* @type {string}
@ -95,8 +95,8 @@ export function TttHistory200ResponsePayloadDataInnerFromJSONTyped(json: any, ig
return {
'gameId': json['gameId'],
'playerX': TttHistory200ResponsePayloadDataInnerPlayerXFromJSON(json['playerX']),
'playerO': TttHistory200ResponsePayloadDataInnerPlayerXFromJSON(json['playerO']),
'playerX': ListFriend200ResponsePayloadFriendsInnerFromJSON(json['playerX']),
'playerO': ListFriend200ResponsePayloadFriendsInnerFromJSON(json['playerO']),
'date': json['date'],
'outcome': json['outcome'],
};
@ -114,8 +114,8 @@ export function TttHistory200ResponsePayloadDataInnerToJSONTyped(value?: TttHist
return {
'gameId': value['gameId'],
'playerX': TttHistory200ResponsePayloadDataInnerPlayerXToJSON(value['playerX']),
'playerO': TttHistory200ResponsePayloadDataInnerPlayerXToJSON(value['playerO']),
'playerX': ListFriend200ResponsePayloadFriendsInnerToJSON(value['playerX']),
'playerO': ListFriend200ResponsePayloadFriendsInnerToJSON(value['playerO']),
'date': value['date'],
'outcome': value['outcome'],
};

View file

@ -1,5 +1,7 @@
/* tslint:disable */
/* eslint-disable */
export * from './AddFriend200Response';
export * from './AddFriend404Response';
export * from './AllowGuestMessage200Response';
export * from './AllowGuestMessage403Response';
export * from './ChangeDesc200Response';
@ -37,6 +39,9 @@ export * from './GuestLogin200ResponsePayload';
export * from './GuestLogin400Response';
export * from './GuestLogin500Response';
export * from './GuestLoginRequest';
export * from './ListFriend200Response';
export * from './ListFriend200ResponsePayload';
export * from './ListFriend200ResponsePayloadFriendsInner';
export * from './Login200Response';
export * from './Login202Response';
export * from './Login202ResponsePayload';
@ -59,6 +64,8 @@ export * from './ProviderList200Response';
export * from './ProviderList200ResponsePayload';
export * from './ProviderList200ResponsePayloadListInner';
export * from './ProviderList200ResponsePayloadListInnerColors';
export * from './RemoveFriend200Response';
export * from './RemoveFriend404Response';
export * from './Signin200Response';
export * from './Signin200ResponsePayload';
export * from './Signin400Response';
@ -81,5 +88,4 @@ export * from './TournamentList404Response';
export * from './TttHistory200Response';
export * from './TttHistory200ResponsePayload';
export * from './TttHistory200ResponsePayloadDataInner';
export * from './TttHistory200ResponsePayloadDataInnerPlayerX';
export * from './TttHistory404Response';

View file

@ -4,17 +4,19 @@ import { FastifyInstance, FastifyPluginAsync } from 'fastify';
import { Database as DbImpl } from './mixin/_base';
import { IUserDb, UserImpl } from './mixin/user';
import { IBlockedDb, BlockedImpl } from './mixin/blocked';
import { IFriendsDb, FriendsImpl } from './mixin/friends';
import { ITicTacToeDb, TicTacToeImpl } from './mixin/tictactoe';
import { IPongDb, PongImpl } from './mixin/pong';
import { ITournamentDb, TournamentImpl } from './mixin/tournament';
Object.assign(DbImpl.prototype, UserImpl);
Object.assign(DbImpl.prototype, BlockedImpl);
Object.assign(DbImpl.prototype, FriendsImpl);
Object.assign(DbImpl.prototype, TicTacToeImpl);
Object.assign(DbImpl.prototype, PongImpl);
Object.assign(DbImpl.prototype, TournamentImpl);
export interface Database extends DbImpl, IUserDb, IBlockedDb, ITicTacToeDb, IPongDb, ITournamentDb { }
export interface Database extends DbImpl, IUserDb, IBlockedDb, ITicTacToeDb, IPongDb, ITournamentDb, IFriendsDb { }
// When using .decorate you have to specify added properties for Typescript
declare module 'fastify' {

View file

@ -27,6 +27,15 @@ CREATE TABLE IF NOT EXISTS blocked (
CREATE UNIQUE INDEX IF NOT EXISTS idx_blocked_user_pair ON blocked (user, blocked);
CREATE TABLE IF NOT EXISTS friends (
id INTEGER PRIMARY KEY NOT NULL,
user TEXT NOT NULL,
friend TEXT NOT NULL,
FOREIGN KEY (user) REFERENCES user (id) FOREIGN KEY (friend) REFERENCES user (id)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_friends_user_pair ON friends (user, friend);
----------------
-- TICTACTOE --
----------------

View file

@ -0,0 +1,72 @@
import { isNullish } from '@shared/utils';
import type { Database } from './_base';
import { UserId } from './user';
// describe every function in the object
export interface IFriendsDb extends Database {
getFriendsUserFor(id: UserId): FriendsData[],
addFriendsUserFor(id: UserId, friend: UserId): void,
removeFriendsUserFor(id: UserId, friend: UserId): void,
removeAllFriendUserFor(id: UserId): void,
getAllFriendsUsers(this: IFriendsDb): FriendsData[] | undefined,
};
export const FriendsImpl: Omit<IFriendsDb, keyof Database> = {
getFriendsUserFor(this: IFriendsDb, id: UserId): FriendsData[] {
const query = this.prepare('SELECT * FROM friends WHERE user = @id');
const data = query.all({ id }) as Partial<FriendsData>[];
return data.map(friendsFromRow).filter(b => !isNullish(b));
},
removeAllFriendUserFor(this: IFriendsDb, id: UserId): void {
this.prepare('DELETE FROM friends WHERE user = @id').run({ id });
},
addFriendsUserFor(this: IFriendsDb, id: UserId, friend: UserId): void {
this.prepare('INSERT OR IGNORE INTO friends (user, friend) VALUES (@id, @friend)').run({ id, friend });
},
removeFriendsUserFor(this: IFriendsDb, id: UserId, friend: UserId): void {
this.prepare('DELETE FROM friends WHERE user = @id AND friend = @friend').run({ id, friend });
},
/**
* Get all friends user
*
* @param
*
* @returns The list of users if it exists, undefined otherwise
*/
getAllFriendsUsers(this: IFriendsDb): FriendsData[] {
const rows = this.prepare('SELECT * FROM friends').all() as Partial<FriendsData>[];
return rows
.map(row => friendsFromRow(row))
.filter((u): u is FriendsData => u !== undefined);
},
};
export type FriendsId = number & { readonly __brand: unique symbol };
export type FriendsData = {
readonly id: FriendsId;
readonly user: UserId;
readonly friend: UserId;
};
/**
* Get a friends from a row
*
* @param row The data from sqlite
*
* @returns The friends if it exists, undefined otherwise
*/
export function friendsFromRow(row?: Partial<FriendsData>): FriendsData | undefined {
if (isNullish(row)) return undefined;
if (isNullish(row.id)) return undefined;
if (isNullish(row.user)) return undefined;
if (isNullish(row.friend)) return undefined;
return row as FriendsData;
}

21
src/icons/openapi.json Normal file
View file

@ -0,0 +1,21 @@
{
"openapi": "3.1.0",
"info": {
"version": "9.6.1",
"title": "@fastify/swagger"
},
"components": {
"schemas": {}
},
"paths": {},
"servers": [
{
"url": "https://local.maix.me:8888",
"description": "direct from docker"
},
{
"url": "https://local.maix.me:8000",
"description": "using fnginx"
}
]
}

View file

@ -6,18 +6,17 @@ import sharp from 'sharp';
import path from 'path';
import fs from 'node:fs/promises';
export const IconSetRes = {
'200': typeResponse('success', 'iconset.success'),
'400': typeResponse('success', ['iconset.failure.invalidFile', 'iconset.failure.noFile']),
'400': typeResponse('success', [
'iconset.failure.invalidFile',
'iconset.failure.noFile',
]),
};
export type IconSetRes = MakeStaticResponse<typeof IconSetRes>;
const validMimeTypes = new Set([
'image/jpeg',
'image/png',
]);
const validMimeTypes = new Set(['image/jpeg', 'image/png']);
async function resizeAndSaveImage(
imageBuffer: Buffer,
@ -42,20 +41,42 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
await fastify.register(multipart);
fastify.post(
'/api/icons/set',
{ schema: { response: IconSetRes, operationId: 'setIcons' }, config: { requireAuth: true } },
{
schema: {
response: IconSetRes,
hide: true,
},
config: { requireAuth: true },
},
async function(req, res) {
// req.authUser is always set, since this is gated
const userid = req.authUser!.id;
const file = await req.file();
if (!file) {
return res.makeResponse(400, 'failure', 'iconset.failure.noFile');
return res.makeResponse(
400,
'failure',
'iconset.failure.noFile',
);
}
if (!validMimeTypes.has(file.mimetype)) {
return res.makeResponse(400, 'failure', 'iconset.failure.invalidFile');
return res.makeResponse(
400,
'failure',
'iconset.failure.invalidFile',
);
}
const buf = await file.toBuffer();
if (!validMimeTypes.has((await fileTypeFromBuffer(buf))?.mime ?? 'unknown')) {
return res.makeResponse(400, 'failure', 'iconset.failure.invalidFile');
if (
!validMimeTypes.has(
(await fileTypeFromBuffer(buf))?.mime ?? 'unknown',
)
) {
return res.makeResponse(
400,
'failure',
'iconset.failure.invalidFile',
);
}
try {
resizeAndSaveImage(buf, userid);
@ -63,7 +84,11 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
}
catch (e: unknown) {
this.log.warn(e);
return res.makeResponse(400, 'failure', 'iconset.failure.invalidFile');
return res.makeResponse(
400,
'failure',
'iconset.failure.invalidFile',
);
}
},
);

View file

@ -1714,6 +1714,326 @@
]
}
},
"/api/user/friend/add/{user}": {
"put": {
"operationId": "addFriend",
"parameters": [
{
"schema": {
"type": "string"
},
"in": "path",
"name": "user",
"required": true
}
],
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"addFriend.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"404": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"addFriend.failure.unknownUser"
]
}
}
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/friend/list": {
"get": {
"operationId": "listFriend",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg",
"payload"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"listFriend.success"
]
},
"payload": {
"type": "object",
"required": [
"friends"
],
"properties": {
"friends": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/friend/remove/{user}": {
"put": {
"operationId": "removeFriend",
"parameters": [
{
"schema": {
"type": "string"
},
"in": "path",
"name": "user",
"required": true
}
],
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"removeFriend.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"404": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"removeFriend.failure.unknownUser"
]
}
}
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/info/{user}": {
"get": {
"operationId": "getUser",

View file

@ -476,6 +476,317 @@
}
}
},
"/api/user/friend/add/{user}": {
"put": {
"operationId": "addFriend",
"parameters": [
{
"schema": {
"type": "string"
},
"in": "path",
"name": "user",
"required": true
}
],
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"addFriend.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"404": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"addFriend.failure.unknownUser"
]
}
}
}
}
}
}
}
}
},
"/api/user/friend/list": {
"get": {
"operationId": "listFriend",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg",
"payload"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"listFriend.success"
]
},
"payload": {
"type": "object",
"required": [
"friends"
],
"properties": {
"friends": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
}
}
}
},
"/api/user/friend/remove/{user}": {
"put": {
"operationId": "removeFriend",
"parameters": [
{
"schema": {
"type": "string"
},
"in": "path",
"name": "user",
"required": true
}
],
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"removeFriend.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"404": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"removeFriend.failure.unknownUser"
]
}
}
}
}
}
}
}
}
},
"/api/user/info/{user}": {
"get": {
"operationId": "getUser",

View file

@ -0,0 +1,44 @@
import { FastifyPluginAsync } from 'fastify';
import { MakeStaticResponse, typeResponse } from '@shared/utils';
import Type, { Static } from 'typebox';
export const AddFriendRes = {
'200': typeResponse('success', 'addFriend.success'),
'404': typeResponse('failure', 'addFriend.failure.unknownUser'),
};
export type AddFriendRes = MakeStaticResponse<typeof AddFriendRes>;
const AddFriendParams = Type.Object({
user: Type.String(),
});
export type AddFriendParams = Static<typeof AddFriendParams>;
const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.put<{ Params: AddFriendParams }>(
'/api/user/friend/add/:user',
{
schema: {
params: AddFriendParams,
response: AddFriendRes,
operationId: 'addFriend',
},
config: { requireAuth: true },
},
async function(req, res) {
const friend = this.db.getUser(req.params.user);
if (!friend) {
return res.makeResponse(
404,
'failure',
'addFriend.failure.unknownUser',
);
}
this.db.addFriendsUserFor(req.authUser!.id, friend.id);
return res.makeResponse(200, 'success', 'addFriend.success');
},
);
};
export default route;

View file

@ -0,0 +1,40 @@
import { FastifyPluginAsync } from 'fastify';
import { isNullish, MakeStaticResponse, typeResponse } from '@shared/utils';
import Type, { Static } from 'typebox';
export const ListFriendRes = {
'200': typeResponse('success', 'listFriend.success', {
friends: Type.Array(Type.Object({
id: Type.String(),
name: Type.String(),
})),
}),
};
export type ListFriendRes = MakeStaticResponse<typeof ListFriendRes>;
const RemoveFriendParams = Type.Object({
user: Type.String(),
});
export type RemoveFriendParams = Static<typeof RemoveFriendParams>;
const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.get(
'/api/user/friend/list',
{
schema: {
response: ListFriendRes,
operationId: 'listFriend',
},
config: { requireAuth: true },
},
async function(req, res) {
void req;
const friends: ListFriendRes['200']['payload']['friends'] = this.db.getFriendsUserFor(req.authUser!.id).map(v => this.db.getUser(v.friend)).filter(v => !isNullish(v)).map(v => ({ id: v.id, name: v.name }));
return res.makeResponse(200, 'success', 'listFriend.success', { friends });
},
);
};
export default route;

View file

@ -0,0 +1,44 @@
import { FastifyPluginAsync } from 'fastify';
import { MakeStaticResponse, typeResponse } from '@shared/utils';
import Type, { Static } from 'typebox';
export const RemoveFriendRes = {
'200': typeResponse('success', 'removeFriend.success'),
'404': typeResponse('failure', 'removeFriend.failure.unknownUser'),
};
export type RemoveFriendRes = MakeStaticResponse<typeof RemoveFriendRes>;
const RemoveFriendParams = Type.Object({
user: Type.String(),
});
export type RemoveFriendParams = Static<typeof RemoveFriendParams>;
const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.put<{ Params: RemoveFriendParams }>(
'/api/user/friend/remove/:user',
{
schema: {
params: RemoveFriendParams,
response: RemoveFriendRes,
operationId: 'removeFriend',
},
config: { requireAuth: true },
},
async function(req, res) {
const friend = this.db.getUser(req.params.user);
if (!friend) {
return res.makeResponse(
404,
'failure',
'removeFriend.failure.unknownUser',
);
}
this.db.removeFriendsUserFor(req.authUser!.id, friend.id);
return res.makeResponse(200, 'success', 'removeFriend.success');
},
);
};
export default route;