summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-04-08 21:27:21 +0900
committerGitHub <noreply@github.com>2023-04-08 21:27:21 +0900
commita096f621cf5a47c3330935c2b9b5bfe54dfc0091 (patch)
treeb3b6a1a1ce5105091bebc80b96cfd5a73402da80 /packages/backend/src/server/api/endpoints
parentMerge pull request #10402 from misskey-dev/develop (diff)
parent[ci skip] Update CHANGELOG.md (diff)
downloadmisskey-a096f621cf5a47c3330935c2b9b5bfe54dfc0091.tar.gz
misskey-a096f621cf5a47c3330935c2b9b5bfe54dfc0091.tar.bz2
misskey-a096f621cf5a47c3330935c2b9b5bfe54dfc0091.zip
Merge pull request #10506 from misskey-dev/develop
13.11.0
Diffstat (limited to 'packages/backend/src/server/api/endpoints')
-rw-r--r--packages/backend/src/server/api/endpoints/admin/accounts/delete.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts34
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/copy.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts35
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/delete.ts36
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts34
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts30
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts30
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/update.ts46
-rw-r--r--packages/backend/src/server/api/endpoints/admin/suspend-user.ts21
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/notes.ts46
-rw-r--r--packages/backend/src/server/api/endpoints/channels/favorite.ts61
-rw-r--r--packages/backend/src/server/api/endpoints/channels/follow.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/channels/my-favorites.ts54
-rw-r--r--packages/backend/src/server/api/endpoints/channels/show.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/channels/timeline.ts82
-rw-r--r--packages/backend/src/server/api/endpoints/channels/unfavorite.ts56
-rw-r--r--packages/backend/src/server/api/endpoints/channels/unfollow.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/channels/update.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/clips/notes.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/emojis.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/i/known-as.ts92
-rw-r--r--packages/backend/src/server/api/endpoints/i/move.ts140
-rw-r--r--packages/backend/src/server/api/endpoints/i/notifications.ts106
-rw-r--r--packages/backend/src/server/api/endpoints/i/regenerate-token.ts7
-rw-r--r--packages/backend/src/server/api/endpoints/i/revoke-token.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/i/update.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/mute/create.ts18
-rw-r--r--packages/backend/src/server/api/endpoints/mute/delete.ts13
-rw-r--r--packages/backend/src/server/api/endpoints/notes.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/children.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/featured.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/global-timeline.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/notes/local-timeline.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/mentions.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/reactions.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/notes/renotes.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/notes/replies.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/search-by-tag.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/search.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/state.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/notes/timeline.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts22
-rw-r--r--packages/backend/src/server/api/endpoints/notifications/read.ts57
-rw-r--r--packages/backend/src/server/api/endpoints/renote-mute/create.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/renote-mute/delete.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/users/notes.ts8
49 files changed, 597 insertions, 600 deletions
diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
index e9f72676f0..16232813a8 100644
--- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
@@ -61,11 +61,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.usersRepository.update(user.id, {
isDeleted: true,
});
-
- if (this.userEntityService.isLocalUser(user)) {
- // Terminate streaming
- this.globalEventService.publishUserEvent(user.id, 'terminate', {});
- }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts
index 4e4f845b0b..6e604ed885 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts
@@ -1,10 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, In } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -26,38 +22,14 @@ export const paramDef = {
required: ['ids', 'aliases'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- const emojis = await this.emojisRepository.findBy({
- id: In(ps.ids),
- });
-
- for (const emoji of emojis) {
- await this.emojisRepository.update(emoji.id, {
- updatedAt: new Date(),
- aliases: [...new Set(emoji.aliases.concat(ps.aliases))],
- });
- }
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: await this.emojiEntityService.packDetailedMany(ps.ids),
- });
+ await this.customEmojiService.addAliasesBulk(ps.ids, ps.aliases);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
index fea11a67d6..82dca9cc70 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
@@ -90,8 +90,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
license: emoji.license,
}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
this.globalEventService.publishBroadcastStream('emojiAdded', {
emoji: await this.emojiEntityService.packDetailed(copied.id),
});
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
index 84aad020af..9f8263629b 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
@@ -1,11 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, In } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { ModerationLogService } from '@/core/ModerationLogService.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -24,38 +19,14 @@ export const paramDef = {
required: ['ids'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private moderationLogService: ModerationLogService,
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- const emojis = await this.emojisRepository.findBy({
- id: In(ps.ids),
- });
-
- for (const emoji of emojis) {
- await this.emojisRepository.delete(emoji.id);
- await this.db.queryResultCache?.remove(['meta_emojis']);
- this.moderationLogService.insertModerationLog(me, 'deleteEmoji', {
- emoji: emoji,
- });
- }
-
- this.globalEventService.publishBroadcastStream('emojiDeleted', {
- emojis: await this.emojiEntityService.packDetailedMany(emojis),
- });
+ await this.customEmojiService.deleteBulk(ps.ids);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
index 90a5856a1b..429c819fe0 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
@@ -1,12 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { ModerationLogService } from '@/core/ModerationLogService.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
-import { ApiError } from '../../../error.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -31,38 +25,14 @@ export const paramDef = {
required: ['id'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private moderationLogService: ModerationLogService,
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- const emoji = await this.emojisRepository.findOneBy({ id: ps.id });
-
- if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
-
- await this.emojisRepository.delete(emoji.id);
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- this.globalEventService.publishBroadcastStream('emojiDeleted', {
- emojis: [await this.emojiEntityService.packDetailed(emoji)],
- });
-
- this.moderationLogService.insertModerationLog(me, 'deleteEmoji', {
- emoji: emoji,
- });
+ await this.customEmojiService.delete(ps.id);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts
index 3935183502..83f882cac5 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts
@@ -1,10 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, In } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -26,38 +22,14 @@ export const paramDef = {
required: ['ids', 'aliases'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- const emojis = await this.emojisRepository.findBy({
- id: In(ps.ids),
- });
-
- for (const emoji of emojis) {
- await this.emojisRepository.update(emoji.id, {
- updatedAt: new Date(),
- aliases: emoji.aliases.filter(x => !ps.aliases.includes(x)),
- });
- }
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: await this.emojiEntityService.packDetailedMany(ps.ids),
- });
+ await this.customEmojiService.removeAliasesBulk(ps.ids, ps.aliases);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts
index 6a875f9c83..1d3a432bb7 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts
@@ -1,10 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, In } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -26,34 +22,14 @@ export const paramDef = {
required: ['ids', 'aliases'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- await this.emojisRepository.update({
- id: In(ps.ids),
- }, {
- updatedAt: new Date(),
- aliases: ps.aliases,
- });
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: await this.emojiEntityService.packDetailedMany(ps.ids),
- });
+ await this.customEmojiService.setAliasesBulk(ps.ids, ps.aliases);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
index d3b999c0ed..453968c7a9 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
@@ -1,10 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, In } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
@@ -28,34 +24,14 @@ export const paramDef = {
required: ['ids'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- await this.emojisRepository.update({
- id: In(ps.ids),
- }, {
- updatedAt: new Date(),
- category: ps.category,
- });
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: await this.emojiEntityService.packDetailedMany(ps.ids),
- });
+ await this.customEmojiService.setCategoryBulk(ps.ids, ps.category ?? null);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
index bc0475e05c..f63348b60b 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -1,10 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
-import { DataSource, IsNull } from 'typeorm';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { EmojisRepository } from '@/models/index.js';
-import { DI } from '@/di-symbols.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -45,51 +41,19 @@ export const paramDef = {
required: ['id', 'name', 'aliases'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.db)
- private db: DataSource,
-
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
- private emojiEntityService: EmojiEntityService,
- private globalEventService: GlobalEventService,
+ private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- const emoji = await this.emojisRepository.findOneBy({ id: ps.id });
- const sameNameEmoji = await this.emojisRepository.findOneBy({ name: ps.name, host: IsNull() });
- if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
- if (sameNameEmoji != null && sameNameEmoji.id !== ps.id) throw new ApiError(meta.errors.sameNameEmojiExists);
- await this.emojisRepository.update(emoji.id, {
- updatedAt: new Date(),
+ await this.customEmojiService.update(ps.id, {
name: ps.name,
- category: ps.category,
+ category: ps.category ?? null,
aliases: ps.aliases,
- license: ps.license,
+ license: ps.license ?? null,
});
-
- await this.db.queryResultCache?.remove(['meta_emojis']);
-
- const updated = await this.emojiEntityService.packDetailed(emoji.id);
-
- if (emoji.name === ps.name) {
- this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: [updated],
- });
- } else {
- this.globalEventService.publishBroadcastStream('emojiDeleted', {
- emojis: [await this.emojiEntityService.packDetailed(emoji)],
- });
-
- this.globalEventService.publishBroadcastStream('emojiAdded', {
- emoji: updated,
- });
- }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
index 3ad6c7c484..3c99225272 100644
--- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { UsersRepository, FollowingsRepository, NotificationsRepository } from '@/models/index.js';
+import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
import type { User } from '@/models/entities/User.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
@@ -36,9 +36,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.followingsRepository)
private followingsRepository: FollowingsRepository,
- @Inject(DI.notificationsRepository)
- private notificationsRepository: NotificationsRepository,
-
private userEntityService: UserEntityService,
private userFollowingService: UserFollowingService,
private userSuspendService: UserSuspendService,
@@ -65,15 +62,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
targetId: user.id,
});
- // Terminate streaming
- if (this.userEntityService.isLocalUser(user)) {
- this.globalEventService.publishUserEvent(user.id, 'terminate', {});
- }
-
(async () => {
await this.userSuspendService.doPostSuspend(user).catch(e => {});
await this.unFollowAll(user).catch(e => {});
- await this.readAllNotify(user).catch(e => {});
})();
});
}
@@ -96,14 +87,4 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.userFollowingService.unfollow(follower, followee, true);
}
}
-
- @bindThis
- private async readAllNotify(notifier: User) {
- await this.notificationsRepository.update({
- notifierId: notifier.id,
- isRead: false,
- }, {
- isRead: true,
- });
- }
}
diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts
index 039ba1115a..f08c20ae48 100644
--- a/packages/backend/src/server/api/endpoints/antennas/notes.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts
@@ -1,10 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';
+import Redis from 'ioredis';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { NotesRepository, AntennaNotesRepository, AntennasRepository } from '@/models/index.js';
+import type { NotesRepository, AntennasRepository } from '@/models/index.js';
import { QueryService } from '@/core/QueryService.js';
import { NoteReadService } from '@/core/NoteReadService.js';
import { DI } from '@/di-symbols.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import { IdService } from '@/core/IdService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -50,15 +52,16 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
+
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@Inject(DI.antennasRepository)
private antennasRepository: AntennasRepository,
- @Inject(DI.antennaNotesRepository)
- private antennaNotesRepository: AntennaNotesRepository,
-
+ private idService: IdService,
private noteEntityService: NoteEntityService,
private queryService: QueryService,
private noteReadService: NoteReadService,
@@ -73,29 +76,36 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchAntenna);
}
- const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .innerJoin(this.antennaNotesRepository.metadata.targetName, 'antennaNote', 'antennaNote.noteId = note.id')
+ const noteIdsRes = await this.redisClient.xrevrange(
+ `antennaTimeline:${antenna.id}`,
+ ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+',
+ '-',
+ 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1
+
+ if (noteIdsRes.length === 0) {
+ return [];
+ }
+
+ const noteIds = noteIdsRes.map(x => x[1][1]).filter(x => x !== ps.untilId);
+
+ if (noteIds.length === 0) {
+ return [];
+ }
+
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
.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')
- .andWhere('antennaNote.antennaId = :antennaId', { antennaId: antenna.id });
+ .leftJoinAndSelect('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
this.queryService.generateMutedUserQuery(query, me);
this.queryService.generateBlockedUserQuery(query, me);
- const notes = await query
- .take(ps.limit)
- .getMany();
+ const notes = await query.getMany();
+ notes.sort((a, b) => a.id > b.id ? -1 : 1);
if (notes.length > 0) {
this.noteReadService.read(me.id, notes);
diff --git a/packages/backend/src/server/api/endpoints/channels/favorite.ts b/packages/backend/src/server/api/endpoints/channels/favorite.ts
new file mode 100644
index 0000000000..f52b45ccf3
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/channels/favorite.ts
@@ -0,0 +1,61 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/index.js';
+import { IdService } from '@/core/IdService.js';
+import { DI } from '@/di-symbols.js';
+import { ApiError } from '../../error.js';
+
+export const meta = {
+ tags: ['channels'],
+
+ requireCredential: true,
+
+ kind: 'write:channels',
+
+ errors: {
+ noSuchChannel: {
+ message: 'No such channel.',
+ code: 'NO_SUCH_CHANNEL',
+ id: '4938f5f3-6167-4c04-9149-6607b7542861',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ channelId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['channelId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
+
+ @Inject(DI.channelFavoritesRepository)
+ private channelFavoritesRepository: ChannelFavoritesRepository,
+
+ private idService: IdService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
+
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
+
+ await this.channelFavoritesRepository.insert({
+ id: this.idService.genId(),
+ createdAt: new Date(),
+ userId: me.id,
+ channelId: channel.id,
+ });
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts
index 91693918f2..8ab59991c7 100644
--- a/packages/backend/src/server/api/endpoints/channels/follow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/follow.ts
@@ -41,7 +41,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private channelFollowingsRepository: ChannelFollowingsRepository,
private idService: IdService,
- private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
const channel = await this.channelsRepository.findOneBy({
@@ -58,8 +57,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
followerId: me.id,
followeeId: channel.id,
});
-
- this.globalEventService.publishUserEvent(me.id, 'followChannel', channel);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/channels/my-favorites.ts b/packages/backend/src/server/api/endpoints/channels/my-favorites.ts
new file mode 100644
index 0000000000..60525ed060
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/channels/my-favorites.ts
@@ -0,0 +1,54 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import type { ChannelFavoritesRepository } 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'],
+
+ requireCredential: true,
+
+ kind: 'read:channels',
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'Channel',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ },
+ required: [],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelFavoritesRepository)
+ private channelFavoritesRepository: ChannelFavoritesRepository,
+
+ private channelEntityService: ChannelEntityService,
+ private queryService: QueryService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const query = this.channelFavoritesRepository.createQueryBuilder('favorite')
+ .andWhere('favorite.userId = :meId', { meId: me.id })
+ .leftJoinAndSelect('favorite.channel', 'channel');
+
+ const favorites = await query
+ .getMany();
+
+ return await Promise.all(favorites.map(x => this.channelEntityService.pack(x.channel!, me)));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts
index 8718615db2..070d14631e 100644
--- a/packages/backend/src/server/api/endpoints/channels/show.ts
+++ b/packages/backend/src/server/api/endpoints/channels/show.ts
@@ -51,7 +51,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchChannel);
}
- return await this.channelEntityService.pack(channel, me);
+ return await this.channelEntityService.pack(channel, me, true);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index cdaa400137..2556557b24 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -1,10 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';
+import Redis from 'ioredis';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { ChannelsRepository, NotesRepository } from '@/models/index.js';
+import type { ChannelsRepository, Note, 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 { IdService } from '@/core/IdService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -48,12 +50,16 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
+
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@Inject(DI.channelsRepository)
private channelsRepository: ChannelsRepository,
+ private idService: IdService,
private noteEntityService: NoteEntityService,
private queryService: QueryService,
private activeUsersChart: ActiveUsersChart,
@@ -67,30 +73,60 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchChannel);
}
- //#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');
+ let timeline: Note[] = [];
- if (me) {
- this.queryService.generateMutedUserQuery(query, me);
- this.queryService.generateMutedNoteQuery(query, me);
- this.queryService.generateBlockedUserQuery(query, me);
- }
- //#endregion
+ const noteIdsRes = await this.redisClient.xrevrange(
+ `channelTimeline:${channel.id}`,
+ ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+',
+ '-',
+ 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1
+
+ if (noteIdsRes.length === 0) {
+ //#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('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
+
+ if (me) {
+ this.queryService.generateMutedUserQuery(query, me);
+ this.queryService.generateMutedNoteQuery(query, me);
+ this.queryService.generateBlockedUserQuery(query, me);
+ }
+ //#endregion
+
+ timeline = await query.take(ps.limit).getMany();
+ } else {
+ const noteIds = noteIdsRes.map(x => x[1][1]).filter(x => x !== ps.untilId);
- const timeline = await query.take(ps.limit).getMany();
+ if (noteIds.length === 0) {
+ return [];
+ }
+
+ //#region Construct query
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
+
+ if (me) {
+ this.queryService.generateMutedUserQuery(query, me);
+ this.queryService.generateMutedNoteQuery(query, me);
+ this.queryService.generateBlockedUserQuery(query, me);
+ }
+ //#endregion
+
+ timeline = await query.getMany();
+ timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+ }
if (me) this.activeUsersChart.read(me);
diff --git a/packages/backend/src/server/api/endpoints/channels/unfavorite.ts b/packages/backend/src/server/api/endpoints/channels/unfavorite.ts
new file mode 100644
index 0000000000..0c3f6c4855
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/channels/unfavorite.ts
@@ -0,0 +1,56 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/index.js';
+import { DI } from '@/di-symbols.js';
+import { ApiError } from '../../error.js';
+
+export const meta = {
+ tags: ['channels'],
+
+ requireCredential: true,
+
+ kind: 'write:channels',
+
+ errors: {
+ noSuchChannel: {
+ message: 'No such channel.',
+ code: 'NO_SUCH_CHANNEL',
+ id: '353c68dd-131a-476c-aa99-88a345e83668',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ channelId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['channelId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.channelsRepository)
+ private channelsRepository: ChannelsRepository,
+
+ @Inject(DI.channelFavoritesRepository)
+ private channelFavoritesRepository: ChannelFavoritesRepository,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const channel = await this.channelsRepository.findOneBy({
+ id: ps.channelId,
+ });
+
+ if (channel == null) {
+ throw new ApiError(meta.errors.noSuchChannel);
+ }
+
+ await this.channelFavoritesRepository.delete({
+ userId: me.id,
+ channelId: channel.id,
+ });
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
index ac2ef825be..855ba47f8c 100644
--- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
@@ -38,8 +38,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.channelFollowingsRepository)
private channelFollowingsRepository: ChannelFollowingsRepository,
-
- private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
const channel = await this.channelsRepository.findOneBy({
@@ -54,8 +52,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
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 a86cc2565a..084b3f919e 100644
--- a/packages/backend/src/server/api/endpoints/channels/update.ts
+++ b/packages/backend/src/server/api/endpoints/channels/update.ts
@@ -3,8 +3,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import type { 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 { RoleService } from '@/core/RoleService.js';
+import { ApiError } from '../../error.js';
export const meta = {
tags: ['channels'],
@@ -47,6 +47,12 @@ export const paramDef = {
name: { type: 'string', minLength: 1, maxLength: 128 },
description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 },
bannerId: { type: 'string', format: 'misskey:id', nullable: true },
+ pinnedNoteIds: {
+ type: 'array',
+ items: {
+ type: 'string', format: 'misskey:id',
+ },
+ },
},
required: ['channelId'],
} as const;
@@ -64,7 +70,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private channelEntityService: ChannelEntityService,
private roleService: RoleService,
- ) {
+ ) {
super(meta, paramDef, async (ps, me) => {
const channel = await this.channelsRepository.findOneBy({
id: ps.channelId,
@@ -97,6 +103,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.channelsRepository.update(channel.id, {
...(ps.name !== undefined ? { name: ps.name } : {}),
...(ps.description !== undefined ? { description: ps.description } : {}),
+ ...(ps.pinnedNoteIds !== undefined ? { pinnedNoteIds: ps.pinnedNoteIds } : {}),
...(banner ? { bannerId: banner.id } : {}),
});
diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts
index 6818d31cc4..dcb415b752 100644
--- a/packages/backend/src/server/api/endpoints/clips/notes.ts
+++ b/packages/backend/src/server/api/endpoints/clips/notes.ts
@@ -75,16 +75,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.innerJoin(this.clipNotesRepository.metadata.targetName, 'clipNote', 'clipNote.noteId = note.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')
.andWhere('clipNote.clipId = :clipId', { clipId: clip.id });
if (me) {
diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts
index 0711fe4a57..13cc709d31 100644
--- a/packages/backend/src/server/api/endpoints/emojis.ts
+++ b/packages/backend/src/server/api/endpoints/emojis.ts
@@ -58,10 +58,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
category: 'ASC',
name: 'ASC',
},
- cache: {
- id: 'meta_emojis',
- milliseconds: 3600000, // 1 hour
- },
});
return {
diff --git a/packages/backend/src/server/api/endpoints/i/known-as.ts b/packages/backend/src/server/api/endpoints/i/known-as.ts
new file mode 100644
index 0000000000..964704d82b
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/i/known-as.ts
@@ -0,0 +1,92 @@
+import { Injectable } from '@nestjs/common';
+import ms from 'ms';
+
+import { User } from '@/models/entities/User.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ApiError } from '@/server/api/error.js';
+
+import { AccountMoveService } from '@/core/AccountMoveService.js';
+import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { ApiLoggerService } from '@/server/api/ApiLoggerService.js';
+
+export const meta = {
+ tags: ['users'],
+
+ secure: true,
+ requireCredential: true,
+
+ limit: {
+ duration: ms('1day'),
+ max: 30,
+ },
+
+ errors: {
+ noSuchUser: {
+ message: 'No such user.',
+ code: 'NO_SUCH_USER',
+ id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5',
+ },
+ notRemote: {
+ message: 'User is not remote. You can only migrate from other instances.',
+ code: 'NOT_REMOTE',
+ id: '4362f8dc-731f-4ad8-a694-be2a88922a24',
+ },
+ uriNull: {
+ message: 'User ActivityPup URI is null.',
+ code: 'URI_NULL',
+ id: 'bf326f31-d430-4f97-9933-5d61e4d48a23',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ alsoKnownAs: { type: 'string' },
+ },
+ required: ['alsoKnownAs'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ private userEntityService: UserEntityService,
+ private remoteUserResolveService: RemoteUserResolveService,
+ private apiLoggerService: ApiLoggerService,
+ private accountMoveService: AccountMoveService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ // Check parameter
+ if (!ps.alsoKnownAs) throw new ApiError(meta.errors.noSuchUser);
+
+ let unfiltered = ps.alsoKnownAs;
+ const updates = {} as Partial<User>;
+
+ if (!unfiltered) {
+ updates.alsoKnownAs = null;
+ } else {
+ // Parse user's input into the old account
+ if (unfiltered.startsWith('acct:')) unfiltered = unfiltered.substring(5);
+ if (unfiltered.startsWith('@')) unfiltered = unfiltered.substring(1);
+ if (!unfiltered.includes('@')) throw new ApiError(meta.errors.notRemote);
+
+ const userAddress = unfiltered.split('@');
+ // Retrieve the old account
+ const knownAs = await this.remoteUserResolveService.resolveUser(userAddress[0], userAddress[1]).catch((e) => {
+ this.apiLoggerService.logger.warn(`failed to resolve remote user: ${e}`);
+ throw new ApiError(meta.errors.noSuchUser);
+ });
+
+ const toUrl: string | null = knownAs.uri;
+ if (!toUrl) throw new ApiError(meta.errors.uriNull);
+ // Only allow moving from a remote account
+ if (this.userEntityService.isLocalUser(knownAs)) throw new ApiError(meta.errors.notRemote);
+
+ updates.alsoKnownAs = updates.alsoKnownAs?.concat([toUrl]) ?? [toUrl];
+ }
+
+ return await this.accountMoveService.createAlias(me, updates);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts
new file mode 100644
index 0000000000..ac76e1f620
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/i/move.ts
@@ -0,0 +1,140 @@
+import { Inject, Injectable } from '@nestjs/common';
+import ms from 'ms';
+
+import type { Config } from '@/config.js';
+import { DI } from '@/di-symbols.js';
+
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ApiError } from '@/server/api/error.js';
+
+import { AccountMoveService } from '@/core/AccountMoveService.js';
+import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { ApiLoggerService } from '@/server/api/ApiLoggerService.js';
+import { GetterService } from '@/server/api/GetterService.js';
+import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
+
+export const meta = {
+ tags: ['users'],
+
+ secure: true,
+ requireCredential: true,
+ limit: {
+ duration: ms('1day'),
+ max: 5,
+ },
+
+ errors: {
+ noSuchMoveTarget: {
+ message: 'No such move target.',
+ code: 'NO_SUCH_MOVE_TARGET',
+ id: 'b5c90186-4ab0-49c8-9bba-a1f76c202ba4',
+ },
+ remoteAccountForbids: {
+ message:
+ 'Remote account doesn\'t have proper \'Known As\' alias. Did you remember to set it?',
+ code: 'REMOTE_ACCOUNT_FORBIDS',
+ id: 'b5c90186-4ab0-49c8-9bba-a1f766282ba4',
+ },
+ notRemote: {
+ message: 'User is not remote. You can only migrate to other instances.',
+ code: 'NOT_REMOTE',
+ id: '4362f8dc-731f-4ad8-a694-be2a88922a24',
+ },
+ rootForbidden: {
+ message: 'The root can\'t migrate.',
+ code: 'NOT_ROOT_FORBIDDEN',
+ id: '4362e8dc-731f-4ad8-a694-be2a88922a24',
+ },
+ noSuchUser: {
+ message: 'No such user.',
+ code: 'NO_SUCH_USER',
+ id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5',
+ },
+ uriNull: {
+ message: 'User ActivityPup URI is null.',
+ code: 'URI_NULL',
+ id: 'bf326f31-d430-4f97-9933-5d61e4d48a23',
+ },
+ localUriNull: {
+ message: 'Local User ActivityPup URI is null.',
+ code: 'URI_NULL',
+ id: '95ba11b9-90e8-43a5-ba16-7acc1ab32e71',
+ },
+ alreadyMoved: {
+ message: 'Account was already moved to another account.',
+ code: 'ALREADY_MOVED',
+ id: 'b234a14e-9ebe-4581-8000-074b3c215962',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ moveToAccount: { type: 'string' },
+ },
+ required: ['moveToAccount'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.config)
+ private config: Config,
+
+ private userEntityService: UserEntityService,
+ private remoteUserResolveService: RemoteUserResolveService,
+ private apiLoggerService: ApiLoggerService,
+ private accountMoveService: AccountMoveService,
+ private getterService: GetterService,
+ private apPersonService: ApPersonService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ // check parameter
+ if (!ps.moveToAccount) throw new ApiError(meta.errors.noSuchMoveTarget);
+ // abort if user is the root
+ if (me.isRoot) throw new ApiError(meta.errors.rootForbidden);
+ // abort if user has already moved
+ if (me.movedToUri) throw new ApiError(meta.errors.alreadyMoved);
+
+ let unfiltered = ps.moveToAccount;
+ if (!unfiltered) throw new ApiError(meta.errors.noSuchMoveTarget);
+
+ // parse user's input into the destination account
+ if (unfiltered.startsWith('acct:')) unfiltered = unfiltered.substring(5);
+ if (unfiltered.startsWith('@')) unfiltered = unfiltered.substring(1);
+ if (!unfiltered.includes('@')) throw new ApiError(meta.errors.notRemote);
+
+ const userAddress = unfiltered.split('@');
+ // retrieve the destination account
+ let moveTo = await this.remoteUserResolveService.resolveUser(userAddress[0], userAddress[1]).catch((e) => {
+ this.apiLoggerService.logger.warn(`failed to resolve remote user: ${e}`);
+ throw new ApiError(meta.errors.noSuchMoveTarget);
+ });
+ const remoteMoveTo = await this.getterService.getRemoteUser(moveTo.id);
+ if (!remoteMoveTo.uri) throw new ApiError(meta.errors.uriNull);
+
+ // update local db
+ await this.apPersonService.updatePerson(remoteMoveTo.uri);
+ // retrieve updated user
+ moveTo = await this.apPersonService.resolvePerson(remoteMoveTo.uri);
+ // only allow moving to a remote account
+ if (this.userEntityService.isLocalUser(moveTo)) throw new ApiError(meta.errors.notRemote);
+
+ let allowed = false;
+
+ const fromUrl = `${this.config.url}/users/${me.id}`;
+ // make sure that the user has indicated the old account as an alias
+ moveTo.alsoKnownAs?.forEach((elem) => {
+ if (fromUrl.includes(elem)) allowed = true;
+ });
+
+ // abort if unintended
+ if (!(allowed && moveTo.uri && fromUrl)) throw new ApiError(meta.errors.remoteAccountForbids);
+
+ return await this.accountMoveService.moveToRemote(me, moveTo);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts
index e3897d38bd..f27b4e86d4 100644
--- a/packages/backend/src/server/api/endpoints/i/notifications.ts
+++ b/packages/backend/src/server/api/endpoints/i/notifications.ts
@@ -1,6 +1,7 @@
-import { Brackets } from 'typeorm';
+import { Brackets, In } from 'typeorm';
+import Redis from 'ioredis';
import { Inject, Injectable } from '@nestjs/common';
-import type { UsersRepository, FollowingsRepository, MutingsRepository, UserProfilesRepository, NotificationsRepository } from '@/models/index.js';
+import type { UsersRepository, FollowingsRepository, MutingsRepository, UserProfilesRepository, NotesRepository } from '@/models/index.js';
import { obsoleteNotificationTypes, notificationTypes } from '@/types.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
@@ -8,6 +9,8 @@ import { NoteReadService } from '@/core/NoteReadService.js';
import { NotificationEntityService } from '@/core/entities/NotificationEntityService.js';
import { NotificationService } from '@/core/NotificationService.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
+import { Notification } from '@/models/entities/Notification.js';
export const meta = {
tags: ['account', 'notifications'],
@@ -38,8 +41,6 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
- following: { type: 'boolean', default: false },
- unreadOnly: { type: 'boolean', default: false },
markAsRead: { type: 'boolean', default: true },
// 後方互換のため、廃止された通知タイプも受け付ける
includeTypes: { type: 'array', items: {
@@ -56,21 +57,22 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
+
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
- @Inject(DI.followingsRepository)
- private followingsRepository: FollowingsRepository,
-
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
- @Inject(DI.notificationsRepository)
- private notificationsRepository: NotificationsRepository,
+ @Inject(DI.notesRepository)
+ private notesRepository: NotesRepository,
+ private idService: IdService,
private notificationEntityService: NotificationEntityService,
private notificationService: NotificationService,
private queryService: QueryService,
@@ -89,85 +91,39 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const includeTypes = ps.includeTypes && ps.includeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][];
const excludeTypes = ps.excludeTypes && ps.excludeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][];
- const followingQuery = this.followingsRepository.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: me.id });
-
- const mutingQuery = this.mutingsRepository.createQueryBuilder('muting')
- .select('muting.muteeId')
- .where('muting.muterId = :muterId', { muterId: me.id });
-
- const mutingInstanceQuery = this.userProfilesRepository.createQueryBuilder('user_profile')
- .select('user_profile.mutedInstances')
- .where('user_profile.userId = :muterId', { muterId: me.id });
-
- const suspendedQuery = this.usersRepository.createQueryBuilder('users')
- .select('users.id')
- .where('users.isSuspended = TRUE');
-
- const query = this.queryService.makePaginationQuery(this.notificationsRepository.createQueryBuilder('notification'), ps.sinceId, ps.untilId)
- .andWhere('notification.notifieeId = :meId', { meId: me.id })
- .leftJoinAndSelect('notification.notifier', 'notifier')
- .leftJoinAndSelect('notification.note', 'note')
- .leftJoinAndSelect('notifier.avatar', 'notifierAvatar')
- .leftJoinAndSelect('notifier.banner', 'notifierBanner')
- .leftJoinAndSelect('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');
-
- // muted users
- query.andWhere(new Brackets(qb => { qb
- .where(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`)
- .orWhere('notification.notifierId IS NULL');
- }));
- query.setParameters(mutingQuery.getParameters());
+ const notificationsRes = await this.redisClient.xrevrange(
+ `notificationTimeline:${me.id}`,
+ ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+',
+ '-',
+ 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1
- // muted instances
- query.andWhere(new Brackets(qb => { qb
- .andWhere('notifier.host IS NULL')
- .orWhere(`NOT (( ${mutingInstanceQuery.getQuery()} )::jsonb ? notifier.host)`);
- }));
- query.setParameters(mutingInstanceQuery.getParameters());
-
- // suspended users
- query.andWhere(new Brackets(qb => { qb
- .where(`notification.notifierId NOT IN (${ suspendedQuery.getQuery() })`)
- .orWhere('notification.notifierId IS NULL');
- }));
-
- if (ps.following) {
- query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: me.id });
- query.setParameters(followingQuery.getParameters());
+ if (notificationsRes.length === 0) {
+ return [];
}
+ let notifications = notificationsRes.map(x => JSON.parse(x[1][1])).filter(x => x.id !== ps.untilId) as Notification[];
+
if (includeTypes && includeTypes.length > 0) {
- query.andWhere('notification.type IN (:...includeTypes)', { includeTypes });
+ notifications = notifications.filter(notification => includeTypes.includes(notification.type));
} else if (excludeTypes && excludeTypes.length > 0) {
- query.andWhere('notification.type NOT IN (:...excludeTypes)', { excludeTypes });
+ notifications = notifications.filter(notification => !excludeTypes.includes(notification.type));
}
- if (ps.unreadOnly) {
- query.andWhere('notification.isRead = false');
+ if (notifications.length === 0) {
+ return [];
}
- const notifications = await query.take(ps.limit).getMany();
-
// Mark all as read
- if (notifications.length > 0 && ps.markAsRead) {
- this.notificationService.readNotification(me.id, notifications.map(x => x.id));
+ if (ps.markAsRead) {
+ this.notificationService.readAllNotification(me.id);
}
- const notes = notifications.filter(notification => ['mention', 'reply', 'quote'].includes(notification.type)).map(notification => notification.note!);
+ const noteIds = notifications
+ .filter(notification => ['mention', 'reply', 'quote'].includes(notification.type))
+ .map(notification => notification.noteId!);
- if (notes.length > 0) {
+ if (noteIds.length > 0) {
+ const notes = await this.notesRepository.findBy({ id: In(noteIds) });
this.noteReadService.read(me.id, notes);
}
diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
index f942f43cc8..23ff63f5e9 100644
--- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
+++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
@@ -34,7 +34,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
) {
super(meta, paramDef, async (ps, me) => {
const freshUser = await this.usersRepository.findOneByOrFail({ id: me.id });
- const oldToken = freshUser.token;
+ const oldToken = freshUser.token!;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
@@ -54,11 +54,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
// Publish event
this.globalEventService.publishInternalEvent('userTokenRegenerated', { id: me.id, oldToken, newToken });
this.globalEventService.publishMainStream(me.id, 'myTokenRegenerated');
-
- // Terminate streaming
- setTimeout(() => {
- this.globalEventService.publishUserEvent(me.id, 'terminate', {});
- }, 5000);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
index 5e1dddb6b7..93daeb0cd7 100644
--- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts
+++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
@@ -35,9 +35,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
id: ps.tokenId,
userId: me.id,
});
-
- // Terminate streaming
- this.globalEventService.publishUserEvent(me.id, 'terminate');
}
});
}
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index b1eaab3908..be1c72b207 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -18,6 +18,8 @@ import { AccountUpdateService } from '@/core/AccountUpdateService.js';
import { HashtagService } from '@/core/HashtagService.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
+import { CacheService } from '@/core/CacheService.js';
+import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -147,11 +149,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private pagesRepository: PagesRepository,
private userEntityService: UserEntityService,
+ private driveFileEntityService: DriveFileEntityService,
private globalEventService: GlobalEventService,
private userFollowingService: UserFollowingService,
private accountUpdateService: AccountUpdateService,
private hashtagService: HashtagService,
private roleService: RoleService,
+ private cacheService: CacheService,
) {
super(meta, paramDef, async (ps, _user, token) => {
const user = await this.usersRepository.findOneByOrFail({ id: _user.id });
@@ -168,8 +172,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (ps.location !== undefined) profileUpdates.location = ps.location;
if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility;
- if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
- if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
if (ps.mutedWords !== undefined) {
// TODO: ちゃんと数える
const length = JSON.stringify(ps.mutedWords).length;
@@ -215,6 +217,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar);
if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage);
+
+ updates.avatarId = avatar.id;
+ updates.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
+ updates.avatarBlurhash = avatar.blurhash;
}
if (ps.bannerId) {
@@ -222,6 +228,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner);
if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage);
+
+ updates.bannerId = banner.id;
+ updates.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
+ updates.bannerBlurhash = banner.blurhash;
}
if (ps.pinnedPageId) {
@@ -276,9 +286,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
includeSecrets: isSecure,
});
+ const updatedProfile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
+
+ this.cacheService.userProfileCache.set(user.id, updatedProfile);
+
// Publish meUpdated event
this.globalEventService.publishMainStream(user.id, 'meUpdated', iObj);
- this.globalEventService.publishUserEvent(user.id, 'updateUserProfile', await this.userProfilesRepository.findOneByOrFail({ userId: user.id }));
// 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
if (user.isLocked && ps.isLocked === false) {
diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts
index 9099eea52e..6e24e1024d 100644
--- a/packages/backend/src/server/api/endpoints/mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/mute/create.ts
@@ -1,12 +1,10 @@
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import { IdService } from '@/core/IdService.js';
import type { MutingsRepository } from '@/models/index.js';
-import type { Muting } from '@/models/entities/Muting.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { GetterService } from '@/server/api/GetterService.js';
+import { UserMutingService } from '@/core/UserMutingService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -62,9 +60,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
- private globalEventService: GlobalEventService,
private getterService: GetterService,
- private idService: IdService,
+ private userMutingService: UserMutingService,
) {
super(meta, paramDef, async (ps, me) => {
const muter = me;
@@ -94,16 +91,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
return;
}
- // Create mute
- await this.mutingsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
- expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null,
- muterId: muter.id,
- muteeId: mutee.id,
- } as Muting);
-
- this.globalEventService.publishUserEvent(me.id, 'mute', mutee);
+ await this.userMutingService.mute(muter, mutee, ps.expiresAt ? new Date(ps.expiresAt) : null);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts
index 612c4a4c04..90b74590be 100644
--- a/packages/backend/src/server/api/endpoints/mute/delete.ts
+++ b/packages/backend/src/server/api/endpoints/mute/delete.ts
@@ -1,10 +1,10 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { MutingsRepository } from '@/models/index.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
-import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
+import { UserMutingService } from '@/core/UserMutingService.js';
+import { ApiError } from '../../error.js';
export const meta = {
tags: ['account'],
@@ -49,7 +49,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
- private globalEventService: GlobalEventService,
+ private userMutingService: UserMutingService,
private getterService: GetterService,
) {
super(meta, paramDef, async (ps, me) => {
@@ -76,12 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.notMuting);
}
- // Delete mute
- await this.mutingsRepository.delete({
- id: exist.id,
- });
-
- this.globalEventService.publishUserEvent(me.id, 'unmute', mutee);
+ await this.userMutingService.unmute([exist]);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts
index 0a8f2292ac..5fbc7aba58 100644
--- a/packages/backend/src/server/api/endpoints/notes.ts
+++ b/packages/backend/src/server/api/endpoints/notes.ts
@@ -49,16 +49,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.andWhere('note.visibility = \'public\'')
.andWhere('note.localOnly = FALSE')
.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('renote.user', 'renoteUser');
if (ps.local) {
query.andWhere('note.userHost IS NULL');
diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts
index ea7a825f9d..26f2d6772d 100644
--- a/packages/backend/src/server/api/endpoints/notes/children.ts
+++ b/packages/backend/src/server/api/endpoints/notes/children.ts
@@ -57,16 +57,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}));
}))
.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) {
diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts
index 6bf17b222a..bdb06498bc 100644
--- a/packages/backend/src/server/api/endpoints/notes/featured.ts
+++ b/packages/backend/src/server/api/endpoints/notes/featured.ts
@@ -53,16 +53,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.andWhere('note.createdAt > :date', { date: new Date(Date.now() - day) })
.andWhere('note.visibility = \'public\'')
.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('renote.user', 'renoteUser');
if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId });
diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
index 9118d33936..c11c1eac40 100644
--- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
@@ -73,16 +73,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.andWhere('note.visibility = \'public\'')
.andWhere('note.channelId IS NULL')
.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('renote.user', 'renoteUser');
this.queryService.generateRepliesQuery(query, me);
if (me) {
diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
index 8a7ec65ab4..89abd91c7e 100644
--- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -91,16 +91,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
}))
.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')
.setParameters(followingQuery.getParameters());
this.queryService.generateChannelQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
index 8c1c07a9f4..afdafc7c55 100644
--- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
@@ -80,16 +80,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
.andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
.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('renote.user', 'renoteUser');
this.queryService.generateChannelQuery(query, me);
this.queryService.generateRepliesQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts
index dcb0d0adcb..4e9f604d8d 100644
--- a/packages/backend/src/server/api/endpoints/notes/mentions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts
@@ -60,16 +60,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.orWhere(`'{"${me.id}"}' <@ note.visibleUserIds`);
}))
.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
this.queryService.generateMutedUserQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts
index f758bfe9b1..4772c4f809 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts
@@ -75,7 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
order: {
id: -1,
},
- relations: ['user', 'user.avatar', 'user.banner', 'note'],
+ relations: ['user', 'note'],
});
return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me)));
diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts
index 026a1baa3e..d406855660 100644
--- a/packages/backend/src/server/api/endpoints/notes/renotes.ts
+++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts
@@ -4,8 +4,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js';
-import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
+import { ApiError } from '../../error.js';
export const meta = {
tags: ['notes'],
@@ -62,16 +62,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere('note.renoteId = :renoteId', { renoteId: note.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts
index 4df95962c8..f2af71d55f 100644
--- a/packages/backend/src/server/api/endpoints/notes/replies.ts
+++ b/packages/backend/src/server/api/endpoints/notes/replies.ts
@@ -46,16 +46,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere('note.replyId = :replyId', { replyId: ps.noteId })
.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
index da1a4bcc46..2956bf1cbd 100644
--- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
@@ -71,16 +71,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts
index 5db5b6267f..fb5abd917f 100644
--- a/packages/backend/src/server/api/endpoints/notes/search.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search.ts
@@ -85,16 +85,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
query
.andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` })
.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) this.queryService.generateMutedUserQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notes/state.ts b/packages/backend/src/server/api/endpoints/notes/state.ts
index d0036f0fb7..93517ab10c 100644
--- a/packages/backend/src/server/api/endpoints/notes/state.ts
+++ b/packages/backend/src/server/api/endpoints/notes/state.ts
@@ -59,7 +59,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
this.noteThreadMutingsRepository.count({
where: {
userId: me.id,
- threadId: note.threadId || note.id,
+ threadId: note.threadId ?? note.id,
},
take: 1,
}),
diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts
index d9e72d2603..c6ee1e5c2b 100644
--- a/packages/backend/src/server/api/endpoints/notes/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts
@@ -70,16 +70,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
.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('renote.user', 'renoteUser');
if (followees.length > 0) {
const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)];
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index 9b23103fd4..afc9bc4213 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -84,16 +84,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.innerJoin(this.userListJoiningsRepository.metadata.targetName, 'userListJoining', 'userListJoining.userId = note.userId')
.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')
.andWhere('userListJoining.userListId = :userListId', { userListId: list.id });
this.queryService.generateVisibilityQuery(query, me);
diff --git a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
index 09134cf48f..e601bf9d5b 100644
--- a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
+++ b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
@@ -1,9 +1,7 @@
import { Inject, Injectable } from '@nestjs/common';
-import type { NotificationsRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
-import { PushNotificationService } from '@/core/PushNotificationService.js';
import { DI } from '@/di-symbols.js';
+import { NotificationService } from '@/core/NotificationService.js';
export const meta = {
tags: ['notifications', 'account'],
@@ -23,24 +21,10 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
- @Inject(DI.notificationsRepository)
- private notificationsRepository: NotificationsRepository,
-
- private globalEventService: GlobalEventService,
- private pushNotificationService: PushNotificationService,
+ private notificationService: NotificationService,
) {
super(meta, paramDef, async (ps, me) => {
- // Update documents
- await this.notificationsRepository.update({
- notifieeId: me.id,
- isRead: false,
- }, {
- isRead: true,
- });
-
- // 全ての通知を読みましたよというイベントを発行
- this.globalEventService.publishMainStream(me.id, 'readAllNotifications');
- this.pushNotificationService.pushNotification(me.id, 'readAllNotifications', undefined);
+ this.notificationService.readAllNotification(me.id, true);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notifications/read.ts b/packages/backend/src/server/api/endpoints/notifications/read.ts
deleted file mode 100644
index 6262c47fd0..0000000000
--- a/packages/backend/src/server/api/endpoints/notifications/read.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Injectable } from '@nestjs/common';
-import { Endpoint } from '@/server/api/endpoint-base.js';
-import { NotificationService } from '@/core/NotificationService.js';
-
-export const meta = {
- tags: ['notifications', 'account'],
-
- requireCredential: true,
-
- kind: 'write:notifications',
-
- description: 'Mark a notification as read.',
-
- errors: {
- noSuchNotification: {
- message: 'No such notification.',
- code: 'NO_SUCH_NOTIFICATION',
- id: 'efa929d5-05b5-47d1-beec-e6a4dbed011e',
- },
- },
-} as const;
-
-export const paramDef = {
- oneOf: [
- {
- type: 'object',
- properties: {
- notificationId: { type: 'string', format: 'misskey:id' },
- },
- required: ['notificationId'],
- },
- {
- type: 'object',
- properties: {
- notificationIds: {
- type: 'array',
- items: { type: 'string', format: 'misskey:id' },
- maxItems: 100,
- },
- },
- required: ['notificationIds'],
- },
- ],
-} as const;
-
-// eslint-disable-next-line import/no-default-export
-@Injectable()
-export default class extends Endpoint<typeof meta, typeof paramDef> {
- constructor(
- private notificationService: NotificationService,
- ) {
- super(meta, paramDef, async (ps, me) => {
- if ('notificationId' in ps) return this.notificationService.readNotification(me.id, [ps.notificationId]);
- return this.notificationService.readNotification(me.id, ps.notificationIds);
- });
- }
-}
diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
index 051a005b67..b285269617 100644
--- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
@@ -92,8 +92,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
muterId: muter.id,
muteeId: mutee.id,
} as RenoteMuting);
-
- // publishUserEvent(user.id, 'mute', mutee);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts
index 51a895fb7e..70901a1406 100644
--- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts
+++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts
@@ -80,8 +80,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.renoteMutingsRepository.delete({
id: exist.id,
});
-
- // publishUserEvent(user.id, 'unmute', mutee);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts
index aab32cc58c..aaf94734a3 100644
--- a/packages/backend/src/server/api/endpoints/users/notes.ts
+++ b/packages/backend/src/server/api/endpoints/users/notes.ts
@@ -74,16 +74,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.userId = :userId', { userId: user.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('renote.user', 'renoteUser');
this.queryService.generateVisibilityQuery(query, me);
if (me) {