Add validation to threadgate records, check for max hidden replies (#9178)
This commit is contained in:
@@ -46,7 +46,12 @@ import {
|
||||
useProfileBlockMutationQueue,
|
||||
useProfileMuteMutationQueue,
|
||||
} from '#/state/queries/profile'
|
||||
import {useToggleReplyVisibilityMutation} from '#/state/queries/threadgate'
|
||||
import {
|
||||
InvalidInteractionSettingsError,
|
||||
MAX_HIDDEN_REPLIES,
|
||||
MaxHiddenRepliesError,
|
||||
useToggleReplyVisibilityMutation,
|
||||
} from '#/state/queries/threadgate'
|
||||
import {useRequireAuth, useSession} from '#/state/session'
|
||||
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
@@ -339,10 +344,30 @@ let PostMenuItems = ({
|
||||
: _(msg({message: 'Reply visibility updated', context: 'toast'})),
|
||||
)
|
||||
} catch (e: any) {
|
||||
Toast.show(
|
||||
_(msg({message: 'Updating reply visibility failed', context: 'toast'})),
|
||||
)
|
||||
logger.error(`Failed to ${action} reply`, {safeMessage: e.message})
|
||||
if (e instanceof MaxHiddenRepliesError) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg({
|
||||
message: `You can hide a maximum of ${MAX_HIDDEN_REPLIES} replies.`,
|
||||
context: 'toast',
|
||||
}),
|
||||
),
|
||||
)
|
||||
} else if (e instanceof InvalidInteractionSettingsError) {
|
||||
Toast.show(
|
||||
_(msg({message: 'Invalid interaction settings.', context: 'toast'})),
|
||||
)
|
||||
} else {
|
||||
Toast.show(
|
||||
_(
|
||||
msg({
|
||||
message: 'Updating reply visibility failed',
|
||||
context: 'toast',
|
||||
}),
|
||||
),
|
||||
)
|
||||
logger.error(`Failed to ${action} reply`, {safeMessage: e.message})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ import * as bsky from '#/types/bsky'
|
||||
export * from '#/state/queries/threadgate/types'
|
||||
export * from '#/state/queries/threadgate/util'
|
||||
|
||||
/**
|
||||
* Must match the threadgate lexicon record definition.
|
||||
*/
|
||||
export const MAX_HIDDEN_REPLIES = 300
|
||||
|
||||
export const threadgateRecordQueryKeyRoot = 'threadgate-record'
|
||||
export const createThreadgateRecordQueryKey = (uri: string) => [
|
||||
threadgateRecordQueryKeyRoot,
|
||||
@@ -205,6 +210,7 @@ export async function upsertThreadgate(
|
||||
})
|
||||
const next = await callback(prev)
|
||||
if (!next) return
|
||||
validateThreadgateRecordOrThrow(next)
|
||||
await writeThreadgateRecord({
|
||||
agent,
|
||||
postUri,
|
||||
@@ -358,3 +364,31 @@ export function useToggleReplyVisibilityMutation() {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export class MaxHiddenRepliesError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message || 'Maximum number of hidden replies reached')
|
||||
this.name = 'MaxHiddenRepliesError'
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidInteractionSettingsError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message || 'Invalid interaction settings')
|
||||
this.name = 'InvalidInteractionSettingsError'
|
||||
}
|
||||
}
|
||||
|
||||
export function validateThreadgateRecordOrThrow(
|
||||
record: AppBskyFeedThreadgate.Record,
|
||||
) {
|
||||
const result = AppBskyFeedThreadgate.validateRecord(record)
|
||||
|
||||
if (result.success) {
|
||||
if ((result.value.hiddenReplies?.length ?? 0) > MAX_HIDDEN_REPLIES) {
|
||||
throw new MaxHiddenRepliesError()
|
||||
}
|
||||
} else {
|
||||
throw new InvalidInteractionSettingsError()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user