diff --git a/DIFFERENCE.md b/DIFFERENCE.md index 6365923051..602c14efbe 100755 --- a/DIFFERENCE.md +++ b/DIFFERENCE.md @@ -1,4 +1,5 @@ # DIFFRENCE +<<<<<<< HEAD ## 2024.9.0-yami-1.3.1 ## Client - フォロー/フォロワー/アナウンス/みつける/Play/ギャラリー/チャンネル/TL/ユーザー/ノートのページをログイン必須に @@ -28,6 +29,8 @@ ### Server - `notes/show`, `users/notes`の認証を不要に(revert?) +======= +>>>>>>> 12828a4aa2 (Merge pull request #35 from lqvp/master) ## 2024.9.0-yami-1.2.5 ### Feat - フォロー解除時にも通知するように diff --git a/locales/en-US.yml b/locales/en-US.yml index 46e72a8ba8..59e87061d7 100755 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -68,6 +68,7 @@ loadMore: "Load more" showMore: "Show more" showLess: "Close" youGotNewFollower: "followed you" +youGotUnFollower: "unfollowed you" receiveFollowRequest: "Follow request received" followRequestAccepted: "Follow request accepted" mention: "Mention" @@ -1884,6 +1885,8 @@ _gallery: _email: _follow: title: "You've got a new follower" + _unfollow: + title: "You have been unfollowed" _receiveFollowRequest: title: "You've received a follow request" _plugin: @@ -2440,6 +2443,7 @@ _notification: youGotQuote: "{name} quoted you" youRenoted: "Boost from {name}" youWereFollowed: "followed you" + youWereUnFollower: "unfollowed you" youReceivedFollowRequest: "You've received a follow request" yourFollowRequestAccepted: "Your follow request was accepted" pollEnded: "Poll results have become available" @@ -2456,12 +2460,14 @@ _notification: likedBySomeUsers: "{n} users liked your note" renotedBySomeUsers: "Boosted by {n} users" followedBySomeUsers: "Followed by {n} users" + unfollowerBySomeUsers: "UnFollowed by {n} users" flushNotification: "Clear notifications" edited: "Note got edited" _types: all: "All" note: "New notes" follow: "New followers" + unfollow: "Unfollowers" mention: "Mentions" reply: "Replies" renote: "Boosts" diff --git a/locales/index.d.ts b/locales/index.d.ts index 7d67454f51..c61abd2520 100755 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -288,6 +288,10 @@ export interface Locale extends ILocale { * フォローされました */ "youGotNewFollower": string; + /** + * フォロー解除されました + */ + "youGotUnFollower": string; /** * フォローリクエストされました */ @@ -7340,6 +7344,12 @@ export interface Locale extends ILocale { */ "title": string; }; + "_unfollow" : { + /** + * フォロー解除されました + */ + "title": string; + } "_receiveFollowRequest": { /** * フォローリクエストを受け取りました @@ -9480,6 +9490,10 @@ export interface Locale extends ILocale { * フォローされました */ "youWereFollowed": string; + /** + * フォロー解除されました + */ + "youWereUnFollower": string; /** * フォローリクエストが来ました */ @@ -9548,6 +9562,10 @@ export interface Locale extends ILocale { * {n}人にフォローされました */ "followedBySomeUsers": ParameterizedString<"n">; + /** + * {n}人にフォロー解除されました + */ + "unfollowerBySomeUser": ParameterizedString<"n">; /** * 通知の履歴をリセットする */ @@ -9565,6 +9583,10 @@ export interface Locale extends ILocale { * フォロー */ "follow": string; + /** + * フォロー解除 + */ + "unfollow": string; /** * メンション */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 538f93ad75..5d4a867cc4 100755 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -68,6 +68,7 @@ loadMore: "もっと見る" showMore: "もっと見る" showLess: "閉じる" youGotNewFollower: "フォローされました" +youGotUnFollower: "フォロー解除されました" receiveFollowRequest: "フォローリクエストされました" followRequestAccepted: "フォローが承認されました" mention: "メンション" @@ -1907,6 +1908,8 @@ _gallery: _email: _follow: title: "フォローされました" + _unfollow: + title: "フォロー解除されました" _receiveFollowRequest: title: "フォローリクエストを受け取りました" @@ -2501,6 +2504,7 @@ _notification: youGotQuote: "{name}による引用" youRenoted: "{name}がBoostしました" youWereFollowed: "フォローされました" + youWereUnFollower: "フォロー解除されました" youReceivedFollowRequest: "フォローリクエストが来ました" yourFollowRequestAccepted: "フォローリクエストが承認されました" pollEnded: "アンケートの結果が出ました" @@ -2518,12 +2522,14 @@ _notification: likedBySomeUsers: "{n}人がいいねしました" renotedBySomeUsers: "{n}人がリノートしました" followedBySomeUsers: "{n}人にフォローされました" + unfollowerBySomeUsers: "{n}人にフォロー解除されました" flushNotification: "通知の履歴をリセットする" _types: all: "すべて" note: "ユーザーの新規投稿" follow: "フォロー" + unfollow: "フォロー解除" mention: "メンション" reply: "リプライ" renote: "Boost" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 1f0ed41e33..58664a5b38 100755 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -66,6 +66,7 @@ loadMore: "まだまだあるで!" showMore: "まだまだあるで!" showLess: "さいなら" youGotNewFollower: "フォローされたで" +youGotUnFollower: "フォロー解除されたで" receiveFollowRequest: "フォローリクエストされたで" followRequestAccepted: "フォローが承認されたで" mention: "メンション" @@ -1806,6 +1807,8 @@ _gallery: _email: _follow: title: "フォローされたで" + _unfollow: + title: "フォロー解除されたで" _receiveFollowRequest: title: "フォローリクエストを受け取ったで" _plugin: @@ -2349,6 +2352,7 @@ _notification: youGotQuote: "{name}による引用" youRenoted: "{name}がブーストしたみたいやで" youWereFollowed: "フォローされたで" + youWereUnFollower: "フォロー解除されたで" youReceivedFollowRequest: "フォロー許可してほしいみたいやな" yourFollowRequestAccepted: "フォローさせてもろたで" pollEnded: "アンケートの結果が出たみたいや" @@ -2365,11 +2369,13 @@ _notification: likedBySomeUsers: "{n}人がいいねしたで" renotedBySomeUsers: "{n}人がブーストしたで" followedBySomeUsers: "{n}人にフォローされたで" + unfollowerBySomeUser: "{n}人にフォロー解除されたで" flushNotification: "通知の履歴をリセットする" _types: all: "すべて" note: "あんたらの新規投稿" follow: "フォロー" + unfollow: "フォロー解除" mention: "メンション" reply: "リプライ" renote: "Renote" diff --git a/packages/backend/assets/tabler-badges/user-minus.png b/packages/backend/assets/tabler-badges/user-minus.png new file mode 100644 index 0000000000..bcec3cf8a9 Binary files /dev/null and b/packages/backend/assets/tabler-badges/user-minus.png differ diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts index 68ad92f396..11deeaa5cb 100755 --- a/packages/backend/src/core/NotificationService.ts +++ b/packages/backend/src/core/NotificationService.ts @@ -179,6 +179,7 @@ export class NotificationService implements OnApplicationShutdown { this.pushNotificationService.pushNotification(notifieeId, 'notification', packed); if (type === 'follow') this.emailNotificationFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: notifierId! })); + if (type === 'unfollow') this.emailNotificationUnFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: notifierId! })); if (type === 'receiveFollowRequest') this.emailNotificationReceiveFollowRequest(notifieeId, await this.usersRepository.findOneByOrFail({ id: notifierId! })); }, () => { /* aborted, ignore it */ }); @@ -202,6 +203,18 @@ export class NotificationService implements OnApplicationShutdown { */ } + @bindThis + private async emailNotificationUnFollow(userId: MiUser['id'], follower: MiUser) { + /* + const userProfile = await UserProfiles.findOneByOrFail({ userId: userId }); + if (!userProfile.email || !userProfile.emailNotificationTypes.includes('follow')) return; + const locale = locales[userProfile.lang ?? 'ja-JP']; + const i18n = new I18n(locale); + // TODO: render user information html + sendEmail(userProfile.email, i18n.t('_email._unfollow.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`); + */ + } + @bindThis private async emailNotificationReceiveFollowRequest(userId: MiUser['id'], follower: MiUser) { /* diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 8cb3c7e720..1d81990d2a 100755 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -431,6 +431,24 @@ export class UserFollowingService implements OnModuleInit { const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower as MiPartialRemoteUser, followee as MiPartialLocalUser), followee)); this.queueService.deliver(followee, content, follower.inbox, false); } + + // UnFollow + if (this.userEntityService.isLocalUser(followee)) { + this.userEntityService.pack(follower.id, followee).then(async packed => { + this.globalEventService.publishMainStream(followee.id, 'unfollow', packed); + + const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === followee.id && x.on.includes('unfollow')); + for (const webhook of webhooks) { + this.queueService.userWebhookDeliver(webhook, 'unfollow', { + user: packed, + }); + } + }); + + // 通知を作成 + this.notificationService.createNotification(followee.id, 'unfollow', { + }, follower.id); + } } @bindThis diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index 4ed71a106c..996ffa2d2a 100755 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -19,6 +19,11 @@ export type MiNotification = { id: string; createdAt: string; notifierId: MiUser['id']; +} | { + type: 'unfollow'; + id: string; + createdAt: string; + notifierId: MiUser['id']; } | { type: 'mention'; id: string; diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index d83d414096..1496606465 100755 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -6,6 +6,7 @@ /** * note - 通知オンにしているユーザーが投稿した * follow - フォローされた + * unfollow - フォロー解除された * mention - 投稿で自分が言及された * reply - 投稿に返信された * renote - 投稿がRenoteされた @@ -22,6 +23,7 @@ export const notificationTypes = [ 'note', 'follow', + 'unfollow', 'mention', 'reply', 'renote', diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index 9948676198..f64cde1e23 100755 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -17,6 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+ @@ -60,7 +62,8 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._notification.roleAssigned }} {{ i18n.ts._notification.achievementEarned }} {{ i18n.ts._notification.testNotification }} - + {{ i18n.tsx._notification.exportOfXCompleted({ x: exportEntityName[notification.exportedEntity] }) }} + {{ i18n.tsx._notification.likedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }} {{ i18n.tsx._notification.reactedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }} {{ i18n.tsx._notification.renotedBySomeUsers({ n: notification.users.length }) }} @@ -106,6 +109,10 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.youGotNewFollower }} {{ i18n.ts.followRequestAccepted }} +