diff --git a/DIFFERENCE.md b/DIFFERENCE.md index 4883d62052..00aab04f23 100755 --- a/DIFFERENCE.md +++ b/DIFFERENCE.md @@ -1,6 +1,5 @@ # DIFFRENCE <<<<<<< HEAD -<<<<<<< HEAD ## 2024.9.0-yami-1.3.1 ## Client - フォロー/フォロワー/アナウンス/みつける/Play/ギャラリー/チャンネル/TL/ユーザー/ノートのページをログイン必須に @@ -10,17 +9,12 @@ ## Feat - ロールで引用通知の設定を制限出来るように -======= ->>>>>>> 3c53bbbac6 (Merge pull request #40 from lqvp/master) ## 2024.9.0-yami-1.2.9 ## Feat - ノート数を隠せるように(連合しません) -<<<<<<< HEAD ======= >>>>>>> 00cf91cf30 (Merge pull request #39 from lqvp/master) -======= ->>>>>>> 3c53bbbac6 (Merge pull request #40 from lqvp/master) ## 2024.9.0-yami-1.2.8 ## Feat - Cherry-Pick アクティビティの非公開機能(hideki0403/kakurega.app) diff --git a/locales/index.d.ts b/locales/index.d.ts index 57facc1d30..7d67454f51 100755 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -3788,10 +3788,6 @@ export interface Locale extends ILocale { * スレッドのミュートを解除 */ "unmuteThread": string; - /** - * ノート数の公開範囲 - */ - "notesVisibility": string; /** * フォローの公開範囲 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index aaae9c65b0..538f93ad75 100755 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -943,7 +943,6 @@ makeReactionsPublicDescription: "あなたがしたリアクション一覧を classic: "クラシック" muteThread: "スレッドをミュート" unmuteThread: "スレッドのミュートを解除" -notesVisibility: "ノート数の公開範囲" followingVisibility: "フォローの公開範囲" followersVisibility: "フォロワーの公開範囲" continueThread: "さらにスレッドを見る" diff --git a/packages/backend/migration/1702718871542-notesvisibility.js b/packages/backend/migration/1702718871542-notesvisibility.js deleted file mode 100644 index 3c0b0ea680..0000000000 --- a/packages/backend/migration/1702718871542-notesvisibility.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export class notesvisibility1702718871542 { - constructor() { - this.name = 'notesvisibility1702718871542'; - } - - async up(queryRunner) { - await queryRunner.query(`CREATE TYPE "public"."user_profile_notesVisibility_enum" AS ENUM('public', 'followers', 'private')`); - await queryRunner.query(`ALTER TABLE "user_profile" ADD "notesVisibility" "public"."user_profile_notesVisibility_enum" NOT NULL DEFAULT 'public'`); - await queryRunner.query(`UPDATE "user_profile" SET "notesVisibility" = 'public'`); - } - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "notesVisibility"`); - await queryRunner.query(`DROP TYPE "public"."user_profile_notesVisibility_enum"`); - } -} - diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts deleted file mode 100644 index 99e3fc3c8f..0000000000 --- a/packages/backend/src/core/WebhookTestService.ts +++ /dev/null @@ -1,436 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js'; -import { bindThis } from '@/decorators.js'; -import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { Packed } from '@/misc/json-schema.js'; -import { type WebhookEventTypes } from '@/models/Webhook.js'; -import { UserWebhookService } from '@/core/UserWebhookService.js'; -import { QueueService } from '@/core/QueueService.js'; - -const oneDayMillis = 24 * 60 * 60 * 1000; - -function generateAbuseReport(override?: Partial): MiAbuseUserReport { - return { - id: 'dummy-abuse-report1', - targetUserId: 'dummy-target-user', - targetUser: null, - reporterId: 'dummy-reporter-user', - reporter: null, - assigneeId: null, - assignee: null, - resolved: false, - forwarded: false, - comment: 'This is a dummy report for testing purposes.', - targetUserHost: null, - reporterHost: null, - ...override, - }; -} - -function generateDummyUser(override?: Partial): MiUser { - return { - id: 'dummy-user-1', - updatedAt: new Date(Date.now() - oneDayMillis * 7), - lastFetchedAt: new Date(Date.now() - oneDayMillis * 5), - lastActiveDate: new Date(Date.now() - oneDayMillis * 3), - hideOnlineStatus: false, - username: 'dummy1', - usernameLower: 'dummy1', - name: 'DummyUser1', - followersCount: 10, - followingCount: 5, - movedToUri: null, - movedAt: null, - alsoKnownAs: null, - notesCount: 30, - avatarId: null, - avatar: null, - bannerId: null, - banner: null, - avatarUrl: null, - bannerUrl: null, - avatarBlurhash: null, - bannerBlurhash: null, - avatarDecorations: [], - tags: [], - isSuspended: false, - isLocked: false, - isBot: false, - isCat: true, - isRoot: false, - isExplorable: true, - isHibernated: false, - isDeleted: false, - emojis: [], - score: 0, - host: null, - inbox: null, - sharedInbox: null, - featured: null, - uri: null, - followersUri: null, - token: null, - ...override, - }; -} - -function generateDummyNote(override?: Partial): MiNote { - return { - id: 'dummy-note-1', - replyId: null, - reply: null, - renoteId: null, - renote: null, - threadId: null, - text: 'This is a dummy note for testing purposes.', - name: null, - cw: null, - userId: 'dummy-user-1', - user: null, - localOnly: true, - reactionAcceptance: 'likeOnly', - renoteCount: 10, - repliesCount: 5, - clippedCount: 0, - reactions: {}, - visibility: 'public', - uri: null, - url: null, - fileIds: [], - attachedFileTypes: [], - visibleUserIds: [], - mentions: [], - mentionedRemoteUsers: '[]', - reactionAndUserPairCache: [], - emojis: [], - tags: [], - hasPoll: false, - channelId: null, - channel: null, - userHost: null, - replyUserId: null, - replyUserHost: null, - renoteUserId: null, - renoteUserHost: null, - ...override, - }; -} - -function toPackedNote(note: MiNote, detail = true, override?: Packed<'Note'>): Packed<'Note'> { - return { - id: note.id, - createdAt: new Date().toISOString(), - deletedAt: null, - text: note.text, - cw: note.cw, - userId: note.userId, - user: toPackedUserLite(note.user ?? generateDummyUser()), - replyId: note.replyId, - renoteId: note.renoteId, - isHidden: false, - visibility: note.visibility, - mentions: note.mentions, - visibleUserIds: note.visibleUserIds, - fileIds: note.fileIds, - files: [], - tags: note.tags, - poll: null, - emojis: note.emojis, - channelId: note.channelId, - channel: note.channel, - localOnly: note.localOnly, - reactionAcceptance: note.reactionAcceptance, - reactionEmojis: {}, - reactions: {}, - reactionCount: 0, - renoteCount: note.renoteCount, - repliesCount: note.repliesCount, - uri: note.uri ?? undefined, - url: note.url ?? undefined, - reactionAndUserPairCache: note.reactionAndUserPairCache, - ...(detail ? { - clippedCount: note.clippedCount, - reply: note.reply ? toPackedNote(note.reply, false) : null, - renote: note.renote ? toPackedNote(note.renote, true) : null, - myReaction: null, - } : {}), - ...override, - }; -} - -function toPackedUserLite(user: MiUser, override?: Packed<'UserLite'>): Packed<'UserLite'> { - return { - id: user.id, - name: user.name, - username: user.username, - host: user.host, - avatarUrl: user.avatarUrl, - avatarBlurhash: user.avatarBlurhash, - avatarDecorations: user.avatarDecorations.map(it => ({ - id: it.id, - angle: it.angle, - flipH: it.flipH, - url: 'https://example.com/dummy-image001.png', - offsetX: it.offsetX, - offsetY: it.offsetY, - })), - isBot: user.isBot, - isCat: user.isCat, - emojis: user.emojis, - onlineStatus: 'active', - badgeRoles: [], - ...override, - }; -} - -function toPackedUserDetailedNotMe(user: MiUser, override?: Packed<'UserDetailedNotMe'>): Packed<'UserDetailedNotMe'> { - return { - ...toPackedUserLite(user), - url: null, - uri: null, - movedTo: null, - alsoKnownAs: [], - createdAt: new Date().toISOString(), - updatedAt: user.updatedAt?.toISOString() ?? null, - lastFetchedAt: user.lastFetchedAt?.toISOString() ?? null, - bannerUrl: user.bannerUrl, - bannerBlurhash: user.bannerBlurhash, - isLocked: user.isLocked, - isSilenced: false, - isSuspended: user.isSuspended, - description: null, - location: null, - birthday: null, - lang: null, - fields: [], - verifiedLinks: [], - followersCount: user.followersCount, - followingCount: user.followingCount, - notesCount: user.notesCount, - pinnedNoteIds: [], - pinnedNotes: [], - pinnedPageId: null, - pinnedPage: null, - publicReactions: true, - notesVisibility: 'public', - followersVisibility: 'public', - followingVisibility: 'public', - twoFactorEnabled: false, - usePasswordLessLogin: false, - securityKeys: false, - roles: [], - memo: null, - moderationNote: undefined, - isFollowing: false, - isFollowed: false, - hasPendingFollowRequestFromYou: false, - hasPendingFollowRequestToYou: false, - isBlocking: false, - isBlocked: false, - isMuted: false, - isRenoteMuted: false, - notify: 'none', - withReplies: true, - ...override, - }; -} - -const dummyUser1 = generateDummyUser(); -const dummyUser2 = generateDummyUser({ - id: 'dummy-user-2', - updatedAt: new Date(Date.now() - oneDayMillis * 30), - lastFetchedAt: new Date(Date.now() - oneDayMillis), - lastActiveDate: new Date(Date.now() - oneDayMillis), - username: 'dummy2', - usernameLower: 'dummy2', - name: 'DummyUser2', - followersCount: 40, - followingCount: 50, - notesCount: 900, -}); -const dummyUser3 = generateDummyUser({ - id: 'dummy-user-3', - updatedAt: new Date(Date.now() - oneDayMillis * 15), - lastFetchedAt: new Date(Date.now() - oneDayMillis * 2), - lastActiveDate: new Date(Date.now() - oneDayMillis * 2), - username: 'dummy3', - usernameLower: 'dummy3', - name: 'DummyUser3', - followersCount: 60, - followingCount: 70, - notesCount: 15900, -}); - -@Injectable() -export class WebhookTestService { - public static NoSuchWebhookError = class extends Error {}; - - constructor( - private userWebhookService: UserWebhookService, - private systemWebhookService: SystemWebhookService, - private queueService: QueueService, - ) { - } - - /** - * UserWebhookのテスト送信を行う. - * 送信されるペイロードはいずれもダミーの値で、実際にはデータベース上に存在しない. - * - * また、この関数経由で送信されるWebhookは以下の設定を無視する. - * - Webhookそのものの有効・無効設定(active) - * - 送信対象イベント(on)に関する設定 - */ - @bindThis - public async testUserWebhook( - params: { - webhookId: MiWebhook['id'], - type: WebhookEventTypes, - override?: Partial>, - }, - sender: MiUser | null, - ) { - const webhooks = await this.userWebhookService.fetchWebhooks({ ids: [params.webhookId] }) - .then(it => it.filter(it => it.userId === sender?.id)); - if (webhooks.length === 0) { - throw new WebhookTestService.NoSuchWebhookError(); - } - - const webhook = webhooks[0]; - const send = (contents: unknown) => { - const merged = { - ...webhook, - ...params.override, - }; - - // テスト目的なのでUserWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図). - // また、Jobの試行回数も1回だけ. - this.queueService.userWebhookDeliver(merged, params.type, contents, { attempts: 1 }); - }; - - const dummyNote1 = generateDummyNote({ - userId: dummyUser1.id, - user: dummyUser1, - }); - const dummyReply1 = generateDummyNote({ - id: 'dummy-reply-1', - replyId: dummyNote1.id, - reply: dummyNote1, - userId: dummyUser1.id, - user: dummyUser1, - }); - const dummyRenote1 = generateDummyNote({ - id: 'dummy-renote-1', - renoteId: dummyNote1.id, - renote: dummyNote1, - userId: dummyUser2.id, - user: dummyUser2, - text: null, - }); - const dummyMention1 = generateDummyNote({ - id: 'dummy-mention-1', - userId: dummyUser1.id, - user: dummyUser1, - text: `@${dummyUser2.username} This is a mention to you.`, - mentions: [dummyUser2.id], - }); - - switch (params.type) { - case 'note': { - send(toPackedNote(dummyNote1)); - break; - } - case 'reply': { - send(toPackedNote(dummyReply1)); - break; - } - case 'renote': { - send(toPackedNote(dummyRenote1)); - break; - } - case 'mention': { - send(toPackedNote(dummyMention1)); - break; - } - case 'follow': { - send(toPackedUserDetailedNotMe(dummyUser1)); - break; - } - case 'followed': { - send(toPackedUserLite(dummyUser2)); - break; - } - case 'unfollow': { - send(toPackedUserDetailedNotMe(dummyUser3)); - break; - } - } - } - - /** - * SystemWebhookのテスト送信を行う. - * 送信されるペイロードはいずれもダミーの値で、実際にはデータベース上に存在しない. - * - * また、この関数経由で送信されるWebhookは以下の設定を無視する. - * - Webhookそのものの有効・無効設定(isActive) - * - 送信対象イベント(on)に関する設定 - */ - @bindThis - public async testSystemWebhook( - params: { - webhookId: MiSystemWebhook['id'], - type: SystemWebhookEventType, - override?: Partial>, - }, - ) { - const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ ids: [params.webhookId] }); - if (webhooks.length === 0) { - throw new WebhookTestService.NoSuchWebhookError(); - } - - const webhook = webhooks[0]; - const send = (contents: unknown) => { - const merged = { - ...webhook, - ...params.override, - }; - - // テスト目的なのでSystemWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図). - // また、Jobの試行回数も1回だけ. - this.queueService.systemWebhookDeliver(merged, params.type, contents, { attempts: 1 }); - }; - - switch (params.type) { - case 'abuseReport': { - send(generateAbuseReport({ - targetUserId: dummyUser1.id, - targetUser: dummyUser1, - reporterId: dummyUser2.id, - reporter: dummyUser2, - })); - break; - } - case 'abuseReportResolved': { - send(generateAbuseReport({ - targetUserId: dummyUser1.id, - targetUser: dummyUser1, - reporterId: dummyUser2.id, - reporter: dummyUser2, - assigneeId: dummyUser3.id, - assignee: dummyUser3, - resolved: true, - })); - break; - } - case 'userCreated': { - send(toPackedUserLite(dummyUser1)); - break; - } - } - } -} diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 3483e9d81a..10b1fc0bf4 100755 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -49,7 +49,6 @@ import type { ApLoggerService } from '../ApLoggerService.js'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import type { ApImageService } from './ApImageService.js'; import type { IActor, ICollection, IObject, IOrderedCollection } from '../type.js'; -import unfavorite from '@/server/api/endpoints/channels/unfavorite.js'; const nameLength = 128; const summaryLength = 2048; @@ -309,16 +308,15 @@ export class ApPersonService implements OnModuleInit { const isBot = getApType(object) === 'Service' || getApType(object) === 'Application'; - const [notesVisibility, followingVisibility, followersVisibility] = await Promise.all( + const [followingVisibility, followersVisibility] = await Promise.all( [ - this.isPublicCollection(person.notes, resolver), this.isPublicCollection(person.following, resolver), this.isPublicCollection(person.followers, resolver), ].map((p): Promise<'public' | 'private'> => p .then(isPublic => isPublic ? 'public' : 'private') .catch(err => { if (!(err instanceof StatusError) || err.isRetryable) { - this.logger.error('error occurred while fetching notes/following/followers collection', { stack: err }); + this.logger.error('error occurred while fetching following/followers collection', { stack: err }); } return 'private'; }) @@ -399,7 +397,6 @@ export class ApPersonService implements OnModuleInit { description: _description, url, fields, - notesVisibility, followingVisibility, followersVisibility, birthday: bday?.[0] ?? null, @@ -510,16 +507,15 @@ export class ApPersonService implements OnModuleInit { const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32); - const [notesVisibility, followingVisibility, followersVisibility] = await Promise.all( + const [followingVisibility, followersVisibility] = await Promise.all( [ - this.isPublicCollection(person.notes, resolver), this.isPublicCollection(person.following, resolver), this.isPublicCollection(person.followers, resolver), ].map((p): Promise<'public' | 'private' | undefined> => p .then(isPublic => isPublic ? 'public' : 'private') .catch(err => { if (!(err instanceof StatusError) || err.isRetryable) { - this.logger.error('error occurred while fetching notes/following/followers collection', { stack: err }); + this.logger.error('error occurred while fetching following/followers collection', { stack: err }); // Do not update the visibiility on transient errors. return undefined; } @@ -599,7 +595,6 @@ export class ApPersonService implements OnModuleInit { url, fields, description: _description, - notesVisibility, followingVisibility, followersVisibility, birthday: bday?.[0] ?? null, diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 7a3e3cd964..2f58825de1 100755 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -185,7 +185,6 @@ export interface IActor extends IObject { id: string; publicKeyPem: string; }; - notes?: string | ICollection | IOrderedCollection; followers?: string | ICollection | IOrderedCollection; following?: string | ICollection | IOrderedCollection; featured?: string | IOrderedCollection; diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index ada891e7d1..a16b2b7d41 100755 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -489,10 +489,6 @@ export class UserEntityService implements OnModuleInit { } const mastoapi = !isDetailed ? opts.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id }) : null; - const notesCount = profile == null ? null : - (profile.notesVisibility === 'public') || isMe || iAmModerator ? user.notesCount : - (profile.notesVisibility === 'followers') && (relation && relation.isFollowing) ? user.notesCount : - null; const followingCount = profile == null ? null : (profile.followingVisibility === 'public') || isMe || iAmModerator ? user.followingCount : @@ -548,7 +544,7 @@ export class UserEntityService implements OnModuleInit { } : undefined) : undefined, followersCount: followersCount ?? 0, followingCount: followingCount ?? 0, - notesCount: notesCount ?? 0, + notesCount: user.notesCount, emojis: this.customEmojiService.populateEmojis(user.emojis, checkHost), onlineStatus: this.getOnlineStatus(user), // パフォーマンス上の理由でローカルユーザーのみ @@ -592,7 +588,6 @@ export class UserEntityService implements OnModuleInit { pinnedPage: profile!.pinnedPageId ? this.pageEntityService.pack(profile!.pinnedPageId, me) : null, publicReactions: this.isLocalUser(user) ? profile!.publicReactions : false, // https://github.com/misskey-dev/misskey/issues/12964 hideActivity: this.isLocalUser(user) ? profile!.hideActivity : false, // - notesVisibility: profile!.notesVisibility, followersVisibility: profile!.followersVisibility, followingVisibility: profile!.followingVisibility, twoFactorEnabled: profile!.twoFactorEnabled, diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts index c8ec48297c..34cc86d49f 100755 --- a/packages/backend/src/models/UserProfile.ts +++ b/packages/backend/src/models/UserProfile.ts @@ -4,7 +4,7 @@ */ import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm'; -import { obsoleteNotificationTypes, notesVisibilities, followingVisibilities, followersVisibilities, notificationTypes } from '@/types.js'; +import { obsoleteNotificationTypes, followingVisibilities, followersVisibilities, notificationTypes } from '@/types.js'; import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiPage } from './Page.js'; @@ -100,12 +100,6 @@ export class MiUserProfile { }) public publicReactions: boolean; - @Column('enum', { - enum: notesVisibilities, - default: 'public', - }) - public notesVisibility: typeof notesVisibilities[number] - @Column('enum', { enum: followingVisibilities, default: 'public', diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 6b8d74df8d..1806c3dace 100755 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -373,11 +373,6 @@ export const packedUserDetailedNotMeOnlySchema = { type: 'boolean', nullable: false, optional: false, }, - notesVisibility: { - type: 'string', - nullable: false, optional: false, - enum: ['public', 'followers', 'private'], - }, followingVisibility: { type: 'string', nullable: false, optional: false, diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 74d0981542..2e940894a5 100755 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -195,7 +195,6 @@ export const paramDef = { receiveAnnouncementEmail: { type: 'boolean' }, alwaysMarkNsfw: { type: 'boolean' }, autoSensitive: { type: 'boolean' }, - notesVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, followingVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, followersVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, pinnedPageId: { type: 'string', format: 'misskey:id', nullable: true }, @@ -290,7 +289,6 @@ export default class extends Endpoint { // eslint- if (ps.location !== undefined) profileUpdates.location = ps.location; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; if (ps.listenbrainz !== undefined) profileUpdates.listenbrainz = ps.listenbrainz; - if (ps.notesVisibility !== undefined) profileUpdates.notesVisibility = ps.notesVisibility; if (ps.followingVisibility !== undefined) profileUpdates.followingVisibility = ps.followingVisibility; if (ps.followersVisibility !== undefined) profileUpdates.followersVisibility = ps.followersVisibility; diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 26d6346271..fc0174d692 100755 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { MiMeta, UsersRepository, NotesRepository, UserProfilesRepository } from '@/models/_.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; @@ -16,9 +16,6 @@ import { MetaService } from '@/core/MetaService.js'; import { MiLocalUser } from '@/models/User.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { FanoutTimelineName } from '@/core/FanoutTimelineService.js'; -import { IsNull } from 'typeorm'; -import { UtilityService } from '@/core/UtilityService.js'; -import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '@/server/api/error.js'; export const meta = { @@ -43,12 +40,6 @@ export const meta = { id: '27e494ba-2ac2-48e8-893b-10d4d8c2387b', }, - forbidden: { - message: 'Forbidden.', - code: 'FORBIDDEN', - id: 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', - }, - bothWithRepliesAndWithFiles: { message: 'Specifying both withReplies and withFiles is not supported', code: 'BOTH_WITH_REPLIES_AND_WITH_FILES', @@ -71,45 +62,22 @@ export const paramDef = { untilDate: { type: 'integer' }, allowPartial: { type: 'boolean', default: false }, // true is recommended but for compatibility false by default withFiles: { type: 'boolean', default: false }, - - username: { type: 'string' }, - host: { - type: 'string', - nullable: true, - description: 'The local host is represented with `null`.', - }, }, - anyOf: [ - { required: ['userId'] }, - { required: ['username', 'host'] }, - ], required: ['userId'], } as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - - @Inject(DI.meta) - private serverSettings: MiMeta, - - @Inject(DI.userProfilesRepository) - private userProfilesRepository: UserProfilesRepository, - @Inject(DI.notesRepository) private notesRepository: NotesRepository, - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - - private utilityService: UtilityService, private noteEntityService: NoteEntityService, private queryService: QueryService, private cacheService: CacheService, private idService: IdService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, private metaService: MetaService, - private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); @@ -120,38 +88,6 @@ export default class extends Endpoint { // eslint- if (ps.withReplies && ps.withFiles) throw new ApiError(meta.errors.bothWithRepliesAndWithFiles); - const user = await this.usersRepository.findOneBy(ps.userId != null - ? { id: ps.userId } - : { usernameLower: ps.username!.toLowerCase(), host: this.utilityService.toPunyNullable(ps.host) ?? IsNull() }); - - if (user == null) { - throw new ApiError(meta.errors.noSuchUser); - } - - const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); - - if (profile.notesVisibility !== 'public' && !await this.roleService.isModerator(me)) { - if (profile.notesVisibility === 'private') { - if (me == null || (me.id !== user.id)) { - throw new ApiError(meta.errors.forbidden); - } - } else if (profile.notesVisibility === 'followers') { - if (me == null) { - throw new ApiError(meta.errors.forbidden); - } else if (me.id !== user.id) { - const isFollowing = await this.notesRepository.exists({ - where: { - followeeId: user.id, - followerId: me.id, - }, - }); - if (!isFollowing) { - throw new ApiError(meta.errors.forbidden); - } - } - } - } - // early return if me is blocked by requesting user if (me != null) { const userIdsWhoBlockingMe = await this.cacheService.userBlockedCache.fetch(me.id); diff --git a/packages/backend/src/server/web/FeedService.ts b/packages/backend/src/server/web/FeedService.ts index 3c2a1cc4aa..8c880baa85 100755 --- a/packages/backend/src/server/web/FeedService.ts +++ b/packages/backend/src/server/web/FeedService.ts @@ -58,21 +58,21 @@ export class FeedService { take: 20, }); - const feed = new Feed({ - id: author.link, - title: `${author.name} (@${user.username}@${this.config.host})`, - updated: notes.length !== 0 ? this.idService.parse(notes[0].id).date : undefined, - generator: 'Misskey', - description: `${(profile.notesVisibility === 'public') ? user.notesCount : '?'} Notes ${profile.followingVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.followersVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`, - link: author.link, - image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), - feedLinks: { - json: `${author.link}.json`, - atom: `${author.link}.atom`, - }, - author, - copyright: user.name ?? user.username, - }); + const feed = new Feed({ + id: author.link, + title: `${author.name} (@${user.username}@${this.config.host})`, + updated: notes.length !== 0 ? this.idService.parse(notes[0].id).date : undefined, + generator: 'Sharkey', + description: `${user.notesCount} Notes, ${profile.followingVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.followersVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`, + link: author.link, + image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), + feedLinks: { + json: `${author.link}.json`, + atom: `${author.link}.atom`, + }, + author, + copyright: user.name ?? user.username, + }); for (const note of notes) { const files = note.fileIds.length > 0 ? await this.driveFilesRepository.findBy({ diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index c3d73c2edb..d83d414096 100755 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -49,7 +49,6 @@ export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const; -export const notesVisibilities = ['public', 'followers', 'private'] as const; export const followingVisibilities = ['public', 'followers', 'private'] as const; export const followersVisibilities = ['public', 'followers', 'private'] as const; diff --git a/packages/frontend/src/components/MkUserInfo.vue b/packages/frontend/src/components/MkUserInfo.vue index 7af4df5d3f..e528f04dfc 100755 --- a/packages/frontend/src/components/MkUserInfo.vue +++ b/packages/frontend/src/components/MkUserInfo.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.noAccountDescription }}
-
+

