This commit is contained in:
syuilo 2024-01-19 10:59:55 +09:00
parent 1259fabd7f
commit 037a1daa79
20 changed files with 114 additions and 253 deletions

View file

@ -116,7 +116,6 @@ 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 { ReversiMatchingEntityService } from './entities/ReversiMatchingEntityService.js';
import { ApAudienceService } from './activitypub/ApAudienceService.js';
import { ApDbResolverService } from './activitypub/ApDbResolverService.js';
@ -255,7 +254,6 @@ const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisti
const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService };
const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService };
const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService };
const $ReversiMatchingEntityService: Provider = { provide: 'ReversiMatchingEntityService', useExisting: ReversiMatchingEntityService };
const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService };
const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService };
@ -395,7 +393,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashLikeEntityService,
RoleEntityService,
ReversiGameEntityService,
ReversiMatchingEntityService,
ApAudienceService,
ApDbResolverService,
@ -531,7 +528,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashLikeEntityService,
$RoleEntityService,
$ReversiGameEntityService,
$ReversiMatchingEntityService,
$ApAudienceService,
$ApDbResolverService,
@ -667,7 +663,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashLikeEntityService,
RoleEntityService,
ReversiGameEntityService,
ReversiMatchingEntityService,
ApAudienceService,
ApDbResolverService,
@ -802,7 +797,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashLikeEntityService,
$RoleEntityService,
$ReversiGameEntityService,
$ReversiMatchingEntityService,
$ApAudienceService,
$ApDbResolverService,

View file

@ -165,7 +165,7 @@ export interface ReversiEventTypes {
game: Packed<'ReversiGameDetailed'>;
};
invited: {
game: Packed<'ReversiMatching'>;
user: Packed<'User'>;
};
}
@ -180,12 +180,12 @@ export interface ReversiGameEventTypes {
key: string;
value: any;
};
putStone: {
at: Date;
color: boolean;
pos: number;
next: boolean;
};
putStone: {
at: Date;
color: boolean;
pos: number;
next: boolean;
};
syncState: {
crc32: string;
};

View file

