From 4e66ef10c7e0bd33fa7db909ca7672ca64c8bef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 8 Apr 2026 20:10:22 +0800 Subject: [PATCH] feat(pairing): add generatePairingCode and removePairedUser to adapter store Co-Authored-By: Claude Opus 4.6 (1M context) --- desktop/src/stores/adapterStore.ts | 42 ++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/desktop/src/stores/adapterStore.ts b/desktop/src/stores/adapterStore.ts index d5e4e2de..b0639a16 100644 --- a/desktop/src/stores/adapterStore.ts +++ b/desktop/src/stores/adapterStore.ts @@ -2,6 +2,16 @@ import { create } from 'zustand' import { adaptersApi } from '../api/adapters' import type { AdapterFileConfig } from '../types/adapter' +const SAFE_ALPHABET = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789' +const CODE_LENGTH = 6 +const CODE_TTL_MS = 60 * 60 * 1000 // 60 minutes + +function generateCode(): string { + const array = new Uint8Array(CODE_LENGTH) + crypto.getRandomValues(array) + return Array.from(array, (b) => SAFE_ALPHABET[b % SAFE_ALPHABET.length]).join('') +} + type AdapterStore = { config: AdapterFileConfig isLoading: boolean @@ -9,9 +19,11 @@ type AdapterStore = { fetchConfig: () => Promise updateConfig: (patch: Partial) => Promise + generatePairingCode: () => Promise + removePairedUser: (platform: 'telegram' | 'feishu', userId: string | number) => Promise } -export const useAdapterStore = create((set) => ({ +export const useAdapterStore = create((set, get) => ({ config: {}, isLoading: false, error: null, @@ -28,8 +40,34 @@ export const useAdapterStore = create((set) => ({ }, updateConfig: async (patch) => { - // PUT returns the merged masked config — no need for a separate GET const config = await adaptersApi.updateConfig(patch) set({ config }) }, + + generatePairingCode: async () => { + const code = generateCode() + const now = Date.now() + await get().updateConfig({ + pairing: { + code, + expiresAt: now + CODE_TTL_MS, + createdAt: now, + }, + }) + return code + }, + + removePairedUser: async (platform, userId) => { + const { config } = get() + const platformConfig = config[platform] + if (!platformConfig) return + + const pairedUsers = (platformConfig.pairedUsers ?? []).filter( + (u) => String(u.userId) !== String(userId), + ) + + await get().updateConfig({ + [platform]: { ...platformConfig, pairedUsers }, + }) + }, }))