This commit is contained in:
syuilo 2024-01-18 20:03:15 +09:00
parent 7ca93893ca
commit 58f4d5d790
13 changed files with 805 additions and 6 deletions

View file

@ -300,6 +300,25 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}
}
@bindThis
public async surrender(game: MiReversiGame, user: MiUser) {
if (game.isEnded) return;
if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
const winnerId = game.user1Id === user.id ? game.user2Id : game.user1Id;
await this.reversiGamesRepository.update(game.id, {
surrendered: user.id,
isEnded: true,
winnerId: winnerId,
});
this.globalEventService.publishReversiGameStream(game.id, 'ended', {
winnerId: winnerId,
game: await this.reversiGameEntityService.pack(game.id, user),
});
}
@bindThis
public async get(id: MiReversiGame['id']) {
return this.reversiGamesRepository.findOneBy({ id });

View file

@ -366,6 +366,12 @@ import * as ep___fetchExternalResources from './endpoints/fetch-external-resourc
import * as ep___retention from './endpoints/retention.js';
import * as ep___bubbleGame_register from './endpoints/bubble-game/register.js';
import * as ep___bubbleGame_ranking from './endpoints/bubble-game/ranking.js';
import * as ep___reversi_cancelMatch from './endpoints/reversi/cancel-match.js';
import * as ep___reversi_games from './endpoints/reversi/games.js';
import * as ep___reversi_match from './endpoints/reversi/match.js';
import * as ep___reversi_invitations from './endpoints/reversi/invitations.js';
import * as ep___reversi_showGame from './endpoints/reversi/show-game.js';
import * as ep___reversi_surrender from './endpoints/reversi/surrender.js';
import { GetterService } from './GetterService.js';
import { ApiLoggerService } from './ApiLoggerService.js';
import type { Provider } from '@nestjs/common';
@ -730,6 +736,12 @@ const $fetchExternalResources: Provider = { provide: 'ep:fetch-external-resource
const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention.default };
const $bubbleGame_register: Provider = { provide: 'ep:bubble-game/register', useClass: ep___bubbleGame_register.default };
const $bubbleGame_ranking: Provider = { provide: 'ep:bubble-game/ranking', useClass: ep___bubbleGame_ranking.default };
const $reversi_cancelMatch: Provider = { provide: 'ep:reversi/cancel-match', useClass: ep___reversi_cancelMatch.default };
const $reversi_games: Provider = { provide: 'ep:reversi/games', useClass: ep___reversi_games.default };
const $reversi_match: Provider = { provide: 'ep:reversi/match', useClass: ep___reversi_match.default };
const $reversi_invitations: Provider = { provide: 'ep:reversi/invitations', useClass: ep___reversi_invitations.default };
const $reversi_showGame: Provider = { provide: 'ep:reversi/show-game', useClass: ep___reversi_showGame.default };
const $reversi_surrender: Provider = { provide: 'ep:reversi/surrender', useClass: ep___reversi_surrender.default };
@Module({
imports: [
@ -1098,6 +1110,12 @@ const $bubbleGame_ranking: Provider = { provide: 'ep:bubble-game/ranking', useCl
$retention,
$bubbleGame_register,
$bubbleGame_ranking,
$reversi_cancelMatch,
$reversi_games,
$reversi_match,
$reversi_invitations,
$reversi_showGame,
$reversi_surrender,
],
exports: [
$admin_meta,
@ -1457,6 +1475,12 @@ const $bubbleGame_ranking: Provider = { provide: 'ep:bubble-game/ranking', useCl
$retention,
$bubbleGame_register,
$bubbleGame_ranking,
$reversi_cancelMatch,
$reversi_games,
$reversi_match,
$reversi_invitations,
$reversi_showGame,
$reversi_surrender,
],
})
export class EndpointsModule {}

View file

@ -367,6 +367,12 @@ import * as ep___fetchExternalResources from './endpoints/fetch-external-resourc
import * as ep___retention from './endpoints/retention.js';
import * as ep___bubbleGame_register from './endpoints/bubble-game/register.js';
import * as ep___bubbleGame_ranking from './endpoints/bubble-game/ranking.js';
import * as ep___reversi_cancelMatch from './endpoints/reversi/cancel-match.js';
import * as ep___reversi_games from './endpoints/reversi/games.js';
import * as ep___reversi_match from './endpoints/reversi/match.js';
import * as ep___reversi_invitations from './endpoints/reversi/invitations.js';
import * as ep___reversi_showGame from './endpoints/reversi/show-game.js';
import * as ep___reversi_surrender from './endpoints/reversi/surrender.js';
const eps = [
['admin/meta', ep___admin_meta],
@ -729,6 +735,12 @@ const eps = [
['retention', ep___retention],
['bubble-game/register', ep___bubbleGame_register],
['bubble-game/ranking', ep___bubbleGame_ranking],
['reversi/cancel-match', ep___reversi_cancelMatch],
['reversi/games', ep___reversi_games],
['reversi/match', ep___reversi_match],
['reversi/invitations', ep___reversi_invitations],
['reversi/show-game', ep___reversi_showGame],
['reversi/surrender', ep___reversi_surrender],
];
interface IEndpointMetaBase {

View file

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { Brackets } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
import { DI } from '@/di-symbols.js';
import type { ReversiGamesRepository } from '@/models/_.js';
import { QueryService } from '@/core/QueryService.js';
export const meta = {
requireCredential: false,
res: {
type: 'array',
optional: false, nullable: false,
items: { ref: 'ReversiGame' },
},
} as const;
export const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
my: { type: 'boolean', default: false },
},
required: [],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.reversiGamesRepository)
private reversiGamesRepository: ReversiGamesRepository,
private reversiGameEntityService: ReversiGameEntityService,
private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.reversiGamesRepository.createQueryBuilder('game'), ps.sinceId, ps.untilId)
.andWhere('game.isStarted = TRUE');
if (ps.my && me) {
query.andWhere(new Brackets(qb => {
qb
.where('game.user1Id = :userId', { userId: me.id })
.orWhere('game.user2Id = :userId', { userId: me.id });
}));
}
const games = await query.take(ps.limit).getMany();
return await this.reversiGameEntityService.packMany(games, me);
});
}
}

