diff --git a/.github/workflows/check-spdx-license-id.yml b/.github/workflows/check-spdx-license-id.yml index 6cd8bf60d5..170150281b 100644 --- a/.github/workflows/check-spdx-license-id.yml +++ b/.github/workflows/check-spdx-license-id.yml @@ -55,7 +55,6 @@ jobs: "packages/frontend/src" "packages/frontend/test" "packages/misskey-bubble-game/src" - "packages/misskey-reversi/src" "packages/sw/src" "scripts" ) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0cc6e6975d..3d4ded680e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -112,6 +112,4 @@ jobs: - run: pnpm i --frozen-lockfile - run: pnpm --filter cherrypick-js run build if: ${{ matrix.workspace == 'backend' }} - - run: pnpm --filter misskey-reversi run build - if: ${{ matrix.workspace == 'backend' }} - run: pnpm --filter ${{ matrix.workspace }} run typecheck diff --git a/CHANGELOG_engawa.md b/CHANGELOG_engawa.md index 51cec6a22f..52acdd1d0e 100644 --- a/CHANGELOG_engawa.md +++ b/CHANGELOG_engawa.md @@ -20,7 +20,7 @@ ### Release Date ### General -- +- リバーシは削除されました ### Client - 検索ウィジェットにオートフォーカスが当たらなくなりました diff --git a/Dockerfile b/Dockerfile index bee178ce28..1f6f7d0f43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,6 @@ COPY --link ["packages/backend/package.json", "./packages/backend/"] COPY --link ["packages/frontend/package.json", "./packages/frontend/"] COPY --link ["packages/sw/package.json", "./packages/sw/"] COPY --link ["packages/cherrypick-js/package.json", "./packages/cherrypick-js/"] -COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"] COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"] ARG NODE_ENV=production @@ -54,7 +53,6 @@ COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] COPY --link ["scripts", "./scripts"] COPY --link ["packages/backend/package.json", "./packages/backend/"] COPY --link ["packages/cherrypick-js/package.json", "./packages/cherrypick-js/"] -COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"] COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"] ARG NODE_ENV=production @@ -89,11 +87,9 @@ RUN corepack install COPY --chown=cherrypick:cherrypick --from=target-builder /cherrypick/node_modules ./node_modules COPY --chown=cherrypick:cherrypick --from=target-builder /cherrypick/packages/backend/node_modules ./packages/backend/node_modules COPY --chown=cherrypick:cherrypick --from=target-builder /cherrypick/packages/cherrypick-js/node_modules ./packages/cherrypick-js/node_modules -COPY --chown=cherrypick:cherrypick --from=target-builder /cherrypick/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules COPY --chown=cherrypick:cherrypick --from=target-builder /cherrypick/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/built ./built COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/packages/cherrypick-js/built ./packages/cherrypick-js/built -COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/packages/misskey-reversi/built ./packages/misskey-reversi/built COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/packages/backend/built ./packages/backend/built COPY --chown=cherrypick:cherrypick --from=native-builder /cherrypick/fluent-emojis /cherrypick/fluent-emojis diff --git a/package.json b/package.json index 4db4f2de21..2141eb33a9 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "packages/backend", "packages/sw", "packages/cherrypick-js", - "packages/misskey-reversi", "packages/misskey-bubble-game" ], "private": true, diff --git a/packages/backend/package.json b/packages/backend/package.json index 08c4bced11..2d9f3016cf 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -146,7 +146,6 @@ "meilisearch": "0.41.0", "microformats-parser": "2.0.2", "mime-types": "2.1.35", - "misskey-reversi": "workspace:*", "ms": "3.0.0-canary.1", "nanoid": "5.0.7", "nested-property": "4.0.0", diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 5109628e1e..44f820fb0d 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -77,7 +77,6 @@ import { FeaturedService } from './FeaturedService.js'; import { FanoutTimelineService } from './FanoutTimelineService.js'; import { ChannelFollowingService } from './ChannelFollowingService.js'; import { RegistryApiService } from './RegistryApiService.js'; -import { ReversiService } from './ReversiService.js'; import { ChartLoggerService } from './chart/ChartLoggerService.js'; import FederationChart from './chart/charts/federation.js'; @@ -130,7 +129,6 @@ import { UserListEntityService } from './entities/UserListEntityService.js'; import { FlashEntityService } from './entities/FlashEntityService.js'; import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js'; import { RoleEntityService } from './entities/RoleEntityService.js'; -import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js'; import { MetaEntityService } from './entities/MetaEntityService.js'; import { ApAudienceService } from './activitypub/ApAudienceService.js'; @@ -228,7 +226,6 @@ const $FanoutTimelineService: Provider = { provide: 'FanoutTimelineService', use const $FanoutTimelineEndpointService: Provider = { provide: 'FanoutTimelineEndpointService', useExisting: FanoutTimelineEndpointService }; const $ChannelFollowingService: Provider = { provide: 'ChannelFollowingService', useExisting: ChannelFollowingService }; const $RegistryApiService: Provider = { provide: 'RegistryApiService', useExisting: RegistryApiService }; -const $ReversiService: Provider = { provide: 'ReversiService', useExisting: ReversiService }; const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService }; const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart }; @@ -282,7 +279,6 @@ const $UserListEntityService: Provider = { provide: 'UserListEntityService', use const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisting: FlashEntityService }; const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService }; const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService }; -const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService }; const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService }; const $SystemWebhookEntityService: Provider = { provide: 'SystemWebhookEntityService', useExisting: SystemWebhookEntityService }; @@ -382,7 +378,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv FanoutTimelineEndpointService, ChannelFollowingService, RegistryApiService, - ReversiService, ChartLoggerService, FederationChart, @@ -436,7 +431,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv FlashEntityService, FlashLikeEntityService, RoleEntityService, - ReversiGameEntityService, MetaEntityService, SystemWebhookEntityService, @@ -532,7 +526,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv $FanoutTimelineEndpointService, $ChannelFollowingService, $RegistryApiService, - $ReversiService, $ChartLoggerService, $FederationChart, @@ -586,7 +579,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv $FlashEntityService, $FlashLikeEntityService, $RoleEntityService, - $ReversiGameEntityService, $MetaEntityService, $SystemWebhookEntityService, @@ -683,7 +675,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv FanoutTimelineEndpointService, ChannelFollowingService, RegistryApiService, - ReversiService, FederationChart, NotesChart, @@ -736,7 +727,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv FlashEntityService, FlashLikeEntityService, RoleEntityService, - ReversiGameEntityService, MetaEntityService, SystemWebhookEntityService, @@ -832,7 +822,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv $FanoutTimelineEndpointService, $ChannelFollowingService, $RegistryApiService, - $ReversiService, $FederationChart, $NotesChart, @@ -885,7 +874,6 @@ const $ApEventService: Provider = { provide: 'ApEventService', useExisting: ApEv $FlashEntityService, $FlashLikeEntityService, $RoleEntityService, - $ReversiGameEntityService, $MetaEntityService, $SystemWebhookEntityService, diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 1ce47d4ab4..3b8057e442 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -5,7 +5,6 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import * as Reversi from 'misskey-reversi'; import type { MiChannel } from '@/models/Channel.js'; import type { MiUser } from '@/models/User.js'; import type { MiUserProfile } from '@/models/UserProfile.js'; @@ -23,7 +22,7 @@ import type { MiWebhook } from '@/models/Webhook.js'; import type { MiSystemWebhook } from '@/models/SystemWebhook.js'; import type { MiMeta } from '@/models/Meta.js'; import type { MiNotification } from '@/models/Notification.js'; -import { MiAvatarDecoration, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js'; +import { MiAvatarDecoration, MiRole, MiRoleAssignment } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; @@ -195,38 +194,6 @@ export interface AdminEventTypes { comment: string; }; } - -export interface ReversiEventTypes { - matched: { - game: Packed<'ReversiGameDetailed'>; - }; - invited: { - user: Packed<'User'>; - }; -} - -export interface ReversiGameEventTypes { - changeReadyStates: { - user1: boolean; - user2: boolean; - }; - updateSettings: { - userId: MiUser['id']; - key: string; - value: any; - }; - log: Reversi.Serializer.Log & { id: string | null }; - started: { - game: Packed<'ReversiGameDetailed'>; - }; - ended: { - winnerId: MiUser['id'] | null; - game: Packed<'ReversiGameDetailed'>; - }; - canceled: { - userId: MiUser['id']; - }; -} //#endregion // 辞書(interface or type)から{ type, body }ユニオンを定義 @@ -344,14 +311,6 @@ export type GlobalEvents = { name: 'notesStream'; payload: Serialized>; }; - reversi: { - name: `reversiStream:${MiUser['id']}`; - payload: EventTypesToEventPayload; - }; - reversiGame: { - name: `reversiGameStream:${MiReversiGame['id']}`; - payload: EventTypesToEventPayload; - }; }; // API event definitions @@ -456,14 +415,4 @@ export class GlobalEventService { public publishAdminStream(userId: MiUser['id'], type: K, value?: AdminEventTypes[K]): void { this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - - @bindThis - public publishReversiStream(userId: MiUser['id'], type: K, value?: ReversiEventTypes[K]): void { - this.publish(`reversiStream:${userId}`, type, typeof value === 'undefined' ? null : value); - } - - @bindThis - public publishReversiGameStream(gameId: MiReversiGame['id'], type: K, value?: ReversiGameEventTypes[K]): void { - this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value); - } } diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts deleted file mode 100644 index 7f939b99c7..0000000000 --- a/packages/backend/src/core/ReversiService.ts +++ /dev/null @@ -1,610 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; -import { ModuleRef } from '@nestjs/core'; -import * as Reversi from 'misskey-reversi'; -import { IsNull, LessThan, MoreThan } from 'typeorm'; -import type { - MiReversiGame, - ReversiGamesRepository, -} from '@/models/_.js'; -import type { MiUser } from '@/models/User.js'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import { CacheService } from '@/core/CacheService.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { IdService } from '@/core/IdService.js'; -import { NotificationService } from '@/core/NotificationService.js'; -import { Serialized } from '@/types.js'; -import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js'; -import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common'; - -const INVITATION_TIMEOUT_MS = 1000 * 20; // 20sec - -@Injectable() -export class ReversiService implements OnApplicationShutdown, OnModuleInit { - private notificationService: NotificationService; - - constructor( - private moduleRef: ModuleRef, - - @Inject(DI.redis) - private redisClient: Redis.Redis, - - @Inject(DI.reversiGamesRepository) - private reversiGamesRepository: ReversiGamesRepository, - - private cacheService: CacheService, - private userEntityService: UserEntityService, - private globalEventService: GlobalEventService, - private reversiGameEntityService: ReversiGameEntityService, - private idService: IdService, - ) { - } - - async onModuleInit() { - this.notificationService = this.moduleRef.get(NotificationService.name); - } - - @bindThis - private async cacheGame(game: MiReversiGame) { - await this.redisClient.setex(`reversi:game:cache:${game.id}`, 60 * 60, JSON.stringify(game)); - } - - @bindThis - private async deleteGameCache(gameId: MiReversiGame['id']) { - await this.redisClient.del(`reversi:game:cache:${gameId}`); - } - - @bindThis - private getBakeProps(game: MiReversiGame) { - return { - startedAt: game.startedAt, - endedAt: game.endedAt, - // ゲームの途中からユーザーが変わることは無いので - //user1Id: game.user1Id, - //user2Id: game.user2Id, - user1Ready: game.user1Ready, - user2Ready: game.user2Ready, - black: game.black, - isStarted: game.isStarted, - isEnded: game.isEnded, - winnerId: game.winnerId, - surrenderedUserId: game.surrenderedUserId, - timeoutUserId: game.timeoutUserId, - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - timeLimitForEachTurn: game.timeLimitForEachTurn, - logs: game.logs, - map: game.map, - bw: game.bw, - crc32: game.crc32, - noIrregularRules: game.noIrregularRules, - } satisfies Partial; - } - - @bindThis - public async matchSpecificUser(me: MiUser, targetUser: MiUser, multiple = false): Promise { - if (targetUser.id === me.id) { - throw new Error('You cannot match yourself.'); - } - - if (!multiple) { - // 既にマッチしている対局が無いか探す(3分以内) - const games = await this.reversiGamesRepository.find({ - where: [ - { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: me.id, user2Id: targetUser.id, isStarted: false }, - { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: targetUser.id, user2Id: me.id, isStarted: false }, - ], - relations: ['user1', 'user2'], - order: { id: 'DESC' }, - }); - if (games.length > 0) { - return games[0]; - } - } - - //#region 相手から既に招待されてないか確認 - const invitations = await this.redisClient.zrange( - `reversi:matchSpecific:${me.id}`, - Date.now() - INVITATION_TIMEOUT_MS, - '+inf', - 'BYSCORE'); - - if (invitations.includes(targetUser.id)) { - await this.redisClient.zrem(`reversi:matchSpecific:${me.id}`, targetUser.id); - - const game = await this.matched(targetUser.id, me.id, { - noIrregularRules: false, - }); - - return game; - } - //#endregion - - const redisPipeline = this.redisClient.pipeline(); - redisPipeline.zadd(`reversi:matchSpecific:${targetUser.id}`, Date.now(), me.id); - redisPipeline.expire(`reversi:matchSpecific:${targetUser.id}`, 120, 'NX'); - await redisPipeline.exec(); - - this.globalEventService.publishReversiStream(targetUser.id, 'invited', { - user: await this.userEntityService.pack(me, targetUser), - }); - - return null; - } - - @bindThis - public async matchAnyUser(me: MiUser, options: { noIrregularRules: boolean }, multiple = false): Promise { - if (!multiple) { - // 既にマッチしている対局が無いか探す(3分以内) - const games = await this.reversiGamesRepository.find({ - where: [ - { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: me.id, isStarted: false }, - { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user2Id: me.id, isStarted: false }, - ], - relations: ['user1', 'user2'], - order: { id: 'DESC' }, - }); - if (games.length > 0) { - return games[0]; - } - } - - //#region まず自分宛ての招待を探す - const invitations = await this.redisClient.zrange( - `reversi:matchSpecific:${me.id}`, - Date.now() - INVITATION_TIMEOUT_MS, - '+inf', - 'BYSCORE'); - - if (invitations.length > 0) { - const invitorId = invitations[Math.floor(Math.random() * invitations.length)]; - await this.redisClient.zrem(`reversi:matchSpecific:${me.id}`, invitorId); - - const game = await this.matched(invitorId, me.id, { - noIrregularRules: false, - }); - - return game; - } - //#endregion - - const matchings = await this.redisClient.zrange( - 'reversi:matchAny', - 0, - 2, // 自分自身のIDが入っている場合もあるので2つ取得 - 'REV'); - - const items = matchings.filter(id => !id.startsWith(me.id)); - - if (items.length > 0) { - const [matchedUserId, option] = items[0].split(':'); - - await this.redisClient.zrem('reversi:matchAny', - me.id, - matchedUserId, - me.id + ':noIrregularRules', - matchedUserId + ':noIrregularRules'); - - const game = await this.matched(matchedUserId, me.id, { - noIrregularRules: options.noIrregularRules || option === 'noIrregularRules', - }); - - return game; - } else { - const redisPipeline = this.redisClient.pipeline(); - if (options.noIrregularRules) { - redisPipeline.zadd('reversi:matchAny', Date.now(), me.id + ':noIrregularRules'); - } else { - redisPipeline.zadd('reversi:matchAny', Date.now(), me.id); - } - redisPipeline.expire('reversi:matchAny', 15, 'NX'); - await redisPipeline.exec(); - return null; - } - } - - @bindThis - public async matchSpecificUserCancel(user: MiUser, targetUserId: MiUser['id']) { - await this.redisClient.zrem(`reversi:matchSpecific:${targetUserId}`, user.id); - } - - @bindThis - public async matchAnyUserCancel(user: MiUser) { - await this.redisClient.zrem('reversi:matchAny', user.id, user.id + ':noIrregularRules'); - } - - @bindThis - public async cleanOutdatedGames() { - await this.reversiGamesRepository.delete({ - id: LessThan(this.idService.gen(Date.now() - 1000 * 60 * 10)), - isStarted: false, - }); - } - - @bindThis - public async gameReady(gameId: MiReversiGame['id'], user: MiUser, ready: boolean) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - if (game.isStarted) return; - - let isBothReady = false; - - if (game.user1Id === user.id) { - const updatedGame = { - ...game, - user1Ready: ready, - }; - this.cacheGame(updatedGame); - - this.globalEventService.publishReversiGameStream(game.id, 'changeReadyStates', { - user1: ready, - user2: updatedGame.user2Ready, - }); - - if (ready && updatedGame.user2Ready) isBothReady = true; - } else if (game.user2Id === user.id) { - const updatedGame = { - ...game, - user2Ready: ready, - }; - this.cacheGame(updatedGame); - - this.globalEventService.publishReversiGameStream(game.id, 'changeReadyStates', { - user1: updatedGame.user1Ready, - user2: ready, - }); - - if (ready && updatedGame.user1Ready) isBothReady = true; - } else { - return; - } - - if (isBothReady) { - // 3秒後、両者readyならゲーム開始 - setTimeout(async () => { - const freshGame = await this.get(game.id); - if (freshGame == null || freshGame.isStarted || freshGame.isEnded) return; - if (!freshGame.user1Ready || !freshGame.user2Ready) return; - - this.startGame(freshGame); - }, 3000); - } - } - - @bindThis - private async matched(parentId: MiUser['id'], childId: MiUser['id'], options: { noIrregularRules: boolean; }): Promise { - const game = await this.reversiGamesRepository.insertOne({ - id: this.idService.gen(), - user1Id: parentId, - user2Id: childId, - user1Ready: false, - user2Ready: false, - isStarted: false, - isEnded: false, - logs: [], - map: Reversi.maps.eighteight.data, - bw: 'random', - isLlotheo: false, - noIrregularRules: options.noIrregularRules, - }, { relations: ['user1', 'user2'] }); - this.cacheGame(game); - - const packed = await this.reversiGameEntityService.packDetail(game); - this.globalEventService.publishReversiStream(parentId, 'matched', { game: packed }); - - return game; - } - - @bindThis - private async startGame(game: MiReversiGame) { - let bw: number; - if (game.bw === 'random') { - bw = Math.random() > 0.5 ? 1 : 2; - } else { - bw = parseInt(game.bw, 10); - } - - const engine = new Reversi.Game(game.map, { - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - }); - - const crc32 = engine.calcCrc32().toString(); - - const updatedGame = await this.reversiGamesRepository.createQueryBuilder().update() - .set({ - ...this.getBakeProps(game), - startedAt: new Date(), - isStarted: true, - black: bw, - map: game.map, - crc32, - }) - .where('id = :id', { id: game.id }) - .returning('*') - .execute() - .then((response) => response.raw[0]); - // キャッシュ効率化のためにユーザー情報は再利用 - updatedGame.user1 = game.user1; - updatedGame.user2 = game.user2; - this.cacheGame(updatedGame); - - //#region 盤面に最初から石がないなどして始まった瞬間に勝敗が決定する場合があるのでその処理 - if (engine.isEnded) { - let winnerId; - if (engine.winner === true) { - winnerId = bw === 1 ? updatedGame.user1Id : updatedGame.user2Id; - } else if (engine.winner === false) { - winnerId = bw === 1 ? updatedGame.user2Id : updatedGame.user1Id; - } else { - winnerId = null; - } - - await this.endGame(updatedGame, winnerId, null); - - return; - } - //#endregion - - this.redisClient.setex(`reversi:game:turnTimer:${game.id}:1`, updatedGame.timeLimitForEachTurn, ''); - - this.globalEventService.publishReversiGameStream(game.id, 'started', { - game: await this.reversiGameEntityService.packDetail(updatedGame), - }); - } - - @bindThis - private async endGame(game: MiReversiGame, winnerId: MiUser['id'] | null, reason: 'surrender' | 'timeout' | null) { - const updatedGame = await this.reversiGamesRepository.createQueryBuilder().update() - .set({ - ...this.getBakeProps(game), - isEnded: true, - endedAt: new Date(), - winnerId: winnerId, - surrenderedUserId: reason === 'surrender' ? (winnerId === game.user1Id ? game.user2Id : game.user1Id) : null, - timeoutUserId: reason === 'timeout' ? (winnerId === game.user1Id ? game.user2Id : game.user1Id) : null, - }) - .where('id = :id', { id: game.id }) - .returning('*') - .execute() - .then((response) => response.raw[0]); - // キャッシュ効率化のためにユーザー情報は再利用 - updatedGame.user1 = game.user1; - updatedGame.user2 = game.user2; - this.cacheGame(updatedGame); - - this.globalEventService.publishReversiGameStream(game.id, 'ended', { - winnerId: winnerId, - game: await this.reversiGameEntityService.packDetail(updatedGame), - }); - } - - @bindThis - public async getInvitations(user: MiUser): Promise { - const invitations = await this.redisClient.zrange( - `reversi:matchSpecific:${user.id}`, - Date.now() - INVITATION_TIMEOUT_MS, - '+inf', - 'BYSCORE'); - return invitations; - } - - @bindThis - public async updateSettings(gameId: MiReversiGame['id'], user: MiUser, key: string, value: any) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - if (game.isStarted) return; - if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return; - if ((game.user1Id === user.id) && game.user1Ready) return; - if ((game.user2Id === user.id) && game.user2Ready) return; - - if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard', 'timeLimitForEachTurn'].includes(key)) return; - - // TODO: より厳格なバリデーション - - const updatedGame = { - ...game, - [key]: value, - }; - this.cacheGame(updatedGame); - - this.globalEventService.publishReversiGameStream(game.id, 'updateSettings', { - userId: user.id, - key: key, - value: value, - }); - } - - @bindThis - public async putStoneToGame(gameId: MiReversiGame['id'], user: MiUser, pos: number, id?: string | null) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - if (!game.isStarted) return; - if (game.isEnded) return; - if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return; - - const myColor = - ((game.user1Id === user.id) && game.black === 1) || ((game.user2Id === user.id) && game.black === 2) - ? true - : false; - - const engine = Reversi.Serializer.restoreGame({ - map: game.map, - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - logs: game.logs, - }); - - if (engine.turn !== myColor) return; - if (!engine.canPut(myColor, pos)) return; - - engine.putStone(pos); - - const logs = Reversi.Serializer.deserializeLogs(game.logs); - - const log = { - time: Date.now(), - player: myColor, - operation: 'put', - pos, - } as const; - - logs.push(log); - - const serializeLogs = Reversi.Serializer.serializeLogs(logs); - - const crc32 = engine.calcCrc32().toString(); - - const updatedGame = { - ...game, - crc32, - logs: serializeLogs, - }; - this.cacheGame(updatedGame); - - this.globalEventService.publishReversiGameStream(game.id, 'log', { - ...log, - id: id ?? null, - }); - - if (engine.isEnded) { - let winnerId; - if (engine.winner === true) { - winnerId = game.black === 1 ? game.user1Id : game.user2Id; - } else if (engine.winner === false) { - winnerId = game.black === 1 ? game.user2Id : game.user1Id; - } else { - winnerId = null; - } - - await this.endGame(updatedGame, winnerId, null); - } else { - this.redisClient.setex(`reversi:game:turnTimer:${game.id}:${engine.turn ? '1' : '0'}`, updatedGame.timeLimitForEachTurn, ''); - } - } - - @bindThis - public async surrender(gameId: MiReversiGame['id'], user: MiUser) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - 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.endGame(game, winnerId, 'surrender'); - } - - @bindThis - public async checkTimeout(gameId: MiReversiGame['id']) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - if (game.isEnded) return; - - const engine = Reversi.Serializer.restoreGame({ - map: game.map, - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - logs: game.logs, - }); - - if (engine.turn == null) return; - - const timer = await this.redisClient.exists(`reversi:game:turnTimer:${game.id}:${engine.turn ? '1' : '0'}`); - - if (timer === 0) { - const winnerId = engine.turn ? (game.black === 1 ? game.user2Id : game.user1Id) : (game.black === 1 ? game.user1Id : game.user2Id); - - await this.endGame(game, winnerId, 'timeout'); - } - } - - @bindThis - public async cancelGame(gameId: MiReversiGame['id'], user: MiUser) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - if (game.isStarted) return; - if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return; - - await this.reversiGamesRepository.delete(game.id); - this.deleteGameCache(game.id); - - this.globalEventService.publishReversiGameStream(game.id, 'canceled', { - userId: user.id, - }); - } - - @bindThis - public async get(id: MiReversiGame['id']): Promise { - const cached = await this.redisClient.get(`reversi:game:cache:${id}`); - if (cached != null) { - // TODO: この辺りのデシリアライズ処理をどこか別のサービスに切り出したい - const parsed = JSON.parse(cached) as Serialized; - return { - ...parsed, - startedAt: parsed.startedAt != null ? new Date(parsed.startedAt) : null, - endedAt: parsed.endedAt != null ? new Date(parsed.endedAt) : null, - user1: parsed.user1 != null ? { - ...parsed.user1, - avatar: null, - banner: null, - updatedAt: parsed.user1.updatedAt != null ? new Date(parsed.user1.updatedAt) : null, - lastActiveDate: parsed.user1.lastActiveDate != null ? new Date(parsed.user1.lastActiveDate) : null, - lastFetchedAt: parsed.user1.lastFetchedAt != null ? new Date(parsed.user1.lastFetchedAt) : null, - movedAt: parsed.user1.movedAt != null ? new Date(parsed.user1.movedAt) : null, - } : null, - user2: parsed.user2 != null ? { - ...parsed.user2, - avatar: null, - banner: null, - updatedAt: parsed.user2.updatedAt != null ? new Date(parsed.user2.updatedAt) : null, - lastActiveDate: parsed.user2.lastActiveDate != null ? new Date(parsed.user2.lastActiveDate) : null, - lastFetchedAt: parsed.user2.lastFetchedAt != null ? new Date(parsed.user2.lastFetchedAt) : null, - movedAt: parsed.user2.movedAt != null ? new Date(parsed.user2.movedAt) : null, - } : null, - }; - } else { - const game = await this.reversiGamesRepository.findOne({ - where: { id }, - relations: ['user1', 'user2'], - }); - if (game == null) return null; - - this.cacheGame(game); - - return game; - } - } - - @bindThis - public async checkCrc(gameId: MiReversiGame['id'], crc32: string | number) { - const game = await this.get(gameId); - if (game == null) throw new Error('game not found'); - - if (crc32.toString() !== game.crc32) { - return game; - } else { - return null; - } - } - - @bindThis - public dispose(): void { - } - - @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); - } -} diff --git a/packages/backend/src/core/entities/ReversiGameEntityService.ts b/packages/backend/src/core/entities/ReversiGameEntityService.ts deleted file mode 100644 index df042e75c1..0000000000 --- a/packages/backend/src/core/entities/ReversiGameEntityService.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { DI } from '@/di-symbols.js'; -import type { ReversiGamesRepository } from '@/models/_.js'; -import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/Blocking.js'; -import type { MiReversiGame } from '@/models/ReversiGame.js'; -import { bindThis } from '@/decorators.js'; -import { IdService } from '@/core/IdService.js'; -import { UserEntityService } from './UserEntityService.js'; - -@Injectable() -export class ReversiGameEntityService { - constructor( - @Inject(DI.reversiGamesRepository) - private reversiGamesRepository: ReversiGamesRepository, - - private userEntityService: UserEntityService, - private idService: IdService, - ) { - } - - @bindThis - public async packDetail( - src: MiReversiGame['id'] | MiReversiGame, - hint?: { - packedUser1?: Packed<'UserLite'>, - packedUser2?: Packed<'UserLite'>, - }, - ): Promise> { - const game = typeof src === 'object' ? src : await this.reversiGamesRepository.findOneByOrFail({ id: src }); - - const user1 = hint?.packedUser1 ?? await this.userEntityService.pack(game.user1 ?? game.user1Id); - const user2 = hint?.packedUser2 ?? await this.userEntityService.pack(game.user2 ?? game.user2Id); - - return await awaitAll({ - id: game.id, - createdAt: this.idService.parse(game.id).date.toISOString(), - startedAt: game.startedAt && game.startedAt.toISOString(), - endedAt: game.endedAt && game.endedAt.toISOString(), - isStarted: game.isStarted, - isEnded: game.isEnded, - form1: game.form1, - form2: game.form2, - user1Ready: game.user1Ready, - user2Ready: game.user2Ready, - user1Id: game.user1Id, - user2Id: game.user2Id, - user1, - user2, - winnerId: game.winnerId, - winner: game.winnerId ? [user1, user2].find(u => u.id === game.winnerId)! : null, - surrenderedUserId: game.surrenderedUserId, - timeoutUserId: game.timeoutUserId, - black: game.black, - bw: game.bw, - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - timeLimitForEachTurn: game.timeLimitForEachTurn, - noIrregularRules: game.noIrregularRules, - logs: game.logs, - map: game.map, - }); - } - - @bindThis - public async packDetailMany( - games: MiReversiGame[], - ) { - const _user1s = games.map(({ user1, user1Id }) => user1 ?? user1Id); - const _user2s = games.map(({ user2, user2Id }) => user2 ?? user2Id); - const _userMap = await this.userEntityService.packMany([..._user1s, ..._user2s]) - .then(users => new Map(users.map(u => [u.id, u]))); - return Promise.all( - games.map(game => { - return this.packDetail(game, { - packedUser1: _userMap.get(game.user1Id), - packedUser2: _userMap.get(game.user2Id), - }); - }), - ); - } - - @bindThis - public async packLite( - src: MiReversiGame['id'] | MiReversiGame, - hint?: { - packedUser1?: Packed<'UserLite'>, - packedUser2?: Packed<'UserLite'>, - }, - ): Promise> { - const game = typeof src === 'object' ? src : await this.reversiGamesRepository.findOneByOrFail({ id: src }); - - const user1 = hint?.packedUser1 ?? await this.userEntityService.pack(game.user1 ?? game.user1Id); - const user2 = hint?.packedUser2 ?? await this.userEntityService.pack(game.user2 ?? game.user2Id); - - return await awaitAll({ - id: game.id, - createdAt: this.idService.parse(game.id).date.toISOString(), - startedAt: game.startedAt && game.startedAt.toISOString(), - endedAt: game.endedAt && game.endedAt.toISOString(), - isStarted: game.isStarted, - isEnded: game.isEnded, - user1Id: game.user1Id, - user2Id: game.user2Id, - user1, - user2, - winnerId: game.winnerId, - winner: game.winnerId ? [user1, user2].find(u => u.id === game.winnerId)! : null, - surrenderedUserId: game.surrenderedUserId, - timeoutUserId: game.timeoutUserId, - black: game.black, - bw: game.bw, - isLlotheo: game.isLlotheo, - canPutEverywhere: game.canPutEverywhere, - loopedBoard: game.loopedBoard, - timeLimitForEachTurn: game.timeLimitForEachTurn, - noIrregularRules: game.noIrregularRules, - }); - } - - @bindThis - public async packLiteMany( - games: MiReversiGame[], - ) { - const _user1s = games.map(({ user1, user1Id }) => user1 ?? user1Id); - const _user2s = games.map(({ user2, user2Id }) => user2 ?? user2Id); - const _userMap = await this.userEntityService.packMany([..._user1s, ..._user2s]) - .then(users => new Map(users.map(u => [u.id, u]))); - return Promise.all( - games.map(game => { - return this.packLite(game, { - packedUser1: _userMap.get(game.user1Id), - packedUser2: _userMap.get(game.user2Id), - }); - }), - ); - } -} - diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 9f060e81be..a88c695958 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -90,6 +90,5 @@ export const DI = { flashLikesRepository: Symbol('flashLikesRepository'), userMemosRepository: Symbol('userMemosRepository'), bubbleGameRecordsRepository: Symbol('bubbleGameRecordsRepository'), - reversiGamesRepository: Symbol('reversiGamesRepository'), //#endregion }; diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index 6c1b92ef16..9f35cd0c0f 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -53,7 +53,6 @@ import { packedRoleSchema, } from '@/models/json-schema/role.js'; import { packedAdSchema } from '@/models/json-schema/ad.js'; -import { packedReversiGameDetailedSchema, packedReversiGameLiteSchema } from '@/models/json-schema/reversi-game.js'; import { packedMetaDetailedOnlySchema, packedMetaDetailedSchema, @@ -112,8 +111,6 @@ export const refs = { RoleLite: packedRoleLiteSchema, Role: packedRoleSchema, RolePolicies: packedRolePoliciesSchema, - ReversiGameLite: packedReversiGameLiteSchema, - ReversiGameDetailed: packedReversiGameDetailedSchema, MetaLite: packedMetaLiteSchema, MetaDetailedOnly: packedMetaDetailedOnlySchema, MetaDetailed: packedMetaDetailedSchema, diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index 325645cbd6..facd56ba08 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -60,7 +60,6 @@ import { MiRepository, miRepository, MiRetentionAggregation, - MiReversiGame, MiRole, MiRoleAssignment, MiSignin, @@ -525,12 +524,6 @@ const $bubbleGameRecordsRepository: Provider = { inject: [DI.db], }; -const $reversiGamesRepository: Provider = { - provide: DI.reversiGamesRepository, - useFactory: (db: DataSource) => db.getRepository(MiReversiGame).extend(miRepository as MiRepository), - inject: [DI.db], -}; - const $abuseReportResolversRepository: Provider = { provide: DI.abuseReportResolversRepository, useFactory: (db: DataSource) => db.getRepository(MiAbuseReportResolver).extend(miRepository as MiRepository), @@ -614,7 +607,6 @@ const $abuseReportResolversRepository: Provider = { $userMemosRepository, $abuseReportResolversRepository, $bubbleGameRecordsRepository, - $reversiGamesRepository, ], exports: [ $usersRepository, @@ -691,7 +683,6 @@ const $abuseReportResolversRepository: Provider = { $userMemosRepository, $abuseReportResolversRepository, $bubbleGameRecordsRepository, - $reversiGamesRepository, ], }) export class RepositoryModule { diff --git a/packages/backend/src/models/ReversiGame.ts b/packages/backend/src/models/ReversiGame.ts deleted file mode 100644 index 6b29a0ce8c..0000000000 --- a/packages/backend/src/models/ReversiGame.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from './util/id.js'; -import { MiUser } from './User.js'; - -@Entity('reversi_game') -export class MiReversiGame { - @PrimaryColumn(id()) - public id: string; - - @Column('timestamp with time zone', { - nullable: true, - comment: 'The started date of the ReversiGame.', - }) - public startedAt: Date | null; - - @Column('timestamp with time zone', { - nullable: true, - comment: 'The ended date of the ReversiGame.', - }) - public endedAt: Date | null; - - @Column(id()) - public user1Id: MiUser['id']; - - @ManyToOne(type => MiUser, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public user1: MiUser | null; - - @Column(id()) - public user2Id: MiUser['id']; - - @ManyToOne(type => MiUser, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public user2: MiUser | null; - - @Column('boolean', { - default: false, - }) - public user1Ready: boolean; - - @Column('boolean', { - default: false, - }) - public user2Ready: boolean; - - /** - * どちらのプレイヤーが先行(黒)か - * 1 ... user1 - * 2 ... user2 - */ - @Column('integer', { - nullable: true, - }) - public black: number | null; - - @Column('boolean', { - default: false, - }) - public isStarted: boolean; - - @Column('boolean', { - default: false, - }) - public isEnded: boolean; - - @Column({ - ...id(), - nullable: true, - }) - public winnerId: MiUser['id'] | null; - - @Column({ - ...id(), - nullable: true, - }) - public surrenderedUserId: MiUser['id'] | null; - - @Column({ - ...id(), - nullable: true, - }) - public timeoutUserId: MiUser['id'] | null; - - // in sec - @Column('smallint', { - default: 90, - }) - public timeLimitForEachTurn: number; - - @Column('jsonb', { - default: [], - }) - public logs: number[][]; - - @Column('varchar', { - array: true, length: 64, - }) - public map: string[]; - - @Column('varchar', { - length: 32, - }) - public bw: string; - - @Column('boolean', { - default: false, - }) - public noIrregularRules: boolean; - - @Column('boolean', { - default: false, - }) - public isLlotheo: boolean; - - @Column('boolean', { - default: false, - }) - public canPutEverywhere: boolean; - - @Column('boolean', { - default: false, - }) - public loopedBoard: boolean; - - @Column('jsonb', { - nullable: true, default: null, - }) - public form1: any | null; - - @Column('jsonb', { - nullable: true, default: null, - }) - public form2: any | null; - - @Column('varchar', { - length: 32, nullable: true, - }) - public crc32: string | null; -} diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 92f9dbf21e..47bf1bf34a 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -84,7 +84,6 @@ import { MiFlash } from '@/models/Flash.js'; import { MiFlashLike } from '@/models/FlashLike.js'; import { MiUserListFavorite } from '@/models/UserListFavorite.js'; import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; -import { MiReversiGame } from '@/models/ReversiGame.js'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; export interface MiRepository { @@ -205,7 +204,6 @@ export { MiFlashLike, MiUserMemo, MiBubbleGameRecord, - MiReversiGame, }; export type AbuseReportResolversRepository = Repository & MiRepository; @@ -282,4 +280,3 @@ export type FlashsRepository = Repository & MiRepository; export type FlashLikesRepository = Repository & MiRepository; export type UserMemoRepository = Repository & MiRepository; export type BubbleGameRecordsRepository = Repository & MiRepository; -export type ReversiGamesRepository = Repository & MiRepository; diff --git a/packages/backend/src/models/json-schema/reversi-game.ts b/packages/backend/src/models/json-schema/reversi-game.ts deleted file mode 100644 index cb37200384..0000000000 --- a/packages/backend/src/models/json-schema/reversi-game.ts +++ /dev/null @@ -1,243 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export const packedReversiGameLiteSchema = { - type: 'object', - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - createdAt: { - type: 'string', - optional: false, nullable: false, - format: 'date-time', - }, - startedAt: { - type: 'string', - optional: false, nullable: true, - format: 'date-time', - }, - endedAt: { - type: 'string', - optional: false, nullable: true, - format: 'date-time', - }, - isStarted: { - type: 'boolean', - optional: false, nullable: false, - }, - isEnded: { - type: 'boolean', - optional: false, nullable: false, - }, - user1Id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - user2Id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - user1: { - type: 'object', - optional: false, nullable: false, - ref: 'UserLite', - }, - user2: { - type: 'object', - optional: false, nullable: false, - ref: 'UserLite', - }, - winnerId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - winner: { - type: 'object', - optional: false, nullable: true, - ref: 'UserLite', - }, - surrenderedUserId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - timeoutUserId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - black: { - type: 'number', - optional: false, nullable: true, - }, - bw: { - type: 'string', - optional: false, nullable: false, - }, - noIrregularRules: { - type: 'boolean', - optional: false, nullable: false, - }, - isLlotheo: { - type: 'boolean', - optional: false, nullable: false, - }, - canPutEverywhere: { - type: 'boolean', - optional: false, nullable: false, - }, - loopedBoard: { - type: 'boolean', - optional: false, nullable: false, - }, - timeLimitForEachTurn: { - type: 'number', - optional: false, nullable: false, - }, - }, -} as const; - -export const packedReversiGameDetailedSchema = { - type: 'object', - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - createdAt: { - type: 'string', - optional: false, nullable: false, - format: 'date-time', - }, - startedAt: { - type: 'string', - optional: false, nullable: true, - format: 'date-time', - }, - endedAt: { - type: 'string', - optional: false, nullable: true, - format: 'date-time', - }, - isStarted: { - type: 'boolean', - optional: false, nullable: false, - }, - isEnded: { - type: 'boolean', - optional: false, nullable: false, - }, - form1: { - type: 'object', - optional: false, nullable: true, - }, - form2: { - type: 'object', - optional: false, nullable: true, - }, - user1Ready: { - type: 'boolean', - optional: false, nullable: false, - }, - user2Ready: { - type: 'boolean', - optional: false, nullable: false, - }, - user1Id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - user2Id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - user1: { - type: 'object', - optional: false, nullable: false, - ref: 'UserLite', - }, - user2: { - type: 'object', - optional: false, nullable: false, - ref: 'UserLite', - }, - winnerId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - winner: { - type: 'object', - optional: false, nullable: true, - ref: 'UserLite', - }, - surrenderedUserId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - timeoutUserId: { - type: 'string', - optional: false, nullable: true, - format: 'id', - }, - black: { - type: 'number', - optional: false, nullable: true, - }, - bw: { - type: 'string', - optional: false, nullable: false, - }, - noIrregularRules: { - type: 'boolean', - optional: false, nullable: false, - }, - isLlotheo: { - type: 'boolean', - optional: false, nullable: false, - }, - canPutEverywhere: { - type: 'boolean', - optional: false, nullable: false, - }, - loopedBoard: { - type: 'boolean', - optional: false, nullable: false, - }, - timeLimitForEachTurn: { - type: 'number', - optional: false, nullable: false, - }, - logs: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'number', - }, - }, - }, - map: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'string', - optional: false, nullable: false, - }, - }, - }, -} as const; diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index ee9ecafacc..e816a7ef71 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -83,7 +83,6 @@ import { MiFlash } from '@/models/Flash.js'; import { MiFlashLike } from '@/models/FlashLike.js'; import { MiUserMemo } from '@/models/UserMemo.js'; import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; -import { MiReversiGame } from '@/models/ReversiGame.js'; import { Config } from '@/config.js'; import MisskeyLogger from '@/logger.js'; @@ -209,7 +208,6 @@ export const entities = [ MiFlashLike, MiUserMemo, MiBubbleGameRecord, - MiReversiGame, ...charts, ]; diff --git a/packages/backend/src/queue/processors/CleanProcessorService.ts b/packages/backend/src/queue/processors/CleanProcessorService.ts index a26b69cd2b..ec648c9a31 100644 --- a/packages/backend/src/queue/processors/CleanProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanProcessorService.ts @@ -11,7 +11,6 @@ import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; import type { Config } from '@/config.js'; -import { ReversiService } from '@/core/ReversiService.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -33,7 +32,6 @@ export class CleanProcessorService { private roleAssignmentsRepository: RoleAssignmentsRepository, private queueLoggerService: QueueLoggerService, - private reversiService: ReversiService, private idService: IdService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('clean'); @@ -67,8 +65,6 @@ export class CleanProcessorService { }); } - this.reversiService.cleanOutdatedGames(); - this.logger.succ('Cleaned.'); } } diff --git a/packages/backend/src/server/ServerModule.ts b/packages/backend/src/server/ServerModule.ts index 41b960fc0f..3eb8aef4ed 100644 --- a/packages/backend/src/server/ServerModule.ts +++ b/packages/backend/src/server/ServerModule.ts @@ -46,8 +46,6 @@ import { QueueStatsChannelService } from './api/stream/channels/queue-stats.js'; import { ServerStatsChannelService } from './api/stream/channels/server-stats.js'; import { UserListChannelService } from './api/stream/channels/user-list.js'; import { RoleTimelineChannelService } from './api/stream/channels/role-timeline.js'; -import { ReversiChannelService } from './api/stream/channels/reversi.js'; -import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js'; @Module({ imports: [ @@ -84,8 +82,6 @@ import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js GlobalTimelineChannelService, HashtagChannelService, RoleTimelineChannelService, - ReversiChannelService, - ReversiGameChannelService, HomeTimelineChannelService, HybridTimelineChannelService, LocalTimelineChannelService, diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 69b31ac571..d46d067d66 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -411,13 +411,6 @@ 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 * as ep___reversi_verify from './endpoints/reversi/verify.js'; import { GetterService } from './GetterService.js'; import { ApiLoggerService } from './ApiLoggerService.js'; import type { Provider } from '@nestjs/common'; @@ -826,13 +819,6 @@ 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 }; -const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep___reversi_verify.default }; @Module({ imports: [ @@ -1246,13 +1232,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $retention, $bubbleGame_register, $bubbleGame_ranking, - $reversi_cancelMatch, - $reversi_games, - $reversi_match, - $reversi_invitations, - $reversi_showGame, - $reversi_surrender, - $reversi_verify, ], exports: [ $admin_meta, @@ -1656,13 +1635,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $retention, $bubbleGame_register, $bubbleGame_ranking, - $reversi_cancelMatch, - $reversi_games, - $reversi_match, - $reversi_invitations, - $reversi_showGame, - $reversi_surrender, - $reversi_verify, ], }) export class EndpointsModule {} diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index f23ca7dfb9..c2a229c591 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -416,13 +416,6 @@ 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 * as ep___reversi_verify from './endpoints/reversi/verify.js'; const eps = [ ['admin/meta', ep___admin_meta], @@ -829,13 +822,6 @@ 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], - ['reversi/verify', ep___reversi_verify], ]; interface IEndpointMetaBase { diff --git a/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts b/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts deleted file mode 100644 index dd6f273e01..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/cancel-match.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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: { - }, -} 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 { // 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 deleted file mode 100644 index 6b06068727..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/games.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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 { // 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) - .innerJoinAndSelect('game.user1', 'user1') - .innerJoinAndSelect('game.user2', 'user2'); - - if (ps.my && me) { - query.andWhere(new Brackets(qb => { - qb - .where('game.user1Id = :userId', { userId: me.id }) - .orWhere('game.user2Id = :userId', { userId: me.id }); - })); - } else { - query.andWhere('game.isStarted = TRUE'); - } - - const games = await query.take(ps.limit).getMany(); - - return await this.reversiGameEntityService.packLiteMany(games); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/reversi/invitations.ts b/packages/backend/src/server/api/endpoints/reversi/invitations.ts deleted file mode 100644 index 5b3b9da75b..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/invitations.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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 { // 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 deleted file mode 100644 index aa8b8a7d72..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/match.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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: { - type: 'object', - optional: true, - ref: 'ReversiGameDetailed', - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - userId: { type: 'string', format: 'misskey:id', nullable: true }, - noIrregularRules: { type: 'boolean', default: false }, - multiple: { type: 'boolean', default: false }, - }, - required: [], -} as const; - -@Injectable() -export default class extends Endpoint { // 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, ps.multiple) - : await this.reversiService.matchAnyUser(me, { noIrregularRules: ps.noIrregularRules }, ps.multiple); - - if (game == null) return; - - return await this.reversiGameEntityService.packDetail(game); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/reversi/show-game.ts b/packages/backend/src/server/api/endpoints/reversi/show-game.ts deleted file mode 100644 index fc3b96eb51..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/show-game.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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 { // 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); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/reversi/surrender.ts b/packages/backend/src/server/api/endpoints/reversi/surrender.ts deleted file mode 100644 index 75e5372862..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/surrender.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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 { // 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); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/reversi/verify.ts b/packages/backend/src/server/api/endpoints/reversi/verify.ts deleted file mode 100644 index 981735a3d7..0000000000 --- a/packages/backend/src/server/api/endpoints/reversi/verify.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * 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 = { - errors: { - noSuchGame: { - message: 'No such game.', - code: 'NO_SUCH_GAME', - id: '8fb05624-b525-43dd-90f7-511852bdfeee', - }, - }, - - res: { - type: 'object', - optional: false, nullable: false, - properties: { - desynced: { type: 'boolean' }, - game: { - type: 'object', - optional: true, nullable: true, - ref: 'ReversiGameDetailed', - }, - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - gameId: { type: 'string', format: 'misskey:id' }, - crc32: { type: 'string' }, - }, - required: ['gameId', 'crc32'], -} as const; - -@Injectable() -export default class extends Endpoint { // 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.checkCrc(ps.gameId, ps.crc32); - if (game) { - return { - desynced: true, - game: await this.reversiGameEntityService.packDetail(game), - }; - } else { - return { - desynced: false, - }; - } - }); - } -} diff --git a/packages/backend/src/server/api/stream/ChannelsService.ts b/packages/backend/src/server/api/stream/ChannelsService.ts index ac528952db..5d734fb378 100644 --- a/packages/backend/src/server/api/stream/ChannelsService.ts +++ b/packages/backend/src/server/api/stream/ChannelsService.ts @@ -21,8 +21,6 @@ import { MessagingIndexChannelService } from './channels/messaging-index.js'; import { DriveChannelService } from './channels/drive.js'; import { HashtagChannelService } from './channels/hashtag.js'; import { RoleTimelineChannelService } from './channels/role-timeline.js'; -import { ReversiChannelService } from './channels/reversi.js'; -import { ReversiGameChannelService } from './channels/reversi-game.js'; import { type MiChannelService } from './channel.js'; @Injectable() @@ -44,8 +42,6 @@ export class ChannelsService { private serverStatsChannelService: ServerStatsChannelService, private queueStatsChannelService: QueueStatsChannelService, private adminChannelService: AdminChannelService, - private reversiChannelService: ReversiChannelService, - private reversiGameChannelService: ReversiGameChannelService, ) { } @@ -69,8 +65,6 @@ export class ChannelsService { case 'serverStats': return this.serverStatsChannelService; case 'queueStats': return this.queueStatsChannelService; case 'admin': return this.adminChannelService; - case 'reversi': return this.reversiChannelService; - case 'reversiGame': return this.reversiGameChannelService; default: throw new Error(`no such channel: ${name}`); diff --git a/packages/backend/src/server/api/stream/channels/reversi-game.ts b/packages/backend/src/server/api/stream/channels/reversi-game.ts deleted file mode 100644 index 17823a164a..0000000000 --- a/packages/backend/src/server/api/stream/channels/reversi-game.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import type { MiReversiGame } from '@/models/_.js'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import { ReversiService } from '@/core/ReversiService.js'; -import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js'; -import type { JsonObject, JsonValue } from '@/misc/json-value.js'; -import Channel, { type MiChannelService } from '../channel.js'; - -class ReversiGameChannel extends Channel { - public readonly chName = 'reversiGame'; - public static shouldShare = false; - public static requireCredential = false as const; - private gameId: MiReversiGame['id'] | null = null; - - constructor( - private reversiService: ReversiService, - private reversiGameEntityService: ReversiGameEntityService, - - id: string, - connection: Channel['connection'], - ) { - super(id, connection); - } - - @bindThis - public async init(params: JsonObject) { - if (typeof params.gameId !== 'string') return; - this.gameId = params.gameId; - - this.subscriber.on(`reversiGameStream:${this.gameId}`, this.send); - } - - @bindThis - public onMessage(type: string, body: JsonValue) { - switch (type) { - case 'ready': - if (typeof body !== 'boolean') return; - this.ready(body); - break; - case 'updateSettings': - if (typeof body !== 'object' || body === null || Array.isArray(body)) return; - if (typeof body.key !== 'string') return; - if (typeof body.value !== 'object' || body.value === null || Array.isArray(body.value)) return; - this.updateSettings(body.key, body.value); - break; - case 'cancel': - this.cancelGame(); - break; - case 'putStone': - if (typeof body !== 'object' || body === null || Array.isArray(body)) return; - if (typeof body.pos !== 'number') return; - if (typeof body.id !== 'string') return; - this.putStone(body.pos, body.id); - break; - case 'claimTimeIsUp': this.claimTimeIsUp(); break; - } - } - - @bindThis - private async updateSettings(key: string, value: JsonObject) { - if (this.user == null) return; - - this.reversiService.updateSettings(this.gameId!, this.user, key, value); - } - - @bindThis - private async ready(ready: boolean) { - if (this.user == null) return; - - this.reversiService.gameReady(this.gameId!, this.user, ready); - } - - @bindThis - private async cancelGame() { - if (this.user == null) return; - - this.reversiService.cancelGame(this.gameId!, this.user); - } - - @bindThis - private async putStone(pos: number, id: string) { - if (this.user == null) return; - - this.reversiService.putStoneToGame(this.gameId!, this.user, pos, id); - } - - @bindThis - private async claimTimeIsUp() { - if (this.user == null) return; - - this.reversiService.checkTimeout(this.gameId!); - } - - @bindThis - public dispose() { - // Unsubscribe events - this.subscriber.off(`reversiGameStream:${this.gameId}`, this.send); - } -} - -@Injectable() -export class ReversiGameChannelService implements MiChannelService { - public readonly shouldShare = ReversiGameChannel.shouldShare; - public readonly requireCredential = ReversiGameChannel.requireCredential; - public readonly kind = ReversiGameChannel.kind; - - constructor( - private reversiService: ReversiService, - private reversiGameEntityService: ReversiGameEntityService, - ) { - } - - @bindThis - public create(id: string, connection: Channel['connection']): ReversiGameChannel { - return new ReversiGameChannel( - this.reversiService, - this.reversiGameEntityService, - id, - connection, - ); - } -} diff --git a/packages/backend/src/server/api/stream/channels/reversi.ts b/packages/backend/src/server/api/stream/channels/reversi.ts deleted file mode 100644 index 6e88939724..0000000000 --- a/packages/backend/src/server/api/stream/channels/reversi.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { bindThis } from '@/decorators.js'; -import type { JsonObject } from '@/misc/json-value.js'; -import Channel, { type MiChannelService } from '../channel.js'; - -class ReversiChannel extends Channel { - public readonly chName = 'reversi'; - public static shouldShare = true; - public static requireCredential = true as const; - public static kind = 'read:account'; - - constructor( - id: string, - connection: Channel['connection'], - ) { - super(id, connection); - } - - @bindThis - public async init(params: JsonObject) { - this.subscriber.on(`reversiStream:${this.user!.id}`, this.send); - } - - @bindThis - public dispose() { - // Unsubscribe events - this.subscriber.off(`reversiStream:${this.user!.id}`, this.send); - } -} - -@Injectable() -export class ReversiChannelService implements MiChannelService { - public readonly shouldShare = ReversiChannel.shouldShare; - public readonly requireCredential = ReversiChannel.requireCredential; - public readonly kind = ReversiChannel.kind; - - constructor( - ) { - } - - @bindThis - public create(id: string, connection: Channel['connection']): ReversiChannel { - return new ReversiChannel( - id, - connection, - ); - } -} diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 7b4e95f93c..ceed7adcb8 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -43,13 +43,12 @@ import { MetaEntityService } from '@/core/entities/MetaEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; -import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js'; import { bindThis } from '@/decorators.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { RoleService } from '@/core/RoleService.js'; -import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js'; import { FeedService } from './FeedService.js'; import { UrlPreviewService } from './UrlPreviewService.js'; import { ClientLoggerService } from './ClientLoggerService.js'; @@ -97,9 +96,6 @@ export class ClientServerService { @Inject(DI.flashsRepository) private flashsRepository: FlashsRepository, - @Inject(DI.reversiGamesRepository) - private reversiGamesRepository: ReversiGamesRepository, - private flashEntityService: FlashEntityService, private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, @@ -108,7 +104,6 @@ export class ClientServerService { private galleryPostEntityService: GalleryPostEntityService, private clipEntityService: ClipEntityService, private channelEntityService: ChannelEntityService, - private reversiGameEntityService: ReversiGameEntityService, private metaService: MetaService, private urlPreviewService: UrlPreviewService, private feedService: FeedService, @@ -746,26 +741,6 @@ export class ClientServerService { } }); - // Reversi game - fastify.get<{ Params: { game: string; } }>('/reversi/g/:game', async (request, reply) => { - const game = await this.reversiGamesRepository.findOneBy({ - id: request.params.game, - }); - - if (game) { - const _game = await this.reversiGameEntityService.packDetail(game); - const meta = await this.metaService.fetch(); - reply.header('Cache-Control', 'public, max-age=3600'); - return await reply.view('reversi-game', { - game: _game, - ...await this.generateCommonPugData(meta), - }); - } else { - return await renderBase(reply); - } - }); - //#endregion - //region noindex pages // Tags fastify.get<{ Params: { clip: string; } }>('/tags/:tag', async (request, reply) => { diff --git a/packages/backend/src/server/web/views/reversi-game.pug b/packages/backend/src/server/web/views/reversi-game.pug deleted file mode 100644 index 2e9b6881d2..0000000000 --- a/packages/backend/src/server/web/views/reversi-game.pug +++ /dev/null @@ -1,20 +0,0 @@ -extends ./base - -block vars - - const user1 = game.user1; - - const user2 = game.user2; - - const title = `${user1.username} vs ${user2.username}`; - - const url = `${config.url}/reversi/g/${game.id}`; - -block title - = `${title} | ${instanceName}` - -block desc - meta(name='description' content='⚫⚪CherryPick Reversi⚪⚫') - -block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content='⚫⚪CherryPick Reversi⚪⚫') - meta(property='og:url' content= url) - meta(property='twitter:card' content='summary') diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts deleted file mode 100644 index 53d91afed4..0000000000 --- a/packages/backend/test/e2e/reversi-game.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -process.env.NODE_ENV = 'test'; - -import * as assert from 'assert'; -import { ReversiMatchResponse } from 'cherrypick-js/entities.js'; -import { api, signup } from '../utils.js'; -import type * as misskey from 'cherrypick-js'; - -describe('ReversiGame', () => { - let alice: misskey.entities.SignupResponse; - let bob: misskey.entities.SignupResponse; - - beforeAll(async () => { - alice = await signup({ username: 'alice' }); - bob = await signup({ username: 'bob' }); - }, 1000 * 60 * 2); - - test('matches when alice invites bob and bob accepts', async () => { - const response1 = await api('reversi/match', { userId: bob.id }, alice); - assert.strictEqual(response1.status, 204); - assert.strictEqual(response1.body, null); - const response2 = await api('reversi/match', { userId: alice.id }, bob); - assert.strictEqual(response2.status, 200); - assert.notStrictEqual(response2.body, null); - const body = response2.body as ReversiMatchResponse; - assert.strictEqual(body.user1.id, alice.id); - assert.strictEqual(body.user2.id, bob.id); - }); -}); diff --git a/packages/cherrypick-js/etc/cherrypick-js.api.md b/packages/cherrypick-js/etc/cherrypick-js.api.md index 9841520378..e8376d0118 100644 --- a/packages/cherrypick-js/etc/cherrypick-js.api.md +++ b/packages/cherrypick-js/etc/cherrypick-js.api.md @@ -812,43 +812,6 @@ export type Channels = { }; receives: null; }; - reversiGame: { - params: { - gameId: string; - }; - events: { - started: (payload: { - game: ReversiGameDetailed; - }) => void; - ended: (payload: { - winnerId: User['id'] | null; - game: ReversiGameDetailed; - }) => void; - canceled: (payload: { - userId: User['id']; - }) => void; - changeReadyStates: (payload: { - user1: boolean; - user2: boolean; - }) => void; - updateSettings: (payload: { - userId: User['id']; - key: K; - value: ReversiGameDetailed[K]; - }) => void; - log: (payload: Record) => void; - }; - receives: { - putStone: { - pos: number; - id: string; - }; - ready: boolean; - cancel: null | Record; - updateSettings: ReversiUpdateSettings; - claimTimeIsUp: null | Record; - }; - }; }; // @public (undocumented) @@ -1856,17 +1819,6 @@ declare namespace entities { BubbleGameRegisterRequest, BubbleGameRankingRequest, BubbleGameRankingResponse, - ReversiCancelMatchRequest, - ReversiGamesRequest, - ReversiGamesResponse, - ReversiMatchRequest, - ReversiMatchResponse, - ReversiInvitationsResponse, - ReversiShowGameRequest, - ReversiShowGameResponse, - ReversiSurrenderRequest, - ReversiVerifyRequest, - ReversiVerifyResponse, Error_2 as Error, UserLite, UserDetailedNotMeOnly, @@ -1916,8 +1868,6 @@ declare namespace entities { RoleLite, Role, RolePolicies, - ReversiGameLite, - ReversiGameDetailed, MetaLite, MetaDetailedOnly, MetaDetailed, @@ -2955,45 +2905,6 @@ type ResetPasswordRequest = operations['reset-password']['requestBody']['content // @public (undocumented) type RetentionResponse = operations['retention']['responses']['200']['content']['application/json']; -// @public (undocumented) -type ReversiCancelMatchRequest = operations['reversi___cancel-match']['requestBody']['content']['application/json']; - -// @public (undocumented) -type ReversiGameDetailed = components['schemas']['ReversiGameDetailed']; - -// @public (undocumented) -type ReversiGameLite = components['schemas']['ReversiGameLite']; - -// @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 ReversiInvitationsResponse = operations['reversi___invitations']['responses']['200']['content']['application/json']; - -// @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 ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json']; - -// @public (undocumented) -type ReversiVerifyResponse = operations['reversi___verify']['responses']['200']['content']['application/json']; - // @public (undocumented) type Role = components['schemas']['Role']; @@ -3449,8 +3360,6 @@ type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody'][' // Warnings were encountered during analysis: // // src/entities.ts:35:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts -// src/streaming.types.ts:252:4 - (ae-forgotten-export) The symbol "ReversiUpdateKey" needs to be exported by the entry point index.d.ts -// src/streaming.types.ts:262:4 - (ae-forgotten-export) The symbol "ReversiUpdateSettings" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/cherrypick-js/src/autogen/apiClientJSDoc.ts b/packages/cherrypick-js/src/autogen/apiClientJSDoc.ts index 398fcebfdd..5f08f1a424 100644 --- a/packages/cherrypick-js/src/autogen/apiClientJSDoc.ts +++ b/packages/cherrypick-js/src/autogen/apiClientJSDoc.ts @@ -4501,82 +4501,5 @@ declare module '../api.js' { params: P, credential?: string | null, ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:account* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *No* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:account* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *Yes* / **Permission**: *read:account* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *No* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:account* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Credential required**: *No* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; } } diff --git a/packages/cherrypick-js/src/autogen/endpoint.ts b/packages/cherrypick-js/src/autogen/endpoint.ts index 2c0c01a021..0bad22b24f 100644 --- a/packages/cherrypick-js/src/autogen/endpoint.ts +++ b/packages/cherrypick-js/src/autogen/endpoint.ts @@ -606,17 +606,6 @@ import type { BubbleGameRegisterRequest, BubbleGameRankingRequest, BubbleGameRankingResponse, - ReversiCancelMatchRequest, - ReversiGamesRequest, - ReversiGamesResponse, - ReversiMatchRequest, - ReversiMatchResponse, - ReversiInvitationsResponse, - ReversiShowGameRequest, - ReversiShowGameResponse, - ReversiSurrenderRequest, - ReversiVerifyRequest, - ReversiVerifyResponse, } from './entities.js'; export type Endpoints = { @@ -1024,13 +1013,6 @@ export type Endpoints = { 'retention': { req: EmptyRequest; res: RetentionResponse }; 'bubble-game/register': { req: BubbleGameRegisterRequest; res: EmptyResponse }; 'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse }; - 'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: EmptyResponse }; - 'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse }; - 'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse }; - 'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse }; - 'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse }; - 'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse }; - 'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse }; } export const endpointReqTypes: Record = { @@ -1438,11 +1420,4 @@ export const endpointReqTypes: Record; @@ -5168,76 +5105,6 @@ export type components = { fileSizeLimit: number; canEditNote: boolean; }; - ReversiGameLite: { - /** Format: id */ - id: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - startedAt: string | null; - /** Format: date-time */ - endedAt: string | null; - isStarted: boolean; - isEnded: boolean; - /** Format: id */ - user1Id: string; - /** Format: id */ - user2Id: string; - user1: components['schemas']['UserLite']; - user2: components['schemas']['UserLite']; - /** Format: id */ - winnerId: string | null; - winner: components['schemas']['UserLite'] | null; - /** Format: id */ - surrenderedUserId: string | null; - /** Format: id */ - timeoutUserId: string | null; - black: number | null; - bw: string; - noIrregularRules: boolean; - isLlotheo: boolean; - canPutEverywhere: boolean; - loopedBoard: boolean; - timeLimitForEachTurn: number; - }; - ReversiGameDetailed: { - /** Format: id */ - id: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - startedAt: string | null; - /** Format: date-time */ - endedAt: string | null; - isStarted: boolean; - isEnded: boolean; - form1: Record | null; - form2: Record | null; - user1Ready: boolean; - user2Ready: boolean; - /** Format: id */ - user1Id: string; - /** Format: id */ - user2Id: string; - user1: components['schemas']['UserLite']; - user2: components['schemas']['UserLite']; - /** Format: id */ - winnerId: string | null; - winner: components['schemas']['UserLite'] | null; - /** Format: id */ - surrenderedUserId: string | null; - /** Format: id */ - timeoutUserId: string | null; - black: number | null; - bw: string; - noIrregularRules: boolean; - isLlotheo: boolean; - canPutEverywhere: boolean; - loopedBoard: boolean; - timeLimitForEachTurn: number; - logs: number[][]; - map: string[]; - }; MetaLite: { maintainerName: string | null; maintainerEmail: string | null; @@ -29488,389 +29355,5 @@ export type operations = { }; }; }; - /** - * reversi/cancel-match - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:account* - */ - 'reversi___cancel-match': { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - userId?: string | null; - }; - }; - }; - 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']; - }; - }; - }; - }; - /** - * 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']['ReversiGameLite'][]; - }; - }; - /** @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 | null; - /** @default false */ - noIrregularRules?: boolean; - /** @default false */ - multiple?: boolean; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['ReversiGameDetailed']; - }; - }; - /** @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']; - }; - }; - }; - }; - /** - * reversi/invitations - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *read:account* - */ - reversi___invitations: { - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['UserLite'][]; - }; - }; - /** @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']['ReversiGameDetailed']; - }; - }; - /** @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']; - }; - }; - }; - }; - /** - * reversi/verify - * @description No description provided. - * - * **Credential required**: *No* - */ - reversi___verify: { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - gameId: string; - crc32: string; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': { - desynced: boolean; - game?: components['schemas']['ReversiGameDetailed'] | null; - }; - }; - }; - /** @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']; - }; - }; - }; - }; }; diff --git a/packages/cherrypick-js/src/consts.ts b/packages/cherrypick-js/src/consts.ts index 3e28cd99fe..ea30c64158 100644 --- a/packages/cherrypick-js/src/consts.ts +++ b/packages/cherrypick-js/src/consts.ts @@ -151,18 +151,6 @@ export const moderationLogTypes = [ 'deleteAbuseReportNotificationRecipient', ] as const; -// See: packages/backend/src/core/ReversiService.ts@L410 -export const reversiUpdateKeys = [ - 'map', - 'bw', - 'isLlotheo', - 'canPutEverywhere', - 'loopedBoard', - 'timeLimitForEachTurn', -] as const; - -export type ReversiUpdateKey = typeof reversiUpdateKeys[number]; - type AvatarDecoration = UserLite['avatarDecorations'][number]; type ReceivedAbuseReport = { diff --git a/packages/cherrypick-js/src/streaming.types.ts b/packages/cherrypick-js/src/streaming.types.ts index fa54f28040..6e2941b933 100644 --- a/packages/cherrypick-js/src/streaming.types.ts +++ b/packages/cherrypick-js/src/streaming.types.ts @@ -21,16 +21,7 @@ import { QueueStatsLog, ServerStats, ServerStatsLog, - ReversiGameDetailed, } from './entities.js'; -import { - ReversiUpdateKey, -} from './consts.js'; - -type ReversiUpdateSettings = { - key: K; - value: ReversiGameDetailed[K]; -}; export type Channels = { main: { @@ -240,29 +231,6 @@ export type Channels = { }; receives: null; }; - reversiGame: { - params: { - gameId: string; - }; - events: { - started: (payload: { game: ReversiGameDetailed; }) => void; - ended: (payload: { winnerId: User['id'] | null; game: ReversiGameDetailed; }) => void; - canceled: (payload: { userId: User['id']; }) => void; - changeReadyStates: (payload: { user1: boolean; user2: boolean; }) => void; - updateSettings: (payload: { userId: User['id']; key: K; value: ReversiGameDetailed[K]; }) => void; - log: (payload: Record) => void; - }; - receives: { - putStone: { - pos: number; - id: string; - }; - ready: boolean; - cancel: null | Record; - updateSettings: ReversiUpdateSettings; - claimTimeIsUp: null | Record; - } - } }; export type NoteUpdatedEvent = { diff --git a/packages/frontend/package.json b/packages/frontend/package.json index b41218ddf6..89f9c1dbef 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -58,7 +58,6 @@ "json5": "2.2.3", "matter-js": "0.19.0", "misskey-bubble-game": "workspace:*", - "misskey-reversi": "workspace:*", "photoswipe": "5.4.4", "prismjs": "1.29.0", "punycode": "2.3.1", diff --git a/packages/frontend/src/pages/games.vue b/packages/frontend/src/pages/games.vue index 5650f5095d..de5d2ddb65 100644 --- a/packages/frontend/src/pages/games.vue +++ b/packages/frontend/src/pages/games.vue @@ -13,11 +13,6 @@ SPDX-License-Identifier: AGPL-3.0-only -
- - - -
diff --git a/packages/frontend/src/pages/reversi/game.board.vue b/packages/frontend/src/pages/reversi/game.board.vue deleted file mode 100644 index 9f97d0c9b2..0000000000 --- a/packages/frontend/src/pages/reversi/game.board.vue +++ /dev/null @@ -1,661 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue deleted file mode 100644 index 8bb7bb994b..0000000000 --- a/packages/frontend/src/pages/reversi/game.setting.vue +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/reversi/game.vue b/packages/frontend/src/pages/reversi/game.vue deleted file mode 100644 index 5e04312365..0000000000 --- a/packages/frontend/src/pages/reversi/game.vue +++ /dev/null @@ -1,121 +0,0 @@ - - - - - diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue deleted file mode 100644 index 89f23da941..0000000000 --- a/packages/frontend/src/pages/reversi/index.vue +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts index 5da5a41ef2..575b3c0cd2 100644 --- a/packages/frontend/src/router/definition.ts +++ b/packages/frontend/src/router/definition.ts @@ -613,14 +613,6 @@ const routes: RouteDef[] = [{ path: '/bubble-game', component: page(() => import('@/pages/drop-and-fusion.vue')), loginRequired: true, -}, { - path: '/reversi', - component: page(() => import('@/pages/reversi/index.vue')), - loginRequired: false, -}, { - path: '/reversi/g/:gameId', - component: page(() => import('@/pages/reversi/game.vue')), - loginRequired: false, }, { path: '/timeline', component: page(() => import('@/pages/timeline.vue')), diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index 8cbb629750..6bd9b144be 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -170,7 +170,7 @@ export function getConfig(): UserConfig { // https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies commonjsOptions: { - include: [/cherrypick-js/, /misskey-reversi/, /misskey-bubble-game/, /node_modules/], + include: [/cherrypick-js/, /misskey-bubble-game/, /node_modules/], }, }, diff --git a/packages/misskey-reversi/build.js b/packages/misskey-reversi/build.js deleted file mode 100644 index e626c97a59..0000000000 --- a/packages/misskey-reversi/build.js +++ /dev/null @@ -1,104 +0,0 @@ -import * as esbuild from "esbuild"; -import { build } from "esbuild"; -import { globSync } from "glob"; -import { execa } from "execa"; -import fs from "node:fs"; -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; - -const _filename = fileURLToPath(import.meta.url); -const _dirname = dirname(_filename); -const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); - -const entryPoints = globSync("./src/**/**.{ts,tsx}"); - -/** @type {import('esbuild').BuildOptions} */ -const options = { - entryPoints, - minify: process.env.NODE_ENV === 'production', - outdir: "./built", - target: "es2022", - platform: "browser", - format: "esm", - sourcemap: 'linked', -}; - -// built配下をすべて削除する -fs.rmSync('./built', { recursive: true, force: true }); - -if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { - await watchSrc(); -} else { - await buildSrc(); -} - -async function buildSrc() { - console.log(`[${_package.name}] start building...`); - - await build(options) - .then(it => { - console.log(`[${_package.name}] build succeeded.`); - }) - .catch((err) => { - process.stderr.write(err.stderr); - process.exit(1); - }); - - if (process.env.NODE_ENV === 'production') { - console.log(`[${_package.name}] skip building d.ts because NODE_ENV is production.`); - } else { - await buildDts(); - } - - console.log(`[${_package.name}] finish building.`); -} - -function buildDts() { - return execa( - 'tsc', - [ - '--project', 'tsconfig.json', - '--outDir', 'built', - '--declaration', 'true', - '--emitDeclarationOnly', 'true', - ], - { - stdout: process.stdout, - stderr: process.stderr, - } - ); -} - -async function watchSrc() { - const plugins = [{ - name: 'gen-dts', - setup(build) { - build.onStart(() => { - console.log(`[${_package.name}] detect changed...`); - }); - build.onEnd(async result => { - if (result.errors.length > 0) { - console.error(`[${_package.name}] watch build failed:`, result); - return; - } - await buildDts(); - }); - }, - }]; - - console.log(`[${_package.name}] start watching...`) - - const context = await esbuild.context({ ...options, plugins }); - await context.watch(); - - await new Promise((resolve, reject) => { - process.on('SIGHUP', resolve); - process.on('SIGINT', resolve); - process.on('SIGTERM', resolve); - process.on('uncaughtException', reject); - process.on('exit', resolve); - }).finally(async () => { - await context.dispose(); - console.log(`[${_package.name}] finish watching.`); - }); -} diff --git a/packages/misskey-reversi/eslint.config.js b/packages/misskey-reversi/eslint.config.js deleted file mode 100644 index 3f81df7145..0000000000 --- a/packages/misskey-reversi/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import tsParser from '@typescript-eslint/parser'; -import sharedConfig from '../shared/eslint.config.js'; - -export default [ - ...sharedConfig, - { - ignores: [ - '**/node_modules', - 'built', - ], - }, - { - files: ['**/*.ts', '**/*.tsx'], - languageOptions: { - parserOptions: { - parser: tsParser, - project: ['./tsconfig.json'], - sourceType: 'module', - tsconfigRootDir: import.meta.dirname, - }, - }, - }, -]; diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json deleted file mode 100644 index 7df5de84ba..0000000000 --- a/packages/misskey-reversi/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "type": "module", - "name": "misskey-reversi", - "version": "0.0.1", - "main": "./built/index.js", - "types": "./built/index.d.ts", - "exports": { - ".": { - "import": "./built/index.js", - "types": "./built/index.d.ts" - }, - "./*": { - "import": "./built/*", - "types": "./built/*" - } - }, - "scripts": { - "build": "node ./build.js", - "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", - "eslint": "eslint './**/*.{js,jsx,ts,tsx}'", - "typecheck": "tsc --noEmit", - "lint": "pnpm typecheck && pnpm eslint" - }, - "devDependencies": { - "@types/node": "20.11.5", - "@typescript-eslint/eslint-plugin": "7.1.0", - "@typescript-eslint/parser": "7.1.0", - "execa": "8.0.1", - "nodemon": "3.0.2", - "typescript": "5.4.5", - "esbuild": "0.19.11", - "glob": "10.3.10" - }, - "files": [ - "built" - ], - "dependencies": { - "crc-32": "1.2.2" - } -} diff --git a/packages/misskey-reversi/src/game.ts b/packages/misskey-reversi/src/game.ts deleted file mode 100644 index 4afca9898c..0000000000 --- a/packages/misskey-reversi/src/game.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import CRC32 from 'crc-32'; - -/** - * true ... 黒 - * false ... 白 - */ -export type Color = boolean; -const BLACK = true; -const WHITE = false; - -export type MapCell = 'null' | 'empty'; - -export type Options = { - isLlotheo: boolean; - canPutEverywhere: boolean; - loopedBoard: boolean; -}; - -export type Undo = { - color: Color; - pos: number; - - /** - * 反転した石の位置の配列 - */ - effects: number[]; - - turn: Color | null; -}; - -export class Game { - public map: MapCell[]; - public mapWidth: number; - public mapHeight: number; - public board: (Color | null | undefined)[]; - public turn: Color | null = BLACK; - public opts: Options; - - public prevPos = -1; - public prevColor: Color | null = null; - - private logs: Undo[] = []; - - constructor(map: string[], opts: Options) { - //#region binds - this.putStone = this.putStone.bind(this); - //#endregion - - //#region Options - this.opts = opts; - if (this.opts.isLlotheo == null) this.opts.isLlotheo = false; - if (this.opts.canPutEverywhere == null) this.opts.canPutEverywhere = false; - if (this.opts.loopedBoard == null) this.opts.loopedBoard = false; - //#endregion - - //#region Parse map data - this.mapWidth = map[0].length; - this.mapHeight = map.length; - const mapData = map.join(''); - - this.board = mapData.split('').map(d => d === '-' ? null : d === 'b' ? BLACK : d === 'w' ? WHITE : undefined); - - this.map = mapData.split('').map(d => d === '-' || d === 'b' || d === 'w' ? 'empty' : 'null'); - //#endregion - - // ゲームが始まった時点で片方の色の石しかないか、始まった時点で勝敗が決定するようなマップの場合がある - if (!this.canPutSomewhere(BLACK)) this.turn = this.canPutSomewhere(WHITE) ? WHITE : null; - } - - public get blackCount() { - return this.board.filter(x => x === BLACK).length; - } - - public get whiteCount() { - return this.board.filter(x => x === WHITE).length; - } - - public posToXy(pos: number): number[] { - const x = pos % this.mapWidth; - const y = Math.floor(pos / this.mapWidth); - return [x, y]; - } - - public xyToPos(x: number, y: number): number { - return x + (y * this.mapWidth); - } - - public putStone(pos: number) { - const color = this.turn; - if (color == null) return; - - this.prevPos = pos; - this.prevColor = color; - - this.board[pos] = color; - - // 反転させられる石を取得 - const effects = this.effects(color, pos); - - // 反転させる - for (const pos of effects) { - this.board[pos] = color; - } - - const turn = this.turn; - - this.logs.push({ - color, - pos, - effects, - turn, - }); - - this.calcTurn(); - } - - private calcTurn() { - // ターン計算 - this.turn = - this.canPutSomewhere(!this.prevColor) ? !this.prevColor : - this.canPutSomewhere(this.prevColor!) ? this.prevColor : - null; - } - - public undo() { - const undo = this.logs.pop()!; - this.prevColor = undo.color; - this.prevPos = undo.pos; - this.board[undo.pos] = null; - for (const pos of undo.effects) { - const color = this.board[pos]; - this.board[pos] = !color; - } - this.turn = undo.turn; - } - - public mapDataGet(pos: number): MapCell { - const [x, y] = this.posToXy(pos); - return x < 0 || y < 0 || x >= this.mapWidth || y >= this.mapHeight ? 'null' : this.map[pos]; - } - - public getPuttablePlaces(color: Color): number[] { - return Array.from(this.board.keys()).filter(i => this.canPut(color, i)); - } - - public canPutSomewhere(color: Color): boolean { - return this.getPuttablePlaces(color).length > 0; - } - - public canPut(color: Color, pos: number): boolean { - return ( - this.board[pos] !== null ? false : // 既に石が置いてある場所には打てない - this.opts.canPutEverywhere ? this.mapDataGet(pos) === 'empty' : // 挟んでなくても置けるモード - this.effects(color, pos).length !== 0); // 相手の石を1つでも反転させられるか - } - - /** - * 指定のマスに石を置いた時の、反転させられる石を取得します - * @param color 自分の色 - * @param initPos 位置 - */ - public effects(color: Color, initPos: number): number[] { - const enemyColor = !color; - - const diffVectors: [number, number][] = [ - [0, -1], // 上 - [+1, -1], // 右上 - [+1, 0], // 右 - [+1, +1], // 右下 - [0, +1], // 下 - [-1, +1], // 左下 - [-1, 0], // 左 - [-1, -1], // 左上 - ]; - - const effectsInLine = ([dx, dy]: [number, number]): number[] => { - const nextPos = (x: number, y: number): [number, number] => [x + dx, y + dy]; - - const found: number[] = []; // 挟めるかもしれない相手の石を入れておく配列 - let [x, y] = this.posToXy(initPos); - while (true) { - [x, y] = nextPos(x, y); - - // 座標が指し示す位置がボード外に出たとき - if (this.opts.loopedBoard && this.xyToPos( - (x = ((x % this.mapWidth) + this.mapWidth) % this.mapWidth), - (y = ((y % this.mapHeight) + this.mapHeight) % this.mapHeight)) === initPos) { - // 盤面の境界でループし、自分が石を置く位置に戻ってきたとき、挟めるようにしている (ref: Test4のマップ) - return found; - } else if (x === -1 || y === -1 || x === this.mapWidth || y === this.mapHeight) return []; // 挟めないことが確定 (盤面外に到達) - - const pos = this.xyToPos(x, y); - if (this.mapDataGet(pos) === 'null') return []; // 挟めないことが確定 (配置不可能なマスに到達) - const stone = this.board[pos]; - if (stone === null) return []; // 挟めないことが確定 (石が置かれていないマスに到達) - if (stone === enemyColor) found.push(pos); // 挟めるかもしれない (相手の石を発見) - if (stone === color) return found; // 挟めることが確定 (対となる自分の石を発見) - } - }; - - return ([] as number[]).concat(...diffVectors.map(effectsInLine)); - } - - public calcCrc32(): number { - return CRC32.str(JSON.stringify({ - board: this.board, - turn: this.turn, - })); - } - - public get isEnded(): boolean { - return this.turn === null; - } - - public get winner(): Color | null { - return this.isEnded ? - this.blackCount === this.whiteCount ? null : - this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK : - undefined as never; - } -} diff --git a/packages/misskey-reversi/src/index.ts b/packages/misskey-reversi/src/index.ts deleted file mode 100644 index cfd27d48cb..0000000000 --- a/packages/misskey-reversi/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export { Game } from './game.js'; -export * as Serializer from './serializer.js'; -export * as maps from './maps.js'; diff --git a/packages/misskey-reversi/src/maps.ts b/packages/misskey-reversi/src/maps.ts deleted file mode 100644 index 29ea3591c2..0000000000 --- a/packages/misskey-reversi/src/maps.ts +++ /dev/null @@ -1,697 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -/** - * 組み込みマップ定義 - * - * データ値: - * (スペース) ... マス無し - * - ... マス - * b ... 初期配置される黒石 - * w ... 初期配置される白石 - */ - -export type Map = { - name?: string; - category?: string; - author?: string; - data: string[]; -}; - -export const fourfour: Map = { - name: '4x4', - category: '4x4', - data: [ - '----', - '-wb-', - '-bw-', - '----', - ], -}; - -export const sixsix: Map = { - name: '6x6', - category: '6x6', - data: [ - '------', - '------', - '--wb--', - '--bw--', - '------', - '------', - ], -}; - -export const roundedSixsix: Map = { - name: '6x6 rounded', - category: '6x6', - author: 'syuilo', - data: [ - ' ---- ', - '------', - '--wb--', - '--bw--', - '------', - ' ---- ', - ], -}; - -export const roundedSixsix2: Map = { - name: '6x6 rounded 2', - category: '6x6', - author: 'syuilo', - data: [ - ' -- ', - ' ---- ', - '--wb--', - '--bw--', - ' ---- ', - ' -- ', - ], -}; - -export const eighteight: Map = { - name: '8x8', - category: '8x8', - data: [ - '--------', - '--------', - '--------', - '---wb---', - '---bw---', - '--------', - '--------', - '--------', - ], -}; - -export const eighteightH28: Map = { - name: '8x8 handicap 28', - category: '8x8', - data: [ - 'bbbbbbbb', - 'b------b', - 'b------b', - 'b--wb--b', - 'b--bw--b', - 'b------b', - 'b------b', - 'bbbbbbbb', - ], -}; - -export const roundedEighteight: Map = { - name: '8x8 rounded', - category: '8x8', - author: 'syuilo', - data: [ - ' ------ ', - '--------', - '--------', - '---wb---', - '---bw---', - '--------', - '--------', - ' ------ ', - ], -}; - -export const roundedEighteight2: Map = { - name: '8x8 rounded 2', - category: '8x8', - author: 'syuilo', - data: [ - ' ---- ', - ' ------ ', - '--------', - '---wb---', - '---bw---', - '--------', - ' ------ ', - ' ---- ', - ], -}; - -export const roundedEighteight3: Map = { - name: '8x8 rounded 3', - category: '8x8', - author: 'syuilo', - data: [ - ' -- ', - ' ---- ', - ' ------ ', - '---wb---', - '---bw---', - ' ------ ', - ' ---- ', - ' -- ', - ], -}; - -export const eighteightWithNotch: Map = { - name: '8x8 with notch', - category: '8x8', - author: 'syuilo', - data: [ - '--- ---', - '--------', - '--------', - ' --wb-- ', - ' --bw-- ', - '--------', - '--------', - '--- ---', - ], -}; - -export const eighteightWithSomeHoles: Map = { - name: '8x8 with some holes', - category: '8x8', - author: 'syuilo', - data: [ - '--- ----', - '----- --', - '-- -----', - '---wb---', - '---bw- -', - ' -------', - '--- ----', - '--------', - ], -}; - -export const circle: Map = { - name: 'Circle', - category: '8x8', - author: 'syuilo', - data: [ - ' -- ', - ' ------ ', - ' ------ ', - '---wb---', - '---bw---', - ' ------ ', - ' ------ ', - ' -- ', - ], -}; - -export const smile: Map = { - name: 'Smile', - category: '8x8', - author: 'syuilo', - data: [ - ' ------ ', - '--------', - '-- -- --', - '---wb---', - '-- bw --', - '--- ---', - '--------', - ' ------ ', - ], -}; - -export const window: Map = { - name: 'Window', - category: '8x8', - author: 'syuilo', - data: [ - '--------', - '- -- -', - '- -- -', - '---wb---', - '---bw---', - '- -- -', - '- -- -', - '--------', - ], -}; - -export const reserved: Map = { - name: 'Reserved', - category: '8x8', - author: 'Aya', - data: [ - 'w------b', - '--------', - '--------', - '---wb---', - '---bw---', - '--------', - '--------', - 'b------w', - ], -}; - -export const x: Map = { - name: 'X', - category: '8x8', - author: 'Aya', - data: [ - 'w------b', - '-w----b-', - '--w--b--', - '---wb---', - '---bw---', - '--b--w--', - '-b----w-', - 'b------w', - ], -}; - -export const parallel: Map = { - name: 'Parallel', - category: '8x8', - author: 'Aya', - data: [ - '--------', - '--------', - '--------', - '---bb---', - '---ww---', - '--------', - '--------', - '--------', - ], -}; - -export const lackOfBlack: Map = { - name: 'Lack of Black', - category: '8x8', - data: [ - '--------', - '--------', - '--------', - '---w----', - '---bw---', - '--------', - '--------', - '--------', - ], -}; - -export const squareParty: Map = { - name: 'Square Party', - category: '8x8', - author: 'syuilo', - data: [ - '--------', - '-wwwbbb-', - '-w-wb-b-', - '-wwwbbb-', - '-bbbwww-', - '-b-bw-w-', - '-bbbwww-', - '--------', - ], -}; - -export const minesweeper: Map = { - name: 'Minesweeper', - category: '8x8', - author: 'syuilo', - data: [ - 'b-b--w-w', - '-w-wb-b-', - 'w-b--w-b', - '-b-wb-w-', - '-w-bw-b-', - 'b-w--b-w', - '-b-bw-w-', - 'w-w--b-b', - ], -}; - -export const tenthtenth: Map = { - name: '10x10', - category: '10x10', - data: [ - '----------', - '----------', - '----------', - '----------', - '----wb----', - '----bw----', - '----------', - '----------', - '----------', - '----------', - ], -}; - -export const hole: Map = { - name: 'The Hole', - category: '10x10', - author: 'syuilo', - data: [ - '----------', - '----------', - '--wb--wb--', - '--bw--bw--', - '---- ----', - '---- ----', - '--wb--wb--', - '--bw--bw--', - '----------', - '----------', - ], -}; - -export const grid: Map = { - name: 'Grid', - category: '10x10', - author: 'syuilo', - data: [ - '----------', - '- - -- - -', - '----------', - '- - -- - -', - '----wb----', - '----bw----', - '- - -- - -', - '----------', - '- - -- - -', - '----------', - ], -}; - -export const cross: Map = { - name: 'Cross', - category: '10x10', - author: 'Aya', - data: [ - ' ---- ', - ' ---- ', - ' ---- ', - '----------', - '----wb----', - '----bw----', - '----------', - ' ---- ', - ' ---- ', - ' ---- ', - ], -}; - -export const charX: Map = { - name: 'Char X', - category: '10x10', - author: 'syuilo', - data: [ - '--- ---', - '---- ----', - '----------', - ' -------- ', - ' --wb-- ', - ' --bw-- ', - ' -------- ', - '----------', - '---- ----', - '--- ---', - ], -}; - -export const charY: Map = { - name: 'Char Y', - category: '10x10', - author: 'syuilo', - data: [ - '--- ---', - '---- ----', - '----------', - ' -------- ', - ' --wb-- ', - ' --bw-- ', - ' ------ ', - ' ------ ', - ' ------ ', - ' ------ ', - ], -}; - -export const walls: Map = { - name: 'Walls', - category: '10x10', - author: 'Aya', - data: [ - ' bbbbbbbb ', - 'w--------w', - 'w--------w', - 'w--------w', - 'w---wb---w', - 'w---bw---w', - 'w--------w', - 'w--------w', - 'w--------w', - ' bbbbbbbb ', - ], -}; - -export const cpu: Map = { - name: 'CPU', - category: '10x10', - author: 'syuilo', - data: [ - ' b b b b ', - 'w--------w', - ' -------- ', - 'w--------w', - ' ---wb--- ', - ' ---bw--- ', - 'w--------w', - ' -------- ', - 'w--------w', - ' b b b b ', - ], -}; - -export const checker: Map = { - name: 'Checker', - category: '10x10', - author: 'Aya', - data: [ - '----------', - '----------', - '----------', - '---wbwb---', - '---bwbw---', - '---wbwb---', - '---bwbw---', - '----------', - '----------', - '----------', - ], -}; - -export const japaneseCurry: Map = { - name: 'Japanese curry', - category: '10x10', - author: 'syuilo', - data: [ - 'w-b-b-b-b-', - '-w-b-b-b-b', - 'w-w-b-b-b-', - '-w-w-b-b-b', - 'w-w-wwb-b-', - '-w-wbb-b-b', - 'w-w-w-b-b-', - '-w-w-w-b-b', - 'w-w-w-w-b-', - '-w-w-w-w-b', - ], -}; - -export const mosaic: Map = { - name: 'Mosaic', - category: '10x10', - author: 'syuilo', - data: [ - '- - - - - ', - ' - - - - -', - '- - - - - ', - ' - w w - -', - '- - b b - ', - ' - w w - -', - '- - b b - ', - ' - - - - -', - '- - - - - ', - ' - - - - -', - ], -}; - -export const arena: Map = { - name: 'Arena', - category: '10x10', - author: 'syuilo', - data: [ - '- - -- - -', - ' - - - - ', - '- ------ -', - ' -------- ', - '- --wb-- -', - '- --bw-- -', - ' -------- ', - '- ------ -', - ' - - - - ', - '- - -- - -', - ], -}; - -export const reactor: Map = { - name: 'Reactor', - category: '10x10', - author: 'syuilo', - data: [ - '-w------b-', - 'b- - - -w', - '- --wb-- -', - '---b w---', - '- b wb w -', - '- w bw b -', - '---w b---', - '- --bw-- -', - 'w- - - -b', - '-b------w-', - ], -}; - -export const sixeight: Map = { - name: '6x8', - category: 'Special', - data: [ - '------', - '------', - '------', - '--wb--', - '--bw--', - '------', - '------', - '------', - ], -}; - -export const spark: Map = { - name: 'Spark', - category: 'Special', - author: 'syuilo', - data: [ - ' - - ', - '----------', - ' -------- ', - ' -------- ', - ' ---wb--- ', - ' ---bw--- ', - ' -------- ', - ' -------- ', - '----------', - ' - - ', - ], -}; - -export const islands: Map = { - name: 'Islands', - category: 'Special', - author: 'syuilo', - data: [ - '-------- ', - '---wb--- ', - '---bw--- ', - '-------- ', - ' - - ', - ' - - ', - ' --------', - ' --------', - ' --------', - ' --------', - ], -}; - -export const galaxy: Map = { - name: 'Galaxy', - category: 'Special', - author: 'syuilo', - data: [ - ' ------ ', - ' --www--- ', - ' ------w--- ', - '---bbb--w---', - '--b---b-w-b-', - '-b--wwb-w-b-', - '-b-w-bww--b-', - '-b-w-b---b--', - '---w--bbb---', - ' ---w------ ', - ' ---www-- ', - ' ------ ', - ], -}; - -export const triangle: Map = { - name: 'Triangle', - category: 'Special', - author: 'syuilo', - data: [ - ' -- ', - ' -- ', - ' ---- ', - ' ---- ', - ' --wb-- ', - ' --bw-- ', - ' -------- ', - ' -------- ', - '----------', - '----------', - ], -}; - -export const iphonex: Map = { - name: 'iPhone X', - category: 'Special', - author: 'syuilo', - data: [ - ' -- -- ', - '--------', - '--------', - '--------', - '--------', - '---wb---', - '---bw---', - '--------', - '--------', - '--------', - '--------', - ' ------ ', - ], -}; - -export const dealWithIt: Map = { - name: 'Deal with it!', - category: 'Special', - author: 'syuilo', - data: [ - '------------', - '--w-b-------', - ' --b-w------', - ' --w-b---- ', - ' ------- ', - ], -}; - -export const twoBoard: Map = { - name: 'Two board', - category: 'Special', - author: 'Aya', - data: [ - '-------- --------', - '-------- --------', - '-------- --------', - '---wb--- ---wb---', - '---bw--- ---bw---', - '-------- --------', - '-------- --------', - '-------- --------', - ], -}; diff --git a/packages/misskey-reversi/src/serializer.ts b/packages/misskey-reversi/src/serializer.ts deleted file mode 100644 index aa5987a1e5..0000000000 --- a/packages/misskey-reversi/src/serializer.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Game } from './game.js'; - -export type Log = { - time: number; - player: boolean; - operation: 'put'; - pos: number; -}; - -export type SerializedLog = number[]; - -export function serializeLogs(logs: Log[]) { - const _logs: number[][] = []; - - for (let i = 0; i < logs.length; i++) { - const log = logs[i]; - const timeDelta = i === 0 ? log.time : log.time - logs[i - 1].time; - - switch (log.operation) { - case 'put': - _logs.push([timeDelta, log.player ? 1 : 0, 0, log.pos]); - break; - //case 'surrender': - // _logs.push([timeDelta, log.player, 1]); - // break; - } - } - - return _logs; -} - -export function deserializeLogs(logs: SerializedLog[]) { - const _logs: Log[] = []; - - let time = 0; - - for (const log of logs) { - const timeDelta = log[0]; - time += timeDelta; - - const player = log[1]; - const operation = log[2]; - - switch (operation) { - case 0: - _logs.push({ - time, - player: player === 1, - operation: 'put', - pos: log[3], - }); - break; - //case 1: - // _logs.push({ - // time, - // player: player === 1, - // operation: 'surrender', - // }); - // break; - } - } - - return _logs; -} - -export function restoreGame(env: { - map: string[]; - isLlotheo: boolean; - canPutEverywhere: boolean; - loopedBoard: boolean; - logs: SerializedLog[]; -}) { - const logs = deserializeLogs(env.logs); - - const game = new Game(env.map, { - isLlotheo: env.isLlotheo, - canPutEverywhere: env.canPutEverywhere, - loopedBoard: env.loopedBoard, - }); - - for (const log of logs) { - switch (log.operation) { - case 'put': - game.putStone(log.pos); - break; - //case 'surrender': - // game.surrender(log.player); - // break; - } - } - - return game; -} diff --git a/packages/misskey-reversi/tsconfig.json b/packages/misskey-reversi/tsconfig.json deleted file mode 100644 index 6e34e332e0..0000000000 --- a/packages/misskey-reversi/tsconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "ES2022", - "module": "nodenext", - "moduleResolution": "nodenext", - "declaration": true, - "declarationMap": true, - "sourceMap": false, - "outDir": "./built/", - "removeComments": true, - "strict": true, - "strictFunctionTypes": true, - "strictNullChecks": true, - "experimentalDecorators": true, - "noImplicitReturns": true, - "esModuleInterop": true, - "typeRoots": [ - "./node_modules/@types" - ], - "lib": [ - "esnext", - "dom" - ] - }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "test/**/*" - ] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a950424e4..9513302c3d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -317,9 +317,6 @@ importers: mime-types: specifier: 2.1.35 version: 2.1.35 - misskey-reversi: - specifier: workspace:* - version: link:../misskey-reversi ms: specifier: 3.0.0-canary.1 version: 3.0.0-canary.1 @@ -923,9 +920,6 @@ importers: misskey-bubble-game: specifier: workspace:* version: link:../misskey-bubble-game - misskey-reversi: - specifier: workspace:* - version: link:../misskey-reversi photoswipe: specifier: 5.4.4 version: 5.4.4 @@ -12812,7 +12806,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.24.9 convert-source-map: 2.0.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12872,7 +12866,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-compilation-targets': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -13616,7 +13610,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.8 '@babel/types': 7.24.9 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -14116,7 +14110,7 @@ snapshots: '@eslint/config-array@0.17.1': dependencies: '@eslint/object-schema': 2.1.4 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -14124,7 +14118,7 @@ snapshots: '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) espree: 10.1.0 globals: 14.0.0 ignore: 5.3.1 @@ -14976,7 +14970,7 @@ snapshots: '@opensearch-project/opensearch@2.10.0': dependencies: aws4: 1.13.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) hpagent: 1.2.0 json11: 1.1.2 ms: 2.1.3 @@ -17354,7 +17348,7 @@ snapshots: '@typescript-eslint/types': 7.17.0 '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 7.17.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) eslint: 9.8.0 optionalDependencies: typescript: 5.5.4 @@ -17409,7 +17403,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4) '@typescript-eslint/utils': 7.17.0(eslint@9.8.0)(typescript@5.5.4) - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) eslint: 9.8.0 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -17429,7 +17423,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.2 @@ -17472,7 +17466,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.17.0 '@typescript-eslint/visitor-keys': 7.17.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 @@ -17576,7 +17570,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -17823,13 +17817,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color agent-base@7.1.1: dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -18118,7 +18112,7 @@ snapshots: axios@0.24.0: dependencies: - follow-redirects: 1.15.6(debug@4.3.5) + follow-redirects: 1.15.6 transitivePeerDependencies: - debug @@ -19044,6 +19038,10 @@ snapshots: dependencies: ms: 2.0.0 + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@3.2.7(supports-color@8.1.1): dependencies: ms: 2.1.3 @@ -19183,7 +19181,7 @@ snapshots: detect-port@1.6.1: dependencies: address: 1.2.2 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -19423,7 +19421,7 @@ snapshots: esbuild-register@3.5.0(esbuild@0.19.11): dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) esbuild: 0.19.11 transitivePeerDependencies: - supports-color @@ -19680,7 +19678,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 @@ -20140,9 +20138,11 @@ snapshots: async: 0.2.10 which: 1.3.1 + follow-redirects@1.15.6: {} + follow-redirects@1.15.6(debug@4.3.5): optionalDependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) for-each@0.3.3: dependencies: @@ -20701,14 +20701,14 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -20739,7 +20739,7 @@ snapshots: https-proxy-agent@2.2.4: dependencies: agent-base: 4.3.0 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 transitivePeerDependencies: - supports-color optional: true @@ -20747,21 +20747,21 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -20857,7 +20857,7 @@ snapshots: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -21112,7 +21112,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -21121,7 +21121,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -22278,7 +22278,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -22539,7 +22539,7 @@ snapshots: needle@2.9.1: dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.4.1 transitivePeerDependencies: @@ -23914,7 +23914,7 @@ snapshots: require-in-the-middle@7.3.0: dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -23967,7 +23967,7 @@ snapshots: retry-request@5.0.2: dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) extend: 3.0.2 transitivePeerDependencies: - supports-color @@ -24223,7 +24223,7 @@ snapshots: dependencies: '@hapi/hoek': 11.0.4 '@hapi/wreck': 18.1.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) joi: 17.13.3 transitivePeerDependencies: - supports-color @@ -24323,7 +24323,7 @@ snapshots: socks-proxy-agent@8.0.3: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -24418,7 +24418,7 @@ snapshots: arg: 5.0.2 bluebird: 3.7.2 check-more-types: 2.24.0 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) execa: 5.1.1 lazy-ass: 1.6.0 ps-tree: 1.2.0 @@ -24987,7 +24987,7 @@ snapshots: chalk: 4.1.2 cli-highlight: 2.1.11 dayjs: 1.11.11 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) dotenv: 16.4.5 glob: 10.4.2 mkdirp: 2.1.6 @@ -25200,7 +25200,7 @@ snapshots: vite-node@1.6.0(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3): dependencies: cac: 6.7.14 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) pathe: 1.1.2 picocolors: 1.0.1 vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3) @@ -25243,7 +25243,7 @@ snapshots: '@vitest/utils': 1.6.0 acorn-walk: 8.3.3 chai: 4.4.1 - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) execa: 8.0.1 local-pkg: 0.5.0 magic-string: 0.30.10 @@ -25329,7 +25329,7 @@ snapshots: vue-eslint-parser@9.4.3(eslint@9.8.0): dependencies: - debug: 4.3.5(supports-color@8.1.1) + debug: 4.3.5(supports-color@5.5.0) eslint: 9.8.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c97e4fb4c9..403842482d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,5 +4,4 @@ packages: - 'packages/sw' - 'packages/cherrypick-js' - 'packages/cherrypick-js/generator' - - 'packages/misskey-reversi' - 'packages/misskey-bubble-game' diff --git a/scripts/clean.js b/scripts/clean.js index eebfdf9438..79b306178b 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -10,7 +10,6 @@ const fs = require('fs'); fs.rmSync(__dirname + '/../packages/frontend/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../packages/sw/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../packages/cherrypick-js/built', { recursive: true, force: true }); - fs.rmSync(__dirname + '/../packages/misskey-reversi/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../packages/misskey-bubble-game/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../built', { recursive: true, force: true }); })(); diff --git a/scripts/dev.mjs b/scripts/dev.mjs index ae42bbd2f3..241d10e42e 100644 --- a/scripts/dev.mjs +++ b/scripts/dev.mjs @@ -35,11 +35,6 @@ await Promise.all([ ]); await Promise.all([ - execa('pnpm', ['--filter', 'misskey-reversi', 'build'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, - }), execa('pnpm', ['--filter', 'misskey-bubble-game', 'build'], { cwd: _dirname + '/../', stdout: process.stdout, @@ -83,12 +78,6 @@ execa('pnpm', ['--filter', 'cherrypick-js', 'watch'], { stderr: process.stderr, }); -execa('pnpm', ['--filter', 'misskey-reversi', 'watch'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); - execa('pnpm', ['--filter', 'misskey-bubble-game', 'watch'], { cwd: _dirname + '/../', stdout: process.stdout,