{{ i18n.ts.notes }}

{{ number(user.notesCount) }}
@@ -40,7 +40,7 @@ import number from '@/filters/number.js'; import { userPage } from '@/filters/user.js'; import { i18n } from '@/i18n.js'; import { $i } from '@/account.js'; -import { isNotesVisibilityForMe, isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; +import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; import { getStaticImageUrl } from '@/scripts/media-proxy.js'; import { defaultStore } from '@/store.js'; diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue index 12cc186442..c6f4699b3e 100755 --- a/packages/frontend/src/components/MkUserPopup.vue +++ b/packages/frontend/src/components/MkUserPopup.vue @@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
{{ i18n.ts.notes }}
{{ number(user.notesCount) }}
@@ -78,7 +78,7 @@ import number from '@/filters/number.js'; import { i18n } from '@/i18n.js'; import { defaultStore } from '@/store.js'; import { $i } from '@/account.js'; -import { isNotesVisibilityForMe, isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; +import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; import { getStaticImageUrl } from '@/scripts/media-proxy.js'; const props = defineProps<{ diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue index c749c8c337..eca135cf30 100755 --- a/packages/frontend/src/pages/settings/privacy.vue +++ b/packages/frontend/src/pages/settings/privacy.vue @@ -22,13 +22,6 @@ SPDX-License-Identifier: AGPL-3.0-only - - - - - - - @@ -110,7 +103,6 @@ const isExplorable = ref($i.isExplorable); const hideOnlineStatus = ref($i.hideOnlineStatus); const publicReactions = ref($i.publicReactions); const hideActivity = ref($i.hideActivity); -const notesVisibility = ref($i.notesVisibility); const followingVisibility = ref($i.followingVisibility); const followersVisibility = ref($i.followersVisibility); @@ -130,7 +122,6 @@ function save() { hideOnlineStatus: !!hideOnlineStatus.value, publicReactions: !!publicReactions.value, hideActivity: !!hideActivity.value, - notesVisibility: notesVisibility.value, followingVisibility: followingVisibility.value, followersVisibility: followersVisibility.value, }); diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index 842c63ba20..e5c428897b 100755 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -103,7 +103,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- + {{ number(user.notesCount) }} {{ i18n.ts.notes }} @@ -186,7 +186,7 @@ import { $i, iAmModerator } from '@/account.js'; import { dateString } from '@/filters/date.js'; import { confetti } from '@/scripts/confetti.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; -import { isNotesVisibilityForMe, isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; +import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; import { useRouter } from '@/router/supplier.js'; import { getStaticImageUrl } from '@/scripts/media-proxy.js'; diff --git a/packages/frontend/src/scripts/isFfVisibleForMe.ts b/packages/frontend/src/scripts/isFfVisibleForMe.ts index b4a7224cd0..e28e5725bc 100755 --- a/packages/frontend/src/scripts/isFfVisibleForMe.ts +++ b/packages/frontend/src/scripts/isFfVisibleForMe.ts @@ -6,14 +6,6 @@ import * as Misskey from 'misskey-js'; import { $i } from '@/account.js'; -export function isNotesVisibilityForMe(user: Misskey.entities.UserDetailed): boolean { - if ($i && ($i.id === user.id || $i.isAdmin || $i.isModerator)) return true; - - if (user.notesVisibility === 'private') return false; - if (user.notesVisibility === 'followers' && !user.isFollowing) return false; - - return true; -} export function isFollowingVisibleForMe(user: Misskey.entities.UserDetailed): boolean { if ($i && ($i.id === user.id || $i.isAdmin || $i.isModerator)) return true; diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 7000ab79df..87fda5568e 100755 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2030,9 +2030,6 @@ type FollowingUpdateRequest = operations['following___update']['requestBody']['c // @public (undocumented) type FollowingUpdateResponse = operations['following___update']['responses']['200']['content']['application/json']; -// @public (undocumented) -export const notesVisibilities: readonly ["public", "followers", "private"]; - // @public (undocumented) export const followingVisibilities: readonly ["public", "followers", "private"]; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index a26cd4a4f5..67c04cc2c2 100755 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -3889,8 +3889,6 @@ export type components = { pinnedPage: components['schemas']['Page'] | null; publicReactions: boolean; hideActivity: boolean; - /** @enum {string} */ - notesVisibility: 'public' | 'followers' | 'private'; /** @enum {string} */ followingVisibility: 'public' | 'followers' | 'private'; /** @enum {string} */ diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index dcb5d26f00..890b43639d 100755 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -22,8 +22,6 @@ export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const; -export const notesVisibilities = ['public', 'followers', 'private'] as const; - export const followingVisibilities = ['public', 'followers', 'private'] as const; export const followersVisibilities = ['public', 'followers', 'private'] as const; diff --git a/packages/misskey-js/src/index.ts b/packages/misskey-js/src/index.ts index 6c569ce381..ace9738e6a 100755 --- a/packages/misskey-js/src/index.ts +++ b/packages/misskey-js/src/index.ts @@ -19,7 +19,6 @@ export const permissions = consts.permissions; export const notificationTypes = consts.notificationTypes; export const noteVisibilities = consts.noteVisibilities; export const mutedNoteReasons = consts.mutedNoteReasons; -export const notesVisibilities = consts.notesVisibilities; export const followingVisibilities = consts.followingVisibilities; export const followersVisibilities = consts.followersVisibilities; export const moderationLogTypes = consts.moderationLogTypes;