summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints/channels
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/api/endpoints/channels')
-rw-r--r--packages/backend/src/server/api/endpoints/channels/create.ts67
-rw-r--r--packages/backend/src/server/api/endpoints/channels/featured.ts31
-rw-r--r--packages/backend/src/server/api/endpoints/channels/follow.ts54
-rw-r--r--packages/backend/src/server/api/endpoints/channels/followed.ts36
-rw-r--r--packages/backend/src/server/api/endpoints/channels/owned.ts36
-rw-r--r--packages/backend/src/server/api/endpoints/channels/show.ts35
-rw-r--r--packages/backend/src/server/api/endpoints/channels/timeline.ts80
-rw-r--r--packages/backend/src/server/api/endpoints/channels/unfollow.ts47
-rw-r--r--packages/backend/src/server/api/endpoints/channels/update.ts80
9 files changed, 301 insertions, 165 deletions
diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts
index 94dcfe5023..21979884f9 100644
--- a/packages/backend/src/server/api/endpoints/channels/create.ts
+++ b/packages/backend/src/server/api/endpoints/channels/create.ts
@@ -1,8 +1,11 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelsRepository, DriveFilesRepository } from '@/models/index.js';
+import type { Channel } from '@/models/entities/Channel.js';
+import { IdService } from '@/core/IdService.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Channels, DriveFiles } from '@/models/index.js';
-import { Channel } from '@/models/entities/channel.js';
-import { genId } from '@/misc/gen-id.js';
export const meta = {
tags: ['channels'],
@@ -37,27 +40,41 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, user) => {
- let banner = null;
- if (ps.bannerId != null) {
- banner = await DriveFiles.findOneBy({
- id: ps.bannerId,
- userId: user.id,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.driveFilesRepository)
+ private driveFilesRepository: DriveFilesRepository,
- if (banner == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- }
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
+
+ private idService: IdService,
+ private channelEntityService: ChannelEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ let banner = null;
+ if (ps.bannerId != null) {
+ banner = await this.driveFilesRepository.findOneBy({
+ id: ps.bannerId,
+ userId: me.id,
+ });
- const channel = await Channels.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- description: ps.description || null,
- bannerId: banner ? banner.id : null,
- } as Channel).then(x => Channels.findOneByOrFail(x.identifiers[0]));
+ if (banner == null) {
+ throw new ApiError(meta.errors.noSuchFile);
+ }
+ }
- return await Channels.pack(channel, user);
-});
+ const channel = await this.channelsRepository.insert({
+ id: this.idService.genId(),
+ createdAt: new Date(),
+ userId: me.id,
+ name: ps.name,
+ description: ps.description ?? null,
+ bannerId: banner ? banner.id : null,
+ } as Channel).then(x => this.channelsRepository.findOneByOrFail(x.identifiers[0]));
+
+ return await this.channelEntityService.pack(channel, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts
index 73980c0fad..0c3f9509d1 100644
--- a/packages/backend/src/server/api/endpoints/channels/featured.ts
+++ b/packages/backend/src/server/api/endpoints/channels/featured.ts
@@ -1,5 +1,8 @@
-import define from '../../define.js';
-import { Channels } from '@/models/index.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelsRepository } from '@/models/index.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
export const meta = {
tags: ['channels'],
@@ -24,12 +27,22 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, me) => {
- const query = Channels.createQueryBuilder('channel')
- .where('channel.lastNotedAt IS NOT NULL')
- .orderBy('channel.lastNotedAt', 'DESC');
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- const channels = await query.take(10).getMany();
+ private channelEntityService: ChannelEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const query = this.channelsRepository.createQueryBuilder('channel')
+ .where('channel.lastNotedAt IS NOT NULL')
+ .orderBy('channel.lastNotedAt', 'DESC');
- return await Promise.all(channels.map(x => Channels.pack(x, me)));
-});
+ const channels = await query.take(10).getMany();
+
+ return await Promise.all(channels.map(x => this.channelEntityService.pack(x, me)));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts
index 895ffed0bd..6c6b498a94 100644
--- a/packages/backend/src/server/api/endpoints/channels/follow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/follow.ts
@@ -1,8 +1,10 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelFollowingsRepository, ChannelsRepository } from '@/models/index.js';
+import { IdService } from '@/core/IdService.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Channels, ChannelFollowings } from '@/models/index.js';
-import { genId } from '@/misc/gen-id.js';
-import { publishUserEvent } from '@/services/stream.js';
export const meta = {
tags: ['channels'],
@@ -29,21 +31,35 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, user) => {
- const channel = await Channels.findOneBy({
- id: ps.channelId,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
+ @Inject(DI.channelFollowingsRepository)
+ private channelFollowingsRepository: ChannelFollowingsRepository,
+
+ private idService: IdService,
+ private globalEventService: GlobalEventService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await Channels.findOneBy({
+ id: ps.channelId,
+ });
- await ChannelFollowings.insert({
- id: genId(),
- createdAt: new Date(),
- followerId: user.id,
- followeeId: channel.id,
- });
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
- publishUserEvent(user.id, 'followChannel', channel);
-});
+ await this.channelFollowingsRepository.insert({
+ id: this.idService.genId(),
+ createdAt: new Date(),
+ followerId: me.id,
+ followeeId: channel.id,
+ });
+
+ this.globalEventService.publishUserEvent(me.id, 'followChannel', channel);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/followed.ts b/packages/backend/src/server/api/endpoints/channels/followed.ts
index e4aa4d1614..5a8ab26af9 100644
--- a/packages/backend/src/server/api/endpoints/channels/followed.ts
+++ b/packages/backend/src/server/api/endpoints/channels/followed.ts
@@ -1,6 +1,9 @@
-import define from '../../define.js';
-import { Channels, ChannelFollowings } from '@/models/index.js';
-import { makePaginationQuery } from '../../common/make-pagination-query.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelFollowingsRepository } from '@/models/index.js';
+import { QueryService } from '@/core/QueryService.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
export const meta = {
tags: ['channels', 'account'],
@@ -31,13 +34,24 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, me) => {
- const query = makePaginationQuery(ChannelFollowings.createQueryBuilder(), ps.sinceId, ps.untilId)
- .andWhere({ followerId: me.id });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelFollowingsRepository)
+ private channelFollowingsRepository: ChannelFollowingsRepository,
- const followings = await query
- .take(ps.limit)
- .getMany();
+ private channelEntityService: ChannelEntityService,
+ private queryService: QueryService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const query = this.queryService.makePaginationQuery(this.channelFollowingsRepository.createQueryBuilder(), ps.sinceId, ps.untilId)
+ .andWhere({ followerId: me.id });
- return await Promise.all(followings.map(x => Channels.pack(x.followeeId, me)));
-});
+ const followings = await query
+ .take(ps.limit)
+ .getMany();
+
+ return await Promise.all(followings.map(x => this.channelEntityService.pack(x.followeeId, me)));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/owned.ts b/packages/backend/src/server/api/endpoints/channels/owned.ts
index ed7e41cac2..8b8b5819e6 100644
--- a/packages/backend/src/server/api/endpoints/channels/owned.ts
+++ b/packages/backend/src/server/api/endpoints/channels/owned.ts
@@ -1,6 +1,9 @@
-import define from '../../define.js';
-import { Channels } from '@/models/index.js';
-import { makePaginationQuery } from '../../common/make-pagination-query.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelsRepository } from '@/models/index.js';
+import { QueryService } from '@/core/QueryService.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
export const meta = {
tags: ['channels', 'account'],
@@ -31,13 +34,24 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, me) => {
- const query = makePaginationQuery(Channels.createQueryBuilder(), ps.sinceId, ps.untilId)
- .andWhere({ userId: me.id });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- const channels = await query
- .take(ps.limit)
- .getMany();
+ private channelEntityService: ChannelEntityService,
+ private queryService: QueryService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const query = this.queryService.makePaginationQuery(this.channelsRepository.createQueryBuilder(), ps.sinceId, ps.untilId)
+ .andWhere({ userId: me.id });
- return await Promise.all(channels.map(x => Channels.pack(x, me)));
-});
+ const channels = await query
+ .take(ps.limit)
+ .getMany();
+
+ return await Promise.all(channels.map(x => this.channelEntityService.pack(x, me)));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts
index 87665a9865..54ae31790b 100644
--- a/packages/backend/src/server/api/endpoints/channels/show.ts
+++ b/packages/backend/src/server/api/endpoints/channels/show.ts
@@ -1,6 +1,9 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelsRepository } from '@/models/index.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Channels } from '@/models/index.js';
export const meta = {
tags: ['channels'],
@@ -31,14 +34,24 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, me) => {
- const channel = await Channels.findOneBy({
- id: ps.channelId,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
+ private channelEntityService: ChannelEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
+
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
- return await Channels.pack(channel, me);
-});
+ return await this.channelEntityService.pack(channel, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index deaa299013..1c7f1360b9 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -1,8 +1,11 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelsRepository, NotesRepository } from '@/models/index.js';
+import { QueryService } from '@/core/QueryService.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import ActiveUsersChart from '@/core/chart/charts/active-users.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Notes, Channels } from '@/models/index.js';
-import { makePaginationQuery } from '../../common/make-pagination-query.js';
-import { activeUsersChart } from '@/services/chart/index.js';
export const meta = {
tags: ['notes', 'channels'],
@@ -42,35 +45,50 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, user) => {
- const channel = await Channels.findOneBy({
- id: ps.channelId,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.notesRepository)
+ private notesRepository: NotesRepository,
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
+
+ private noteEntityService: NoteEntityService,
+ private queryService: QueryService,
+ private activeUsersChart: ActiveUsersChart,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
- //#region Construct query
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere('note.channelId = :channelId', { channelId: channel.id })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('user.avatar', 'avatar')
- .leftJoinAndSelect('user.banner', 'banner')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
- .leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
- .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
- .leftJoinAndSelect('note.channel', 'channel');
- //#endregion
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
- const timeline = await query.take(ps.limit).getMany();
+ //#region Construct query
+ const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .andWhere('note.channelId = :channelId', { channelId: channel.id })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('user.avatar', 'avatar')
+ .leftJoinAndSelect('user.banner', 'banner')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
+ .leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
+ .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
+ .leftJoinAndSelect('note.channel', 'channel');
+ //#endregion
- if (user) activeUsersChart.read(user);
+ const timeline = await query.take(ps.limit).getMany();
- return await Notes.packMany(timeline, user);
-});
+ if (me) this.activeUsersChart.read(me);
+
+ return await this.noteEntityService.packMany(timeline, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
index e065d897a5..b464c55097 100644
--- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
@@ -1,7 +1,9 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ChannelFollowingsRepository, ChannelsRepository } from '@/models/index.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Channels, ChannelFollowings } from '@/models/index.js';
-import { publishUserEvent } from '@/services/stream.js';
export const meta = {
tags: ['channels'],
@@ -28,19 +30,32 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, user) => {
- const channel = await Channels.findOneBy({
- id: ps.channelId,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
+ @Inject(DI.channelFollowingsRepository)
+ private channelFollowingsRepository: ChannelFollowingsRepository,
+
+ private globalEventService: GlobalEventService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
- await ChannelFollowings.delete({
- followerId: user.id,
- followeeId: channel.id,
- });
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
- publishUserEvent(user.id, 'unfollowChannel', channel);
-});
+ await this.channelFollowingsRepository.delete({
+ followerId: me.id,
+ followeeId: channel.id,
+ });
+
+ this.globalEventService.publishUserEvent(me.id, 'unfollowChannel', channel);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts
index 13104f324f..ba62e9d371 100644
--- a/packages/backend/src/server/api/endpoints/channels/update.ts
+++ b/packages/backend/src/server/api/endpoints/channels/update.ts
@@ -1,6 +1,9 @@
-import define from '../../define.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DriveFilesRepository, ChannelsRepository } from '@/models/index.js';
+import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
+import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
-import { Channels, DriveFiles } from '@/models/index.js';
export const meta = {
tags: ['channels'],
@@ -48,39 +51,52 @@ export const paramDef = {
} as const;
// eslint-disable-next-line import/no-default-export
-export default define(meta, paramDef, async (ps, me) => {
- const channel = await Channels.findOneBy({
- id: ps.channelId,
- });
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
+ @Inject(DI.driveFilesRepository)
+ private driveFilesRepository: DriveFilesRepository,
- if (channel.userId !== me.id) {
- throw new ApiError(meta.errors.accessDenied);
- }
+ private channelEntityService: ChannelEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
- // eslint:disable-next-line:no-unnecessary-initializer
- let banner = undefined;
- if (ps.bannerId != null) {
- banner = await DriveFiles.findOneBy({
- id: ps.bannerId,
- userId: me.id,
- });
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
- if (banner == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- } else if (ps.bannerId === null) {
- banner = null;
- }
+ if (channel.userId !== me.id) {
+ throw new ApiError(meta.errors.accessDenied);
+ }
- await Channels.update(channel.id, {
- ...(ps.name !== undefined ? { name: ps.name } : {}),
- ...(ps.description !== undefined ? { description: ps.description } : {}),
- ...(banner ? { bannerId: banner.id } : {}),
- });
+ // eslint:disable-next-line:no-unnecessary-initializer
+ let banner = undefined;
+ if (ps.bannerId != null) {
+ banner = await this.driveFilesRepository.findOneBy({
+ id: ps.bannerId,
+ userId: me.id,
+ });
- return await Channels.pack(channel.id, me);
-});
+ if (banner == null) {
+ throw new ApiError(meta.errors.noSuchFile);
+ }
+ } else if (ps.bannerId === null) {
+ banner = null;
+ }
+
+ await this.channelsRepository.update(channel.id, {
+ ...(ps.name !== undefined ? { name: ps.name } : {}),
+ ...(ps.description !== undefined ? { description: ps.description } : {}),
+ ...(banner ? { bannerId: banner.id } : {}),
+ });
+
+ return await this.channelEntityService.pack(channel.id, me);
+ });
+ }
+}