diff --git a/src/BaseClient.ts b/src/BaseClient.ts index 840ab95..4ac88d8 100644 --- a/src/BaseClient.ts +++ b/src/BaseClient.ts @@ -99,11 +99,21 @@ export abstract class BaseClient { options?: RequestOptions, ): Promise<{ comment_view: types.CommentView }>; + abstract editCommunityNotifications( + payload: types.EditCommunityNotifications, + options?: RequestOptions, + ): Promise; + abstract editPost( payload: types.EditPost, options?: RequestOptions, ): Promise<{ post_view: types.PostView }>; + abstract editPostNotifications( + payload: types.EditPostNotifications, + options?: RequestOptions, + ): Promise; + abstract featurePost( payload: { feature_type: "community" | "local"; diff --git a/src/SafeClient.ts b/src/SafeClient.ts index d866c71..940f99b 100644 --- a/src/SafeClient.ts +++ b/src/SafeClient.ts @@ -102,11 +102,23 @@ export default function buildSafeClient(_Client: AnyClient): AnyClient { return { comment_view: schemas.CommentView.parse(comment_view) }; } + async editCommunityNotifications( + ...params: Parameters + ) { + await super.editCommunityNotifications(...params); + } + async editPost(...params: Parameters) { const { post_view } = await super.editPost(...params); return { post_view: schemas.PostView.parse(post_view) }; } + async editPostNotifications( + ...params: Parameters + ) { + await super.editPostNotifications(...params); + } + async featurePost(...params: Parameters) { const { post_view } = await super.featurePost(...params); return { post_view: schemas.PostView.parse(post_view) }; diff --git a/src/ThreadiverseClient.ts b/src/ThreadiverseClient.ts index 9bf22af..1cfe227 100644 --- a/src/ThreadiverseClient.ts +++ b/src/ThreadiverseClient.ts @@ -147,11 +147,25 @@ export default class ThreadiverseClient implements BaseClient { return client.editComment(...params); } + async editCommunityNotifications( + ...params: Parameters + ) { + const client = await this.ensureClient(); + return client.editCommunityNotifications(...params); + } + async editPost(...params: Parameters) { const client = await this.ensureClient(); return client.editPost(...params); } + async editPostNotifications( + ...params: Parameters + ) { + const client = await this.ensureClient(); + return client.editPostNotifications(...params); + } + async featurePost(...params: Parameters) { const client = await this.ensureClient(); return client.featurePost(...params); diff --git a/src/providers/lemmyv0/compat.ts b/src/providers/lemmyv0/compat.ts index 1b12ed7..7a2cf1f 100644 --- a/src/providers/lemmyv0/compat.ts +++ b/src/providers/lemmyv0/compat.ts @@ -203,6 +203,7 @@ export function toCommunityView(v: LemmyV0.CommunityView): types.CommunityView { return { blocked: false, community: toCommunityWithCounts(v.community, v.counts), + notifications: "replies_and_mentions", subscribed: v.subscribed, }; } @@ -630,6 +631,7 @@ export function toPostView(v: LemmyV0.PostView): types.PostView { creator_is_moderator: v.creator_is_moderator, hidden: v.hidden ?? false, // v0.13.3 my_vote: toVote(v.my_vote), + notifications: "replies_and_mentions", post: toPost(v.post, v.counts), read: v.read, saved: v.saved, diff --git a/src/providers/lemmyv0/index.ts b/src/providers/lemmyv0/index.ts index f3cbe43..fcfe21a 100644 --- a/src/providers/lemmyv0/index.ts +++ b/src/providers/lemmyv0/index.ts @@ -176,6 +176,14 @@ export class UnsafeLemmyV0Client implements BaseClient { }; } + async editCommunityNotifications( + ..._params: Parameters + ): ReturnType { + throw new UnsupportedError( + "Edit community notifications is not supported by Lemmy v0", + ); + } + async editPost( ...params: Parameters ): ReturnType { @@ -186,6 +194,14 @@ export class UnsafeLemmyV0Client implements BaseClient { }; } + async editPostNotifications( + ..._params: Parameters + ): ReturnType { + throw new UnsupportedError( + "Edit post notifications is not supported by Lemmy v0", + ); + } + async featurePost( payload: Parameters[0], options?: RequestOptions, diff --git a/src/providers/lemmyv1/compat.ts b/src/providers/lemmyv1/compat.ts index 087083a..a2ee851 100644 --- a/src/providers/lemmyv1/compat.ts +++ b/src/providers/lemmyv1/compat.ts @@ -49,6 +49,7 @@ export function toCommunityView(v: LemmyV1.CommunityView): types.CommunityView { return { ...v, blocked: !!v.community_actions?.blocked_at, + notifications: v.community_actions?.notifications ?? "replies_and_mentions", subscribed: toFollowState(v.community_actions?.follow_state), }; } @@ -149,6 +150,7 @@ export function toPostView(v: LemmyV1.PostView): types.PostView { creator_blocked: !!v.person_actions?.blocked_at, hidden: !!v.post_actions?.hidden_at, my_vote: toVote(v.post_actions), + notifications: v.post_actions?.notifications ?? "replies_and_mentions", read: !!v.post_actions?.read_at, saved: !!v.post_actions?.saved_at, subscribed: toFollowState(v.community_actions?.follow_state), @@ -233,9 +235,22 @@ export function toSupportedNotificationView( }; } case "subscribed": - // "Someone posted/commented in a community you subscribe to." Voyager - // already surfaces these via the home feed; not shown in inbox. - return; + switch (item.data.type_) { + case "comment": + return { + ...item, + data: { type_: "comment", ...toCommentView(item.data) }, + notification, + }; + case "post": + return { + ...item, + data: { type_: "post", ...toPostView(item.data) }, + notification, + }; + default: + return undefined; + } } } diff --git a/src/providers/lemmyv1/index.ts b/src/providers/lemmyv1/index.ts index 85a5b14..a6b4dc8 100644 --- a/src/providers/lemmyv1/index.ts +++ b/src/providers/lemmyv1/index.ts @@ -184,6 +184,12 @@ export class UnsafeLemmyV1Client implements BaseClient { }; } + async editCommunityNotifications( + ...params: Parameters + ): ReturnType { + unwrap(await this.#client.editCommunityNotifications(...params)); + } + async editPost( ...params: Parameters ): ReturnType { @@ -194,6 +200,12 @@ export class UnsafeLemmyV1Client implements BaseClient { }; } + async editPostNotifications( + ...params: Parameters + ): ReturnType { + unwrap(await this.#client.editPostNotifications(...params)); + } + async featurePost( ...params: Parameters ): ReturnType { diff --git a/src/providers/piefed/compat.ts b/src/providers/piefed/compat.ts index 9534f0a..2c03ee0 100644 --- a/src/providers/piefed/compat.ts +++ b/src/providers/piefed/compat.ts @@ -114,6 +114,7 @@ export function toCommunityView( return { blocked: v.blocked, community: toCommunity(v.community, v.counts), + notifications: "replies_and_mentions", subscribed: toSubscribedType(v.subscribed), }; } @@ -249,6 +250,7 @@ export function toPostView( creator_is_moderator: v.creator_is_moderator, hidden: v.hidden, my_vote: v.my_vote, + notifications: "replies_and_mentions", post: toPost(v.post, v.counts), read: v.read, saved: v.saved, diff --git a/src/providers/piefed/index.ts b/src/providers/piefed/index.ts index a4239a8..c9c6a79 100644 --- a/src/providers/piefed/index.ts +++ b/src/providers/piefed/index.ts @@ -283,6 +283,14 @@ export class UnsafePiefedClient implements BaseClient { }; } + async editCommunityNotifications( + ..._params: Parameters + ): ReturnType { + throw new UnsupportedError( + "Edit community notifications is not supported by piefed", + ); + } + async editPost( payload: Parameters[0], options?: RequestOptions, @@ -300,6 +308,14 @@ export class UnsafePiefedClient implements BaseClient { }; } + async editPostNotifications( + ..._params: Parameters + ): ReturnType { + throw new UnsupportedError( + "Edit post notifications is not supported by piefed", + ); + } + async featurePost( payload: Parameters[0], options?: RequestOptions, diff --git a/src/schemas/CommunityNotificationsMode.ts b/src/schemas/CommunityNotificationsMode.ts new file mode 100644 index 0000000..0ecf6a7 --- /dev/null +++ b/src/schemas/CommunityNotificationsMode.ts @@ -0,0 +1,18 @@ +import { z } from "zod/v4-mini"; + +/** + * Notification setting for a community. + * + * - `all_posts_and_comments`: notify on every new post and comment in the + * community. + * - `all_posts`: notify on every new post (not comments). + * - `replies_and_mentions`: only notify when the user is replied to or + * mentioned (this is the default for users who haven't customized). + * - `mute`: never notify, even for direct replies/mentions in this community. + */ +export const CommunityNotificationsMode = z.enum([ + "all_posts_and_comments", + "all_posts", + "replies_and_mentions", + "mute", +]); diff --git a/src/schemas/CommunityView.ts b/src/schemas/CommunityView.ts index bcbddbe..3d2332b 100644 --- a/src/schemas/CommunityView.ts +++ b/src/schemas/CommunityView.ts @@ -1,10 +1,12 @@ import { z } from "zod/v4-mini"; import { Community } from "./Community"; +import { CommunityNotificationsMode } from "./CommunityNotificationsMode"; import { SubscribedType } from "./SubscribedType"; export const CommunityView = z.object({ blocked: z.boolean(), community: Community, + notifications: CommunityNotificationsMode, subscribed: SubscribedType, }); diff --git a/src/schemas/PostNotificationsMode.ts b/src/schemas/PostNotificationsMode.ts new file mode 100644 index 0000000..1981e0c --- /dev/null +++ b/src/schemas/PostNotificationsMode.ts @@ -0,0 +1,15 @@ +import { z } from "zod/v4-mini"; + +/** + * Notification setting for a post. + * + * - `all_comments`: notify on every new comment on the post. + * - `replies_and_mentions`: only notify when the user is replied to or + * mentioned (this is the default for users who haven't customized). + * - `mute`: never notify, even for direct replies/mentions on this post. + */ +export const PostNotificationsMode = z.enum([ + "all_comments", + "replies_and_mentions", + "mute", +]); diff --git a/src/schemas/PostView.ts b/src/schemas/PostView.ts index 24b5e63..6ef9b81 100644 --- a/src/schemas/PostView.ts +++ b/src/schemas/PostView.ts @@ -3,6 +3,7 @@ import { z } from "zod/v4-mini"; import { Community } from "./Community"; import { Person } from "./Person"; import { Post } from "./Post"; +import { PostNotificationsMode } from "./PostNotificationsMode"; import { SubscribedType } from "./SubscribedType"; import { Vote } from "./Vote"; @@ -16,6 +17,7 @@ export const PostView = z.object({ creator_is_moderator: z.boolean(), hidden: z.boolean(), my_vote: z.optional(Vote), + notifications: PostNotificationsMode, post: Post, read: z.boolean(), saved: z.boolean(), diff --git a/src/schemas/index.ts b/src/schemas/index.ts index be90834..b211c02 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -10,6 +10,7 @@ export * from "./CommentView"; export * from "./Community"; export * from "./CommunityFollowerView"; export * from "./CommunityModeratorView"; +export * from "./CommunityNotificationsMode"; export * from "./CommunityView"; export * from "./CommunityVisibility"; export * from "./FederatedInstances"; @@ -32,6 +33,7 @@ export * from "./PersonContentItem"; export * from "./PersonContentItem"; export * from "./PersonMention"; export * from "./Post"; +export * from "./PostNotificationsMode"; export * from "./PostReport"; export * from "./PostReportView"; export * from "./PostView"; diff --git a/src/types/EditCommunityNotifications.ts b/src/types/EditCommunityNotifications.ts new file mode 100644 index 0000000..e86ae02 --- /dev/null +++ b/src/types/EditCommunityNotifications.ts @@ -0,0 +1,8 @@ +import type { z } from "zod/v4-mini"; + +import type { CommunityNotificationsMode } from "../schemas/CommunityNotificationsMode"; + +export interface EditCommunityNotifications { + community_id: number; + mode: z.infer; +} diff --git a/src/types/EditPostNotifications.ts b/src/types/EditPostNotifications.ts new file mode 100644 index 0000000..7622fdc --- /dev/null +++ b/src/types/EditPostNotifications.ts @@ -0,0 +1,8 @@ +import type { z } from "zod/v4-mini"; + +import type { PostNotificationsMode } from "../schemas/PostNotificationsMode"; + +export interface EditPostNotifications { + mode: z.infer; + post_id: number; +} diff --git a/src/types/index.ts b/src/types/index.ts index 600ba9f..57cc2df 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -13,6 +13,9 @@ export type CommunityFollowerView = z.infer< export type CommunityModeratorView = z.infer< typeof schemas.CommunityModeratorView >; +export type CommunityNotificationsMode = z.infer< + typeof schemas.CommunityNotificationsMode +>; export type CommunityView = z.infer; export type CommunityVisibility = z.infer; export type FederatedInstances = z.infer; @@ -75,6 +78,9 @@ export type PersonMention = z.infer; export type PersonView = z.infer; export type PiefedErrorResponse = z.infer; export type Post = z.infer; +export type PostNotificationsMode = z.infer< + typeof schemas.PostNotificationsMode +>; export type PostReport = z.infer; export type PostReportView = z.infer; export type PostView = z.infer; @@ -100,7 +106,9 @@ export type * from "./CommunitySortType"; export type * from "./CreateComment"; export type * from "./CreatePost"; export type * from "./EditComment"; +export type * from "./EditCommunityNotifications"; export type * from "./EditPost"; +export type * from "./EditPostNotifications"; export type * from "./GetComments"; export type * from "./GetCommunity"; export type * from "./GetModlog";