diff --git a/.vscode/launch.json b/.vscode/launch.json index 93d408b391..782f007caa 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,7 @@ // "Go_Proxy_BingAI_SOCKS_PWD": "xxx", // "Go_Proxy_BingAI_USER_TOKEN_1": "xxx", // "Go_Proxy_BingAI_USER_TOKEN_2": "xxx" + // "Go_Proxy_BingAI_AUTH_KEY": "xxx", } } ] diff --git a/README.md b/README.md index e4b7f3c02e..692f3d8ed9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ 基于微软 New Bing 简单定制,拥有一致的 UI 体验,支持 ChatGPT 提示词,国内可用,基本兼容微软 Bing AI 所有功能,无需登录即可畅聊。 +⭐ Bing 官方聊天服务器(相对较快和稳定,推荐)不可用时, 可用 ModHeader 添加 X-Forwarded-For 请求头,对应 URL 是 wss://sydney.bing.com/sydney/ChatHub,具体可参考 https://zhuanlan.zhihu.com/p/606655303 + +⭐ 聊天服务器 (暂时默认 Cloudflare ) 可在右上角 设置 => 服务选择 中切换 + +⭐ 自定义聊天服务器参考下面 [部署聊天服务器](#部署聊天服务器) 章节 + ⭐ 国内可用 (部署服务器需要直连 www.bing.com 不重定向 CN ,可配置 socks 连接) ⭐ 支持现有开源提示词库 @@ -22,6 +28,7 @@ - [Railway](#Railway) - [Vercel](#Vercel) - [Render](#Render) + - [部署聊天服务器](#部署聊天服务器) - [TODO](#TODO) ## 网页展示 @@ -104,6 +111,8 @@ Go_Proxy_BingAI_SOCKS_PWD=xxx Go_Proxy_BingAI_USER_TOKEN_1=xxx Go_Proxy_BingAI_USER_TOKEN_2=xxx Go_Proxy_BingAI_USER_TOKEN_3=xxx ... +# 简单授权认证密码,可选 +Go_Proxy_BingAI_AUTH_KEY=xxx ``` ## 部署 @@ -153,7 +162,7 @@ services: ### Release -在 [Github Releases](https://github.com/adams549659584/go-proxy-bingai/releases) 下载适用于对应平台的压缩包,解压后可得到可执行文件 go-proxy-bingai,直接运行即可。 +在 [GitHub Releases](https://github.com/adams549659584/go-proxy-bingai/releases) 下载适用于对应平台的压缩包,解压后可得到可执行文件 go-proxy-bingai,直接运行即可。 ### Railway @@ -176,6 +185,8 @@ RAILWAY_DOCKERFILE_PATH=docker/Dockerfile ### Vercel +> ⭐ Vercel 部署不支持 Websocket ,需选择 官方聊天服务器 或 Cloudflare + 一键部署,点这里 => [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/adams549659584/go-proxy-bingai&project-name=go-proxy-bingai&repository-name=go-proxy-bingai-vercel) ![Vercel 一键部署](./docs/img/vercel-1.png) @@ -190,11 +201,23 @@ RAILWAY_DOCKERFILE_PATH=docker/Dockerfile ![Render 域名](./docs/img/render-2.png) +## 部署聊天服务器 + +> 核心代码 [worker.js](./cloudflare/worker.js) + +> 具体部署 Cloudflare Workers 教程自行查询,大概如下 + +- [注册 Cloudflare 账号](https://dash.cloudflare.com/sign-up) + +- 创建 Worker 服务,复制 [worker.js](./cloudflare/worker.js) 全部代码,粘贴至创建的服务中,保存并部署。 + +- 触发器 中自定义访问域名。 + ## TODO - [x] 撰写 - [x] Vue3 重构 - [x] 提示词 - [x] 历史聊天 -- [ ] 导出消息到本地(Markdown、图片、PDF) -- [ ] 简单访问权限控制 +- [x] 导出消息到本地(Markdown、图片、PDF) +- [x] 简单访问权限控制 diff --git a/api/chathub.go b/api/chathub.go deleted file mode 100644 index 8ffe83fc49..0000000000 --- a/api/chathub.go +++ /dev/null @@ -1,10 +0,0 @@ -package api - -import ( - "adams549659584/go-proxy-bingai/common" - "net/http" -) - -func ChatHub(w http.ResponseWriter, r *http.Request) { - common.NewSingleHostReverseProxy(common.BING_CHAT_URL).ServeHTTP(w, r) -} diff --git a/api/helper/helper.go b/api/helper/helper.go new file mode 100644 index 0000000000..50cccfcda0 --- /dev/null +++ b/api/helper/helper.go @@ -0,0 +1,48 @@ +package helper + +import ( + "adams549659584/go-proxy-bingai/common" + "encoding/json" + "net/http" +) + +type Response struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data"` +} + +func CommonResult(w http.ResponseWriter, code int, msg string, data interface{}) error { + res := Response{ + Code: code, + Message: msg, + Data: data, + } + w.Header().Set("Content-Type", "application/json") + err := json.NewEncoder(w).Encode(res) + if err != nil { + return err + } + return nil +} + +func SuccessResult(w http.ResponseWriter, data interface{}) error { + return CommonResult(w, http.StatusOK, "success", data) +} + +func ErrorResult(w http.ResponseWriter, code int, msg string) error { + return CommonResult(w, code, msg, nil) +} + +func UnauthorizedResult(w http.ResponseWriter) error { + return ErrorResult(w, http.StatusUnauthorized, "unauthorized") +} + +func CheckAuth(r *http.Request) bool { + isAuth := true + if len(common.AUTH_KEY) > 0 { + ckAuthKey, _ := r.Cookie(common.AUTH_KEY_COOKIE_NAME) + isAuth = ckAuthKey != nil && len(ckAuthKey.Value) > 0 && common.AUTH_KEY == ckAuthKey.Value + } + return isAuth +} diff --git a/api/index.go b/api/index.go index ea86b13777..73a40b58c4 100644 --- a/api/index.go +++ b/api/index.go @@ -1,6 +1,7 @@ package api import ( + "adams549659584/go-proxy-bingai/api/helper" "adams549659584/go-proxy-bingai/common" "net/http" ) @@ -9,6 +10,10 @@ func Index(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { http.Redirect(w, r, common.PROXY_WEB_PAGE_PATH, http.StatusFound) } else { + if !helper.CheckAuth(r) { + helper.UnauthorizedResult(w) + return + } common.NewSingleHostReverseProxy(common.BING_URL).ServeHTTP(w, r) } } diff --git a/api/sydney.go b/api/sydney.go new file mode 100644 index 0000000000..601ad16570 --- /dev/null +++ b/api/sydney.go @@ -0,0 +1,15 @@ +package api + +import ( + "adams549659584/go-proxy-bingai/api/helper" + "adams549659584/go-proxy-bingai/common" + "net/http" +) + +func Sydney(w http.ResponseWriter, r *http.Request) { + if !helper.CheckAuth(r) { + helper.UnauthorizedResult(w) + return + } + common.NewSingleHostReverseProxy(common.BING_SYDNEY_URL).ServeHTTP(w, r) +} diff --git a/api/sysConfig.go b/api/sysConfig.go new file mode 100644 index 0000000000..10e1cf5d77 --- /dev/null +++ b/api/sysConfig.go @@ -0,0 +1,24 @@ +package api + +import ( + "adams549659584/go-proxy-bingai/api/helper" + "adams549659584/go-proxy-bingai/common" + "net/http" +) + +type SysConfig struct { + // 是否系统配置 cookie + IsSysCK bool `json:"isSysCK"` + // 是否已授权 + IsAuth bool `json:"isAuth"` + SydneyBaseUrl string `json:"sydneyBaseUrl"` +} + +func SysConf(w http.ResponseWriter, r *http.Request) { + isAuth := helper.CheckAuth(r) + conf := SysConfig{ + IsSysCK: len(common.USER_TOKEN_LIST) > 0, + IsAuth: isAuth, + } + helper.SuccessResult(w, conf) +} diff --git a/api/web.go b/api/web.go index 3ac4830775..8667606bf9 100644 --- a/api/web.go +++ b/api/web.go @@ -1,6 +1,7 @@ package api import ( + "adams549659584/go-proxy-bingai/api/helper" "adams549659584/go-proxy-bingai/common" "adams549659584/go-proxy-bingai/web" "net/http" @@ -10,6 +11,10 @@ func WebStatic(w http.ResponseWriter, r *http.Request) { if _, ok := web.WEB_PATH_MAP[r.URL.Path]; ok || r.URL.Path == common.PROXY_WEB_PREFIX_PATH { http.StripPrefix(common.PROXY_WEB_PREFIX_PATH, http.FileServer(web.GetWebFS())).ServeHTTP(w, r) } else { + if !helper.CheckAuth(r) { + helper.UnauthorizedResult(w) + return + } common.NewSingleHostReverseProxy(common.BING_URL).ServeHTTP(w, r) } } diff --git a/cloudflare/worker.js b/cloudflare/worker.js new file mode 100644 index 0000000000..923c878ffb --- /dev/null +++ b/cloudflare/worker.js @@ -0,0 +1,124 @@ +const SYDNEY_ORIGIN = 'https://sydney.bing.com'; +const KEEP_REQ_HEADERS = [ + 'accept', + 'accept-encoding', + 'accept-language', + 'connection', + 'cookie', + 'upgrade', + 'user-agent', + 'sec-websocket-extensions', + 'sec-websocket-key', + 'sec-websocket-version', + 'x-request-id', + 'content-length', + 'content-type', + 'access-control-request-headers', + 'access-control-request-method', +]; +const IP_RANGE = [ + ['3.2.50.0', '3.5.31.255'], //192,000 + ['3.12.0.0', '3.23.255.255'], //786,432 + ['3.30.0.0', '3.33.34.255'], //205,568 + ['3.40.0.0', '3.63.255.255'], //1,572,864 + ['3.80.0.0', '3.95.255.255'], //1,048,576 + ['3.100.0.0', '3.103.255.255'], //262,144 + ['3.116.0.0', '3.119.255.255'], //262,144 + ['3.128.0.0', '3.247.255.255'], //7,864,320 +]; + +/** + * 随机整数 [min,max) + * @param {number} min + * @param {number} max + * @returns + */ +const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min)) + min; + +/** + * ip 转 int + * @param {string} ip + * @returns + */ +const ipToInt = (ip) => { + const ipArr = ip.split('.'); + let result = 0; + result += +ipArr[0] << 24; + result += +ipArr[1] << 16; + result += +ipArr[2] << 8; + result += +ipArr[3]; + return result; +}; + +/** + * int 转 ip + * @param {number} intIP + * @returns + */ +const intToIp = (intIP) => { + return `${(intIP >> 24) & 255}.${(intIP >> 16) & 255}.${(intIP >> 8) & 255}.${intIP & 255}`; +}; + +const getRandomIP = () => { + const randIndex = getRandomInt(0, IP_RANGE.length); + const startIp = IP_RANGE[randIndex][0]; + const endIp = IP_RANGE[randIndex][1]; + const startIPInt = ipToInt(startIp); + const endIPInt = ipToInt(endIp); + const randomInt = getRandomInt(startIPInt, endIPInt); + const randomIP = intToIp(randomInt); + return randomIP; +}; + +export default { + /** + * fetch + * @param {Request} request + * @param {*} env + * @param {*} ctx + * @returns + */ + async fetch(request, env, ctx) { + const currentUrl = new URL(request.url); + const targetUrl = new URL(SYDNEY_ORIGIN + currentUrl.pathname + currentUrl.search); + + const newHeaders = new Headers(); + request.headers.forEach((value, key) => { + // console.log(`old : ${key} : ${value}`); + if (KEEP_REQ_HEADERS.includes(key)) { + newHeaders.set(key, value); + } + }); + newHeaders.set('host', targetUrl.host); + newHeaders.set('origin', targetUrl.origin); + newHeaders.set('referer', 'https://www.bing.com/search?q=Bing+AI'); + const randIP = getRandomIP(); + // console.log('randIP : ', randIP); + newHeaders.set('X-Forwarded-For', randIP); + const oldUA = request.headers.get('user-agent'); + const isMobile = oldUA.includes('Mobile') || oldUA.includes('Android'); + if (isMobile) { + newHeaders.set( + 'user-agent', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.7 Mobile/15E148 Safari/605.1.15 BingSapphire/1.0.410427012' + ); + } else { + newHeaders.set('user-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35'); + } + + // newHeaders.forEach((value, key) => console.log(`${key} : ${value}`)); + const newReq = new Request(targetUrl, { + method: request.method, + headers: newHeaders, + body: request.body, + }); + // console.log('request url : ', newReq.url); + const res = await fetch(newReq); + return res; + // const newRes = new Response(res.body, res); + // newRes.headers.set('access-control-allow-origin', '*'); + // newRes.headers.set('access-control-allow-methods', '*'); + // newRes.headers.set('access-control-allow-headers', '*'); + // return newRes; + }, +}; diff --git a/common/ip.go b/common/ip.go index ca87f20a34..8b5f67f2eb 100644 --- a/common/ip.go +++ b/common/ip.go @@ -2322,9 +2322,6 @@ var IP_RANGE = [][]string{ {"100.43.0.0", "100.43.95.255"}, //24,576 {"100.43.128.0", "100.63.255.255"}, //1,343,488 {"100.128.0.0", "100.255.255.255"}, //8,388,608 - {"101.45.0.0", "101.45.255.255"}, //65,536 - {"101.49.0.0", "101.49.127.255"}, //32,768 - {"101.49.192.0", "101.49.255.255"}, //16,384 {"104.0.0.0", "104.28.7.255"}, //1,837,056 {"104.28.157.0", "104.28.255.255"}, //25,344 {"104.29.105.0", "104.30.1.255"}, //39,168 @@ -2926,7 +2923,6 @@ var IP_RANGE = [][]string{ {"137.167.0.0", "137.169.40.255"}, //141,568 {"137.169.43.0", "137.170.255.255"}, //120,064 {"137.173.0.0", "137.173.255.255"}, //65,536 - {"137.175.0.0", "137.175.127.255"}, //32,768 {"137.176.0.0", "137.177.34.255"}, //74,496 {"137.177.36.0", "137.184.159.255"}, //490,496 {"137.184.176.0", "137.184.247.255"}, //18,432 diff --git a/common/proxy.go b/common/proxy.go index af5b449eac..566d33e387 100644 --- a/common/proxy.go +++ b/common/proxy.go @@ -20,24 +20,29 @@ import ( ) var ( - BING_CHAT_DOMAIN = "https://sydney.bing.com" - BING_CHAT_URL, _ = url.Parse(BING_CHAT_DOMAIN + "/sydney/ChatHub") - BING_URL, _ = url.Parse("https://www.bing.com") + BING_SYDNEY_DOMAIN = "https://sydney.bing.com" + // BING_CHAT_URL, _ = url.Parse(BING_CHAT_DOMAIN + "/sydney/ChatHub") + BING_SYDNEY_URL, _ = url.Parse(BING_SYDNEY_DOMAIN) + BING_URL, _ = url.Parse("https://www.bing.com") // EDGE_SVC_URL, _ = url.Parse("https://edgeservices.bing.com") KEEP_REQ_HEADER_MAP = map[string]bool{ - "Accept": true, - "Accept-Encoding": true, - "Accept-Language": true, - "Referer": true, - "Connection": true, - "Cookie": true, - "Upgrade": true, - "User-Agent": true, - "Sec-Websocket-Extensions": true, - "Sec-Websocket-Key": true, - "Sec-Websocket-Version": true, - "X-Request-Id": true, - "X-Forwarded-For": true, + "Accept": true, + "Accept-Encoding": true, + "Accept-Language": true, + "Referer": true, + "Connection": true, + "Cookie": true, + "Upgrade": true, + "User-Agent": true, + "Sec-Websocket-Extensions": true, + "Sec-Websocket-Key": true, + "Sec-Websocket-Version": true, + "X-Request-Id": true, + "X-Forwarded-For": true, + "Content-Length": true, + "Content-Type": true, + "Access-Control-Request-Headers": true, + "Access-Control-Request-Method": true, } DEL_LOCATION_DOMAINS = []string{ "https://cn.bing.com", @@ -50,12 +55,29 @@ var ( USER_TOKEN_ENV_NAME_PREFIX = "Go_Proxy_BingAI_USER_TOKEN" USER_TOKEN_LIST []string RAND_COOKIE_INDEX_NAME = "BingAI_Rand_CK" + // socks + SOCKS_URL string + SOCKS_USER string + SOCKS_PWD string + // 访问权限密钥,可选 + AUTH_KEY string + AUTH_KEY_COOKIE_NAME = "BingAI_Auth_Key" ) func init() { + initEnv() initUserToken() } +func initEnv() { + // socks + SOCKS_URL = os.Getenv("Go_Proxy_BingAI_SOCKS_URL") + SOCKS_USER = os.Getenv("Go_Proxy_BingAI_SOCKS_USER") + SOCKS_PWD = os.Getenv("Go_Proxy_BingAI_SOCKS_PWD") + // auth + AUTH_KEY = os.Getenv("Go_Proxy_BingAI_AUTH_KEY") +} + func initUserToken() { for _, env := range os.Environ() { if strings.HasPrefix(env, USER_TOKEN_ENV_NAME_PREFIX) { @@ -70,7 +92,7 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy { httpsSchemeName := "https" var originalHost string var originalPath string - var originalDomain string + // var originalDomain string var randIP string var resCKRandIndex string director := func(req *http.Request) { @@ -79,18 +101,18 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy { } originalHost = req.Host originalPath = req.URL.Path - originalDomain = fmt.Sprintf("%s:%s", originalScheme, originalHost) + // originalDomain = fmt.Sprintf("%s:%s", originalScheme, originalHost) req.URL.Scheme = target.Scheme req.URL.Host = target.Host req.Host = target.Host - originalRefer := req.Referer() - if originalRefer != "" && !strings.Contains(originalRefer, PROXY_WEB_PAGE_PATH) { - req.Header.Set("Referer", strings.ReplaceAll(originalRefer, originalDomain, BING_URL.String())) - } else { - req.Header.Set("Referer", fmt.Sprintf("%s/search?q=Bing+AI", BING_URL.String())) - } + // originalRefer := req.Referer() + // if originalRefer != "" && !strings.Contains(originalRefer, originalDomain) { + // req.Header.Set("Referer", strings.ReplaceAll(originalRefer, originalDomain, BING_URL.String())) + // } else { + req.Header.Set("Referer", fmt.Sprintf("%s/search?q=Bing+AI", BING_URL.String())) + // } // 同一会话尽量保持相同的随机IP ckRandIP, _ := req.Cookie(RAND_IP_COOKIE_NAME) @@ -199,9 +221,9 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy { } // 跨域 - res.Header.Set("Access-Control-Allow-Origin", "*") - res.Header.Set("Access-Control-Allow-Methods", "*") - res.Header.Set("Access-Control-Allow-Headers", "*") + // res.Header.Set("Access-Control-Allow-Origin", "*") + // res.Header.Set("Access-Control-Allow-Methods", "*") + // res.Header.Set("Access-Control-Allow-Headers", "*") return nil } @@ -226,18 +248,15 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy { } // socks - socksUrl := os.Getenv("Go_Proxy_BingAI_SOCKS_URL") - if socksUrl != "" { - socksUser := os.Getenv("Go_Proxy_BingAI_SOCKS_USER") - socksPwd := os.Getenv("Go_Proxy_BingAI_SOCKS_PWD") + if SOCKS_URL != "" { var socksAuth *proxy.Auth - if socksUser != "" && socksPwd != "" { + if SOCKS_USER != "" && SOCKS_PWD != "" { socksAuth = &proxy.Auth{ - User: socksUser, - Password: socksPwd, + User: SOCKS_USER, + Password: SOCKS_PWD, } } - s5Proxy, err := proxy.SOCKS5("tcp", socksUrl, socksAuth, proxy.Direct) + s5Proxy, err := proxy.SOCKS5("tcp", SOCKS_URL, socksAuth, proxy.Direct) if err != nil { panic(err) } diff --git a/frontend/package.json b/frontend/package.json index cc40cb1d05..04d993c5c5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "go-proxy-bingai", - "version": "1.7.0", + "version": "1.8.0", "private": true, "scripts": { "dev": "vite", diff --git a/frontend/public/js/bing/chat/config.js b/frontend/public/js/bing/chat/config.js index 4f2d0c1280..bacb051086 100644 --- a/frontend/public/js/bing/chat/config.js +++ b/frontend/public/js/bing/chat/config.js @@ -24,7 +24,7 @@ _w['_sydConvConfig'] = { Syd2TFlights: '', sydIDs: 'winmuid3tf,osbsdusgreccf,ttstmout,crchatrev,winlongmsgtf,ctrlworkpay,norespwtf,tempcacheread,temptacache,505scss0,508jbcars0,515enbotdets0,5082tsports,515vaoprvs,424dagslnv1s0,kcimgattcf,427startpms0', - sydBaseUrl: 'https://sydney.bing.com', + sydBaseUrl: 'https://sydney.vcanbb.chat', compSydBaseUrl: '', isCompliantSydneyEndpointEnabled: false, useAccountLinkingForConversationLimitUpsell: false, diff --git a/frontend/src/api/model/ApiResult.ts b/frontend/src/api/model/ApiResult.ts new file mode 100644 index 0000000000..7e215d9bda --- /dev/null +++ b/frontend/src/api/model/ApiResult.ts @@ -0,0 +1,17 @@ +export interface ApiResult { + code: ApiResultCode; + message: string; + data: T; +} + +export enum ApiResultCode { + /** + * 成功 + */ + OK = 200, + + /** + * 未授权 + */ + Unauthorized = 401, +} diff --git a/frontend/src/api/model/sysconf/SysConfig.ts b/frontend/src/api/model/sysconf/SysConfig.ts new file mode 100644 index 0000000000..cf921372e5 --- /dev/null +++ b/frontend/src/api/model/sysconf/SysConfig.ts @@ -0,0 +1,4 @@ +export interface SysConfig { + isSysCK: boolean; + isAuth: boolean; +} diff --git a/frontend/src/api/sysconf.ts b/frontend/src/api/sysconf.ts new file mode 100644 index 0000000000..8b45030327 --- /dev/null +++ b/frontend/src/api/sysconf.ts @@ -0,0 +1,15 @@ +import type { ApiResult } from './model/ApiResult'; +import type { SysConfig } from './model/sysconf/SysConfig'; + +export async function getSysConfig() { + const url = '/sysconf'; + return fetch(url, { + credentials: 'include', + }).then((res) => res.json() as unknown as ApiResult); +} + +const sysConfApi = { + getSysConfig, +}; + +export default sysConfApi; diff --git a/frontend/src/components/ChatNav/ChatNav.vue b/frontend/src/components/ChatNav/ChatNav.vue index 3e77795805..433630aff5 100644 --- a/frontend/src/components/ChatNav/ChatNav.vue +++ b/frontend/src/components/ChatNav/ChatNav.vue @@ -2,33 +2,36 @@ import { h, ref } from 'vue'; import { NDropdown, type DropdownOption, NModal, NInput, NButton, useMessage, NImage } from 'naive-ui'; import settingSvgUrl from '@/assets/img/setting.svg?url'; -import cookies from '@/utils/cookies'; import { usePromptStore } from '@/stores/modules/prompt'; import { storeToRefs } from 'pinia'; import ChatNavItem from './ChatNavItem.vue'; import type { Component } from 'vue'; import { isMobile } from '@/utils/utils'; import CreateImage from '@/components/CreateImage/CreateImage.vue'; +import { useChatStore } from '@/stores/modules/chat'; +import { useUserStore } from '@/stores/modules/user'; const isShowMore = ref(false); const isShowSetTokenModal = ref(false); const userToken = ref(''); -const userTokenCookieName = '_U'; -const randIpCookieName = 'BingAI_Rand_IP'; const message = useMessage(); const promptStore = usePromptStore(); const { isShowPromptSotre } = storeToRefs(promptStore); const isShowClearCacheModal = ref(false); const isShowCreateImageModal = ref(false); +const chatStore = useChatStore(); +const { isShowChatServiceSelectModal } = storeToRefs(chatStore); +const userStore = useUserStore(); const navType = { github: 'github', + version: 'version', + chatService: 'chatService', + promptStore: 'promptStore', setToken: 'setToken', compose: 'compose', createImage: 'createImage', - promptStore: 'promptStore', reset: 'reset', - version: 'version', }; const navConfigs = [ { @@ -40,6 +43,10 @@ const navConfigs = [ key: navType.version, label: '版本信息', }, + { + key: navType.chatService, + label: '服务选择', + }, { key: navType.promptStore, label: '提示词库', @@ -74,23 +81,35 @@ const handleSelect = (key: string) => { message.success(`当前版本号为:${__APP_INFO__.version}`); } break; + case navType.chatService: + { + isShowChatServiceSelectModal.value = true; + chatStore.checkAllSydneyConfig(); + } + break; case navType.promptStore: - isShowPromptSotre.value = true; + { + isShowPromptSotre.value = true; + } break; case navType.setToken: { - userToken.value = cookies.get(userTokenCookieName) || ''; + userToken.value = userStore.getUserToken(); isShowSetTokenModal.value = true; } break; - case navType.reset: - isShowClearCacheModal.value = true; - break; case navType.createImage: - if (!cookies.get(userTokenCookieName)) { - message.warning('体验画图功能需先登录'); + { + if (!userStore.sysConfig?.isSysCK && !userStore.getUserToken()) { + message.warning('体验画图功能需先登录'); + } + isShowCreateImageModal.value = true; + } + break; + case navType.reset: + { + isShowClearCacheModal.value = true; } - isShowCreateImageModal.value = true; break; default: break; @@ -98,9 +117,7 @@ const handleSelect = (key: string) => { }; const resetCache = async () => { isShowClearCacheModal.value = false; - cookies.set(userTokenCookieName, '', -1); - cookies.set(randIpCookieName, '', -1); - await clearCache(); + await userStore.resetCache(); message.success('清理完成'); window.location.reload(); }; @@ -110,28 +127,9 @@ const saveUserToken = () => { message.warning('请先填入用户 Cookie'); return; } - cookies.set(userTokenCookieName, userToken.value, 7 * 24 * 60, '/'); + userStore.saveUserToken(userToken.value); isShowSetTokenModal.value = false; }; - -const clearCache = async () => { - // del storage - localStorage.clear(); - sessionStorage.clear(); - // del sw cache - const cacheKeys = await caches.keys(); - for (const cacheKey of cacheKeys) { - await caches.open(cacheKey).then(async (cache) => { - const requests = await cache.keys(); - return await Promise.all( - requests.map((request) => { - console.log(`del cache : `, request.url); - return cache.delete(request); - }) - ); - }); - } -};