wip
This commit is contained in:
parent
1259fabd7f
commit
037a1daa79
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
@ -80,6 +80,5 @@ export const DI = {
|
|||
userMemosRepository: Symbol('userMemosRepository'),
|
||||
bubbleGameRecordsRepository: Symbol('bubbleGameRecordsRepository'),
|
||||
reversiGamesRepository: Symbol('reversiGamesRepository'),
|
||||
reversiMatchingsRepository: Symbol('reversiMatchingsRepository'),
|
||||
//#endregion
|
||||
};
|
||||
|
|
|
@ -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]>;
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>;
|
||||
|
|
|
@ -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;
|
|
@ -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,
|
||||
];
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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'];
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue