From b43de4ecfa1c3a3f95eadf5a481f666e838f1d9b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 24 Sep 2025 20:16:20 +0900 Subject: [PATCH] wip --- locales/ja-JP.yml | 1 + packages/backend/src/models/Notification.ts | 6 +++ .../src/models/json-schema/notification.ts | 15 +++++++ .../backend/src/models/json-schema/user.ts | 1 + .../PostScheduledNoteProcessorService.ts | 18 +++++--- .../server/api/endpoints/admin/show-user.ts | 1 + .../src/server/api/endpoints/i/update.ts | 1 + packages/backend/src/types.ts | 2 + .../src/components/MkNotification.vue | 10 ++++- packages/misskey-js/etc/misskey-js.api.md | 2 +- packages/misskey-js/src/autogen/types.ts | 43 +++++++++++++++++-- packages/misskey-js/src/consts.ts | 1 + 12 files changed, 90 insertions(+), 11 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1767e3da52..d6c4c14c3a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2735,6 +2735,7 @@ _notification: yourFollowRequestAccepted: "フォローリクエストが承認されました" pollEnded: "アンケートの結果が出ました" scheduledNotePosted: "予約ノートが投稿されました" + scheduledNotePostFailed: "予約ノートの投稿に失敗しました" newNote: "新しい投稿" unreadAntennaNote: "アンテナ {name}" roleAssigned: "ロールが付与されました" diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index fffd7fb4c3..7fa17e20fa 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -9,6 +9,7 @@ import { MiNote } from './Note.js'; import { MiAccessToken } from './AccessToken.js'; import { MiRole } from './Role.js'; import { MiDriveFile } from './DriveFile.js'; +import { MiNoteDraft } from './NoteDraft.js'; // misskey-js の notificationTypes と同期すべし export type MiNotification = { @@ -65,6 +66,11 @@ export type MiNotification = { id: string; createdAt: string; noteId: MiNote['id']; +} | { + type: 'scheduledNotePostFailed'; + id: string; + createdAt: string; + noteDraftId: MiNoteDraft['id']; } | { type: 'receiveFollowRequest'; id: string; diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index 8abe385164..30e9c9327a 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -222,6 +222,21 @@ export const packedNotificationSchema = { optional: false, nullable: false, }, }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, + enum: ['scheduledNotePostFailed'], + }, + noteDraft: { + type: 'object', + ref: 'NoteDraft', + optional: false, nullable: false, + }, + }, }, { type: 'object', properties: { diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index a35b336017..b5fd38a7d7 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -610,6 +610,7 @@ export const packedMeDetailedOnlySchema = { reaction: { optional: true, ...notificationRecieveConfig }, pollEnded: { optional: true, ...notificationRecieveConfig }, scheduledNotePosted: { optional: true, ...notificationRecieveConfig }, + scheduledNotePostFailed: { optional: true, ...notificationRecieveConfig }, receiveFollowRequest: { optional: true, ...notificationRecieveConfig }, followRequestAccepted: { optional: true, ...notificationRecieveConfig }, roleAssigned: { optional: true, ...notificationRecieveConfig }, diff --git a/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts b/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts index 4793385990..914fa46e57 100644 --- a/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts +++ b/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts @@ -36,12 +36,20 @@ export class PostScheduledNoteProcessorService { return; } - const note = await this.noteCreateService.create(draft.user, draft); + try { + const note = await this.noteCreateService.create(draft.user, draft); - this.noteDraftsRepository.remove(draft); + // await不要 + this.noteDraftsRepository.remove(draft); - this.notificationService.createNotification(draft.userId, 'scheduledNotePosted', { - noteId: note.id, - }); + // await不要 + this.notificationService.createNotification(draft.userId, 'scheduledNotePosted', { + noteId: note.id, + }); + } catch (err) { + this.notificationService.createNotification(draft.userId, 'scheduledNotePostFailed', { + noteDraftId: draft.id, + }); + } } } diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 7264d10137..2fd7ab8ca2 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -104,6 +104,7 @@ export const meta = { reaction: { optional: true, ...notificationRecieveConfig }, pollEnded: { optional: true, ...notificationRecieveConfig }, scheduledNotePosted: { optional: true, ...notificationRecieveConfig }, + scheduledNotePostFailed: { optional: true, ...notificationRecieveConfig }, receiveFollowRequest: { optional: true, ...notificationRecieveConfig }, followRequestAccepted: { optional: true, ...notificationRecieveConfig }, roleAssigned: { optional: true, ...notificationRecieveConfig }, diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 96619247e0..5c7958fc1c 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -210,6 +210,7 @@ export const paramDef = { reaction: notificationRecieveConfig, pollEnded: notificationRecieveConfig, scheduledNotePosted: notificationRecieveConfig, + scheduledNotePostFailed: notificationRecieveConfig, receiveFollowRequest: notificationRecieveConfig, followRequestAccepted: notificationRecieveConfig, roleAssigned: notificationRecieveConfig, diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index c3ede7afb1..24654b0017 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -13,6 +13,7 @@ * reaction - 投稿にリアクションされた * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * scheduledNotePosted - 予約したノートが投稿された + * scheduledNotePostFailed - 予約したノートの投稿に失敗した * receiveFollowRequest - フォローリクエストされた * followRequestAccepted - 自分の送ったフォローリクエストが承認された * roleAssigned - ロールが付与された @@ -34,6 +35,7 @@ export const notificationTypes = [ 'reaction', 'pollEnded', 'scheduledNotePosted', + 'scheduledNotePostFailed', 'receiveFollowRequest', 'followRequestAccepted', 'roleAssigned', diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index 21df79a98e..45a74e3f02 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -24,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only [$style.t_quote]: notification.type === 'quote', [$style.t_pollEnded]: notification.type === 'pollEnded', [$style.t_scheduledNotePosted]: notification.type === 'scheduledNotePosted', + [$style.t_scheduledNotePostFailed]: notification.type === 'scheduledNotePostFailed', [$style.t_achievementEarned]: notification.type === 'achievementEarned', [$style.t_exportCompleted]: notification.type === 'exportCompleted', [$style.t_login]: notification.type === 'login', @@ -41,6 +42,7 @@ SPDX-License-Identifier: AGPL-3.0-only + @@ -63,6 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._notification.pollEnded }} {{ i18n.ts._notification.scheduledNotePosted }} + {{ i18n.ts._notification.scheduledNotePostFailed }} {{ i18n.ts._notification.newNote }}: {{ i18n.ts._notification.roleAssigned }} {{ i18n.ts._notification.chatRoomInvitationReceived }} @@ -351,6 +354,11 @@ function getActualReactedUsersCount(notification: Misskey.entities.Notification) pointer-events: none; } +.t_scheduledNotePostFailed { + background: var(--eventOther); + pointer-events: none; +} + .t_achievementEarned { background: var(--eventAchievement); pointer-events: none; diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index b117ff4747..c41385e03d 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -3226,7 +3226,7 @@ type Notification_2 = components['schemas']['Notification']; type NotificationsCreateRequest = operations['notifications___create']['requestBody']['content']['application/json']; // @public (undocumented) -export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollEnded", "scheduledNotePosted", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "chatRoomInvitationReceived", "achievementEarned", "exportCompleted", "test", "login", "createToken"]; +export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollEnded", "scheduledNotePosted", "scheduledNotePostFailed", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "chatRoomInvitationReceived", "achievementEarned", "exportCompleted", "test", "login", "createToken"]; // @public (undocumented) export function nyaize(text: string): string; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 27e52267df..a4eb9f1b06 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4168,6 +4168,15 @@ export type components = { /** Format: misskey:id */ userListId: string; }; + scheduledNotePostFailed?: { + /** @enum {string} */ + type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; + } | { + /** @enum {string} */ + type: 'list'; + /** Format: misskey:id */ + userListId: string; + }; receiveFollowRequest?: { /** @enum {string} */ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; @@ -4580,6 +4589,14 @@ export type components = { /** @enum {string} */ type: 'scheduledNotePosted'; note: components['schemas']['Note']; + } | { + /** Format: id */ + id: string; + /** Format: date-time */ + createdAt: string; + /** @enum {string} */ + type: 'scheduledNotePostFailed'; + noteDraft: components['schemas']['NoteDraft']; } | { /** Format: id */ id: string; @@ -11681,6 +11698,15 @@ export interface operations { /** Format: misskey:id */ userListId: string; }; + scheduledNotePostFailed?: { + /** @enum {string} */ + type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; + } | { + /** @enum {string} */ + type: 'list'; + /** Format: misskey:id */ + userListId: string; + }; receiveFollowRequest?: { /** @enum {string} */ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; @@ -25982,8 +26008,8 @@ export interface operations { untilDate?: number; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; @@ -26067,8 +26093,8 @@ export interface operations { untilDate?: number; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; @@ -27351,6 +27377,15 @@ export interface operations { /** Format: misskey:id */ userListId: string; }; + scheduledNotePostFailed?: { + /** @enum {string} */ + type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; + } | { + /** @enum {string} */ + type: 'list'; + /** Format: misskey:id */ + userListId: string; + }; receiveFollowRequest?: { /** @enum {string} */ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never'; diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index b68522cd30..e9f2cb1c31 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -27,6 +27,7 @@ export const notificationTypes = [ 'reaction', 'pollEnded', 'scheduledNotePosted', + 'scheduledNotePostFailed', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited',