summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/stream/channels
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-09-18 03:27:08 +0900
committerGitHub <noreply@github.com>2022-09-18 03:27:08 +0900
commitb75184ec8e3436200bacdcd832e3324702553d20 (patch)
tree8b7e316f29e95df921db57289c8b8da476d18f07 /packages/backend/src/server/api/stream/channels
parentUpdate ROADMAP.md (diff)
downloadsharkey-b75184ec8e3436200bacdcd832e3324702553d20.tar.gz
sharkey-b75184ec8e3436200bacdcd832e3324702553d20.tar.bz2
sharkey-b75184ec8e3436200bacdcd832e3324702553d20.zip
なんかもうめっちゃ変えた
Diffstat (limited to 'packages/backend/src/server/api/stream/channels')
-rw-r--r--packages/backend/src/server/api/stream/channels/admin.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/antenna.ts38
-rw-r--r--packages/backend/src/server/api/stream/channels/channel.ts50
-rw-r--r--packages/backend/src/server/api/stream/channels/drive.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/global-timeline.ts47
-rw-r--r--packages/backend/src/server/api/stream/channels/hashtag.ts38
-rw-r--r--packages/backend/src/server/api/stream/channels/home-timeline.ts42
-rw-r--r--packages/backend/src/server/api/stream/channels/hybrid-timeline.ts54
-rw-r--r--packages/backend/src/server/api/stream/channels/index.ts33
-rw-r--r--packages/backend/src/server/api/stream/channels/local-timeline.ts47
-rw-r--r--packages/backend/src/server/api/stream/channels/main.ts40
-rw-r--r--packages/backend/src/server/api/stream/channels/messaging-index.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/messaging.ts75
-rw-r--r--packages/backend/src/server/api/stream/channels/queue-stats.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/server-stats.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/user-list.ts60
16 files changed, 495 insertions, 129 deletions
diff --git a/packages/backend/src/server/api/stream/channels/admin.ts b/packages/backend/src/server/api/stream/channels/admin.ts
index 945182ea10..8c3c0d2adf 100644
--- a/packages/backend/src/server/api/stream/channels/admin.ts
+++ b/packages/backend/src/server/api/stream/channels/admin.ts
@@ -1,6 +1,7 @@
+import { Inject, Injectable } from '@nestjs/common';
import Channel from '../channel.js';
-export default class extends Channel {
+class AdminChannel extends Channel {
public readonly chName = 'admin';
public static shouldShare = true;
public static requireCredential = true;
@@ -12,3 +13,20 @@ export default class extends Channel {
});
}
}
+
+@Injectable()
+export class AdminChannelService {
+ public readonly shouldShare = AdminChannel.shouldShare;
+ public readonly requireCredential = AdminChannel.requireCredential;
+
+ constructor(
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): AdminChannel {
+ return new AdminChannel(
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts
index d28320d928..7c34aef495 100644
--- a/packages/backend/src/server/api/stream/channels/antenna.ts
+++ b/packages/backend/src/server/api/stream/channels/antenna.ts
@@ -1,15 +1,22 @@
-import Channel from '../channel.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { StreamMessages } from '../types.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
+import type { StreamMessages } from '../types.js';
-export default class extends Channel {
+class AntennaChannel extends Channel {
public readonly chName = 'antenna';
public static shouldShare = false;
public static requireCredential = false;
private antennaId: string;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onEvent = this.onEvent.bind(this);
}
@@ -23,7 +30,7 @@ export default class extends Channel {
private async onEvent(data: StreamMessages['antenna']['payload']) {
if (data.type === 'note') {
- const note = await Notes.pack(data.body.id, this.user, { detail: true });
+ const note = await this.noteEntityService.pack(data.body.id, this.user, { detail: true });
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.muting)) return;
@@ -43,3 +50,22 @@ export default class extends Channel {
this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent);
}
}
+
+@Injectable()
+export class AntennaChannelService {
+ public readonly shouldShare = AntennaChannel.shouldShare;
+ public readonly requireCredential = AntennaChannel.requireCredential;
+
+ constructor(
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): AntennaChannel {
+ return new AntennaChannel(
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts
index 3cdd89a8b3..2ef70e62e9 100644
--- a/packages/backend/src/server/api/stream/channels/channel.ts
+++ b/packages/backend/src/server/api/stream/channels/channel.ts
@@ -1,11 +1,14 @@
-import Channel from '../channel.js';
-import { Notes, Users } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository, UsersRepository } from '@/models/index.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { User } from '@/models/entities/user.js';
-import { StreamMessages } from '../types.js';
-import { Packed } from '@/misc/schema.js';
+import type { User } from '@/models/entities/User.js';
+import type { Packed } from '@/misc/schema.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import Channel from '../channel.js';
+import type { StreamMessages } from '../types.js';
-export default class extends Channel {
+class ChannelChannel extends Channel {
public readonly chName = 'channel';
public static shouldShare = false;
public static requireCredential = false;
@@ -13,7 +16,13 @@ export default class extends Channel {
private typers: Record<User['id'], Date> = {};
private emitTypersIntervalId: ReturnType<typeof setInterval>;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private noteEntityService: NoteEntityService,
+ private userEntityService: UserEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
this.emitTypers = this.emitTypers.bind(this);
@@ -33,13 +42,13 @@ export default class extends Channel {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
detail: true,
});
}
@@ -73,7 +82,7 @@ export default class extends Channel {
if (now.getTime() - date.getTime() > 5000) delete this.typers[userId];
}
- const users = await Users.packMany(Object.keys(this.typers), null, { detail: false });
+ const users = await this.userEntityService.packMany(Object.keys(this.typers), null, { detail: false });
this.send({
type: 'typers',
@@ -89,3 +98,24 @@ export default class extends Channel {
clearInterval(this.emitTypersIntervalId);
}
}
+
+@Injectable()
+export class ChannelChannelService {
+ public readonly shouldShare = ChannelChannel.shouldShare;
+ public readonly requireCredential = ChannelChannel.requireCredential;
+
+ constructor(
+ private noteEntityService: NoteEntityService,
+ private userEntityService: UserEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): ChannelChannel {
+ return new ChannelChannel(
+ this.noteEntityService,
+ this.userEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/drive.ts b/packages/backend/src/server/api/stream/channels/drive.ts
index 140255acd1..80d83cd690 100644
--- a/packages/backend/src/server/api/stream/channels/drive.ts
+++ b/packages/backend/src/server/api/stream/channels/drive.ts
@@ -1,6 +1,7 @@
+import { Inject, Injectable } from '@nestjs/common';
import Channel from '../channel.js';
-export default class extends Channel {
+class DriveChannel extends Channel {
public readonly chName = 'drive';
public static shouldShare = true;
public static requireCredential = true;
@@ -12,3 +13,20 @@ export default class extends Channel {
});
}
}
+
+@Injectable()
+export class DriveChannelService {
+ public readonly shouldShare = DriveChannel.shouldShare;
+ public readonly requireCredential = DriveChannel.requireCredential;
+
+ constructor(
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): DriveChannel {
+ return new DriveChannel(
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts
index 5b4ae850ec..a8617582dc 100644
--- a/packages/backend/src/server/api/stream/channels/global-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts
@@ -1,23 +1,31 @@
-import Channel from '../channel.js';
-import { fetchMeta } from '@/misc/fetch-meta.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { checkWordMute } from '@/misc/check-word-mute.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { MetaService } from '@/core/MetaService.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class GlobalTimelineChannel extends Channel {
public readonly chName = 'globalTimeline';
public static shouldShare = true;
public static requireCredential = false;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
}
public async init(params: any) {
- const meta = await fetchMeta();
+ const meta = await this.metaService.fetch();
if (meta.disableGlobalTimeline) {
if (this.user == null || (!this.user.isAdmin && !this.user.isModerator)) return;
}
@@ -32,13 +40,13 @@ export default class extends Channel {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
detail: true,
});
}
@@ -75,3 +83,24 @@ export default class extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
+
+@Injectable()
+export class GlobalTimelineChannelService {
+ public readonly shouldShare = GlobalTimelineChannel.shouldShare;
+ public readonly requireCredential = GlobalTimelineChannel.requireCredential;
+
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): GlobalTimelineChannel {
+ return new GlobalTimelineChannel(
+ this.metaService,
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts
index 741db447e6..0f6c081c12 100644
--- a/packages/backend/src/server/api/stream/channels/hashtag.ts
+++ b/packages/backend/src/server/api/stream/channels/hashtag.ts
@@ -1,16 +1,23 @@
-import Channel from '../channel.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class HashtagChannel extends Channel {
public readonly chName = 'hashtag';
public static shouldShare = false;
public static requireCredential = false;
private q: string[][];
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
}
@@ -31,7 +38,7 @@ export default class extends Channel {
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
detail: true,
});
}
@@ -51,3 +58,22 @@ export default class extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
+
+@Injectable()
+export class HashtagChannelService {
+ public readonly shouldShare = HashtagChannel.shouldShare;
+ public readonly requireCredential = HashtagChannel.requireCredential;
+
+ constructor(
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): HashtagChannel {
+ return new HashtagChannel(
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts
index 075a242ef0..16e0cebc72 100644
--- a/packages/backend/src/server/api/stream/channels/home-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts
@@ -1,16 +1,23 @@
-import Channel from '../channel.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { checkWordMute } from '@/misc/check-word-mute.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class HomeTimelineChannel extends Channel {
public readonly chName = 'homeTimeline';
public static shouldShare = true;
public static requireCredential = true;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
}
@@ -32,7 +39,7 @@ export default class extends Channel {
if (isInstanceMuted(note, new Set<string>(this.userProfile?.mutedInstances ?? []))) return;
if (['followers', 'specified'].includes(note.visibility)) {
- note = await Notes.pack(note.id, this.user!, {
+ note = await this.noteEntityService.pack(note.id, this.user!, {
detail: true,
});
@@ -42,13 +49,13 @@ export default class extends Channel {
} else {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user!, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user!, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user!, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user!, {
detail: true,
});
}
@@ -83,3 +90,22 @@ export default class extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
+
+@Injectable()
+export class HomeTimelineChannelService {
+ public readonly shouldShare = HomeTimelineChannel.shouldShare;
+ public readonly requireCredential = HomeTimelineChannel.requireCredential;
+
+ constructor(
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): HomeTimelineChannel {
+ return new HomeTimelineChannel(
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
index f5dedf77ce..f1ce822583 100644
--- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
@@ -1,23 +1,32 @@
-import Channel from '../channel.js';
-import { fetchMeta } from '@/misc/fetch-meta.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { checkWordMute } from '@/misc/check-word-mute.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { DI } from '@/di-symbols.js';
+import { MetaService } from '@/core/MetaService.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class HybridTimelineChannel extends Channel {
public readonly chName = 'hybridTimeline';
public static shouldShare = true;
public static requireCredential = true;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
}
- public async init(params: any) {
- const meta = await fetchMeta();
+ public async init(params: any): Promise<void> {
+ const meta = await this.metaService.fetch();
if (meta.disableLocalTimeline && !this.user!.isAdmin && !this.user!.isModerator) return;
// Subscribe events
@@ -37,7 +46,7 @@ export default class extends Channel {
)) return;
if (['followers', 'specified'].includes(note.visibility)) {
- note = await Notes.pack(note.id, this.user!, {
+ note = await this.noteEntityService.pack(note.id, this.user!, {
detail: true,
});
@@ -47,13 +56,13 @@ export default class extends Channel {
} else {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user!, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user!, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user!, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user!, {
detail: true,
});
}
@@ -86,8 +95,29 @@ export default class extends Channel {
this.send('note', note);
}
- public dispose() {
+ public dispose(): void {
// Unsubscribe events
this.subscriber.off('notesStream', this.onNote);
}
}
+
+@Injectable()
+export class HybridTimelineChannelService {
+ public readonly shouldShare = HybridTimelineChannel.shouldShare;
+ public readonly requireCredential = HybridTimelineChannel.requireCredential;
+
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): HybridTimelineChannel {
+ return new HybridTimelineChannel(
+ this.metaService,
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/index.ts b/packages/backend/src/server/api/stream/channels/index.ts
deleted file mode 100644
index d422edde87..0000000000
--- a/packages/backend/src/server/api/stream/channels/index.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import main from './main.js';
-import homeTimeline from './home-timeline.js';
-import localTimeline from './local-timeline.js';
-import hybridTimeline from './hybrid-timeline.js';
-import globalTimeline from './global-timeline.js';
-import serverStats from './server-stats.js';
-import queueStats from './queue-stats.js';
-import userList from './user-list.js';
-import antenna from './antenna.js';
-import messaging from './messaging.js';
-import messagingIndex from './messaging-index.js';
-import drive from './drive.js';
-import hashtag from './hashtag.js';
-import channel from './channel.js';
-import admin from './admin.js';
-
-export default {
- main,
- homeTimeline,
- localTimeline,
- hybridTimeline,
- globalTimeline,
- serverStats,
- queueStats,
- userList,
- antenna,
- messaging,
- messagingIndex,
- drive,
- hashtag,
- channel,
- admin,
-};
diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts
index f01f477238..5a5a43f845 100644
--- a/packages/backend/src/server/api/stream/channels/local-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts
@@ -1,22 +1,30 @@
-import Channel from '../channel.js';
-import { fetchMeta } from '@/misc/fetch-meta.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { checkWordMute } from '@/misc/check-word-mute.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { MetaService } from '@/core/MetaService.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class LocalTimelineChannel extends Channel {
public readonly chName = 'localTimeline';
public static shouldShare = true;
public static requireCredential = false;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onNote = this.onNote.bind(this);
}
public async init(params: any) {
- const meta = await fetchMeta();
+ const meta = await this.metaService.fetch();
if (meta.disableLocalTimeline) {
if (this.user == null || (!this.user.isAdmin && !this.user.isModerator)) return;
}
@@ -32,13 +40,13 @@ export default class extends Channel {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
detail: true,
});
}
@@ -72,3 +80,24 @@ export default class extends Channel {
this.subscriber.off('notesStream', this.onNote);
}
}
+
+@Injectable()
+export class LocalTimelineChannelService {
+ public readonly shouldShare = LocalTimelineChannel.shouldShare;
+ public readonly requireCredential = LocalTimelineChannel.requireCredential;
+
+ constructor(
+ private metaService: MetaService,
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): LocalTimelineChannel {
+ return new LocalTimelineChannel(
+ this.metaService,
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/main.ts b/packages/backend/src/server/api/stream/channels/main.ts
index 9cfea0bfc4..12908e07b4 100644
--- a/packages/backend/src/server/api/stream/channels/main.ts
+++ b/packages/backend/src/server/api/stream/channels/main.ts
@@ -1,12 +1,23 @@
-import Channel from '../channel.js';
-import { Notes } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import type { NotesRepository } from '@/models/index.js';
import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class MainChannel extends Channel {
public readonly chName = 'main';
public static shouldShare = true;
public static requireCredential = true;
+ constructor(
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
+ super(id, connection);
+ }
+
public async init(params: any) {
// Subscribe main stream channel
this.subscriber.on(`mainStream:${this.user!.id}`, async data => {
@@ -17,7 +28,7 @@ export default class extends Channel {
if (data.body.userId && this.muting.has(data.body.userId)) return;
if (data.body.note && data.body.note.isHidden) {
- const note = await Notes.pack(data.body.note.id, this.user, {
+ const note = await this.noteEntityService.pack(data.body.note.id, this.user, {
detail: true,
});
this.connection.cacheNote(note);
@@ -30,7 +41,7 @@ export default class extends Channel {
if (this.muting.has(data.body.userId)) return;
if (data.body.isHidden) {
- const note = await Notes.pack(data.body.id, this.user, {
+ const note = await this.noteEntityService.pack(data.body.id, this.user, {
detail: true,
});
this.connection.cacheNote(note);
@@ -44,3 +55,22 @@ export default class extends Channel {
});
}
}
+
+@Injectable()
+export class MainChannelService {
+ public readonly shouldShare = MainChannel.shouldShare;
+ public readonly requireCredential = MainChannel.requireCredential;
+
+ constructor(
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): MainChannel {
+ return new MainChannel(
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/messaging-index.ts b/packages/backend/src/server/api/stream/channels/messaging-index.ts
index b930785d20..bebc07f4ad 100644
--- a/packages/backend/src/server/api/stream/channels/messaging-index.ts
+++ b/packages/backend/src/server/api/stream/channels/messaging-index.ts
@@ -1,6 +1,7 @@
+import { Inject, Injectable } from '@nestjs/common';
import Channel from '../channel.js';
-export default class extends Channel {
+class MessagingIndexChannel extends Channel {
public readonly chName = 'messagingIndex';
public static shouldShare = true;
public static requireCredential = true;
@@ -12,3 +13,20 @@ export default class extends Channel {
});
}
}
+
+@Injectable()
+export class MessagingIndexChannelService {
+ public readonly shouldShare = MessagingIndexChannel.shouldShare;
+ public readonly requireCredential = MessagingIndexChannel.requireCredential;
+
+ constructor(
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): MessagingIndexChannel {
+ return new MessagingIndexChannel(
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/messaging.ts b/packages/backend/src/server/api/stream/channels/messaging.ts
index 877d44c38e..5bf20c4101 100644
--- a/packages/backend/src/server/api/stream/channels/messaging.ts
+++ b/packages/backend/src/server/api/stream/channels/messaging.ts
@@ -1,11 +1,14 @@
-import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { UserGroupJoiningsRepository, UsersRepository, MessagingMessagesRepository } from '@/models/index.js';
+import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js';
+import type { UserGroup } from '@/models/entities/UserGroup.js';
+import { MessagingService } from '@/core/MessagingService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { DI } from '@/di-symbols.js';
import Channel from '../channel.js';
-import { UserGroupJoinings, Users, MessagingMessages } from '@/models/index.js';
-import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js';
-import { UserGroup } from '@/models/entities/user-group.js';
-import { StreamMessages } from '../types.js';
+import type { StreamMessages } from '../types.js';
-export default class extends Channel {
+class MessagingChannel extends Channel {
public readonly chName = 'messaging';
public static shouldShare = false;
public static requireCredential = true;
@@ -17,7 +20,16 @@ export default class extends Channel {
private typers: Record<User['id'], Date> = {};
private emitTypersIntervalId: ReturnType<typeof setInterval>;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private usersRepository: UsersRepository,
+ private userGroupJoiningsRepository: UserGroupJoiningsRepository,
+ private messagingMessagesRepository: MessagingMessagesRepository,
+ private userEntityService: UserEntityService,
+ private messagingService: MessagingService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.onEvent = this.onEvent.bind(this);
this.onMessage = this.onMessage.bind(this);
@@ -26,12 +38,12 @@ export default class extends Channel {
public async init(params: any) {
this.otherpartyId = params.otherparty;
- this.otherparty = this.otherpartyId ? await Users.findOneByOrFail({ id: this.otherpartyId }) : null;
+ this.otherparty = this.otherpartyId ? await this.usersRepository.findOneByOrFail({ id: this.otherpartyId }) : null;
this.groupId = params.group;
// Check joining
if (this.groupId) {
- const joining = await UserGroupJoinings.findOneBy({
+ const joining = await this.userGroupJoiningsRepository.findOneBy({
userId: this.user!.id,
userGroupId: this.groupId,
});
@@ -68,16 +80,16 @@ export default class extends Channel {
switch (type) {
case 'read':
if (this.otherpartyId) {
- readUserMessagingMessage(this.user!.id, this.otherpartyId, [body.id]);
+ this.messagingService.readUserMessagingMessage(this.user!.id, this.otherpartyId, [body.id]);
// リモートユーザーからのメッセージだったら既読配信
- if (Users.isLocalUser(this.user!) && Users.isRemoteUser(this.otherparty!)) {
- MessagingMessages.findOneBy({ id: body.id }).then(message => {
- if (message) deliverReadActivity(this.user as ILocalUser, this.otherparty as IRemoteUser, message);
+ if (this.userEntityService.isLocalUser(this.user!) && this.userEntityService.isRemoteUser(this.otherparty!)) {
+ this.messagingMessagesRepository.findOneBy({ id: body.id }).then(message => {
+ if (message) this.messagingService.deliverReadActivity(this.user as ILocalUser, this.otherparty as IRemoteUser, message);
});
}
} else if (this.groupId) {
- readGroupMessagingMessage(this.user!.id, this.groupId, [body.id]);
+ this.messagingService.readGroupMessagingMessage(this.user!.id, this.groupId, [body.id]);
}
break;
}
@@ -91,7 +103,7 @@ export default class extends Channel {
if (now.getTime() - date.getTime() > 5000) delete this.typers[userId];
}
- const users = await Users.packMany(Object.keys(this.typers), null, { detail: false });
+ const users = await this.userEntityService.packMany(Object.keys(this.typers), null, { detail: false });
this.send({
type: 'typers',
@@ -105,3 +117,36 @@ export default class extends Channel {
clearInterval(this.emitTypersIntervalId);
}
}
+
+@Injectable()
+export class MessagingChannelService {
+ public readonly shouldShare = MessagingChannel.shouldShare;
+ public readonly requireCredential = MessagingChannel.requireCredential;
+
+ constructor(
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+
+ @Inject(DI.userGroupJoiningsRepository)
+ private userGroupJoiningsRepository: UserGroupJoiningsRepository,
+
+ @Inject(DI.messagingMessagesRepository)
+ private messagingMessagesRepository: MessagingMessagesRepository,
+
+ private userEntityService: UserEntityService,
+ private messagingService: MessagingService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): MessagingChannel {
+ return new MessagingChannel(
+ this.usersRepository,
+ this.userGroupJoiningsRepository,
+ this.messagingMessagesRepository,
+ this.userEntityService,
+ this.messagingService,
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/queue-stats.ts b/packages/backend/src/server/api/stream/channels/queue-stats.ts
index b67600474b..1802c6723b 100644
--- a/packages/backend/src/server/api/stream/channels/queue-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/queue-stats.ts
@@ -1,9 +1,10 @@
import Xev from 'xev';
+import { Inject, Injectable } from '@nestjs/common';
import Channel from '../channel.js';
const ev = new Xev();
-export default class extends Channel {
+class QueueStatsChannel extends Channel {
public readonly chName = 'queueStats';
public static shouldShare = true;
public static requireCredential = false;
@@ -40,3 +41,20 @@ export default class extends Channel {
ev.removeListener('queueStats', this.onStats);
}
}
+
+@Injectable()
+export class QueueStatsChannelService {
+ public readonly shouldShare = QueueStatsChannel.shouldShare;
+ public readonly requireCredential = QueueStatsChannel.requireCredential;
+
+ constructor(
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): QueueStatsChannel {
+ return new QueueStatsChannel(
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/server-stats.ts b/packages/backend/src/server/api/stream/channels/server-stats.ts
index db75a6fa38..e2b00de25f 100644
--- a/packages/backend/src/server/api/stream/channels/server-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/server-stats.ts
@@ -1,9 +1,10 @@
import Xev from 'xev';
+import { Inject, Injectable } from '@nestjs/common';
import Channel from '../channel.js';
const ev = new Xev();
-export default class extends Channel {
+class ServerStatsChannel extends Channel {
public readonly chName = 'serverStats';
public static shouldShare = true;
public static requireCredential = false;
@@ -40,3 +41,20 @@ export default class extends Channel {
ev.removeListener('serverStats', this.onStats);
}
}
+
+@Injectable()
+export class ServerStatsChannelService {
+ public readonly shouldShare = ServerStatsChannel.shouldShare;
+ public readonly requireCredential = ServerStatsChannel.requireCredential;
+
+ constructor(
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): ServerStatsChannel {
+ return new ServerStatsChannel(
+ id,
+ connection,
+ );
+ }
+}
diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts
index 97ad2983c5..a45c7d9468 100644
--- a/packages/backend/src/server/api/stream/channels/user-list.ts
+++ b/packages/backend/src/server/api/stream/channels/user-list.ts
@@ -1,10 +1,14 @@
-import Channel from '../channel.js';
-import { Notes, UserListJoinings, UserLists } from '@/models/index.js';
-import { User } from '@/models/entities/user.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { UserListJoiningsRepository, UserListsRepository } from '@/models/index.js';
+import type { NotesRepository } from '@/models/index.js';
+import type { User } from '@/models/entities/User.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { Packed } from '@/misc/schema.js';
+import type { Packed } from '@/misc/schema.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import { DI } from '@/di-symbols.js';
+import Channel from '../channel.js';
-export default class extends Channel {
+class UserListChannel extends Channel {
public readonly chName = 'userList';
public static shouldShare = false;
public static requireCredential = false;
@@ -12,7 +16,14 @@ export default class extends Channel {
public listUsers: User['id'][] = [];
private listUsersClock: NodeJS.Timer;
- constructor(id: string, connection: Channel['connection']) {
+ constructor(
+ private userListsRepository: UserListsRepository,
+ private userListJoiningsRepository: UserListJoiningsRepository,
+ private noteEntityService: NoteEntityService,
+
+ id: string,
+ connection: Channel['connection'],
+ ) {
super(id, connection);
this.updateListUsers = this.updateListUsers.bind(this);
this.onNote = this.onNote.bind(this);
@@ -22,7 +33,7 @@ export default class extends Channel {
this.listId = params.listId as string;
// Check existence and owner
- const list = await UserLists.findOneBy({
+ const list = await this.userListsRepository.findOneBy({
id: this.listId,
userId: this.user!.id,
});
@@ -38,7 +49,7 @@ export default class extends Channel {
}
private async updateListUsers() {
- const users = await UserListJoinings.find({
+ const users = await this.userListJoiningsRepository.find({
where: {
userListId: this.listId,
},
@@ -52,7 +63,7 @@ export default class extends Channel {
if (!this.listUsers.includes(note.userId)) return;
if (['followers', 'specified'].includes(note.visibility)) {
- note = await Notes.pack(note.id, this.user, {
+ note = await this.noteEntityService.pack(note.id, this.user, {
detail: true,
});
@@ -62,13 +73,13 @@ export default class extends Channel {
} else {
// リプライなら再pack
if (note.replyId != null) {
- note.reply = await Notes.pack(note.replyId, this.user, {
+ note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
detail: true,
});
}
// Renoteなら再pack
if (note.renoteId != null) {
- note.renote = await Notes.pack(note.renoteId, this.user, {
+ note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
detail: true,
});
}
@@ -90,3 +101,30 @@ export default class extends Channel {
clearInterval(this.listUsersClock);
}
}
+
+@Injectable()
+export class UserListChannelService {
+ public readonly shouldShare = UserListChannel.shouldShare;
+ public readonly requireCredential = UserListChannel.requireCredential;
+
+ constructor(
+ @Inject(DI.userListsRepository)
+ private userListsRepository: UserListsRepository,
+
+ @Inject(DI.userListJoiningsRepository)
+ private userListJoiningsRepository: UserListJoiningsRepository,
+
+ private noteEntityService: NoteEntityService,
+ ) {
+ }
+
+ public create(id: string, connection: Channel['connection']): UserListChannel {
+ return new UserListChannel(
+ this.userListsRepository,
+ this.userListJoiningsRepository,
+ this.noteEntityService,
+ id,
+ connection,
+ );
+ }
+}