View file

@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { ReversiMatchingEntityService } from '@/core/entities/ReversiMatchingEntityService.js';
import type { ReversiMatchingsRepository } from '@/models/_.js';
export const meta = {
requireCredential: true,
kind: 'read:account',
res: {
type: 'array',
optional: false, nullable: false,
items: { ref: 'ReversiMatching' },
},
} as const;
export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.reversiMatchingsRepository)
private reversiMatchingsRepository: ReversiMatchingsRepository,
private reversiMatchingEntityService: ReversiMatchingEntityService,
) {
super(meta, paramDef, async (ps, me) => {
const invitations = await this.reversiMatchingsRepository.findBy({
childId: me.id,
});
return await this.reversiMatchingEntityService.packMany(invitations, me);
});
}
}

View file

@ -21,6 +21,8 @@ export const meta = {
},
res: {
type: 'object',
optional: false, nullable: false,
ref: 'ReversiGame',
},
} as const;

View file

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { ReversiService } from '@/core/ReversiService.js';
import { ApiError } from '../../error.js';
export const meta = {
requireCredential: true,
kind: 'write:account',
errors: {
noSuchGame: {
message: 'No such game.',
code: 'NO_SUCH_GAME',
id: 'ace0b11f-e0a6-4076-a30d-e8284c81b2df',
},
alreadyEnded: {
message: 'That game has already ended.',
code: 'ALREADY_ENDED',
id: '6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '6e04164b-a992-4c93-8489-2123069973e1',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
gameId: { type: 'string', format: 'misskey:id' },
},
required: ['gameId'],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
private reversiService: ReversiService,
) {
super(meta, paramDef, async (ps, me) => {
const game = await this.reversiService.get(ps.gameId);
if (game == null) {
throw new ApiError(meta.errors.noSuchGame);
}
if (game.isEnded) {
throw new ApiError(meta.errors.alreadyEnded);
}
if ((game.user1Id !== me.id) && (game.user2Id !== me.id)) {
throw new ApiError(meta.errors.accessDenied);
}
await this.reversiService.surrender(game, me);
});
}
}

View file

