about summary refs log tree commit diff
path: root/src/state/queries/invites.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/queries/invites.ts')
-rw-r--r--src/state/queries/invites.ts55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts
new file mode 100644
index 000000000..367917af5
--- /dev/null
+++ b/src/state/queries/invites.ts
@@ -0,0 +1,55 @@
+import {ComAtprotoServerDefs} from '@atproto/api'
+import {useQuery} from '@tanstack/react-query'
+
+import {getAgent} from '#/state/session'
+import {STALE} from '#/state/queries'
+import {cleanError} from '#/lib/strings/errors'
+
+function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {
+  return invite.available - invite.uses.length > 0 && !invite.disabled
+}
+
+export type InviteCodesQueryResponse = Exclude<
+  ReturnType<typeof useInviteCodesQuery>['data'],
+  undefined
+>
+export function useInviteCodesQuery() {
+  return useQuery({
+    staleTime: STALE.HOURS.ONE,
+    queryKey: ['inviteCodes'],
+    queryFn: async () => {
+      const res = await getAgent()
+        .com.atproto.server.getAccountInviteCodes({})
+        .catch(e => {
+          if (cleanError(e) === 'Bad token scope') {
+            return null
+          } else {
+            throw e
+          }
+        })
+
+      if (res === null) {
+        return {
+          disabled: true,
+          all: [],
+          available: [],
+          used: [],
+        }
+      }
+
+      if (!res.data?.codes) {
+        throw new Error(`useInviteCodesQuery: no codes returned`)
+      }
+
+      const available = res.data.codes.filter(isInviteAvailable)
+      const used = res.data.codes.filter(code => !isInviteAvailable(code))
+
+      return {
+        disabled: false,
+        all: [...available, ...used],
+        available,
+        used,
+      }
+    },
+  })
+}