diff --git a/docs/downgrade.sql b/docs/downgrade.sql index 4600a4b4c6..174c64bc9c 100644 --- a/docs/downgrade.sql +++ b/docs/downgrade.sql @@ -36,10 +36,13 @@ DELETE FROM "migrations" WHERE name IN ( 'AddMastodonSubscriptionType1715181461692' ); +-- addMastodonSubscriptionType +ALTER TABLE "sw_subscription" DROP COLUMN "subscriptionTypes"; +DROP TYPE "push_subscription_type"; + -- sw-subscription-per-access-token ALTER TABLE "sw_subscription" DROP CONSTRAINT "FK_98a1aa2db2a5253924f42f38767"; ALTER TABLE "sw_subscription" DROP COLUMN "appAccessTokenId"; -ALTER TABLE "sw_subscription" DROP COLUMN "subscriptionTypes"; -- user-profile-mentions ALTER TABLE "user_profile" DROP COLUMN "mentions"; diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 32788917b7..b96e4e9812 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -1151,6 +1151,18 @@ export enum PollNoteVisibility { Public = 'public', Specified = 'specified' } +export enum PushSubscriptionType { + AdminReport = 'adminReport', + AdminSignUp = 'adminSignUp', + Favourite = 'favourite', + Follow = 'follow', + FollowRequest = 'followRequest', + Mention = 'mention', + Poll = 'poll', + Reblog = 'reblog', + Status = 'status', + Update = 'update' +} export enum RelayStatus { Accepted = 'accepted', Rejected = 'rejected', @@ -1198,7 +1210,7 @@ export interface SwSubscription { publickey: string sendReadMessage: boolean appAccessTokenId: string | null - subscriptionTypes: Array + subscriptionTypes: Array } export interface UsedUsername { username: string diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index c377b8e34f..987b74aafc 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,7 +310,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, Protocol, Inbound, Outbound, greet, initializeRustLogger, showServerInfo, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, sqlRegexEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isQuote, isSafeUrl, latestVersion, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, cpuInfo, cpuUsage, memoryUsage, storageUsage, AntennaSrc, DriveFileUsageHint, MutedNoteReason, NoteVisibility, NotificationType, PageVisibility, PollNoteVisibility, RelayStatus, UserEmojiModPerm, UserProfileFfvisibility, UserProfileMutingNotificationTypes, updateAntennasOnNewNote, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, generateSecureRandomString, generateUserToken } = nativeBinding +const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, Protocol, Inbound, Outbound, greet, initializeRustLogger, showServerInfo, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, sqlRegexEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isQuote, isSafeUrl, latestVersion, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, cpuInfo, cpuUsage, memoryUsage, storageUsage, AntennaSrc, DriveFileUsageHint, MutedNoteReason, NoteVisibility, NotificationType, PageVisibility, PollNoteVisibility, PushSubscriptionType, RelayStatus, UserEmojiModPerm, UserProfileFfvisibility, UserProfileMutingNotificationTypes, updateAntennasOnNewNote, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, generateSecureRandomString, generateUserToken } = nativeBinding module.exports.SECOND = SECOND module.exports.MINUTE = MINUTE @@ -372,6 +372,7 @@ module.exports.NoteVisibility = NoteVisibility module.exports.NotificationType = NotificationType module.exports.PageVisibility = PageVisibility module.exports.PollNoteVisibility = PollNoteVisibility +module.exports.PushSubscriptionType = PushSubscriptionType module.exports.RelayStatus = RelayStatus module.exports.UserEmojiModPerm = UserEmojiModPerm module.exports.UserProfileFfvisibility = UserProfileFfvisibility diff --git a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs index c25618ef3a..a46a5aa010 100644 --- a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs +++ b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs @@ -151,6 +151,39 @@ pub enum PollNoteVisibility { #[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "push_subscription_type" +)] +pub enum PushSubscriptionType { + #[sea_orm(string_value = "admin.report")] + AdminReport, + #[sea_orm(string_value = "admin.sign_up")] + AdminSignUp, + #[sea_orm(string_value = "favourite")] + Favourite, + #[sea_orm(string_value = "follow")] + Follow, + #[sea_orm(string_value = "follow_request")] + FollowRequest, + #[sea_orm(string_value = "mention")] + Mention, + #[sea_orm(string_value = "poll")] + Poll, + #[sea_orm(string_value = "reblog")] + Reblog, + #[sea_orm(string_value = "status")] + Status, + #[sea_orm(string_value = "update")] + Update, +} +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(not(feature = "napi"), derive(Clone))] +#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status")] pub enum RelayStatus { #[sea_orm(string_value = "accepted")] diff --git a/packages/backend-rs/src/model/entity/sw_subscription.rs b/packages/backend-rs/src/model/entity/sw_subscription.rs index d66a519517..81f1e9aeac 100644 --- a/packages/backend-rs/src/model/entity/sw_subscription.rs +++ b/packages/backend-rs/src/model/entity/sw_subscription.rs @@ -1,5 +1,6 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 +use super::sea_orm_active_enums::PushSubscriptionType; use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] @@ -24,7 +25,7 @@ pub struct Model { #[sea_orm(column_name = "appAccessTokenId")] pub app_access_token_id: Option, #[sea_orm(column_name = "subscriptionTypes")] - pub subscription_types: Vec, + pub subscription_types: Vec, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/packages/backend/src/migration/1715181461692-addMastodonSubscriptionType.ts b/packages/backend/src/migration/1715181461692-addMastodonSubscriptionType.ts index b378c219c5..8ea83ef207 100644 --- a/packages/backend/src/migration/1715181461692-addMastodonSubscriptionType.ts +++ b/packages/backend/src/migration/1715181461692-addMastodonSubscriptionType.ts @@ -7,18 +7,22 @@ export class AddMastodonSubscriptionType1715181461692 public async up(queryRunner: QueryRunner): Promise { await queryRunner.query( - `ALTER TABLE "sw_subscription" ADD "subscriptionTypes" character varying(64) array NOT NULL DEFAULT '{}'`, + `CREATE TYPE "push_subscription_type" AS ENUM ('mention', 'status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update', 'admin.sign_up', 'admin.report')`, + ); + await queryRunner.query( + `ALTER TABLE "sw_subscription" ADD "subscriptionTypes" push_subscription_type array NOT NULL DEFAULT '{}'`, ); await queryRunner.query(` - UPDATE "sw_subscription" - SET "subscriptionTypes" = ARRAY['mention', 'status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update'] - WHERE "appAccessTokenId" IS NOT NULL; - `); + UPDATE "sw_subscription" + SET "subscriptionTypes" = ARRAY['mention', 'status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update']::push_subscription_type[] + WHERE "appAccessTokenId" IS NOT NULL + `); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "sw_subscription" DROP COLUMN "subscriptionTypes"`, ); + await queryRunner.query(`DROP TYPE "push_subscription_type"`); } } diff --git a/packages/backend/src/models/entities/sw-subscription.ts b/packages/backend/src/models/entities/sw-subscription.ts index 41cdcd8cad..7e5467e45f 100644 --- a/packages/backend/src/models/entities/sw-subscription.ts +++ b/packages/backend/src/models/entities/sw-subscription.ts @@ -11,6 +11,22 @@ import { User } from "./user.js"; import { id } from "../id.js"; import { AccessToken } from "./access-token.js"; +// for Mastodon push notifications +const pushSubscriptionTypes = [ + "mention", + "status", + "reblog", + "follow", + "follow_request", + "favourite", + "poll", + "update", + "admin.sign_up", + "admin.report", +] as const; + +type pushSubscriptionType = (typeof pushSubscriptionTypes)[number]; + @Entity() export class SwSubscription { @PrimaryColumn(id()) @@ -47,12 +63,13 @@ export class SwSubscription { * Type of subscription, used for Mastodon API notifications. * Empty for Misskey notifications. */ - @Column("varchar", { - length: 64, + @Column({ + type: "enum", + enum: pushSubscriptionTypes, array: true, default: "{}", }) - public subscriptionTypes: string[]; + public subscriptionTypes: pushSubscriptionType[]; /** * App notification app, used for Mastodon API notifications