summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/api/endpoints')
-rw-r--r--packages/backend/src/server/api/endpoints/bubble-game/register.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/renote-mute/create.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/cancel-match.ts44
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/games.ts61
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/invitations.ts39
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/match.ts66
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/show-game.ts54
-rw-r--r--packages/backend/src/server/api/endpoints/reversi/surrender.ts68
8 files changed, 335 insertions, 3 deletions
diff --git a/packages/backend/src/server/api/endpoints/bubble-game/register.ts b/packages/backend/src/server/api/endpoints/bubble-game/register.ts
index f092d16a70..8eb90fdbf9 100644
--- a/packages/backend/src/server/api/endpoints/bubble-game/register.ts
+++ b/packages/backend/src/server/api/endpoints/bubble-game/register.ts
@@ -63,8 +63,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.invalidSeed);
}
- // シードが古すぎる(1時間以上前)のも弾く
- if (seedDate.getTime() < now.getTime() - 1000 * 60 * 60) {
+ // シードが古すぎる(5時間以上前)のも弾く
+ if (seedDate.getTime() < now.getTime() - 1000 * 60 * 60 * 5) {
throw new ApiError(meta.errors.invalidSeed);
}
diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
index 7ff7b5de3a..2d853b94f3 100644
--- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
@@ -73,7 +73,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
// Get mutee
- const mutee = await getterService.getUser(ps.userId).catch(err => {
+ const mutee = await this.getterService.getUser(ps.userId).catch(err => {
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
throw err;
});
diff --git a/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts b/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts
new file mode 100644
index 0000000000..8edc049500
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts
@@ -0,0 +1,44 @@
+/*
+ * 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';
+
+export const meta = {
+ requireCredential: true,
+
+ kind: 'write:account',
+
+ errors: {
+ },
+
+ res: {
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id', nullable: true },
+ },
+ required: [],
+} 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) => {
+ if (ps.userId) {
+ await this.reversiService.matchSpecificUserCancel(me, ps.userId);
+ return;
+ } else {
+ await this.reversiService.matchAnyUserCancel(me);
+ }
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/reversi/games.ts b/packages/backend/src/server/api/endpoints/reversi/games.ts
new file mode 100644
index 0000000000..5322cd0987
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/games.ts
@@ -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: 'ReversiGameLite' },
+ },
+} 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.packLiteMany(games, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/reversi/invitations.ts b/packages/backend/src/server/api/endpoints/reversi/invitations.ts
new file mode 100644
index 0000000000..0b7107bb0d
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/invitations.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { ReversiService } from '@/core/ReversiService.js';
+
+export const meta = {
+ requireCredential: true,
+
+ kind: 'read:account',
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: { ref: 'UserLite' },
+ },
+} as const;
+
+export const paramDef = {
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private userEntityService: UserEntityService,
+ private reversiService: ReversiService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const invitations = await this.reversiService.getInvitations(me);
+
+ return await this.userEntityService.packMany(invitations, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/reversi/match.ts b/packages/backend/src/server/api/endpoints/reversi/match.ts
new file mode 100644
index 0000000000..da5a3409ef
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/match.ts
@@ -0,0 +1,66 @@
+/*
+ * 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 { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
+import { ApiError } from '../../error.js';
+import { GetterService } from '../../GetterService.js';
+
+export const meta = {
+ requireCredential: true,
+
+ kind: 'write:account',
+
+ errors: {
+ noSuchUser: {
+ message: 'No such user.',
+ code: 'NO_SUCH_USER',
+ id: '0b4f0559-b484-4e31-9581-3f73cee89b28',
+ },
+
+ isYourself: {
+ message: 'Target user is yourself.',
+ code: 'TARGET_IS_YOURSELF',
+ id: '96fd7bd6-d2bc-426c-a865-d055dcd2828e',
+ },
+ },
+
+ res: {
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id', nullable: true },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private getterService: GetterService,
+ private reversiService: ReversiService,
+ private reversiGameEntityService: ReversiGameEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ if (ps.userId === me.id) throw new ApiError(meta.errors.isYourself);
+
+ const target = ps.userId ? await this.getterService.getUser(ps.userId).catch(err => {
+ if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
+ throw err;
+ }) : null;
+
+ const game = target ? await this.reversiService.matchSpecificUser(me, target) : await this.reversiService.matchAnyUser(me);
+
+ if (game == null) return;
+
+ return await this.reversiGameEntityService.packDetail(game, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/reversi/show-game.ts b/packages/backend/src/server/api/endpoints/reversi/show-game.ts
new file mode 100644
index 0000000000..de571053e1
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/show-game.ts
@@ -0,0 +1,54 @@
+/*
+ * 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 { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
+import { ApiError } from '../../error.js';
+
+export const meta = {
+ requireCredential: false,
+
+ errors: {
+ noSuchGame: {
+ message: 'No such game.',
+ code: 'NO_SUCH_GAME',
+ id: 'f13a03db-fae1-46c9-87f3-43c8165419e1',
+ },
+ },
+
+ res: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'ReversiGameDetailed',
+ },
+} 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,
+ private reversiGameEntityService: ReversiGameEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const game = await this.reversiService.get(ps.gameId);
+
+ if (game == null) {
+ throw new ApiError(meta.errors.noSuchGame);
+ }
+
+ return await this.reversiGameEntityService.packDetail(game, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/reversi/surrender.ts b/packages/backend/src/server/api/endpoints/reversi/surrender.ts
new file mode 100644
index 0000000000..c809142e07
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/reversi/surrender.ts
@@ -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.id, me);
+ });
+ }
+}