mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-03-21 03:30:42 +00:00
refactor: use TRANSIENT scope to avoid service bucket relay (#16985)
* refactor: use TRANSIENT scope to avoid service bucket relay * lint: fix lints * refactor: use transient for apResolver * Update packages/backend/src/core/activitypub/models/ApImageService.ts * fix
This commit is contained in:
@@ -141,7 +141,7 @@ import { ApLoggerService } from './activitypub/ApLoggerService.js';
|
|||||||
import { ApMfmService } from './activitypub/ApMfmService.js';
|
import { ApMfmService } from './activitypub/ApMfmService.js';
|
||||||
import { ApRendererService } from './activitypub/ApRendererService.js';
|
import { ApRendererService } from './activitypub/ApRendererService.js';
|
||||||
import { ApRequestService } from './activitypub/ApRequestService.js';
|
import { ApRequestService } from './activitypub/ApRequestService.js';
|
||||||
import { ApResolverService } from './activitypub/ApResolverService.js';
|
import { ApResolverService, Resolver } from './activitypub/ApResolverService.js';
|
||||||
import { JsonLdService } from './activitypub/JsonLdService.js';
|
import { JsonLdService } from './activitypub/JsonLdService.js';
|
||||||
import { RemoteLoggerService } from './RemoteLoggerService.js';
|
import { RemoteLoggerService } from './RemoteLoggerService.js';
|
||||||
import { RemoteUserResolveService } from './RemoteUserResolveService.js';
|
import { RemoteUserResolveService } from './RemoteUserResolveService.js';
|
||||||
@@ -447,6 +447,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
|||||||
ApRendererService,
|
ApRendererService,
|
||||||
ApRequestService,
|
ApRequestService,
|
||||||
ApResolverService,
|
ApResolverService,
|
||||||
|
Resolver,
|
||||||
JsonLdService,
|
JsonLdService,
|
||||||
RemoteLoggerService,
|
RemoteLoggerService,
|
||||||
RemoteUserResolveService,
|
RemoteUserResolveService,
|
||||||
@@ -745,6 +746,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
|
|||||||
ApRendererService,
|
ApRendererService,
|
||||||
ApRequestService,
|
ApRequestService,
|
||||||
ApResolverService,
|
ApResolverService,
|
||||||
|
Resolver,
|
||||||
JsonLdService,
|
JsonLdService,
|
||||||
RemoteLoggerService,
|
RemoteLoggerService,
|
||||||
RemoteUserResolveService,
|
RemoteUserResolveService,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export class ApInboxService {
|
|||||||
if (isCollectionOrOrderedCollection(activity)) {
|
if (isCollectionOrOrderedCollection(activity)) {
|
||||||
const results = [] as [string, string | void][];
|
const results = [] as [string, string | void][];
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const items = toArray(isCollection(activity) ? activity.items : activity.orderedItems);
|
const items = toArray(isCollection(activity) ? activity.items : activity.orderedItems);
|
||||||
if (items.length >= resolver.getRecursionLimit()) {
|
if (items.length >= resolver.getRecursionLimit()) {
|
||||||
@@ -221,7 +221,7 @@ export class ApInboxService {
|
|||||||
this.logger.info(`Accept: ${uri}`);
|
this.logger.info(`Accept: ${uri}`);
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(activity.object).catch(err => {
|
const object = await resolver.resolve(activity.object).catch(err => {
|
||||||
this.logger.error(`Resolution failed: ${err}`);
|
this.logger.error(`Resolution failed: ${err}`);
|
||||||
@@ -284,7 +284,7 @@ export class ApInboxService {
|
|||||||
this.logger.info(`Announce: ${uri}`);
|
this.logger.info(`Announce: ${uri}`);
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
if (!activity.object) return 'skip: activity has no object property';
|
if (!activity.object) return 'skip: activity has no object property';
|
||||||
const targetUri = getApId(activity.object);
|
const targetUri = getApId(activity.object);
|
||||||
@@ -406,7 +406,7 @@ export class ApInboxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(activity.object).catch(e => {
|
const object = await resolver.resolve(activity.object).catch(e => {
|
||||||
this.logger.error(`Resolution failed: ${e}`);
|
this.logger.error(`Resolution failed: ${e}`);
|
||||||
@@ -575,7 +575,7 @@ export class ApInboxService {
|
|||||||
this.logger.info(`Reject: ${uri}`);
|
this.logger.info(`Reject: ${uri}`);
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(activity.object).catch(e => {
|
const object = await resolver.resolve(activity.object).catch(e => {
|
||||||
this.logger.error(`Resolution failed: ${e}`);
|
this.logger.error(`Resolution failed: ${e}`);
|
||||||
@@ -642,7 +642,7 @@ export class ApInboxService {
|
|||||||
this.logger.info(`Undo: ${uri}`);
|
this.logger.info(`Undo: ${uri}`);
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(activity.object).catch(e => {
|
const object = await resolver.resolve(activity.object).catch(e => {
|
||||||
this.logger.error(`Resolution failed: ${e}`);
|
this.logger.error(`Resolution failed: ${e}`);
|
||||||
@@ -774,7 +774,7 @@ export class ApInboxService {
|
|||||||
this.logger.debug('Update');
|
this.logger.debug('Update');
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
resolver ??= this.apResolverService.createResolver();
|
resolver ??= await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(activity.object).catch(e => {
|
const object = await resolver.resolve(activity.object).catch(e => {
|
||||||
this.logger.error(`Resolution failed: ${e}`);
|
this.logger.error(`Resolution failed: ${e}`);
|
||||||
|
|||||||
@@ -3,10 +3,17 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { IsNull, Not } from 'typeorm';
|
import { IsNull, Not } from 'typeorm';
|
||||||
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
|
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
|
||||||
import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository, MiMeta } from '@/models/_.js';
|
import type {
|
||||||
|
FollowRequestsRepository,
|
||||||
|
MiMeta,
|
||||||
|
NoteReactionsRepository,
|
||||||
|
NotesRepository,
|
||||||
|
PollsRepository,
|
||||||
|
UsersRepository
|
||||||
|
} from '@/models/_.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { HttpRequestService } from '@/core/HttpRequestService.js';
|
import { HttpRequestService } from '@/core/HttpRequestService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
@@ -16,26 +23,43 @@ import { LoggerService } from '@/core/LoggerService.js';
|
|||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
import { SystemAccountService } from '@/core/SystemAccountService.js';
|
import { SystemAccountService } from '@/core/SystemAccountService.js';
|
||||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||||
|
import type { ICollection, IObject, IOrderedCollection } from './type.js';
|
||||||
import { isCollectionOrOrderedCollection } from './type.js';
|
import { isCollectionOrOrderedCollection } from './type.js';
|
||||||
import { ApDbResolverService } from './ApDbResolverService.js';
|
import { ApDbResolverService } from './ApDbResolverService.js';
|
||||||
import { ApRendererService } from './ApRendererService.js';
|
import { ApRendererService } from './ApRendererService.js';
|
||||||
import { ApRequestService } from './ApRequestService.js';
|
import { ApRequestService } from './ApRequestService.js';
|
||||||
import { FetchAllowSoftFailMask } from './misc/check-against-url.js';
|
import { FetchAllowSoftFailMask } from './misc/check-against-url.js';
|
||||||
import type { IObject, ICollection, IOrderedCollection } from './type.js';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
|
|
||||||
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
export class Resolver {
|
export class Resolver {
|
||||||
private history: Set<string>;
|
private history: Set<string>;
|
||||||
private user?: MiLocalUser;
|
private user?: MiLocalUser;
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
private recursionLimit = 256;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(DI.config)
|
||||||
private config: Config,
|
private config: Config,
|
||||||
|
|
||||||
|
@Inject(DI.meta)
|
||||||
private meta: MiMeta,
|
private meta: MiMeta,
|
||||||
|
|
||||||
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@Inject(DI.notesRepository)
|
||||||
private notesRepository: NotesRepository,
|
private notesRepository: NotesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.pollsRepository)
|
||||||
private pollsRepository: PollsRepository,
|
private pollsRepository: PollsRepository,
|
||||||
|
|
||||||
|
@Inject(DI.noteReactionsRepository)
|
||||||
private noteReactionsRepository: NoteReactionsRepository,
|
private noteReactionsRepository: NoteReactionsRepository,
|
||||||
|
|
||||||
|
@Inject(DI.followRequestsRepository)
|
||||||
private followRequestsRepository: FollowRequestsRepository,
|
private followRequestsRepository: FollowRequestsRepository,
|
||||||
|
|
||||||
private utilityService: UtilityService,
|
private utilityService: UtilityService,
|
||||||
private systemAccountService: SystemAccountService,
|
private systemAccountService: SystemAccountService,
|
||||||
private apRequestService: ApRequestService,
|
private apRequestService: ApRequestService,
|
||||||
@@ -43,7 +67,6 @@ export class Resolver {
|
|||||||
private apRendererService: ApRendererService,
|
private apRendererService: ApRendererService,
|
||||||
private apDbResolverService: ApDbResolverService,
|
private apDbResolverService: ApDbResolverService,
|
||||||
private loggerService: LoggerService,
|
private loggerService: LoggerService,
|
||||||
private recursionLimit = 256,
|
|
||||||
) {
|
) {
|
||||||
this.history = new Set();
|
this.history = new Set();
|
||||||
this.logger = this.loggerService.getLogger('ap-resolve');
|
this.logger = this.loggerService.getLogger('ap-resolve');
|
||||||
@@ -180,54 +203,12 @@ export class Resolver {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApResolverService {
|
export class ApResolverService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.config)
|
private moduleRef: ModuleRef,
|
||||||
private config: Config,
|
|
||||||
|
|
||||||
@Inject(DI.meta)
|
|
||||||
private meta: MiMeta,
|
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
|
||||||
private usersRepository: UsersRepository,
|
|
||||||
|
|
||||||
@Inject(DI.notesRepository)
|
|
||||||
private notesRepository: NotesRepository,
|
|
||||||
|
|
||||||
@Inject(DI.pollsRepository)
|
|
||||||
private pollsRepository: PollsRepository,
|
|
||||||
|
|
||||||
@Inject(DI.noteReactionsRepository)
|
|
||||||
private noteReactionsRepository: NoteReactionsRepository,
|
|
||||||
|
|
||||||
@Inject(DI.followRequestsRepository)
|
|
||||||
private followRequestsRepository: FollowRequestsRepository,
|
|
||||||
|
|
||||||
private utilityService: UtilityService,
|
|
||||||
private systemAccountService: SystemAccountService,
|
|
||||||
private apRequestService: ApRequestService,
|
|
||||||
private httpRequestService: HttpRequestService,
|
|
||||||
private apRendererService: ApRendererService,
|
|
||||||
private apDbResolverService: ApDbResolverService,
|
|
||||||
private loggerService: LoggerService,
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public createResolver(): Resolver {
|
public async createResolver(): Promise<Resolver> {
|
||||||
return new Resolver(
|
return await this.moduleRef.create(Resolver);
|
||||||
this.config,
|
|
||||||
this.meta,
|
|
||||||
this.usersRepository,
|
|
||||||
this.notesRepository,
|
|
||||||
this.pollsRepository,
|
|
||||||
this.noteReactionsRepository,
|
|
||||||
this.followRequestsRepository,
|
|
||||||
this.utilityService,
|
|
||||||
this.systemAccountService,
|
|
||||||
this.apRequestService,
|
|
||||||
this.httpRequestService,
|
|
||||||
this.apRendererService,
|
|
||||||
this.apDbResolverService,
|
|
||||||
this.loggerService,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class ApImageService {
|
|||||||
throw new Error('actor has been suspended');
|
throw new Error('actor has been suspended');
|
||||||
}
|
}
|
||||||
|
|
||||||
const image = await this.apResolverService.createResolver().resolve(value);
|
const image = await (await this.apResolverService.createResolver()).resolve(value);
|
||||||
|
|
||||||
if (!isDocument(image)) return null;
|
if (!isDocument(image)) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export class ApNoteService {
|
|||||||
@bindThis
|
@bindThis
|
||||||
public async createNote(value: string | IObject, actor?: MiRemoteUser, resolver?: Resolver, silent = false): Promise<MiNote | null> {
|
public async createNote(value: string | IObject, actor?: MiRemoteUser, resolver?: Resolver, silent = false): Promise<MiNote | null> {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(value);
|
const object = await resolver.resolve(value);
|
||||||
|
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = await resolver.resolve(uri);
|
const object = await resolver.resolve(uri);
|
||||||
if (object.id == null) throw new Error('invalid object.id: ' + object.id);
|
if (object.id == null) throw new Error('invalid object.id: ' + object.id);
|
||||||
@@ -500,7 +500,7 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const object = hint ?? await resolver.resolve(uri);
|
const object = hint ?? await resolver.resolve(uri);
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
|
|
||||||
// リモートサーバーからフェッチしてきて登録
|
// リモートサーバーからフェッチしてきて登録
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
return await this.createPerson(uri, resolver);
|
return await this.createPerson(uri, resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,7 +707,7 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
|
|
||||||
this.logger.info(`Updating the featured: ${user.uri}`);
|
this.logger.info(`Updating the featured: ${user.uri}`);
|
||||||
|
|
||||||
const _resolver = resolver ?? this.apResolverService.createResolver();
|
const _resolver = resolver ?? await this.apResolverService.createResolver();
|
||||||
|
|
||||||
// Resolve to (Ordered)Collection Object
|
// Resolve to (Ordered)Collection Object
|
||||||
const collection = await _resolver.resolveCollection(user.featured);
|
const collection = await _resolver.resolveCollection(user.featured);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class ApQuestionService {
|
|||||||
@bindThis
|
@bindThis
|
||||||
public async extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
|
public async extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
|
|
||||||
const question = await resolver.resolve(source);
|
const question = await resolver.resolve(source);
|
||||||
if (!isQuestion(question)) throw new Error('invalid type');
|
if (!isQuestion(question)) throw new Error('invalid type');
|
||||||
@@ -91,7 +91,7 @@ export class ApQuestionService {
|
|||||||
|
|
||||||
// resolve new Question object
|
// resolve new Question object
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
if (resolver == null) resolver = await this.apResolverService.createResolver();
|
||||||
const question = await resolver.resolve(value);
|
const question = await resolver.resolve(value);
|
||||||
this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
|
this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { NodeinfoServerService } from './NodeinfoServerService.js';
|
|||||||
import { ServerService } from './ServerService.js';
|
import { ServerService } from './ServerService.js';
|
||||||
import { WellKnownServerService } from './WellKnownServerService.js';
|
import { WellKnownServerService } from './WellKnownServerService.js';
|
||||||
import { GetterService } from './api/GetterService.js';
|
import { GetterService } from './api/GetterService.js';
|
||||||
import { ChannelsService } from './api/stream/ChannelsService.js';
|
|
||||||
import { ActivityPubServerService } from './ActivityPubServerService.js';
|
import { ActivityPubServerService } from './ActivityPubServerService.js';
|
||||||
import { ApiLoggerService } from './api/ApiLoggerService.js';
|
import { ApiLoggerService } from './api/ApiLoggerService.js';
|
||||||
import { ApiServerService } from './api/ApiServerService.js';
|
import { ApiServerService } from './api/ApiServerService.js';
|
||||||
@@ -31,24 +30,25 @@ import { UrlPreviewService } from './web/UrlPreviewService.js';
|
|||||||
import { ClientLoggerService } from './web/ClientLoggerService.js';
|
import { ClientLoggerService } from './web/ClientLoggerService.js';
|
||||||
import { OAuth2ProviderService } from './oauth/OAuth2ProviderService.js';
|
import { OAuth2ProviderService } from './oauth/OAuth2ProviderService.js';
|
||||||
|
|
||||||
import { MainChannelService } from './api/stream/channels/main.js';
|
import MainStreamConnection from '@/server/api/stream/Connection.js';
|
||||||
import { AdminChannelService } from './api/stream/channels/admin.js';
|
import { MainChannel } from './api/stream/channels/main.js';
|
||||||
import { AntennaChannelService } from './api/stream/channels/antenna.js';
|
import { AdminChannel } from './api/stream/channels/admin.js';
|
||||||
import { ChannelChannelService } from './api/stream/channels/channel.js';
|
import { AntennaChannel } from './api/stream/channels/antenna.js';
|
||||||
import { DriveChannelService } from './api/stream/channels/drive.js';
|
import { ChannelChannel } from './api/stream/channels/channel.js';
|
||||||
import { GlobalTimelineChannelService } from './api/stream/channels/global-timeline.js';
|
import { DriveChannel } from './api/stream/channels/drive.js';
|
||||||
import { HashtagChannelService } from './api/stream/channels/hashtag.js';
|
import { GlobalTimelineChannel } from './api/stream/channels/global-timeline.js';
|
||||||
import { HomeTimelineChannelService } from './api/stream/channels/home-timeline.js';
|
import { HashtagChannel } from './api/stream/channels/hashtag.js';
|
||||||
import { HybridTimelineChannelService } from './api/stream/channels/hybrid-timeline.js';
|
import { HomeTimelineChannel } from './api/stream/channels/home-timeline.js';
|
||||||
import { LocalTimelineChannelService } from './api/stream/channels/local-timeline.js';
|
import { HybridTimelineChannel } from './api/stream/channels/hybrid-timeline.js';
|
||||||
import { QueueStatsChannelService } from './api/stream/channels/queue-stats.js';
|
import { LocalTimelineChannel } from './api/stream/channels/local-timeline.js';
|
||||||
import { ServerStatsChannelService } from './api/stream/channels/server-stats.js';
|
import { QueueStatsChannel } from './api/stream/channels/queue-stats.js';
|
||||||
import { UserListChannelService } from './api/stream/channels/user-list.js';
|
import { ServerStatsChannel } from './api/stream/channels/server-stats.js';
|
||||||
import { RoleTimelineChannelService } from './api/stream/channels/role-timeline.js';
|
import { UserListChannel } from './api/stream/channels/user-list.js';
|
||||||
import { ChatUserChannelService } from './api/stream/channels/chat-user.js';
|
import { RoleTimelineChannel } from './api/stream/channels/role-timeline.js';
|
||||||
import { ChatRoomChannelService } from './api/stream/channels/chat-room.js';
|
import { ChatUserChannel } from './api/stream/channels/chat-user.js';
|
||||||
import { ReversiChannelService } from './api/stream/channels/reversi.js';
|
import { ChatRoomChannel } from './api/stream/channels/chat-room.js';
|
||||||
import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js';
|
import { ReversiChannel } from './api/stream/channels/reversi.js';
|
||||||
|
import { ReversiGameChannel } from './api/stream/channels/reversi-game.js';
|
||||||
import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.js';
|
import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.js';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@@ -69,7 +69,7 @@ import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.j
|
|||||||
ServerService,
|
ServerService,
|
||||||
WellKnownServerService,
|
WellKnownServerService,
|
||||||
GetterService,
|
GetterService,
|
||||||
ChannelsService,
|
MainStreamConnection,
|
||||||
ApiCallService,
|
ApiCallService,
|
||||||
ApiLoggerService,
|
ApiLoggerService,
|
||||||
ApiServerService,
|
ApiServerService,
|
||||||
@@ -80,24 +80,24 @@ import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.j
|
|||||||
SigninService,
|
SigninService,
|
||||||
SignupApiService,
|
SignupApiService,
|
||||||
StreamingApiServerService,
|
StreamingApiServerService,
|
||||||
MainChannelService,
|
MainChannel,
|
||||||
AdminChannelService,
|
AdminChannel,
|
||||||
AntennaChannelService,
|
AntennaChannel,
|
||||||
ChannelChannelService,
|
ChannelChannel,
|
||||||
DriveChannelService,
|
DriveChannel,
|
||||||
GlobalTimelineChannelService,
|
GlobalTimelineChannel,
|
||||||
HashtagChannelService,
|
HashtagChannel,
|
||||||
RoleTimelineChannelService,
|
RoleTimelineChannel,
|
||||||
ChatUserChannelService,
|
ChatUserChannel,
|
||||||
ChatRoomChannelService,
|
ChatRoomChannel,
|
||||||
ReversiChannelService,
|
ReversiChannel,
|
||||||
ReversiGameChannelService,
|
ReversiGameChannel,
|
||||||
HomeTimelineChannelService,
|
HomeTimelineChannel,
|
||||||
HybridTimelineChannelService,
|
HybridTimelineChannel,
|
||||||
LocalTimelineChannelService,
|
LocalTimelineChannel,
|
||||||
QueueStatsChannelService,
|
QueueStatsChannel,
|
||||||
ServerStatsChannelService,
|
ServerStatsChannel,
|
||||||
UserListChannelService,
|
UserListChannel,
|
||||||
OpenApiServerService,
|
OpenApiServerService,
|
||||||
OAuth2ProviderService,
|
OAuth2ProviderService,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -8,18 +8,14 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||||||
import * as Redis from 'ioredis';
|
import * as Redis from 'ioredis';
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { UsersRepository, MiAccessToken } from '@/models/_.js';
|
import type { MiAccessToken } from '@/models/_.js';
|
||||||
import { NotificationService } from '@/core/NotificationService.js';
|
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { CacheService } from '@/core/CacheService.js';
|
|
||||||
import { MiLocalUser } from '@/models/User.js';
|
import { MiLocalUser } from '@/models/User.js';
|
||||||
import { UserService } from '@/core/UserService.js';
|
import { UserService } from '@/core/UserService.js';
|
||||||
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
|
||||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
|
||||||
import { AuthenticateService, AuthenticationError } from './AuthenticateService.js';
|
import { AuthenticateService, AuthenticationError } from './AuthenticateService.js';
|
||||||
import MainStreamConnection from './stream/Connection.js';
|
import MainStreamConnection, { ConnectionRequest } from './stream/Connection.js';
|
||||||
import { ChannelsService } from './stream/ChannelsService.js';
|
|
||||||
import type * as http from 'node:http';
|
import type * as http from 'node:http';
|
||||||
|
import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StreamingApiServerService {
|
export class StreamingApiServerService {
|
||||||
@@ -31,16 +27,9 @@ export class StreamingApiServerService {
|
|||||||
@Inject(DI.redisForSub)
|
@Inject(DI.redisForSub)
|
||||||
private redisForSub: Redis.Redis,
|
private redisForSub: Redis.Redis,
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
private moduleRef: ModuleRef,
|
||||||
private usersRepository: UsersRepository,
|
|
||||||
|
|
||||||
private cacheService: CacheService,
|
|
||||||
private authenticateService: AuthenticateService,
|
private authenticateService: AuthenticateService,
|
||||||
private channelsService: ChannelsService,
|
|
||||||
private notificationService: NotificationService,
|
|
||||||
private usersService: UserService,
|
private usersService: UserService,
|
||||||
private channelFollowingService: ChannelFollowingService,
|
|
||||||
private channelMutingService: ChannelMutingService,
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,14 +83,12 @@ export class StreamingApiServerService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = new MainStreamConnection(
|
const contextId = ContextIdFactory.create();
|
||||||
this.channelsService,
|
this.moduleRef.registerRequestByContextId<ConnectionRequest>({
|
||||||
this.notificationService,
|
user,
|
||||||
this.cacheService,
|
token: app,
|
||||||
this.channelFollowingService,
|
}, contextId);
|
||||||
this.channelMutingService,
|
const stream = await this.moduleRef.create(MainStreamConnection, contextId);
|
||||||
user, app,
|
|
||||||
);
|
|
||||||
|
|
||||||
await stream.init();
|
await stream.init();
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
private apResolverService: ApResolverService,
|
private apResolverService: ApResolverService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const resolver = this.apResolverService.createResolver();
|
const resolver = await this.apResolverService.createResolver();
|
||||||
const object = await resolver.resolve(ps.uri);
|
const object = await resolver.resolve(ps.uri);
|
||||||
return object;
|
return object;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
if (this.utilityService.isSelfHost(host)) return null;
|
if (this.utilityService.isSelfHost(host)) return null;
|
||||||
|
|
||||||
// リモートから一旦オブジェクトフェッチ
|
// リモートから一旦オブジェクトフェッチ
|
||||||
const resolver = this.apResolverService.createResolver();
|
const resolver = await this.apResolverService.createResolver();
|
||||||
// allow ap/show exclusively to lookup URLs that are cross-origin or non-canonical (like https://alice.example.com/@bob@bob.example.com -> https://bob.example.com/@bob)
|
// allow ap/show exclusively to lookup URLs that are cross-origin or non-canonical (like https://alice.example.com/@bob@bob.example.com -> https://bob.example.com/@bob)
|
||||||
const object = await resolver.resolve(uri, FetchAllowSoftFailMask.CrossOrigin | FetchAllowSoftFailMask.NonCanonicalId).catch((err) => {
|
const object = await resolver.resolve(uri, FetchAllowSoftFailMask.CrossOrigin | FetchAllowSoftFailMask.NonCanonicalId).catch((err) => {
|
||||||
if (err instanceof IdentifiableError) {
|
if (err instanceof IdentifiableError) {
|
||||||
|
|||||||
@@ -4,72 +4,54 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { HybridTimelineChannel } from './channels/hybrid-timeline.js';
|
||||||
|
import { LocalTimelineChannel } from './channels/local-timeline.js';
|
||||||
|
import { HomeTimelineChannel } from './channels/home-timeline.js';
|
||||||
|
import { GlobalTimelineChannel } from './channels/global-timeline.js';
|
||||||
|
import { MainChannel } from './channels/main.js';
|
||||||
|
import { ChannelChannel } from './channels/channel.js';
|
||||||
|
import { AdminChannel } from './channels/admin.js';
|
||||||
|
import { ServerStatsChannel } from './channels/server-stats.js';
|
||||||
|
import { QueueStatsChannel } from './channels/queue-stats.js';
|
||||||
|
import { UserListChannel } from './channels/user-list.js';
|
||||||
|
import { AntennaChannel } from './channels/antenna.js';
|
||||||
|
import { DriveChannel } from './channels/drive.js';
|
||||||
|
import { HashtagChannel } from './channels/hashtag.js';
|
||||||
|
import { RoleTimelineChannel } from './channels/role-timeline.js';
|
||||||
|
import { ChatUserChannel } from './channels/chat-user.js';
|
||||||
|
import { ChatRoomChannel } from './channels/chat-room.js';
|
||||||
|
import { ReversiChannel } from './channels/reversi.js';
|
||||||
|
import { ReversiGameChannel } from './channels/reversi-game.js';
|
||||||
|
import type { ChannelConstructor } from './channel.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { HybridTimelineChannelService } from './channels/hybrid-timeline.js';
|
|
||||||
import { LocalTimelineChannelService } from './channels/local-timeline.js';
|
|
||||||
import { HomeTimelineChannelService } from './channels/home-timeline.js';
|
|
||||||
import { GlobalTimelineChannelService } from './channels/global-timeline.js';
|
|
||||||
import { MainChannelService } from './channels/main.js';
|
|
||||||
import { ChannelChannelService } from './channels/channel.js';
|
|
||||||
import { AdminChannelService } from './channels/admin.js';
|
|
||||||
import { ServerStatsChannelService } from './channels/server-stats.js';
|
|
||||||
import { QueueStatsChannelService } from './channels/queue-stats.js';
|
|
||||||
import { UserListChannelService } from './channels/user-list.js';
|
|
||||||
import { AntennaChannelService } from './channels/antenna.js';
|
|
||||||
import { DriveChannelService } from './channels/drive.js';
|
|
||||||
import { HashtagChannelService } from './channels/hashtag.js';
|
|
||||||
import { RoleTimelineChannelService } from './channels/role-timeline.js';
|
|
||||||
import { ChatUserChannelService } from './channels/chat-user.js';
|
|
||||||
import { ChatRoomChannelService } from './channels/chat-room.js';
|
|
||||||
import { ReversiChannelService } from './channels/reversi.js';
|
|
||||||
import { ReversiGameChannelService } from './channels/reversi-game.js';
|
|
||||||
import { type MiChannelService } from './channel.js';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ChannelsService {
|
export class ChannelsService {
|
||||||
constructor(
|
constructor(
|
||||||
private mainChannelService: MainChannelService,
|
|
||||||
private homeTimelineChannelService: HomeTimelineChannelService,
|
|
||||||
private localTimelineChannelService: LocalTimelineChannelService,
|
|
||||||
private hybridTimelineChannelService: HybridTimelineChannelService,
|
|
||||||
private globalTimelineChannelService: GlobalTimelineChannelService,
|
|
||||||
private userListChannelService: UserListChannelService,
|
|
||||||
private hashtagChannelService: HashtagChannelService,
|
|
||||||
private roleTimelineChannelService: RoleTimelineChannelService,
|
|
||||||
private antennaChannelService: AntennaChannelService,
|
|
||||||
private channelChannelService: ChannelChannelService,
|
|
||||||
private driveChannelService: DriveChannelService,
|
|
||||||
private serverStatsChannelService: ServerStatsChannelService,
|
|
||||||
private queueStatsChannelService: QueueStatsChannelService,
|
|
||||||
private adminChannelService: AdminChannelService,
|
|
||||||
private chatUserChannelService: ChatUserChannelService,
|
|
||||||
private chatRoomChannelService: ChatRoomChannelService,
|
|
||||||
private reversiChannelService: ReversiChannelService,
|
|
||||||
private reversiGameChannelService: ReversiGameChannelService,
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public getChannelService(name: string): MiChannelService<boolean> {
|
public getChannelConstructor(name: string): ChannelConstructor<boolean> {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'main': return this.mainChannelService;
|
case 'main': return MainChannel;
|
||||||
case 'homeTimeline': return this.homeTimelineChannelService;
|
case 'homeTimeline': return HomeTimelineChannel;
|
||||||
case 'localTimeline': return this.localTimelineChannelService;
|
case 'localTimeline': return LocalTimelineChannel;
|
||||||
case 'hybridTimeline': return this.hybridTimelineChannelService;
|
case 'hybridTimeline': return HybridTimelineChannel;
|
||||||
case 'globalTimeline': return this.globalTimelineChannelService;
|
case 'globalTimeline': return GlobalTimelineChannel;
|
||||||
case 'userList': return this.userListChannelService;
|
case 'userList': return UserListChannel;
|
||||||
case 'hashtag': return this.hashtagChannelService;
|
case 'hashtag': return HashtagChannel;
|
||||||
case 'roleTimeline': return this.roleTimelineChannelService;
|
case 'roleTimeline': return RoleTimelineChannel;
|
||||||
case 'antenna': return this.antennaChannelService;
|
case 'antenna': return AntennaChannel;
|
||||||
case 'channel': return this.channelChannelService;
|
case 'channel': return ChannelChannel;
|
||||||
case 'drive': return this.driveChannelService;
|
case 'drive': return DriveChannel;
|
||||||
case 'serverStats': return this.serverStatsChannelService;
|
case 'serverStats': return ServerStatsChannel;
|
||||||
case 'queueStats': return this.queueStatsChannelService;
|
case 'queueStats': return QueueStatsChannel;
|
||||||
case 'admin': return this.adminChannelService;
|
case 'admin': return AdminChannel;
|
||||||
case 'chatUser': return this.chatUserChannelService;
|
case 'chatUser': return ChatUserChannel;
|
||||||
case 'chatRoom': return this.chatRoomChannelService;
|
case 'chatRoom': return ChatRoomChannel;
|
||||||
case 'reversi': return this.reversiChannelService;
|
case 'reversi': return ReversiChannel;
|
||||||
case 'reversiGame': return this.reversiGameChannelService;
|
case 'reversiGame': return ReversiGameChannel;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`no such channel: ${name}`);
|
throw new Error(`no such channel: ${name}`);
|
||||||
|
|||||||
@@ -6,19 +6,39 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiAccessToken } from '@/models/AccessToken.js';
|
import type { MiAccessToken } from '@/models/AccessToken.js';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import { NotificationService } from '@/core/NotificationService.js';
|
||||||
import type { NotificationService } from '@/core/NotificationService.js';
|
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { CacheService } from '@/core/CacheService.js';
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
import { MiFollowing, MiUserProfile } from '@/models/_.js';
|
import { MiFollowing, MiUserProfile } from '@/models/_.js';
|
||||||
import type { GlobalEvents, StreamEventEmitter } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents, StreamEventEmitter } from '@/core/GlobalEventService.js';
|
||||||
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
||||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
||||||
import { isJsonObject } from '@/misc/json-value.js';
|
|
||||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||||
import type { ChannelsService } from './ChannelsService.js';
|
import { isJsonObject } from '@/misc/json-value.js';
|
||||||
import type { EventEmitter } from 'events';
|
import type { EventEmitter } from 'events';
|
||||||
import type Channel from './channel.js';
|
import type Channel from './channel.js';
|
||||||
|
import type { ChannelConstructor } from './channel.js';
|
||||||
|
import type { ChannelRequest } from './channel.js';
|
||||||
|
import { ContextIdFactory, ModuleRef, REQUEST } from '@nestjs/core';
|
||||||
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
|
import { MainChannel } from '@/server/api/stream/channels/main.js';
|
||||||
|
import { HomeTimelineChannel } from '@/server/api/stream/channels/home-timeline.js';
|
||||||
|
import { LocalTimelineChannel } from '@/server/api/stream/channels/local-timeline.js';
|
||||||
|
import { HybridTimelineChannel } from '@/server/api/stream/channels/hybrid-timeline.js';
|
||||||
|
import { GlobalTimelineChannel } from '@/server/api/stream/channels/global-timeline.js';
|
||||||
|
import { UserListChannel } from '@/server/api/stream/channels/user-list.js';
|
||||||
|
import { HashtagChannel } from '@/server/api/stream/channels/hashtag.js';
|
||||||
|
import { RoleTimelineChannel } from '@/server/api/stream/channels/role-timeline.js';
|
||||||
|
import { AntennaChannel } from '@/server/api/stream/channels/antenna.js';
|
||||||
|
import { ChannelChannel } from '@/server/api/stream/channels/channel.js';
|
||||||
|
import { DriveChannel } from '@/server/api/stream/channels/drive.js';
|
||||||
|
import { ServerStatsChannel } from '@/server/api/stream/channels/server-stats.js';
|
||||||
|
import { QueueStatsChannel } from '@/server/api/stream/channels/queue-stats.js';
|
||||||
|
import { AdminChannel } from '@/server/api/stream/channels/admin.js';
|
||||||
|
import { ChatUserChannel } from '@/server/api/stream/channels/chat-user.js';
|
||||||
|
import { ChatRoomChannel } from '@/server/api/stream/channels/chat-room.js';
|
||||||
|
import { ReversiChannel } from '@/server/api/stream/channels/reversi.js';
|
||||||
|
import { ReversiGameChannel } from '@/server/api/stream/channels/reversi-game.js';
|
||||||
|
|
||||||
const MAX_CHANNELS_PER_CONNECTION = 32;
|
const MAX_CHANNELS_PER_CONNECTION = 32;
|
||||||
|
|
||||||
@@ -26,6 +46,7 @@ const MAX_CHANNELS_PER_CONNECTION = 32;
|
|||||||
* Main stream connection
|
* Main stream connection
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
export default class Connection {
|
export default class Connection {
|
||||||
public user?: MiUser;
|
public user?: MiUser;
|
||||||
public token?: MiAccessToken;
|
public token?: MiAccessToken;
|
||||||
@@ -44,16 +65,16 @@ export default class Connection {
|
|||||||
private fetchIntervalId: NodeJS.Timeout | null = null;
|
private fetchIntervalId: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private channelsService: ChannelsService,
|
private moduleRef: ModuleRef,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private cacheService: CacheService,
|
private cacheService: CacheService,
|
||||||
private channelFollowingService: ChannelFollowingService,
|
private channelFollowingService: ChannelFollowingService,
|
||||||
private channelMutingService: ChannelMutingService,
|
private channelMutingService: ChannelMutingService,
|
||||||
user: MiUser | null | undefined,
|
@Inject(REQUEST)
|
||||||
token: MiAccessToken | null | undefined,
|
request: ConnectionRequest,
|
||||||
) {
|
) {
|
||||||
if (user) this.user = user;
|
if (request.user) this.user = request.user;
|
||||||
if (token) this.token = token;
|
if (request.token) this.token = request.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -232,28 +253,34 @@ export default class Connection {
|
|||||||
* チャンネルに接続
|
* チャンネルに接続
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
|
public async connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
|
||||||
if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) {
|
if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channelService = this.channelsService.getChannelService(channel);
|
const channelConstructor = this.getChannelConstructor(channel);
|
||||||
|
|
||||||
if (channelService.requireCredential && this.user == null) {
|
if (channelConstructor.requireCredential && this.user == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.token && ((channelService.kind && !this.token.permission.some(p => p === channelService.kind))
|
if (this.token && ((channelConstructor.kind && !this.token.permission.some(p => p === channelConstructor.kind))
|
||||||
|| (!channelService.kind && channelService.requireCredential))) {
|
|| (!channelConstructor.kind && channelConstructor.requireCredential))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
|
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
|
||||||
if (channelService.shouldShare && this.channels.some(c => c.chName === channel)) {
|
if (channelConstructor.shouldShare && this.channels.some(c => c.chName === channel)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ch: Channel = channelService.create(id, this);
|
const contextId = ContextIdFactory.create();
|
||||||
|
this.moduleRef.registerRequestByContextId<ChannelRequest>({
|
||||||
|
id: id,
|
||||||
|
connection: this,
|
||||||
|
}, contextId);
|
||||||
|
const ch: Channel = await this.moduleRef.create<Channel>(channelConstructor, contextId);
|
||||||
|
|
||||||
this.channels.push(ch);
|
this.channels.push(ch);
|
||||||
ch.init(params ?? {});
|
ch.init(params ?? {});
|
||||||
|
|
||||||
@@ -264,6 +291,33 @@ export default class Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public getChannelConstructor(name: string): ChannelConstructor<boolean> {
|
||||||
|
switch (name) {
|
||||||
|
case 'main': return MainChannel;
|
||||||
|
case 'homeTimeline': return HomeTimelineChannel;
|
||||||
|
case 'localTimeline': return LocalTimelineChannel;
|
||||||
|
case 'hybridTimeline': return HybridTimelineChannel;
|
||||||
|
case 'globalTimeline': return GlobalTimelineChannel;
|
||||||
|
case 'userList': return UserListChannel;
|
||||||
|
case 'hashtag': return HashtagChannel;
|
||||||
|
case 'roleTimeline': return RoleTimelineChannel;
|
||||||
|
case 'antenna': return AntennaChannel;
|
||||||
|
case 'channel': return ChannelChannel;
|
||||||
|
case 'drive': return DriveChannel;
|
||||||
|
case 'serverStats': return ServerStatsChannel;
|
||||||
|
case 'queueStats': return QueueStatsChannel;
|
||||||
|
case 'admin': return AdminChannel;
|
||||||
|
case 'chatUser': return ChatUserChannel;
|
||||||
|
case 'chatRoom': return ChatRoomChannel;
|
||||||
|
case 'reversi': return ReversiChannel;
|
||||||
|
case 'reversiGame': return ReversiGameChannel;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(`no such channel: ${name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* チャンネルから切断
|
* チャンネルから切断
|
||||||
* @param id チャンネルコネクションID
|
* @param id チャンネルコネクションID
|
||||||
@@ -306,3 +360,8 @@ export default class Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConnectionRequest {
|
||||||
|
user: MiUser | null | undefined,
|
||||||
|
token: MiAccessToken | null | undefined,
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default abstract class Channel {
|
|||||||
public abstract readonly chName: string;
|
public abstract readonly chName: string;
|
||||||
public static readonly shouldShare: boolean;
|
public static readonly shouldShare: boolean;
|
||||||
public static readonly requireCredential: boolean;
|
public static readonly requireCredential: boolean;
|
||||||
public static readonly kind?: string | null;
|
public static readonly kind: string | null;
|
||||||
|
|
||||||
protected get user() {
|
protected get user() {
|
||||||
return this.connection.user;
|
return this.connection.user;
|
||||||
@@ -85,9 +85,9 @@ export default abstract class Channel {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(id: string, connection: Connection) {
|
constructor(request: ChannelRequest) {
|
||||||
this.id = id;
|
this.id = request.id;
|
||||||
this.connection = connection;
|
this.connection = request.connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public send(payload: { type: string, body: JsonValue }): void;
|
public send(payload: { type: string, body: JsonValue }): void;
|
||||||
@@ -111,9 +111,14 @@ export default abstract class Channel {
|
|||||||
public onMessage?(type: string, body: JsonValue): void;
|
public onMessage?(type: string, body: JsonValue): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MiChannelService<T extends boolean> = {
|
export interface ChannelRequest {
|
||||||
|
id: string,
|
||||||
|
connection: Connection,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChannelConstructor<T extends boolean> {
|
||||||
|
new(...args: any[]): Channel;
|
||||||
shouldShare: boolean;
|
shouldShare: boolean;
|
||||||
requireCredential: T;
|
requireCredential: T;
|
||||||
kind: T extends true ? string : string | null | undefined;
|
kind: T extends true ? string : string | null | undefined;
|
||||||
create: (id: string, connection: Connection) => Channel;
|
}
|
||||||
};
|
|
||||||
|
|||||||
@@ -3,17 +3,26 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class AdminChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class AdminChannel extends Channel {
|
||||||
public readonly chName = 'admin';
|
public readonly chName = 'admin';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
public static kind = 'read:admin:stream';
|
public static kind = 'read:admin:stream';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
) {
|
||||||
|
super(request);
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async init(params: JsonObject) {
|
public async init(params: JsonObject) {
|
||||||
// Subscribe admin stream
|
// Subscribe admin stream
|
||||||
@@ -22,22 +31,3 @@ class AdminChannel extends Channel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AdminChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = AdminChannel.shouldShare;
|
|
||||||
public readonly requireCredential = AdminChannel.requireCredential;
|
|
||||||
public readonly kind = AdminChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): AdminChannel {
|
|
||||||
return new AdminChannel(
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,14 +3,16 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class AntennaChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class AntennaChannel extends Channel {
|
||||||
public readonly chName = 'antenna';
|
public readonly chName = 'antenna';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
@@ -18,12 +20,12 @@ class AntennaChannel extends Channel {
|
|||||||
private antennaId: string;
|
private antennaId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private noteEntityService: NoteEntityService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private noteEntityService: NoteEntityService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onEvent = this.onEvent.bind(this);
|
//this.onEvent = this.onEvent.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,24 +57,3 @@ class AntennaChannel extends Channel {
|
|||||||
this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent);
|
this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AntennaChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = AntennaChannel.shouldShare;
|
|
||||||
public readonly requireCredential = AntennaChannel.requireCredential;
|
|
||||||
public readonly kind = AntennaChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): AntennaChannel {
|
|
||||||
return new AntennaChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
@@ -11,20 +11,23 @@ import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
|||||||
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
|
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
|
||||||
import { isUserRelated } from '@/misc/is-user-related.js';
|
import { isUserRelated } from '@/misc/is-user-related.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class ChannelChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ChannelChannel extends Channel {
|
||||||
public readonly chName = 'channel';
|
public readonly chName = 'channel';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
private channelId: string;
|
private channelId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,24 +95,3 @@ class ChannelChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ChannelChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = ChannelChannel.shouldShare;
|
|
||||||
public readonly requireCredential = ChannelChannel.requireCredential;
|
|
||||||
public readonly kind = ChannelChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): ChannelChannel {
|
|
||||||
return new ChannelChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,14 +3,16 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import { ChatService } from '@/core/ChatService.js';
|
import { ChatService } from '@/core/ChatService.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class ChatRoomChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ChatRoomChannel extends Channel {
|
||||||
public readonly chName = 'chatRoom';
|
public readonly chName = 'chatRoom';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
@@ -18,12 +20,12 @@ class ChatRoomChannel extends Channel {
|
|||||||
private roomId: string;
|
private roomId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private chatService: ChatService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private chatService: ChatService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -55,24 +57,3 @@ class ChatRoomChannel extends Channel {
|
|||||||
this.subscriber.off(`chatRoomStream:${this.roomId}`, this.onEvent);
|
this.subscriber.off(`chatRoomStream:${this.roomId}`, this.onEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ChatRoomChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = ChatRoomChannel.shouldShare;
|
|
||||||
public readonly requireCredential = ChatRoomChannel.requireCredential;
|
|
||||||
public readonly kind = ChatRoomChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private chatService: ChatService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): ChatRoomChannel {
|
|
||||||
return new ChatRoomChannel(
|
|
||||||
this.chatService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,14 +3,16 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import { ChatService } from '@/core/ChatService.js';
|
import { ChatService } from '@/core/ChatService.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class ChatUserChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ChatUserChannel extends Channel {
|
||||||
public readonly chName = 'chatUser';
|
public readonly chName = 'chatUser';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
@@ -18,12 +20,12 @@ class ChatUserChannel extends Channel {
|
|||||||
private otherId: string;
|
private otherId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private chatService: ChatService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private chatService: ChatService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -55,24 +57,3 @@ class ChatUserChannel extends Channel {
|
|||||||
this.subscriber.off(`chatUserStream:${this.user!.id}-${this.otherId}`, this.onEvent);
|
this.subscriber.off(`chatUserStream:${this.user!.id}-${this.otherId}`, this.onEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ChatUserChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = ChatUserChannel.shouldShare;
|
|
||||||
public readonly requireCredential = ChatUserChannel.requireCredential;
|
|
||||||
public readonly kind = ChatUserChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private chatService: ChatService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): ChatUserChannel {
|
|
||||||
return new ChatUserChannel(
|
|
||||||
this.chatService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,17 +3,26 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class DriveChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class DriveChannel extends Channel {
|
||||||
public readonly chName = 'drive';
|
public readonly chName = 'drive';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
public static kind = 'read:account';
|
public static kind = 'read:account';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
) {
|
||||||
|
super(request);
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async init(params: JsonObject) {
|
public async init(params: JsonObject) {
|
||||||
// Subscribe drive stream
|
// Subscribe drive stream
|
||||||
@@ -22,22 +31,3 @@ class DriveChannel extends Channel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DriveChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = DriveChannel.shouldShare;
|
|
||||||
public readonly requireCredential = DriveChannel.requireCredential;
|
|
||||||
public readonly kind = DriveChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): DriveChannel {
|
|
||||||
return new DriveChannel(
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
@@ -11,9 +11,11 @@ import { bindThis } from '@/decorators.js';
|
|||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class GlobalTimelineChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class GlobalTimelineChannel extends Channel {
|
||||||
public readonly chName = 'globalTimeline';
|
public readonly chName = 'globalTimeline';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
@@ -21,14 +23,14 @@ class GlobalTimelineChannel extends Channel {
|
|||||||
private withFiles: boolean;
|
private withFiles: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
private roleService: RoleService,
|
private roleService: RoleService,
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
|
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,28 +76,3 @@ class GlobalTimelineChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class GlobalTimelineChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = GlobalTimelineChannel.shouldShare;
|
|
||||||
public readonly requireCredential = GlobalTimelineChannel.requireCredential;
|
|
||||||
public readonly kind = GlobalTimelineChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private metaService: MetaService,
|
|
||||||
private roleService: RoleService,
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): GlobalTimelineChannel {
|
|
||||||
return new GlobalTimelineChannel(
|
|
||||||
this.metaService,
|
|
||||||
this.roleService,
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,28 +3,30 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
|
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class HashtagChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class HashtagChannel extends Channel {
|
||||||
public readonly chName = 'hashtag';
|
public readonly chName = 'hashtag';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
private q: string[][];
|
private q: string[][];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private noteEntityService: NoteEntityService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private noteEntityService: NoteEntityService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,24 +64,3 @@ class HashtagChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class HashtagChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = HashtagChannel.shouldShare;
|
|
||||||
public readonly requireCredential = HashtagChannel.requireCredential;
|
|
||||||
public readonly kind = HashtagChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): HashtagChannel {
|
|
||||||
return new HashtagChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class HomeTimelineChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class HomeTimelineChannel extends Channel {
|
||||||
public readonly chName = 'homeTimeline';
|
public readonly chName = 'homeTimeline';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
@@ -20,12 +22,12 @@ class HomeTimelineChannel extends Channel {
|
|||||||
private withFiles: boolean;
|
private withFiles: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private noteEntityService: NoteEntityService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private noteEntityService: NoteEntityService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,24 +100,3 @@ class HomeTimelineChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class HomeTimelineChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = HomeTimelineChannel.shouldShare;
|
|
||||||
public readonly requireCredential = HomeTimelineChannel.requireCredential;
|
|
||||||
public readonly kind = HomeTimelineChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): HomeTimelineChannel {
|
|
||||||
return new HomeTimelineChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
@@ -11,9 +11,11 @@ import { bindThis } from '@/decorators.js';
|
|||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class HybridTimelineChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class HybridTimelineChannel extends Channel {
|
||||||
public readonly chName = 'hybridTimeline';
|
public readonly chName = 'hybridTimeline';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
@@ -23,14 +25,14 @@ class HybridTimelineChannel extends Channel {
|
|||||||
private withFiles: boolean;
|
private withFiles: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
private roleService: RoleService,
|
private roleService: RoleService,
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
|
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,28 +120,3 @@ class HybridTimelineChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class HybridTimelineChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = HybridTimelineChannel.shouldShare;
|
|
||||||
public readonly requireCredential = HybridTimelineChannel.requireCredential;
|
|
||||||
public readonly kind = HybridTimelineChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private metaService: MetaService,
|
|
||||||
private roleService: RoleService,
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): HybridTimelineChannel {
|
|
||||||
return new HybridTimelineChannel(
|
|
||||||
this.metaService,
|
|
||||||
this.roleService,
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
@@ -11,25 +11,27 @@ import { bindThis } from '@/decorators.js';
|
|||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js';
|
import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class LocalTimelineChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class LocalTimelineChannel extends Channel {
|
||||||
public readonly chName = 'localTimeline';
|
public readonly chName = 'localTimeline';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false as const;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
private withRenotes: boolean;
|
private withRenotes: boolean;
|
||||||
private withReplies: boolean;
|
private withReplies: boolean;
|
||||||
private withFiles: boolean;
|
private withFiles: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
private roleService: RoleService,
|
private roleService: RoleService,
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
|
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,28 +86,3 @@ class LocalTimelineChannel extends Channel {
|
|||||||
this.subscriber.off('notesStream', this.onNote);
|
this.subscriber.off('notesStream', this.onNote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class LocalTimelineChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = LocalTimelineChannel.shouldShare;
|
|
||||||
public readonly requireCredential = LocalTimelineChannel.requireCredential;
|
|
||||||
public readonly kind = LocalTimelineChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private metaService: MetaService,
|
|
||||||
private roleService: RoleService,
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): LocalTimelineChannel {
|
|
||||||
return new LocalTimelineChannel(
|
|
||||||
this.metaService,
|
|
||||||
this.roleService,
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,26 +3,28 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js';
|
import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class MainChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class MainChannel extends Channel {
|
||||||
public readonly chName = 'main';
|
public readonly chName = 'main';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
public static kind = 'read:account';
|
public static kind = 'read:account';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private noteEntityService: NoteEntityService,
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
id: string,
|
private noteEntityService: NoteEntityService,
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -61,24 +63,3 @@ class MainChannel extends Channel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MainChannelService implements MiChannelService<true> {
|
|
||||||
public readonly shouldShare = MainChannel.shouldShare;
|
|
||||||
public readonly requireCredential = MainChannel.requireCredential;
|
|
||||||
public readonly kind = MainChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): MainChannel {
|
|
||||||
return new MainChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,21 +4,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Xev from 'xev';
|
import Xev from 'xev';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isJsonObject } from '@/misc/json-value.js';
|
import { isJsonObject } from '@/misc/json-value.js';
|
||||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
const ev = new Xev();
|
const ev = new Xev();
|
||||||
|
|
||||||
class QueueStatsChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class QueueStatsChannel extends Channel {
|
||||||
public readonly chName = 'queueStats';
|
public readonly chName = 'queueStats';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel['connection']) {
|
constructor(
|
||||||
super(id, connection);
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
) {
|
||||||
|
super(request);
|
||||||
//this.onStats = this.onStats.bind(this);
|
//this.onStats = this.onStats.bind(this);
|
||||||
//this.onMessage = this.onMessage.bind(this);
|
//this.onMessage = this.onMessage.bind(this);
|
||||||
}
|
}
|
||||||
@@ -56,22 +61,3 @@ class QueueStatsChannel extends Channel {
|
|||||||
ev.removeListener('queueStats', this.onStats);
|
ev.removeListener('queueStats', this.onStats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class QueueStatsChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = QueueStatsChannel.shouldShare;
|
|
||||||
public readonly requireCredential = QueueStatsChannel.requireCredential;
|
|
||||||
public readonly kind = QueueStatsChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): QueueStatsChannel {
|
|
||||||
return new QueueStatsChannel(
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,31 +3,32 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { MiReversiGame } from '@/models/_.js';
|
import type { MiReversiGame } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { ReversiService } from '@/core/ReversiService.js';
|
import { ReversiService } from '@/core/ReversiService.js';
|
||||||
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
|
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
|
||||||
import { isJsonObject } from '@/misc/json-value.js';
|
import { isJsonObject } from '@/misc/json-value.js';
|
||||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
import { reversiUpdateKeys } from 'misskey-js';
|
import { reversiUpdateKeys } from 'misskey-js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class ReversiGameChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ReversiGameChannel extends Channel {
|
||||||
public readonly chName = 'reversiGame';
|
public readonly chName = 'reversiGame';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
private gameId: MiReversiGame['id'] | null = null;
|
private gameId: MiReversiGame['id'] | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private reversiService: ReversiService,
|
private reversiService: ReversiService,
|
||||||
private reversiGameEntityService: ReversiGameEntityService,
|
private reversiGameEntityService: ReversiGameEntityService,
|
||||||
|
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -107,25 +108,3 @@ class ReversiGameChannel extends Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ReversiGameChannelService implements MiChannelService<false> {
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,22 +3,24 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class ReversiChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ReversiChannel extends Channel {
|
||||||
public readonly chName = 'reversi';
|
public readonly chName = 'reversi';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true as const;
|
public static requireCredential = true as const;
|
||||||
public static kind = 'read:account';
|
public static kind = 'read:account';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
@Inject(REQUEST)
|
||||||
connection: Channel['connection'],
|
request: ChannelRequest,
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
@@ -32,22 +34,3 @@ class ReversiChannel extends Channel {
|
|||||||
this.subscriber.off(`reversiStream:${this.user!.id}`, this.send);
|
this.subscriber.off(`reversiStream:${this.user!.id}`, this.send);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ReversiChannelService implements MiChannelService<true> {
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,28 +3,30 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class RoleTimelineChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class RoleTimelineChannel extends Channel {
|
||||||
public readonly chName = 'roleTimeline';
|
public readonly chName = 'roleTimeline';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
private roleId: string;
|
private roleId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
private noteEntityService: NoteEntityService,
|
private noteEntityService: NoteEntityService,
|
||||||
private roleservice: RoleService,
|
private roleservice: RoleService,
|
||||||
|
|
||||||
id: string,
|
|
||||||
connection: Channel['connection'],
|
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,26 +62,3 @@ class RoleTimelineChannel extends Channel {
|
|||||||
this.subscriber.off(`roleTimelineStream:${this.roleId}`, this.onEvent);
|
this.subscriber.off(`roleTimelineStream:${this.roleId}`, this.onEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class RoleTimelineChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = RoleTimelineChannel.shouldShare;
|
|
||||||
public readonly requireCredential = RoleTimelineChannel.requireCredential;
|
|
||||||
public readonly kind = RoleTimelineChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
private roleservice: RoleService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): RoleTimelineChannel {
|
|
||||||
return new RoleTimelineChannel(
|
|
||||||
this.noteEntityService,
|
|
||||||
this.roleservice,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,21 +4,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Xev from 'xev';
|
import Xev from 'xev';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isJsonObject } from '@/misc/json-value.js';
|
import { isJsonObject } from '@/misc/json-value.js';
|
||||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
const ev = new Xev();
|
const ev = new Xev();
|
||||||
|
|
||||||
class ServerStatsChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class ServerStatsChannel extends Channel {
|
||||||
public readonly chName = 'serverStats';
|
public readonly chName = 'serverStats';
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel['connection']) {
|
constructor(
|
||||||
super(id, connection);
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
) {
|
||||||
|
super(request);
|
||||||
//this.onStats = this.onStats.bind(this);
|
//this.onStats = this.onStats.bind(this);
|
||||||
//this.onMessage = this.onMessage.bind(this);
|
//this.onMessage = this.onMessage.bind(this);
|
||||||
}
|
}
|
||||||
@@ -54,22 +59,3 @@ class ServerStatsChannel extends Channel {
|
|||||||
ev.removeListener('serverStats', this.onStats);
|
ev.removeListener('serverStats', this.onStats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ServerStatsChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = ServerStatsChannel.shouldShare;
|
|
||||||
public readonly requireCredential = ServerStatsChannel.requireCredential;
|
|
||||||
public readonly kind = ServerStatsChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): ServerStatsChannel {
|
|
||||||
return new ServerStatsChannel(
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||||
import type { MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js';
|
import type { MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
@@ -11,9 +11,11 @@ import { DI } from '@/di-symbols.js';
|
|||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||||
import type { JsonObject } from '@/misc/json-value.js';
|
import type { JsonObject } from '@/misc/json-value.js';
|
||||||
import Channel, { type MiChannelService } from '../channel.js';
|
import Channel, { type ChannelRequest } from '../channel.js';
|
||||||
|
import { REQUEST } from '@nestjs/core';
|
||||||
|
|
||||||
class UserListChannel extends Channel {
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
|
export class UserListChannel extends Channel {
|
||||||
public readonly chName = 'userList';
|
public readonly chName = 'userList';
|
||||||
public static shouldShare = false;
|
public static shouldShare = false;
|
||||||
public static requireCredential = false as const;
|
public static requireCredential = false as const;
|
||||||
@@ -24,14 +26,18 @@ class UserListChannel extends Channel {
|
|||||||
private withRenotes: boolean;
|
private withRenotes: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(DI.userListsRepository)
|
||||||
private userListsRepository: UserListsRepository,
|
private userListsRepository: UserListsRepository,
|
||||||
private userListMembershipsRepository: UserListMembershipsRepository,
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
|
|
||||||
id: string,
|
@Inject(DI.userListMembershipsRepository)
|
||||||
connection: Channel['connection'],
|
private userListMembershipsRepository: UserListMembershipsRepository,
|
||||||
|
|
||||||
|
@Inject(REQUEST)
|
||||||
|
request: ChannelRequest,
|
||||||
|
|
||||||
|
private noteEntityService: NoteEntityService,
|
||||||
) {
|
) {
|
||||||
super(id, connection);
|
super(request);
|
||||||
//this.updateListUsers = this.updateListUsers.bind(this);
|
//this.updateListUsers = this.updateListUsers.bind(this);
|
||||||
//this.onNote = this.onNote.bind(this);
|
//this.onNote = this.onNote.bind(this);
|
||||||
}
|
}
|
||||||
@@ -130,32 +136,3 @@ class UserListChannel extends Channel {
|
|||||||
clearInterval(this.listUsersClock);
|
clearInterval(this.listUsersClock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class UserListChannelService implements MiChannelService<false> {
|
|
||||||
public readonly shouldShare = UserListChannel.shouldShare;
|
|
||||||
public readonly requireCredential = UserListChannel.requireCredential;
|
|
||||||
public readonly kind = UserListChannel.kind;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(DI.userListsRepository)
|
|
||||||
private userListsRepository: UserListsRepository,
|
|
||||||
|
|
||||||
@Inject(DI.userListMembershipsRepository)
|
|
||||||
private userListMembershipsRepository: UserListMembershipsRepository,
|
|
||||||
|
|
||||||
private noteEntityService: NoteEntityService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public create(id: string, connection: Channel['connection']): UserListChannel {
|
|
||||||
return new UserListChannel(
|
|
||||||
this.userListsRepository,
|
|
||||||
this.userListMembershipsRepository,
|
|
||||||
this.noteEntityService,
|
|
||||||
id,
|
|
||||||
connection,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user