| import { useEffect, useState } from 'react' | |
| import { useAtom } from 'jotai' | |
| import { Switch } from '@headlessui/react' | |
| import { toast } from 'react-hot-toast' | |
| import { hashAtom, voiceAtom } from '@/state' | |
| import { | |
| Dialog, | |
| DialogContent, | |
| DialogDescription, | |
| DialogFooter, | |
| DialogHeader, | |
| DialogTitle | |
| } from '@/components/ui/dialog' | |
| import { Button } from './ui/button' | |
| import { Input } from './ui/input' | |
| import { ChunkKeys, parseCookies, extraCurlFromCookie, randomIP, encodeHeadersToCookie } from '@/lib/utils' | |
| import { ExternalLink } from './external-link' | |
| import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard' | |
| export function Settings() { | |
| const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }) | |
| const [loc, setLoc] = useAtom(hashAtom) | |
| const [curlValue, setCurlValue] = useState(extraCurlFromCookie(parseCookies(document.cookie, ChunkKeys))) | |
| const [enableTTS, setEnableTTS] = useAtom(voiceAtom) | |
| useEffect(() => { | |
| if (isCopied) { | |
| toast.success('复制成功') | |
| } | |
| }, [isCopied]) | |
| if (loc === 'settings') { | |
| return ( | |
| <Dialog open onOpenChange={() => setLoc('')} modal> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle>设置你的用户信息</DialogTitle> | |
| <DialogDescription> | |
| 请使用 Edge 浏览器 | |
| <ExternalLink | |
| href="https://www.bing.com/turing/captcha/challenge" | |
| > | |
| 打开并登录 Bing | |
| </ExternalLink> | |
| ,然后再打开 | |
| <ExternalLink href="https://www.bing.com/turing/captcha/challenge">Challenge 接口</ExternalLink> | |
| 右键 》检查。打开开发者工具,在网络里面找到 Create 接口 》右键复制》复制为 cURL(bash),粘贴到此处,然后保存。 | |
| <div className="h-2" /> | |
| 图文示例: | |
| <ExternalLink href="https://github.com/weaigc/bingo#如何获取%20BING_HEADER">如何获取 BING_HEADER</ExternalLink> | |
| </DialogDescription> | |
| </DialogHeader> | |
| <div className="flex gap-4"> | |
| </div> | |
| <Input | |
| value={curlValue} | |
| placeholder="在此填写用户信息,格式: curl 'https://www.bing.com/turing/captcha/challenge' ..." | |
| onChange={e => setCurlValue(e.target.value)} | |
| /> | |
| <Button variant="ghost" className="bg-[#F5F5F5] hover:bg-[#F2F2F2]" onClick={() => copyToClipboard(btoa(curlValue))}> | |
| 转成 BING_HEADER 并复制 | |
| </Button> | |
| <DialogFooter className="items-center"> | |
| <Button | |
| variant="secondary" | |
| className="bg-[#c7f3ff] hover:bg-[#fdc7ff]" | |
| onClick={() => { | |
| let headerValue = curlValue | |
| if (headerValue) { | |
| try { | |
| headerValue = atob(headerValue) | |
| } catch (e) {} | |
| if (!/^\s*curl ['"]https:\/\/www\.bing\.com\/turing\/captcha\/challenge['"]/.test(headerValue)) { | |
| toast.error('格式不正确') | |
| return | |
| } | |
| const maxAge = 86400 * 30 | |
| encodeHeadersToCookie(headerValue).forEach(cookie => document.cookie = `${cookie}; Max-Age=${maxAge}; Path=/; SameSite=None; Secure`) | |
| } else { | |
| [...ChunkKeys, 'BING_COOKIE', 'BING_UA', 'BING_IP'].forEach(key => document.cookie = `${key}=; Path=/; SameSite=None; Secure`) | |
| } | |
| toast.success('保存成功') | |
| setLoc('') | |
| setTimeout(() => { | |
| location.href = './' | |
| }, 2000) | |
| }} | |
| > | |
| 保存 | |
| </Button> | |
| </DialogFooter> | |
| </DialogContent> | |
| </Dialog> | |
| ) | |
| } else if (loc === 'voice') { | |
| return ( | |
| <Dialog open onOpenChange={() => setLoc('')} modal> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle>语音设置</DialogTitle> | |
| <DialogDescription> | |
| 目前仅支持 PC 端 Edge 及 Chrome 浏览器 | |
| </DialogDescription> | |
| </DialogHeader> | |
| <div className="flex gap-2"> | |
| 启用语音回答 | |
| <Switch | |
| checked={enableTTS} | |
| className={`${enableTTS ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`} | |
| onChange={(checked: boolean) => setEnableTTS(checked)} | |
| > | |
| <span | |
| className={`${enableTTS ? 'translate-x-6' : 'translate-x-1'} inline-block h-4 w-4 transform rounded-full bg-white transition`} | |
| /> | |
| </Switch> | |
| </div> | |
| <DialogFooter className="items-center"> | |
| <Button | |
| variant="secondary" | |
| onClick={() => { | |
| toast.success('保存成功') | |
| setLoc('') | |
| setTimeout(() => { | |
| location.href = './' | |
| }, 2000) | |
| }} | |
| > | |
| 保存 | |
| </Button> | |
| </DialogFooter> | |
| </DialogContent> | |
| </Dialog> | |
| ) | |
| } | |
| return null | |
| } | |