@ -8,10 +8,10 @@ import * as Redis from 'ioredis';
import * as CRC32 from 'crc-32';
import { ModuleRef } from '@nestjs/core';
import * as Reversi from 'misskey-reversi';
import { IsNull } from 'typeorm';
import type {
MiReversiGame,
ReversiGamesRepository,
ReversiMatchingsRepository,
UsersRepository,
} from '@/models/_.js';
import type { MiUser } from '@/models/User.js';
@ -25,10 +25,11 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import type { Packed } from '@/misc/json-schema.js';
import { NotificationService } from '@/core/NotificationService.js';
import { ReversiMatchingEntityService } from '@/core/entities/ReversiMatchingEntityService.js';
import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
const MATCHING_TIMEOUT_MS = 15 * 1000; // 15sec
@Injectable()
export class ReversiService implements OnApplicationShutdown, OnModuleInit {
private notificationService: NotificationService;
@ -36,20 +37,16 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
constructor(
private moduleRef: ModuleRef,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.reversiGamesRepository)
private reversiGamesRepository: ReversiGamesRepository,
@Inject(DI.reversiMatchingsRepository)
private reversiMatchingsRepository: ReversiMatchingsRepository,
private cacheService: CacheService,
private userEntityService: UserEntityService,
private globalEventService: GlobalEventService,
private reversiGameEntityService: ReversiGameEntityService,
private reversiMatchingsEntityService: ReversiMatchingEntityService,
private idService: IdService,
) {
}
@ -59,22 +56,19 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}
@bindThis
public async match(me: MiUser, targetUser: MiUser): Promise<MiReversiGame | null> {
public async matchSpecificUser(me: MiUser, targetUser: MiUser): Promise<MiReversiGame | null> {
if (targetUser.id === me.id) {
throw new Error('You cannot match yourself.');
}
const exist = await this.reversiMatchingsRepository.findOneBy({
parentId: targetUser.id,
childId: me.id,
});
const invitations = await this.redisClient.zrange(`reversi:matchSpecific:${me.id}`, Date.now() - MATCHING_TIMEOUT_MS, '+inf');
if (exist) {
this.reversiMatchingsRepository.delete(exist.id);
if (invitations.includes(targetUser.id)) {
await this.redisClient.zrem(`reversi:matchSpecific:${me.id}`, targetUser.id);
const game = await this.reversiGamesRepository.insert({
id: this.idService.gen(),
user1Id: exist.parentId,
user1Id: targetUser.id,
user2Id: me.id,
user1Accepted: false,
user2Accepted: false,
@ -86,35 +80,64 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
isLlotheo: false,
}).then(x => this.reversiGamesRepository.findOneByOrFail(x.identifiers[0]));
const packed = await this.reversiGameEntityService.packDetail(game, { id: exist.parentId });
this.globalEventService.publishReversiStream(exist.parentId, 'matched', { game: packed });
const packed = await this.reversiGameEntityService.packDetail(game, { id: targetUser.id });
this.globalEventService.publishReversiStream(targetUser.id, 'matched', { game: packed });
return game;
} else {
const child = targetUser;
this.redisClient.zadd(`reversi:matchSpecific:${targetUser.id}`, Date.now(), me.id);
await this.reversiMatchingsRepository.delete({
parentId: me.id,
this.globalEventService.publishReversiStream(targetUser.id, 'invited', {
user: await this.userEntityService.pack(me, targetUser),
});
const matching = await this.reversiMatchingsRepository.insert({
id: this.idService.gen(),
parentId: me.id,
childId: child.id,
}).then(x => this.reversiMatchingsRepository.findOneByOrFail(x.identifiers[0]));
const packed = await this.reversiMatchingsEntityService.pack(matching, child);
this.globalEventService.publishReversiStream(child.id, 'invited', { game: packed });
return null;
}
}
@bindThis
public async matchCancel(user: MiUser) {
await this.reversiMatchingsRepository.delete({
parentId: user.id,
});
public async matchAnyUser(me: MiUser): Promise<MiReversiGame | null> {
const scanRes = await this.redisClient.scan(0, 'MATCH', 'reversi:matchAny:*', 'COUNT', 10);
const userIds = scanRes[1].map(key => key.split(':')[2]).filter(id => id !== me.id);
if (userIds.length > 0) {
// pick random
const matchedUserId = userIds[Math.floor(Math.random() * userIds.length)];
await this.redisClient.del(`reversi:matchAny:${matchedUserId}`);
const game = await this.reversiGamesRepository.insert({
id: this.idService.gen(),
user1Id: matchedUserId,
user2Id: me.id,
user1Accepted: false,
user2Accepted: false,
isStarted: false,
isEnded: false,
logs: [],
map: Reversi.maps.eighteight.data,
bw: 'random',
isLlotheo: false,
}).then(x => this.reversiGamesRepository.findOneByOrFail(x.identifiers[0]));
const packed = await this.reversiGameEntityService.packDetail(game, { id: matchedUserId });
this.globalEventService.publishReversiStream(matchedUserId, 'matched', { game: packed });
return game;
} else {
await this.redisClient.setex(`reversi:matchAny:${me.id}`, MATCHING_TIMEOUT_MS / 1000, '');
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.del(`reversi:matchAny:${user.id}`);
}
@bindThis
@ -214,6 +237,12 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}
}
@bindThis
public async getInvitations(user: MiUser): Promise<MiUser['id'][]> {
const invitations = await this.redisClient.zrange(`reversi:matchSpecific:${user.id}`, Date.now() - MATCHING_TIMEOUT_MS, '+inf');
return invitations;
}
@bindThis
public async updateSettings(game: MiReversiGame, user: MiUser, key: string, value: any) {
if (game.isStarted) return;

View file

@ -1,57 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiReversiMatching, ReversiMatchingsRepository } 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 { MiUser } from '@/models/User.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
export class ReversiMatchingEntityService {
constructor(
@Inject(DI.reversiMatchingsRepository)
private reversiMatchingsRepository: ReversiMatchingsRepository,
private userEntityService: UserEntityService,
private idService: IdService,
) {
}
@bindThis
public async pack(
src: MiReversiMatching['id'] | MiReversiMatching,
me?: { id: MiUser['id'] } | null | undefined,
): Promise<Packed<'ReversiMatching'>> {
const matching = typeof src === 'object' ? src : await this.reversiMatchingsRepository.findOneByOrFail({ id: src });
return await awaitAll({
id: matching.id,
createdAt: this.idService.parse(matching.id).date.toISOString(),
parentId: matching.parentId,
parent: this.userEntityService.pack(matching.parentId, me, {
detail: true,
}),
childId: matching.childId,
child: this.userEntityService.pack(matching.childId, me, {
detail: true,
}),
});
}
@bindThis
public packMany(
xs: MiReversiMatching[],
me?: { id: MiUser['id'] } | null | undefined,
) {
return Promise.all(xs.map(x => this.pack(x, me)));
}
}

View file

@ -80,6 +80,5 @@ export const DI = {
userMemosRepository: Symbol('userMemosRepository'),
bubbleGameRecordsRepository: Symbol('bubbleGameRecordsRepository'),
reversiGamesRepository: Symbol('reversiGamesRepository'),
reversiMatchingsRepository: Symbol('reversiMatchingsRepository'),
//#endregion
};

View file

@ -40,7 +40,6 @@ import { packedSigninSchema } from '@/models/json-schema/signin.js';
import { packedRoleLiteSchema, packedRoleSchema } from '@/models/json-schema/role.js';
import { packedAdSchema } from '@/models/json-schema/ad.js';
import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js';
import { packedReversiMatchingSchema } from '@/models/json-schema/reversi-matching.js';
export const refs = {
UserLite: packedUserLiteSchema,
@ -82,7 +81,6 @@ export const refs = {
Role: packedRoleSchema,
ReversiGameLite: packedReversiGameLiteSchema,
ReversiGameDetailed: packedReversiGameDetailedSchema,
ReversiMatching: packedReversiMatchingSchema,
};
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;

View file

@ -5,7 +5,7 @@
import { Module } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame, MiReversiMatching } from './_.js';
import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame } from './_.js';
import type { DataSource } from 'typeorm';
import type { Provider } from '@nestjs/common';
@ -411,12 +411,6 @@ const $reversiGamesRepository: Provider = {
inject: [DI.db],
};
const $reversiMatchingsRepository: Provider = {
provide: DI.reversiMatchingsRepository,
useFactory: (db: DataSource) => db.getRepository(MiReversiMatching),
inject: [DI.db],
};
@Module({
imports: [
],
@ -488,7 +482,6 @@ const $reversiMatchingsRepository: Provider = {
$userMemosRepository,
$bubbleGameRecordsRepository,
$reversiGamesRepository,
$reversiMatchingsRepository,
],
exports: [
$usersRepository,
@ -558,7 +551,6 @@ const $reversiMatchingsRepository: Provider = {
$userMemosRepository,
$bubbleGameRecordsRepository,
$reversiGamesRepository,
$reversiMatchingsRepository,
],
})
export class RepositoryModule {}

View file

@ -1,29 +0,0 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { id } from './util/id.js';
import { MiUser } from './User.js';
@Entity('reversi_matching')
export class MiReversiMatching {
@PrimaryColumn(id())
public id: string;
@Index()
@Column(id())
public parentId: MiUser['id'];
@ManyToOne(type => MiUser, {
onDelete: 'CASCADE',
})
@JoinColumn()
public parent: MiUser | null;
@Index()
@Column(id())
public childId: MiUser['id'];
@ManyToOne(type => MiUser, {
onDelete: 'CASCADE',
})
@JoinColumn()
public child: MiUser | null;
}

View file

@ -70,7 +70,6 @@ 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 { MiReversiMatching } from '@/models/ReversiMatching.js';
import type { Repository } from 'typeorm';
@ -142,7 +141,6 @@ export {
MiUserMemo,
MiBubbleGameRecord,
MiReversiGame,
MiReversiMatching,
};
export type AbuseUserReportsRepository = Repository<MiAbuseUserReport>;
@ -212,4 +210,3 @@ export type FlashLikesRepository = Repository<MiFlashLike>;
export type UserMemoRepository = Repository<MiUserMemo>;
export type BubbleGameRecordsRepository = Repository<MiBubbleGameRecord>;
export type ReversiGamesRepository = Repository<MiReversiGame>;
export type ReversiMatchingsRepository = Repository<MiReversiMatching>;

View file

@ -1,40 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export const packedReversiMatchingSchema = {
type: 'object',
properties: {
id: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
createdAt: {
type: 'string',
optional: false, nullable: false,
format: 'date-time',
},
parentId: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
parent: {
type: 'object',
optional: false, nullable: true,
ref: 'User',
},
childId: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
child: {
type: 'object',
optional: false, nullable: false,
ref: 'User',
},
},
} as const;

View file

@ -78,7 +78,6 @@ 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 { MiReversiMatching } from '@/models/ReversiMatching.js';
import { Config } from '@/config.js';
import MisskeyLogger from '@/logger.js';
@ -195,7 +194,6 @@ export const entities = [
MiUserMemo,
MiBubbleGameRecord,
MiReversiGame,
MiReversiMatching,
...charts,
];

View file

@ -22,6 +22,7 @@ export const meta = {
export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id', nullable: true },
},
required: [],
} as const;
@ -32,7 +33,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private reversiService: ReversiService,
) {
super(meta, paramDef, async (ps, me) => {
await this.reversiService.matchCancel(me);
if (ps.userId) {
await this.reversiService.matchSpecificUserCancel(me, ps.userId);
return;
} else {
await this.reversiService.matchAnyUserCancel(me);
}
});
}
}

View file

@ -6,8 +6,8 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { ReversiMatchingEntityService } from '@/core/entities/ReversiMatchingEntityService.js';
import type { ReversiMatchingsRepository } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ReversiService } from '@/core/ReversiService.js';
export const meta = {
requireCredential: true,
@ -17,32 +17,23 @@ export const meta = {
res: {
type: 'array',
optional: false, nullable: false,
items: { ref: 'ReversiMatching' },
items: { ref: 'UserLite' },
},
} as const;
export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.reversiMatchingsRepository)
private reversiMatchingsRepository: ReversiMatchingsRepository,
private reversiMatchingEntityService: ReversiMatchingEntityService,
private userEntityService: UserEntityService,
private reversiService: ReversiService,
) {
super(meta, paramDef, async (ps, me) => {
const invitations = await this.reversiMatchingsRepository.findBy({
childId: me.id,
});
const invitations = await this.reversiService.getInvitations(me);
return await this.reversiMatchingEntityService.packMany(invitations, me);
return await this.userEntityService.packMany(invitations, me);
});
}
}

