bingo / src /components /settings.tsx
zhouyi1989's picture
Duplicate from hf4all/bingo
6337686
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, encodeHeadersToCookie, getCookie, setCookie } 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 [imageOnly, setImageOnly] = useState(getCookie('IMAGE_ONLY') !== '0')
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)}
/>
<div className="flex gap-2">
身份信息仅用于画图(推荐)
<Switch
checked={imageOnly}
className={`${imageOnly ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`}
onChange={(checked: boolean) => setImageOnly(checked)}
>
<span
className={`${imageOnly ? 'translate-x-6' : 'translate-x-1'} inline-block h-4 w-4 transform rounded-full bg-white transition`}
/>
</Switch>
</div>
<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|cn)\.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 => setCookie(key, ''))
}
setCookie('IMAGE_ONLY', RegExp.$1 === 'cn' || imageOnly ? '1' : '0')
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
}