code2024/bingo
0
1import { useEffect, useState } from 'react'2import { useAtom } from 'jotai'3import { Switch } from '@headlessui/react'4import { toast } from 'react-hot-toast'5import { hashAtom, voiceAtom } from '@/state'6import {7 Dialog,8 DialogContent,9 DialogDescription,10 DialogFooter,11 DialogHeader,12 DialogTitle13} from '@/components/ui/dialog'14import { Button } from './ui/button'15import { Input } from './ui/input'16import { ChunkKeys, parseCookies, extraCurlFromCookie, encodeHeadersToCookie, getCookie, setCookie } from '@/lib/utils'17import { ExternalLink } from './external-link'18import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard'19 20 21export function Settings() {22 const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })23 const [loc, setLoc] = useAtom(hashAtom)24 const [curlValue, setCurlValue] = useState(extraCurlFromCookie(parseCookies(document.cookie, ChunkKeys)))25 const [imageOnly, setImageOnly] = useState(getCookie('IMAGE_ONLY') !== '0')26 const [enableTTS, setEnableTTS] = useAtom(voiceAtom)27 28 useEffect(() => {29 if (isCopied) {30 toast.success('复制成功')31 }32 }, [isCopied])33 34 if (loc === 'settings') {35 return (36 <Dialog open onOpenChange={() => setLoc('')} modal>37 <DialogContent>38 <DialogHeader>39 <DialogTitle>设置你的用户信息</DialogTitle>40 <DialogDescription>41 请使用 Edge 浏览器42 <ExternalLink43 href="https://www.bing.com/turing/captcha/challenge"44 >45 打开并登录 Bing46 </ExternalLink>47 ,然后再打开48 <ExternalLink href="https://www.bing.com/turing/captcha/challenge">Challenge 接口</ExternalLink>49 右键 》检查。打开开发者工具,在网络里面找到 Create 接口 》右键复制》复制为 cURL(bash),粘贴到此处,然后保存。50 <div className="h-2" />51 图文示例:52 <ExternalLink href="https://github.com/weaigc/bingo#如何获取%20BING_HEADER">如何获取 BING_HEADER</ExternalLink>53 </DialogDescription>54 </DialogHeader>55 <div className="flex gap-4">56 57 </div>58 <Input59 value={curlValue}60 placeholder="在此填写用户信息,格式: curl 'https://www.bing.com/turing/captcha/challenge' ..."61 onChange={e => setCurlValue(e.target.value)}62 />63 <div className="flex gap-2">64 身份信息仅用于画图(推荐)65 <Switch66 checked={imageOnly}67 className={`${imageOnly ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`}68 onChange={(checked: boolean) => setImageOnly(checked)}69 >70 <span71 className={`${imageOnly ? 'translate-x-6' : 'translate-x-1'} inline-block h-4 w-4 transform rounded-full bg-white transition`}72 />73 </Switch>74 </div>75 76 <Button variant="ghost" className="bg-[#F5F5F5] hover:bg-[#F2F2F2]" onClick={() => copyToClipboard(btoa(curlValue))}>77 转成 BING_HEADER 并复制78 </Button>79 80 <DialogFooter className="items-center">81 <Button82 variant="secondary"83 className="bg-[#c7f3ff] hover:bg-[#fdc7ff]"84 onClick={() => {85 let headerValue = curlValue86 if (headerValue) {87 try {88 headerValue = atob(headerValue)89 } catch (e) { }90 if (!/^\s*curl ['"]https:\/\/www\.bing\.com\/turing\/captcha\/challenge['"]/.test(headerValue)) {91 toast.error('格式不正确')92 return93 }94 const maxAge = 86400 * 3095 encodeHeadersToCookie(headerValue).forEach(cookie => document.cookie = `${cookie}; Max-Age=${maxAge}; Path=/; SameSite=None; Secure`)96 } else {97 [...ChunkKeys, 'BING_COOKIE', 'BING_UA', 'BING_IP'].forEach(key => setCookie(key, ''))98 }99 setCookie('IMAGE_ONLY', imageOnly ? '1' : '0')100 101 toast.success('保存成功')102 setLoc('')103 setTimeout(() => {104 location.href = './'105 }, 2000)106 }}107 >108 保存109 </Button>110 </DialogFooter>111 </DialogContent>112 </Dialog>113 )114 } else if (loc === 'voice') {115 return (116 <Dialog open onOpenChange={() => setLoc('')} modal>117 <DialogContent>118 <DialogHeader>119 <DialogTitle>语音设置</DialogTitle>120 <DialogDescription>121 目前仅支持 PC 端 Edge 及 Chrome 浏览器122 </DialogDescription>123 </DialogHeader>124 125 <div className="flex gap-2">126 启用语音回答127 <Switch128 checked={enableTTS}129 className={`${enableTTS ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`}130 onChange={(checked: boolean) => setEnableTTS(checked)}131 >132 <span133 className={`${enableTTS ? 'translate-x-6' : 'translate-x-1'} inline-block h-4 w-4 transform rounded-full bg-white transition`}134 />135 </Switch>136 </div>137 138 <DialogFooter className="items-center">139 <Button140 variant="secondary"141 onClick={() => {142 toast.success('保存成功')143 setLoc('')144 setTimeout(() => {145 location.href = './'146 }, 2000)147 }}148 >149 保存150 </Button>151 </DialogFooter>152 </DialogContent>153 </Dialog>154 )155 }156 return null157}158 