View file

@ -36,9 +36,9 @@ export const meta = {
export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id' },
userId: { type: 'string', format: 'misskey:id', nullable: true },
},
required: ['userId'],
required: [],
} as const;
@Injectable()
@ -51,12 +51,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, me) => {
if (ps.userId === me.id) throw new ApiError(meta.errors.isYourself);
const child = await this.getterService.getUser(ps.userId).catch(err => {
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 = await this.reversiService.match(me, child);
const game = target ? await this.reversiService.matchSpecificUser(me, target) : await this.reversiService.matchAnyUser(me);
if (game == null) return;

View file

@ -1623,12 +1623,12 @@ declare namespace entities {
BubbleGameRegisterResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchRequest,
ReversiCancelMatchResponse,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsRequest,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
@ -1671,8 +1671,7 @@ declare namespace entities {
RoleLite,
Role,
ReversiGameLite,
ReversiGameDetailed,
ReversiMatching
ReversiGameDetailed
}
}
export { entities }
@ -2609,6 +2608,9 @@ 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 ReversiCancelMatchResponse = operations['reversi/cancel-match']['responses']['200']['content']['application/json'];
@ -2624,15 +2626,9 @@ type ReversiGamesRequest = operations['reversi/games']['requestBody']['content']
// @public (undocumented)
type ReversiGamesResponse = operations['reversi/games']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiInvitationsRequest = operations['reversi/invitations']['requestBody']['content']['application/json'];
// @public (undocumented)
type ReversiInvitationsResponse = operations['reversi/invitations']['responses']['200']['content']['application/json'];
// @public (undocumented)
type ReversiMatching = components['schemas']['ReversiMatching'];
// @public (undocumented)
type ReversiMatchRequest = operations['reversi/match']['requestBody']['content']['application/json'];

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-18T11:53:06.433Z
* generatedAt: 2024-01-19T01:59:26.059Z
*/
import type { SwitchCaseResponseType } from '../api.js';

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-18T11:53:06.431Z
* generatedAt: 2024-01-19T01:59:26.057Z
*/
import type {
@ -544,12 +544,12 @@ import type {
BubbleGameRegisterResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchRequest,
ReversiCancelMatchResponse,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsRequest,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
@ -917,10 +917,10 @@ export type Endpoints = {
'retention': { req: EmptyRequest; res: RetentionResponse };
'bubble-game/register': { req: BubbleGameRegisterRequest; res: BubbleGameRegisterResponse };
'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse };
'reversi/cancel-match': { req: EmptyRequest; res: ReversiCancelMatchResponse };
'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: ReversiCancelMatchResponse };
'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse };
'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse };
'reversi/invitations': { req: ReversiInvitationsRequest; res: ReversiInvitationsResponse };
'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse };
'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse };
'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse };
}

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-18T11:53:06.430Z
* generatedAt: 2024-01-19T01:59:26.055Z
*/
import { operations } from './types.js';
@ -546,12 +546,12 @@ export type BubbleGameRegisterRequest = operations['bubble-game/register']['requ
export type BubbleGameRegisterResponse = operations['bubble-game/register']['responses']['200']['content']['application/json'];
export type BubbleGameRankingRequest = operations['bubble-game/ranking']['requestBody']['content']['application/json'];
export type BubbleGameRankingResponse = operations['bubble-game/ranking']['responses']['200']['content']['application/json'];
export type ReversiCancelMatchRequest = operations['reversi/cancel-match']['requestBody']['content']['application/json'];
export type ReversiCancelMatchResponse = operations['reversi/cancel-match']['responses']['200']['content']['application/json'];
export type ReversiGamesRequest = operations['reversi/games']['requestBody']['content']['application/json'];
export type ReversiGamesResponse = operations['reversi/games']['responses']['200']['content']['application/json'];
export type ReversiMatchRequest = operations['reversi/match']['requestBody']['content']['application/json'];
export type ReversiMatchResponse = operations['reversi/match']['responses']['200']['content']['application/json'];
export type ReversiInvitationsRequest = operations['reversi/invitations']['requestBody']['content']['application/json'];
export type ReversiInvitationsResponse = operations['reversi/invitations']['responses']['200']['content']['application/json'];
export type ReversiShowGameRequest = operations['reversi/show-game']['requestBody']['content']['application/json'];
export type ReversiShowGameResponse = operations['reversi/show-game']['responses']['200']['content']['application/json'];

View file

@ -1,6 +1,6 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-18T11:53:06.429Z
* generatedAt: 2024-01-19T01:59:26.054Z
*/
import { components } from './types.js';
@ -43,4 +43,3 @@ export type RoleLite = components['schemas']['RoleLite'];
export type Role = components['schemas']['Role'];
export type ReversiGameLite = components['schemas']['ReversiGameLite'];
export type ReversiGameDetailed = components['schemas']['ReversiGameDetailed'];
export type ReversiMatching = components['schemas']['ReversiMatching'];

View file

@ -3,7 +3,7 @@
/*
* version: 2023.12.2
* generatedAt: 2024-01-18T11:53:06.350Z
* generatedAt: 2024-01-19T01:59:25.971Z
*/
/**
@ -4525,18 +4525,6 @@ export type components = {
}[];
map: string[];
};
ReversiMatching: {
/** Format: id */
id: string;
/** Format: date-time */
createdAt: string;
/** Format: id */
parentId: string;
parent: components['schemas']['User'] | null;
/** Format: id */
childId: string;
child: components['schemas']['User'];
};
};
responses: never;
parameters: never;
@ -25682,6 +25670,14 @@ export type operations = {
* **Credential required**: *Yes* / **Permission**: *write:account*
*/
'reversi/cancel-match': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
userId?: string | null;
};
};
};
responses: {
/** @description OK (with results) */
200: {
@ -25792,7 +25788,7 @@ export type operations = {
content: {
'application/json': {
/** Format: misskey:id */
userId: string;
userId?: string | null;
};
};
};
@ -25842,19 +25838,11 @@ export type operations = {
* **Credential required**: *Yes* / **Permission**: *read:account*
*/
'reversi/invitations': {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
userId: string;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': components['schemas']['ReversiMatching'][];
'application/json': components['schemas']['UserLite'][];
};
};
/** @description Client error */