forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {
2 type $Typed,
3 type ChatBskyConvoDefs,
4 type ComAtprotoModerationCreateReport,
5} from '@atproto/api'
6import {msg} from '@lingui/macro'
7import {useLingui} from '@lingui/react'
8import {useMutation} from '@tanstack/react-query'
9
10import {logger} from '#/logger'
11import {useAgent} from '#/state/session'
12import {NEW_TO_OLD_REASONS_MAP} from './const'
13import {type ReportState} from './state'
14import {type ParsedReportSubject} from './types'
15
16export function useSubmitReportMutation() {
17 const {_} = useLingui()
18 const agent = useAgent()
19
20 return useMutation({
21 async mutationFn({
22 subject,
23 state,
24 }: {
25 subject: ParsedReportSubject
26 state: ReportState
27 }) {
28 if (!state.selectedOption) {
29 throw new Error(_(msg`Please select a reason for this report`))
30 }
31 if (!state.selectedLabeler) {
32 throw new Error(_(msg`Please select a moderation service`))
33 }
34
35 const labeler = state.selectedLabeler
36 const labelerSupportedReasonTypes = labeler.reasonTypes || []
37
38 let reasonType = state.selectedOption.reason
39 const backwardsCompatibleReasonType = NEW_TO_OLD_REASONS_MAP[reasonType]
40 const supportsNewReasonType =
41 labelerSupportedReasonTypes.includes(reasonType)
42 const supportsOldReasonType = labelerSupportedReasonTypes.includes(
43 backwardsCompatibleReasonType,
44 )
45
46 /*
47 * Only fall back for backwards compatibility if the labeler
48 * does not support the new reason type. If the labeler does not declare
49 * supported reason types, send the new version.
50 */
51 if (supportsOldReasonType && !supportsNewReasonType) {
52 reasonType = backwardsCompatibleReasonType
53 }
54
55 let report:
56 | ComAtprotoModerationCreateReport.InputSchema
57 | (Omit<ComAtprotoModerationCreateReport.InputSchema, 'subject'> & {
58 subject: $Typed<ChatBskyConvoDefs.MessageRef>
59 })
60
61 switch (subject.type) {
62 case 'account': {
63 report = {
64 reasonType,
65 reason: state.details,
66 subject: {
67 $type: 'com.atproto.admin.defs#repoRef',
68 did: subject.did,
69 },
70 }
71 break
72 }
73 case 'status':
74 case 'post':
75 case 'list':
76 case 'feed':
77 case 'starterPack': {
78 report = {
79 reasonType,
80 reason: state.details,
81 subject: {
82 $type: 'com.atproto.repo.strongRef',
83 uri: subject.uri,
84 cid: subject.cid,
85 },
86 }
87 break
88 }
89 case 'convoMessage': {
90 report = {
91 reasonType,
92 reason: state.details,
93 subject: {
94 $type: 'chat.bsky.convo.defs#messageRef',
95 messageId: subject.message.id,
96 convoId: subject.convoId,
97 did: subject.message.sender.did,
98 },
99 }
100 break
101 }
102 }
103
104 if (__DEV__) {
105 logger.info('Submitting report', {
106 labeler: {
107 handle: labeler.creator.handle,
108 },
109 report,
110 })
111 } else {
112 await agent.createModerationReport(report, {
113 encoding: 'application/json',
114 headers: {
115 'atproto-proxy': `${labeler.creator.did}#atproto_labeler`,
116 },
117 })
118 }
119 },
120 })
121}