From b39951eef0082f7f2a1079ab4654c9385a687704 Mon Sep 17 00:00:00 2001 From: GCSLaoLi Date: Sun, 17 Dec 2023 22:21:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0UI=E4=BF=AE=E5=A4=8DBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api.go | 2 +- api/index.go | 63 +++++--- api/login.go | 8 +- api/next.go | 78 +++++---- api/session.go | 5 +- arkose/proxyarkose.go | 57 ------- backend-api/backend-api.go | 1 + config.yaml | 1 + config/config.go | 123 +++++++++++++- frontend/.vscode/settings.json | 2 +- frontend/package.json | 1 + frontend/src/main.ts | 3 +- .../src/modules/chatgpt/views/FKArkos.vue | 140 ++++++++++++++++ .../src/modules/chatgpt/views/session.vue | 97 ++++++++++- frontend/stats.html | 2 +- frontend/yarn.lock | 151 ++++++++++++++++++ internal/cmd/cmd.go | 2 - modules/chatgpt/service/chatgpt_session.go | 51 +++--- modules/chatgpt/tasks/refresh_session.go | 3 + .../template/q1uPMR9VmRS6HPYxPKMbH/chat.html | 1 + .../q1uPMR9VmRS6HPYxPKMbH/discovery.html | 1 + .../q1uPMR9VmRS6HPYxPKMbH/editor.html | 1 + .../template/q1uPMR9VmRS6HPYxPKMbH/g.html | 1 + .../template/q1uPMR9VmRS6HPYxPKMbH/gc.html | 1 + .../template/q1uPMR9VmRS6HPYxPKMbH/mine.html | 1 + .../template/q1uPMR9VmRS6HPYxPKMbH/slug.html | 1 + 26 files changed, 633 insertions(+), 164 deletions(-) delete mode 100644 arkose/proxyarkose.go create mode 100644 frontend/src/modules/chatgpt/views/FKArkos.vue create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/chat.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/discovery.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/editor.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/g.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/gc.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/mine.html create mode 100644 resource/template/q1uPMR9VmRS6HPYxPKMbH/slug.html diff --git a/api/api.go b/api/api.go index 2d63b30..d9316e1 100644 --- a/api/api.go +++ b/api/api.go @@ -32,7 +32,7 @@ func init() { group.GET("/g/:gizmoId/c/:convId", GC) group.GET(("/gpts/mine"), Mine) - // s.BindHandler("/_next/data/*any", Next) + s.BindHandler("/_next/data/*any", ProxyNext) group.GET("/login", Login) group.POST("/login", LoginPost) diff --git a/api/index.go b/api/index.go index d1a76a3..ffa18ac 100644 --- a/api/index.go +++ b/api/index.go @@ -10,7 +10,8 @@ import ( func Index(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + ctx := r.GetCtx() + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") // r.Response.Writer.Write([]byte("Hello XyHelper")) return @@ -55,19 +56,22 @@ func Index(r *ghttp.Request) { }` propsJson := gjson.New(props) - propsJson.Set("query.model", model) - propsJson.Set("buildId", config.BuildId) + if model != "" { + propsJson.Set("query.model", model) + } + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) - r.Response.WriteTpl("chat-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/chat.html", g.Map{ "props": propsJson, "arkoseUrl": config.ArkoseUrl, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(ctx), }) } func C(r *ghttp.Request) { - - if r.Session.MustGet("userToken").IsEmpty() { + ctx := r.GetCtx() + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -111,20 +115,21 @@ func C(r *ghttp.Request) { propsJson := gjson.New(props) propsJson.Set("query.default.1", convId) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) - r.Response.WriteTpl("chat-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/chat.html", g.Map{ "props": propsJson, "arkoseUrl": config.ArkoseUrl, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(ctx), }) } // Discovery 发现 func Discovery(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -163,19 +168,20 @@ func Discovery(r *ghttp.Request) { } ` propsJson := gjson.New(props) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) - r.Response.WriteTpl("discovery-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/discovery.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } // Editor 编辑器 func Editor(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -215,7 +221,7 @@ func Editor(r *ghttp.Request) { } ` propsJson := gjson.New(props) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) // if slug != "" { @@ -224,17 +230,18 @@ func Editor(r *ghttp.Request) { // } // propsJson.Dump() - r.Response.WriteTpl("editor-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/editor.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } // Slug 编辑器 func Slug(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -277,20 +284,21 @@ func Slug(r *ghttp.Request) { propsJson := gjson.New(props) propsJson.Set("query.slug", slug) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) - r.Response.WriteTpl("slug-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/slug.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } // G 游戏 func G(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -333,20 +341,21 @@ func G(r *ghttp.Request) { ` propsJson := gjson.New(props) propsJson.Set("query.gizmoId", gizmoId) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) - r.Response.WriteTpl("g-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/g.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } // GC 游戏会话 func GC(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -393,18 +402,19 @@ func GC(r *ghttp.Request) { propsJson := gjson.New(props) propsJson.Set("query.gizmoId", gizmoId) propsJson.Set("query.convId", convId) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) - r.Response.WriteTpl("gc-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/gc.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } // Mine 我的 func Mine(r *ghttp.Request) { - if r.Session.MustGet("userToken").IsEmpty() { + if r.Session.MustGet("offical-session").IsEmpty() { r.Response.RedirectTo("/login") return } @@ -446,13 +456,14 @@ func Mine(r *ghttp.Request) { "scriptLoader": [] }` propsJson := gjson.New(props) - propsJson.Set("buildId", config.BuildId) + propsJson.Set("buildId", config.CacheBuildId) propsJson.Set("assetPrefix", config.AssetPrefix) - r.Response.WriteTpl("mine-"+config.BuildDate+".html", g.Map{ + r.Response.WriteTpl(config.CacheBuildId+"/mine.html", g.Map{ "arkoseUrl": config.ArkoseUrl, "props": propsJson, "assetPrefix": config.AssetPrefix, + "envScript": config.GetEnvScript(r.GetCtx()), }) } diff --git a/api/login.go b/api/login.go index 9ec9cf3..8b3a0ea 100644 --- a/api/login.go +++ b/api/login.go @@ -25,7 +25,7 @@ func Login(r *ghttp.Request) { func LoginPost(r *ghttp.Request) { ctx := r.GetCtx() // 如果用户名为空,就是token登录 - g.Log().Debug(ctx, "1232", r.Get("username").String() == "") + // g.Log().Debug(ctx, "1232", r.Get("username").String() == "") if r.Get("username").String() == "" { // token登录 userToken := r.Get("password").String() @@ -45,6 +45,8 @@ func LoginPost(r *ghttp.Request) { }) return } + officialSession := record["officialSession"].String() + r.Session.Set("offical-session", officialSession) r.Session.Set("userToken", userToken) r.Response.RedirectTo("/") return @@ -94,6 +96,8 @@ func LoginPost(r *ghttp.Request) { }) return } + officialSession := user["officialSession"].String() + r.Session.Set("offical-session", officialSession) r.Session.Set("userToken", user["userToken"].String()) r.Response.RedirectTo("/") @@ -126,6 +130,8 @@ func LoginToken(r *ghttp.Request) { }) return } + officialSession := record["officialSession"].String() + r.Session.Set("offical-session", officialSession) r.Session.Set("userToken", r.Get("access_token").String()) r.Response.RedirectTo("/") } diff --git a/api/next.go b/api/next.go index 81746dc..deea325 100644 --- a/api/next.go +++ b/api/next.go @@ -1,60 +1,54 @@ package api import ( - backendapi "chatgpt-mirror-server/backend-api" + "bytes" "chatgpt-mirror-server/config" - "chatgpt-mirror-server/utility" + "io" "net/http" - "time" + "net/http/httputil" + "net/url" "github.com/gogf/gf/v2/encoding/gjson" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" ) -func Next(r *ghttp.Request) { +func ProxyNext(r *ghttp.Request) { ctx := r.Context() - path := r.RequestURI - userToken := r.Session.MustGet("userToken").String() - if userToken == "" { - r.Response.WriteStatus(401) - return + officalSession := gjson.New(r.Session.MustGet("offical-session")) + refreshCookie := officalSession.Get("refreshToken").String() + u, _ := url.Parse(config.CHATPROXY(ctx)) + proxy := httputil.NewSingleHostReverseProxy(u) + proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) { + writer.WriteHeader(http.StatusBadGateway) } - officialAccessToken := backendapi.AccessTokenCache.MustGet(ctx, userToken).String() - if officialAccessToken == "" { - record, _, err := ChatgptSessionService.GetSessionByUserToken(ctx, userToken) + req := r.Request.Clone(ctx) + // 替换path 中的 cacheBuildId 为 buildId + req.URL.Path = gstr.Replace(req.URL.Path, config.CacheBuildId, config.BuildId, 1) + req.Header.Set("Cookie", "__Secure-next-auth.session-token="+refreshCookie) + proxy.ModifyResponse = func(response *http.Response) error { + response.Header.Del("Set-Cookie") + // 读取响应体 + body, err := io.ReadAll(response.Body) if err != nil { - g.Log().Error(ctx, err) - r.Response.WriteStatus(http.StatusUnauthorized) - return + return err } - if record.IsEmpty() { - g.Log().Error(ctx, "session is empty") - r.Response.WriteStatus(http.StatusUnauthorized) - return - } - officialSession := record["officialSession"].String() - if officialSession == "" { - r.Response.WriteStatus(http.StatusUnauthorized) - return - } - officialAccessToken = utility.AccessTokenFormSession(officialSession) - backendapi.AccessTokenCache.Set(ctx, userToken, officialAccessToken, time.Minute) - } - refreshCookie := gjson.New(officialAccessToken).Get("refreshToken").String() - res, err := g.Client().SetCookie("refreshToken", refreshCookie).Get(ctx, config.CHATPROXY(ctx)+path) - if err != nil { - r.Response.WriteStatus(http.StatusUnauthorized) - return - } - res.RawDump() - resStr := res.ReadAllString() - if res.StatusCode != http.StatusOK { - r.Response.Status = res.StatusCode - r.Response.Write(resStr) + // 修改响应体 + bodyJson := gjson.New(body) + bodyJson.Set("pageProps.user.email", "admin@openai.com") + bodyJson.Set("pageProps.user.name", "admin") + bodyJson.Set("pageProps.user.image", "/avatars.png") + bodyJson.Set("pageProps.user.picture", "/avatars.png") + bodyJson.Set("pageProps.user.id", "user-xadmin") + + // 写入响应体 + response.Body = io.NopCloser(bytes.NewReader(gconv.Bytes(bodyJson))) + // 重写响应头大小 + response.ContentLength = int64(len(body)) - return + return nil } - r.Response.Write(resStr) + proxy.ServeHTTP(r.Response.Writer.RawWriter(), req) } diff --git a/api/session.go b/api/session.go index 8599ddb..08cc494 100644 --- a/api/session.go +++ b/api/session.go @@ -19,7 +19,8 @@ func Session(r *ghttp.Request) { record, expireTime, err := ChatgptSessionService.GetSessionByUserToken(ctx, userToken.String()) if err != nil { g.Log().Error(ctx, err) - r.Response.WriteStatus(http.StatusUnauthorized) + r.Session.RemoveAll() + r.Response.WriteJson(g.Map{}) return } if record.IsEmpty() { @@ -39,12 +40,14 @@ func Session(r *ghttp.Request) { sessionJson := gjson.New(sessionVar) if sessionJson.Get("accessToken").String() == "" { g.Log().Error(ctx, "get session error", sessionJson) + r.Session.RemoveAll() r.Response.WriteStatus(http.StatusUnauthorized) return } cool.DBM(model.NewChatgptSession()).Where("email=?", record["email"].String()).Update(g.Map{ "officialSession": sessionJson.String(), }) + r.Session.Set("offical-session", sessionJson.String()) backendapi.AccessTokenCache.Set(ctx, userToken.String(), sessionJson.Get("accessToken").String(), 10*24*time.Hour) sessionJson.Set("accessToken", userToken.String()) sessionJson.Set("user.email", "admin@openai.com") diff --git a/arkose/proxyarkose.go b/arkose/proxyarkose.go deleted file mode 100644 index f9acffc..0000000 --- a/arkose/proxyarkose.go +++ /dev/null @@ -1,57 +0,0 @@ -package arkose - -import ( - "bytes" - "io" - "net/http" - "net/http/httputil" - "net/url" - - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gconv" -) - -var ( - UpStream = "https://client-api.arkoselabs.com/" - u, _ = url.Parse(UpStream) - proxy = httputil.NewSingleHostReverseProxy(u) -) - -func init() { - -} - -func Proxy(r *ghttp.Request) { - - proxy.Director = func(req *http.Request) { - requrl := r.Request.URL.Path - if requrl == "/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147" { - body := r.GetBodyString() - bodyArray := gstr.Split(body, "&") - // 遍历数组 当数组元素以 "site=http" 开头时,将其替换为 "site=http%3A%2F%2Flocalhost%3A3000" - for i, v := range bodyArray { - if gstr.HasPrefix(v, "site=http") { - bodyArray[i] = "site=http%3A%2F%2Flocalhost%3A3000" - } - } - body = gstr.Join(bodyArray, "&") - - req.Body = io.NopCloser(bytes.NewReader(gconv.Bytes(body))) - req.ContentLength = int64(len(body)) - } - - req.Header = r.Header - req.Host = u.Host - req.URL.Scheme = u.Scheme - req.URL.Host = u.Host - req.URL.Path = requrl - - req.Header.Set("Origin", "http://localhost:3000") - req.Header.Set("Referer", "http://localhost:3000/v2/1.5.4/enforcement.cd12da708fe6cbe6e068918c38de2ad9.html") - - } - - proxy.ServeHTTP(r.Response.RawWriter(), r.Request) - -} diff --git a/backend-api/backend-api.go b/backend-api/backend-api.go index 46249da..6a6a2f6 100644 --- a/backend-api/backend-api.go +++ b/backend-api/backend-api.go @@ -38,6 +38,7 @@ func NotFound(r *ghttp.Request) { func ProxyAll(r *ghttp.Request) { ctx := r.GetCtx() // 获取header中的token Authorization: Bearer xxx 去掉Bearer + userToken := r.Header.Get("Authorization")[7:] officialAccessToken := AccessTokenCache.MustGet(ctx, userToken).String() if officialAccessToken == "" { diff --git a/config.yaml b/config.yaml index 0f4f3d4..8a98d77 100644 --- a/config.yaml +++ b/config.yaml @@ -57,6 +57,7 @@ modules: # 接入网关地址 CHATPROXY: "https://demo.xyhelper.cn" +# CHATPROXY: "http://172.17.0.1:7009" # 接入网关的authkey AUTHKEY: "xyhelper" ONLYTOKEN: true diff --git a/config/config.go b/config/config.go index 8260b47..d7700e4 100644 --- a/config/config.go +++ b/config/config.go @@ -5,8 +5,12 @@ import ( "time" "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gview" + "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) @@ -15,7 +19,7 @@ func CHATPROXY(ctx g.Ctx) string { } func AUTHKEY(ctx g.Ctx) string { - g.Log().Debug(ctx, "config.AUTHKEY", g.Cfg().MustGetWithEnv(ctx, "AUTHKEY").String()) + // g.Log().Debug(ctx, "config.AUTHKEY", g.Cfg().MustGetWithEnv(ctx, "AUTHKEY").String()) return g.Cfg().MustGetWithEnv(ctx, "AUTHKEY").String() } @@ -27,10 +31,20 @@ var ( DefaultModel = "text-davinci-002-render-sha" FreeModels = garray.NewStrArray() PlusModels = garray.NewStrArray() - ArkoseUrl = "https://tcr9i.xyhelper.com.cn/v2/" - BuildDate = "20231202" - BuildId = "h8j8GC1m0GPjiDDpUuDdq" + ArkoseUrl = "https://tcr9i.closeai.biz/v2/" + BuildId = "q1uPMR9VmRS6HPYxPKMbH" + CacheBuildId = "q1uPMR9VmRS6HPYxPKMbH" AssetPrefix = "https://oaistatic-cdn.closeai.biz" + PK40 = "35536E1E-65B4-4D96-9D97-6ADB7EFF8147" + PK35 = "3D86FBBA-9D22-402A-B512-3420086BA6CC" + envScriptTpl = ` + + ` ) func init() { @@ -52,6 +66,32 @@ func init() { AssetPrefix = assetPrefix } g.Log().Info(ctx, "ASSET_PREFIX:", AssetPrefix) + cacheBuildId := CheckVersion(ctx, AssetPrefix) + if cacheBuildId != "" { + CacheBuildId = cacheBuildId + } + g.Log().Info(ctx, "CacheBuildId:", CacheBuildId) + build := CheckNewVersion(ctx) + if build != "" { + BuildId = build + } + g.Log().Info(ctx, "BuildId:", BuildId) + // 每小时更新一次 + go func() { + for { + time.Sleep(time.Hour) + build := CheckNewVersion(ctx) + if build != "" { + BuildId = build + } + g.Log().Info(ctx, "BuildId:", BuildId) + cacheBuildId := CheckVersion(ctx, AssetPrefix) + if cacheBuildId != "" { + CacheBuildId = cacheBuildId + } + g.Log().Info(ctx, "CacheBuildId:", CacheBuildId) + } + }() } @@ -97,3 +137,78 @@ func APIAUTH(ctx g.Ctx) string { func CLEARCHATHISTORY(ctx g.Ctx) bool { return g.Cfg().MustGetWithEnv(ctx, "CLEARCHATHISTORY").Bool() } + +// 检查版本号并同步资源 +func CheckVersion(ctx g.Ctx, assetPrefix string) (CacheBuildId string) { + gclient := g.Client() + // 读取 assetPrefix/version + versionVar := gclient.GetVar(ctx, assetPrefix+"/version.json") + CacheBuildId = gjson.New(versionVar).Get("cacheBuildId").String() + g.Log().Infof(ctx, "Get config From %s ,CacheBuildId: %s", AssetPrefix, CacheBuildId) + if CacheBuildId == "" { + return "" + } + // 读取buildDate目录索引 + indexUrl := assetPrefix + "/template/" + CacheBuildId + "/index.txt" + g.Log().Info(ctx, "Get config From ", indexUrl) + buildDateVar := gclient.GetVar(ctx, indexUrl).String() + if buildDateVar == "" { + return "" + } + // 按回车分割 + buildDateList := gstr.Split(buildDateVar, "\n") + g.Dump(buildDateList) + // 遍历目录索引 如果没有就下载 + for _, v := range buildDateList { + if v == "" { + continue + } + // 检查文件是否存在 + if !gfile.Exists("./resource/template/" + CacheBuildId + "/" + v) { + g.Log().Infof(ctx, "Download %s", v) + // 下载文件 + res, err := gclient.Get(ctx, assetPrefix+"/template/"+CacheBuildId+"/"+v) + if err != nil { + g.Log().Error(ctx, "Download Error: ", v, err) + return "" + } + defer res.Close() + if res.StatusCode != 200 { + g.Log().Error(ctx, "Download Error: ", v, res.StatusCode) + return "" + } + // 写入文件 + err = gfile.PutBytes("./resource/template/"+CacheBuildId+"/"+v, res.ReadAll()) + if err != nil { + g.Log().Error(ctx, "Download Error: ", v, err) + return "" + } + + } + } + + return +} + +func GetEnvScript(ctx g.Ctx) string { + script, err := gview.ParseContent(ctx, envScriptTpl, g.Map{ + "ArkoseUrl": ArkoseUrl, + "AssetPrefix": AssetPrefix, + "PK40": PK40, + "PK35": PK35, + }) + if err != nil { + g.Log().Error(ctx, "GetEnvScript Error: ", err) + return "" + } + return script +} + +// 检查是否有新版本 +func CheckNewVersion(ctx g.Ctx) (buildId string) { + resVar := g.Client().GetVar(ctx, CHATPROXY(ctx)+"/ping") + resJson := gjson.New(resVar) + + buildId = resJson.Get("buildId").String() + return +} diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json index 07f6c52..f24801c 100644 --- a/frontend/.vscode/settings.json +++ b/frontend/.vscode/settings.json @@ -1,4 +1,4 @@ { - "editor.cursorSmoothCaretAnimation": true, + "editor.cursorSmoothCaretAnimation": "on", "editor.formatOnSave": true, } diff --git a/frontend/package.json b/frontend/package.json index 55874ff..720bb08 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,6 +19,7 @@ "echarts": "^5.3.3", "element-plus": "^2.2.28", "file-saver": "^2.0.5", + "fkarkos": "^0.1.1", "lodash-es": "^4.17.21", "mitt": "^3.0.0", "mockjs": "^1.1.0", diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 1c2c5ed..72068c9 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -3,7 +3,8 @@ import App from "./App.vue"; import { bootstrap } from "./cool"; const app = createApp(App); - +// import fkarkos from "fkarkos"; +// app.component("fkarkos", fkarkos); // 启动 bootstrap(app) .then(() => { diff --git a/frontend/src/modules/chatgpt/views/FKArkos.vue b/frontend/src/modules/chatgpt/views/FKArkos.vue new file mode 100644 index 0000000..03209d1 --- /dev/null +++ b/frontend/src/modules/chatgpt/views/FKArkos.vue @@ -0,0 +1,140 @@ + + + diff --git a/frontend/src/modules/chatgpt/views/session.vue b/frontend/src/modules/chatgpt/views/session.vue index b1b86cd..298db02 100644 --- a/frontend/src/modules/chatgpt/views/session.vue +++ b/frontend/src/modules/chatgpt/views/session.vue @@ -25,6 +25,13 @@ + @@ -37,9 +44,24 @@ const { service } = useCool(); // cl-upsert 配置 const Upsert = useUpsert({ items: [ - { label: "邮箱", prop: "email", required: true, component: { name: "el-input" } }, - { label: "密码", prop: "password", required: true, component: { name: "el-input" } }, - { label: "用户ID", prop: "userID", required: true, component: { name: "el-input-number" } }, + { + label: "邮箱", + prop: "email", + required: true, + component: { name: "el-input" } + }, + { + label: "密码", + prop: "password", + required: true, + component: { name: "el-input" } + }, + { + label: "用户ID", + prop: "userID", + required: true, + component: { name: "el-input-number" } + }, { label: "状态", prop: "status", @@ -78,6 +100,20 @@ const Upsert = useUpsert({ if (!data.userID) { data.userID = 0; } + localStorage.removeItem("arkoseToken"); + window.myEnforcement.run(); + }, + onSubmit(data, { done, close, next }) { + // 自动生成uuid 作为userToken + let arkoseToken = localStorage.getItem("arkoseToken"); + if (arkoseToken) { + next({ ...data, arkoseToken }); + done(); + close(); + } else { + alert("请刷新页面,重新验证"); + done(); + } } }); @@ -91,15 +127,30 @@ const Table = useTable({ { label: "邮箱", prop: "email", sortable: true }, { label: "密码", prop: "password", sortable: true }, { label: "用户ID", prop: "userID", sortable: true }, - { label: "状态", prop: "status", component: { name: "cl-switch" }, sortable: true }, - { label: "PLUS", prop: "isPlus", component: { name: "cl-switch" }, sortable: true }, + { + label: "状态", + prop: "status", + component: { name: "cl-switch" }, + sortable: true + }, + { + label: "PLUS", + prop: "isPlus", + component: { name: "cl-switch" }, + sortable: true + }, { label: "session", prop: "officialSession", showOverflowTooltip: true, sortable: true }, - { label: "备注", prop: "remark", showOverflowTooltip: true, sortable: true }, + { + label: "备注", + prop: "remark", + showOverflowTooltip: true, + sortable: true + }, { type: "op", buttons: ["edit", "delete"] } ] }); @@ -114,3 +165,37 @@ const Crud = useCrud( } ); + diff --git a/frontend/stats.html b/frontend/stats.html index 60a591e..afd2939 100644 --- a/frontend/stats.html +++ b/frontend/stats.html @@ -6157,7 +6157,7 @@