about summary refs log tree commit diff
path: root/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/state')
-rw-r--r--src/state/queries/labeler.ts49
1 files changed, 46 insertions, 3 deletions
diff --git a/src/state/queries/labeler.ts b/src/state/queries/labeler.ts
index 058e8fcde..53e923a85 100644
--- a/src/state/queries/labeler.ts
+++ b/src/state/queries/labeler.ts
@@ -2,9 +2,13 @@ import {AppBskyLabelerDefs} from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 import {z} from 'zod'
 
+import {MAX_LABELERS} from '#/lib/constants'
 import {labelersDetailedInfoQueryKeyRoot} from '#/lib/react-query'
 import {STALE} from '#/state/queries'
-import {preferencesQueryKey} from '#/state/queries/preferences'
+import {
+  preferencesQueryKey,
+  usePreferencesQuery,
+} from '#/state/queries/preferences'
 import {useAgent} from '#/state/session'
 
 const labelerInfoQueryKeyRoot = 'labeler-info'
@@ -77,6 +81,7 @@ export function useLabelersDetailedInfoQuery({dids}: {dids: string[]}) {
 export function useLabelerSubscriptionMutation() {
   const queryClient = useQueryClient()
   const agent = useAgent()
+  const preferences = usePreferencesQuery()
 
   return useMutation({
     async mutationFn({did, subscribe}: {did: string; subscribe: boolean}) {
@@ -86,14 +91,52 @@ export function useLabelerSubscriptionMutation() {
         subscribe: z.boolean(),
       }).parse({did, subscribe})
 
+      /**
+       * If a user has invalid/takendown/deactivated labelers, we need to
+       * remove them. We don't have a great way to do this atm on the server,
+       * so we do it here.
+       *
+       * We also need to push validation into this method, since we need to
+       * check {@link MAX_LABELERS} _after_ we've removed invalid or takendown
+       * labelers.
+       */
+      const labelerDids = (
+        preferences.data?.moderationPrefs?.labelers ?? []
+      ).map(l => l.did)
+      const invalidLabelers: string[] = []
+      if (labelerDids.length) {
+        const profiles = await agent.getProfiles({actors: labelerDids})
+        if (profiles.data) {
+          for (const did of labelerDids) {
+            const exists = profiles.data.profiles.find(p => p.did === did)
+            if (exists) {
+              // profile came back but it's not a valid labeler
+              if (exists.associated && !exists.associated.labeler) {
+                invalidLabelers.push(did)
+              }
+            } else {
+              // no response came back, might be deactivated or takendown
+              invalidLabelers.push(did)
+            }
+          }
+        }
+      }
+      if (invalidLabelers.length) {
+        await Promise.all(invalidLabelers.map(did => agent.removeLabeler(did)))
+      }
+
       if (subscribe) {
+        const labelerCount = labelerDids.length - invalidLabelers.length
+        if (labelerCount >= MAX_LABELERS) {
+          throw new Error('MAX_LABELERS')
+        }
         await agent.addLabeler(did)
       } else {
         await agent.removeLabeler(did)
       }
     },
-    onSuccess() {
-      queryClient.invalidateQueries({
+    async onSuccess() {
+      await queryClient.invalidateQueries({
         queryKey: preferencesQueryKey,
       })
     },