summaryrefslogtreecommitdiff
path: root/packages/backend/src
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2024-10-22 17:08:53 +0900
committerGitHub <noreply@github.com>2024-10-22 17:08:53 +0900
commit952fec5665ce0712a78f3ee68f5c46554426dfb4 (patch)
tree425f640754d83b01aaa447996363fe703f45d47a /packages/backend/src
parentfix(frontend): /iのレスポンスに含まれないプロパティが消え... (diff)
downloadsharkey-952fec5665ce0712a78f3ee68f5c46554426dfb4.tar.gz
sharkey-952fec5665ce0712a78f3ee68f5c46554426dfb4.tar.bz2
sharkey-952fec5665ce0712a78f3ee68f5c46554426dfb4.zip
feat: 過去のノートを非公開化/フォロワーのみ表示可能にできる機能 (#14814)
* wip * Update CHANGELOG.md * wip * wip * wip * Update privacy.vue * wip
Diffstat (limited to 'packages/backend/src')
-rw-r--r--packages/backend/src/core/WebhookTestService.ts2
-rw-r--r--packages/backend/src/core/activitypub/ApRendererService.ts2
-rw-r--r--packages/backend/src/core/activitypub/misc/contexts.ts2
-rw-r--r--packages/backend/src/core/activitypub/models/ApPersonService.ts2
-rw-r--r--packages/backend/src/core/activitypub/type.ts2
-rw-r--r--packages/backend/src/core/entities/NoteEntityService.ts99
-rw-r--r--packages/backend/src/core/entities/UserEntityService.ts2
-rw-r--r--packages/backend/src/models/User.ts12
-rw-r--r--packages/backend/src/models/json-schema/user.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/i/update.ts4
10 files changed, 99 insertions, 36 deletions
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index 254d961040..c826a28963 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -84,6 +84,8 @@ function generateDummyUser(override?: Partial<MiUser>): MiUser {
isHibernated: false,
isDeleted: false,
requireSigninToViewContents: false,
+ makeNotesFollowersOnlyBefore: null,
+ makeNotesHiddenBefore: null,
emojis: [],
score: 0,
host: null,
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index 8235d7ba30..5617a29bab 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -496,6 +496,8 @@ export class ApRendererService {
_misskey_summary: profile.description,
_misskey_followedMessage: profile.followedMessage,
_misskey_requireSigninToViewContents: user.requireSigninToViewContents,
+ _misskey_makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore,
+ _misskey_makeNotesHiddenBefore: user.makeNotesHiddenBefore,
icon: avatar ? this.renderImage(avatar) : null,
image: banner ? this.renderImage(banner) : null,
tag,
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 447f7ef3db..94cb0785cb 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -556,6 +556,8 @@ const extension_context_definition = {
'_misskey_summary': 'misskey:_misskey_summary',
'_misskey_followedMessage': 'misskey:_misskey_followedMessage',
'_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents',
+ '_misskey_makeNotesFollowersOnlyBefore': 'misskey:_misskey_makeNotesFollowersOnlyBefore',
+ '_misskey_makeNotesHiddenBefore': 'misskey:_misskey_makeNotesHiddenBefore',
'isCat': 'misskey:isCat',
// vcard
vcard: 'http://www.w3.org/2006/vcard/ns#',
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index c7915ed94f..0e2934301b 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -357,6 +357,8 @@ export class ApPersonService implements OnModuleInit {
isBot,
isCat: (person as any).isCat === true,
requireSigninToViewContents: (person as any).requireSigninToViewContents === true,
+ makeNotesFollowersOnlyBefore: (person as any).makeNotesFollowersOnlyBefore ?? null,
+ makeNotesHiddenBefore: (person as any).makeNotesHiddenBefore ?? null,
emojis,
})) as MiRemoteUser;
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 8a860335fa..7496315f09 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -15,6 +15,8 @@ export interface IObject {
_misskey_summary?: string;
_misskey_followedMessage?: string | null;
_misskey_requireSigninToViewContents?: boolean;
+ _misskey_makeNotesFollowersOnlyBefore?: number | null;
+ _misskey_makeNotesHiddenBefore?: number | null;
published?: string;
cc?: ApObject;
to?: ApObject;
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 62016936a2..96cc6b028e 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -102,57 +102,83 @@ export class NoteEntityService implements OnModuleInit {
}
@bindThis
- private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null) {
+ private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<void> {
+ // FIXME: このvisibility変更処理が当関数にあるのは若干不自然かもしれない(関数名を treatVisibility とかに変える手もある)
+ if (packedNote.visibility === 'public' || packedNote.visibility === 'home') {
+ const followersOnlyBefore = packedNote.user.makeNotesFollowersOnlyBefore;
+ if ((followersOnlyBefore != null)
+ && (
+ (followersOnlyBefore <= 0 && (Date.now() - new Date(packedNote.createdAt).getTime() > 0 - (followersOnlyBefore * 1000)))
+ || (followersOnlyBefore > 0 && (new Date(packedNote.createdAt).getTime() < followersOnlyBefore * 1000))
+ )
+ ) {
+ packedNote.visibility = 'followers';
+ }
+ }
+
+ if (meId === packedNote.userId) return;
+
// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
let hide = false;
- // visibility が specified かつ自分が指定されていなかったら非表示
- if (packedNote.visibility === 'specified') {
- if (meId == null) {
+ if (packedNote.user.requireSigninToViewContents && meId == null) {
+ hide = true;
+ }
+
+ if (!hide) {
+ const hiddenBefore = packedNote.user.makeNotesHiddenBefore;
+ if ((hiddenBefore != null)
+ && (
+ (hiddenBefore <= 0 && (Date.now() - new Date(packedNote.createdAt).getTime() > 0 - (hiddenBefore * 1000)))
+ || (hiddenBefore > 0 && (new Date(packedNote.createdAt).getTime() < hiddenBefore * 1000))
+ )
+ ) {
hide = true;
- } else if (meId === packedNote.userId) {
- hide = false;
- } else {
- // 指定されているかどうか
- const specified = packedNote.visibleUserIds!.some(id => meId === id);
+ }
+ }
- if (specified) {
- hide = false;
- } else {
+ // visibility が specified かつ自分が指定されていなかったら非表示
+ if (!hide) {
+ if (packedNote.visibility === 'specified') {
+ if (meId == null) {
hide = true;
+ } else {
+ // 指定されているかどうか
+ const specified = packedNote.visibleUserIds!.some(id => meId === id);
+
+ if (!specified) {
+ hide = true;
+ }
}
}
}
// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
- if (packedNote.visibility === 'followers') {
- if (meId == null) {
- hide = true;
- } else if (meId === packedNote.userId) {
- hide = false;
- } else if (packedNote.reply && (meId === packedNote.reply.userId)) {
- // 自分の投稿に対するリプライ
- hide = false;
- } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
- // 自分へのメンション
- hide = false;
- } else {
- // フォロワーかどうか
- const isFollowing = await this.followingsRepository.exists({
- where: {
- followeeId: packedNote.userId,
- followerId: meId,
- },
- });
+ if (!hide) {
+ if (packedNote.visibility === 'followers') {
+ if (meId == null) {
+ hide = true;
+ } else if (packedNote.reply && (meId === packedNote.reply.userId)) {
+ // 自分の投稿に対するリプライ
+ hide = false;
+ } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
+ // 自分へのメンション
+ hide = false;
+ } else {
+ // フォロワーかどうか
+ // TODO: 当関数呼び出しごとにクエリが走るのは重そうだからなんとかする
+ const isFollowing = await this.followingsRepository.exists({
+ where: {
+ followeeId: packedNote.userId,
+ followerId: meId,
+ },
+ });
- hide = !isFollowing;
+ hide = !isFollowing;
+ }
}
}
- if (packedNote.user.requireSigninToViewContents && meId == null) {
- hide = true;
- }
-
if (hide) {
packedNote.visibleUserIds = undefined;
packedNote.fileIds = [];
@@ -161,6 +187,7 @@ export class NoteEntityService implements OnModuleInit {
packedNote.poll = undefined;
packedNote.cw = null;
packedNote.isHidden = true;
+ // TODO: hiddenReason みたいなのを提供しても良さそう
}
}
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index 747ffc780f..d3c087a153 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -491,6 +491,8 @@ export class UserEntityService implements OnModuleInit {
isBot: user.isBot,
isCat: user.isCat,
requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true,
+ makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore ?? undefined,
+ makeNotesHiddenBefore: user.makeNotesHiddenBefore ?? undefined,
instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? {
name: instance.name,
softwareName: instance.softwareName,
diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts
index 6fcff77854..96de30c4c2 100644
--- a/packages/backend/src/models/User.ts
+++ b/packages/backend/src/models/User.ts
@@ -207,6 +207,18 @@ export class MiUser {
})
public requireSigninToViewContents: boolean;
+ // in sec, マイナスで相対時間
+ @Column('integer', {
+ nullable: true,
+ })
+ public makeNotesFollowersOnlyBefore: number | null;
+
+ // in sec, マイナスで相対時間
+ @Column('integer', {
+ nullable: true,
+ })
+ public makeNotesHiddenBefore: number | null;
+
// アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ
@Column('boolean', {
default: false,
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index 817f8e9292..38631f907d 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -119,6 +119,14 @@ export const packedUserLiteSchema = {
type: 'boolean',
nullable: false, optional: true,
},
+ makeNotesFollowersOnlyBefore: {
+ type: 'number',
+ nullable: true, optional: true,
+ },
+ makeNotesHiddenBefore: {
+ type: 'number',
+ nullable: true, optional: true,
+ },
instance: {
type: 'object',
nullable: false, optional: true,
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 6680c96f3f..2183beac7c 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -180,6 +180,8 @@ export const paramDef = {
noCrawle: { type: 'boolean' },
preventAiLearning: { type: 'boolean' },
requireSigninToViewContents: { type: 'boolean' },
+ makeNotesFollowersOnlyBefore: { type: 'integer', nullable: true },
+ makeNotesHiddenBefore: { type: 'integer', nullable: true },
isBot: { type: 'boolean' },
isCat: { type: 'boolean' },
injectFeaturedNote: { type: 'boolean' },
@@ -336,6 +338,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning;
if (typeof ps.requireSigninToViewContents === 'boolean') updates.requireSigninToViewContents = ps.requireSigninToViewContents;
+ if ((typeof ps.makeNotesFollowersOnlyBefore === 'number') || (ps.makeNotesFollowersOnlyBefore === null)) updates.makeNotesFollowersOnlyBefore = ps.makeNotesFollowersOnlyBefore;
+ if ((typeof ps.makeNotesHiddenBefore === 'number') || (ps.makeNotesHiddenBefore === null)) updates.makeNotesHiddenBefore = ps.makeNotesHiddenBefore;
if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;