@ -1623,6 +1623,16 @@ declare namespace entities {
BubbleGameRegisterResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchResponse,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsRequest,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
Error_2 as Error,
UserLite,
UserDetailedNotMeOnly,
@ -1659,7 +1669,9 @@ declare namespace entities {
Flash,
Signin,
RoleLite,
Role
Role,
ReversiGame,
ReversiMatching
}
}
export { entities }
@ -2596,6 +2608,42 @@ type ResetPasswordRequest = operations['reset-password']['requestBody']['content
// @public (undocumented)
type RetentionResponse = operations['retention']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiCancelMatchResponse = operations['reversi/cancel-match']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiGame = components['schemas']['ReversiGame'];
// @public (undocumented)
type ReversiGamesRequest = operations['reversi/games']['requestBody']['content']['application/json'];
// @public (undocumented)
type ReversiGamesResponse = operations['reversi/games']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiInvitationsRequest = operations['reversi/invitations']['requestBody']['content']['application/json'];
// @public (undocumented)
type ReversiInvitationsResponse = operations['reversi/invitations']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiMatching = components['schemas']['ReversiMatching'];
// @public (undocumented)
type ReversiMatchRequest = operations['reversi/match']['requestBody']['content']['application/json'];
// @public (undocumented)
type ReversiMatchResponse = operations['reversi/match']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiShowGameRequest = operations['reversi/show-game']['requestBody']['content']['application/json'];
// @public (undocumented)
type ReversiShowGameResponse = operations['reversi/show-game']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiSurrenderRequest = operations['reversi/surrender']['requestBody']['content']['application/json'];
// @public (undocumented)
type Role = components['schemas']['Role'];

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-13T04:31:38.782Z
* generatedAt: 2024-01-18T11:02:35.535Z
*/
import type { SwitchCaseResponseType } from '../api.js';
@ -4007,5 +4007,71 @@ declare module '../api.js' {
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
request<E extends 'reversi/cancel-match', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *No*
*/
request<E extends 'reversi/games', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
request<E extends 'reversi/match', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:account*
*/
request<E extends 'reversi/invitations', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *No*
*/
request<E extends 'reversi/show-game', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
request<E extends 'reversi/surrender', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
}
}

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-13T04:31:38.778Z
* generatedAt: 2024-01-18T11:02:35.533Z
*/
import type {
@ -544,6 +544,16 @@ import type {
BubbleGameRegisterResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchResponse,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsRequest,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
} from './entities.js';
export type Endpoints = {
@ -907,4 +917,10 @@ export type Endpoints = {
'retention': { req: EmptyRequest; res: RetentionResponse };
'bubble-game/register': { req: BubbleGameRegisterRequest; res: BubbleGameRegisterResponse };
'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse };
'reversi/cancel-match': { req: EmptyRequest; res: ReversiCancelMatchResponse };
'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse };
'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse };
'reversi/invitations': { req: ReversiInvitationsRequest; res: ReversiInvitationsResponse };
'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse };
'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse };
}

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-13T04:31:38.775Z
* generatedAt: 2024-01-18T11:02:35.532Z
*/
import { operations } from './types.js';
@ -546,3 +546,13 @@ export type BubbleGameRegisterRequest = operations['bubble-game/register']['requ
export type BubbleGameRegisterResponse = operations['bubble-game/register']['responses']['200']['content']['application/json'];
export type BubbleGameRankingRequest = operations['bubble-game/ranking']['requestBody']['content']['application/json'];
export type BubbleGameRankingResponse = operations['bubble-game/ranking']['responses']['200']['content']['application/json'];
export type ReversiCancelMatchResponse = operations['reversi/cancel-match']['responses']['200']['content']['application/json'];
export type ReversiGamesRequest = operations['reversi/games']['requestBody']['content']['application/json'];
export type ReversiGamesResponse = operations['reversi/games']['responses']['200']['content']['application/json'];
export type ReversiMatchRequest = operations['reversi/match']['requestBody']['content']['application/json'];
export type ReversiMatchResponse = operations['reversi/match']['responses']['200']['content']['application/json'];
export type ReversiInvitationsRequest = operations['reversi/invitations']['requestBody']['content']['application/json'];
export type ReversiInvitationsResponse = operations['reversi/invitations']['responses']['200']['content']['application/json'];
export type ReversiShowGameRequest = operations['reversi/show-game']['requestBody']['content']['application/json'];
export type ReversiShowGameResponse = operations['reversi/show-game']['responses']['200']['content']['application/json'];
export type ReversiSurrenderRequest = operations['reversi/surrender']['requestBody']['content']['application/json'];

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-13T04:31:38.773Z
* generatedAt: 2024-01-18T11:02:35.530Z
*/
import { components } from './types.js';
@ -41,3 +41,5 @@ export type Flash = components['schemas']['Flash'];
export type Signin = components['schemas']['Signin'];
export type RoleLite = components['schemas']['RoleLite'];
export type Role = components['schemas']['Role'];
export type ReversiGame = components['schemas']['ReversiGame'];
export type ReversiMatching = components['schemas']['ReversiMatching'];

View file

@ -3,7 +3,7 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-13T04:31:38.633Z
* generatedAt: 2024-01-18T11:02:35.451Z
*/
/**
@ -3472,6 +3472,60 @@ export type paths = {
*/
post: operations['bubble-game/ranking'];
};
'/reversi/cancel-match': {
/**
* reversi/cancel-match
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
post: operations['reversi/cancel-match'];
};
'/reversi/games': {
/**
* reversi/games
* @description No description provided.
*
* **Credential required**: *No*
*/
post: operations['reversi/games'];
};
'/reversi/match': {
/**
* reversi/match
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
post: operations['reversi/match'];
};
'/reversi/invitations': {
/**
* reversi/invitations
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:account*
*/
post: operations['reversi/invitations'];
};
'/reversi/show-game': {
/**
* reversi/show-game
* @description No description provided.
*
* **Credential required**: *No*
*/
post: operations['reversi/show-game'];
};
'/reversi/surrender': {
/**
* reversi/surrender
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
post: operations['reversi/surrender'];
};
};
export type webhooks = Record<string, never>;
@ -4404,6 +4458,55 @@ export type components = {
};
usersCount: number;
});
ReversiGame: {
/** Format: id */
id: string;
/** Format: date-time */
createdAt: string;
/** Format: date-time */
startedAt: string | null;
isStarted: boolean;
isEnded: boolean;
form1: Record<string, never> | null;
form2: Record<string, never> | null;
user1Accepted: boolean;
user2Accepted: boolean;
/** Format: id */
user1Id: string;
/** Format: id */
user2Id: string;
user1: components['schemas']['User'];
user2: components['schemas']['User'];
/** Format: id */
winnerId: string | null;
winner: components['schemas']['User'] | null;
/** Format: id */
surrendered: string | null;
black: number | null;
bw: string;
isLlotheo: boolean;
canPutEverywhere: boolean;
loopedBoard: boolean;
logs?: {
/** Format: date-time */
at: string;
color: boolean;
pos: number;
}[];
map?: string[];
};
ReversiMatching: {
/** Format: id */
id: string;
/** Format: date-time */
createdAt: string;
/** Format: id */
parentId: string;
parent: components['schemas']['User'] | null;
/** Format: id */
childId: string;
child: components['schemas']['User'];
};
};
responses: never;
parameters: never;
@ -25542,5 +25645,325 @@ export type operations = {
};
};
};
/**
* reversi/cancel-match
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
'reversi/cancel-match': {
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': unknown;
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* reversi/games
* @description No description provided.
*
* **Credential required**: *No*
*/
'reversi/games': {
requestBody: {
content: {
'application/json': {
/** @default 10 */
limit?: number;
/** Format: misskey:id */
sinceId?: string;
/** Format: misskey:id */
untilId?: string;
/** @default false */
my?: boolean;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': components['schemas']['ReversiGame'][];
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* reversi/match
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
'reversi/match': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
userId: string;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': unknown;
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* reversi/invitations
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:account*
*/
'reversi/invitations': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
userId: string;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': components['schemas']['ReversiMatching'][];
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* reversi/show-game
* @description No description provided.
*
* **Credential required**: *No*
*/
'reversi/show-game': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
gameId: string;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': components['schemas']['ReversiGame'];
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* reversi/surrender
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
'reversi/surrender': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
gameId: string;
};
};
};
responses: {
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
};