mirror of
https://gitee.com/chuangxxt/share-copilot
synced 2025-04-16 10:23:25 +00:00
增加代码提示修改功能
This commit is contained in:
parent
f166316c6f
commit
465426e4e1
33
README.md
33
README.md
@ -1,10 +1,9 @@
|
||||
|
||||
[中文](README.md) | [English](README-EN.md)
|
||||
|
||||
|
||||
# share-copilot
|
||||
# share-copilot
|
||||
|
||||
- 作为代理服务器,中转copilot插件的API的请求
|
||||
- 作为代理服务器,中转copilot插件的API的请求(也可以代理无良商贩的,自行研究)
|
||||
- 支持vscode插件和jetbrains插件
|
||||
- 支持多用户共享一个token
|
||||
- 优化请求逻辑,降低suspended概率(别万人骑基本不会)
|
||||
@ -13,30 +12,44 @@
|
||||
简单说一下
|
||||
本地插件的请求逻辑:
|
||||
|
||||
1.本地插件携ghu_token请求github的API
|
||||
1.本地插件携ghu_token 请求github的API
|
||||
|
||||
2.返回带有时间戳的copilot的token(下面简称co_token),
|
||||
2.返回带有时间戳的copilot的token(简称co_token),
|
||||
代码提示都是用的co_token
|
||||
|
||||
3.co_token到期->ghu_token重新请求->获得新的co_token
|
||||
-------------------------------------------------------------
|
||||
|
||||
代理服务器的逻辑:
|
||||
|
||||
代理的是"ghu_token请求"这一环节
|
||||
|
||||
1.携ghu_token请求github的API,暂存co_token
|
||||
1.使用ghu_token请求github的API,暂存co_token
|
||||
|
||||
2.多用户请求时,判断co_token有没有过期,没过期直接返回,
|
||||
减少ghu_token的请求次数(大约10-20分钟过期)
|
||||
2.多用户请求时,判断co_token有没有过期,没过期直接返回co_token,
|
||||
减少对ghu_token的请求次数(大约10-20分钟过期)
|
||||
|
||||
3.至于本地co_token,也就是代码提示没有走代理(可以代理,但是要修改插件,jetbrains的插件还要重新build)
|
||||
猜测风控目前也只是停留在请求ghu_token这一层
|
||||
|
||||
"cocopilot也是代理了ghu_token请求,并没有破解插件"
|
||||
|
||||
```
|
||||
|
||||

|
||||
------
|
||||
|
||||
```xml
|
||||
| 文件名 | 说明
|
||||
| -------------- | -------------------
|
||||
| config.json | 配置文件
|
||||
| copilot_api | guh_token和co_token相关逻辑
|
||||
| global | 全局变量、常量或配置
|
||||
| main | 主要入口文件
|
||||
| middleware | 中间件,验证域名,验证自定义请求头
|
||||
| routers | 路由信息,定义不同请求路径的处理逻辑。
|
||||
| server | 服务端的代码或相关配置,用于启动和运行服务器。
|
||||
| show_msg | 用于显示消息或信息的函数,展示内容。
|
||||
|
||||
```
|
||||
|
||||
***
|
||||
# 一、自行编译:
|
||||
|
@ -39,3 +39,11 @@ var (
|
||||
//请求成功计数
|
||||
successCount = 0
|
||||
)
|
||||
|
||||
// 测试的玩意儿
|
||||
var (
|
||||
diyMsg = ";//授权已经过期,重新获取-> https://www.sharecopilot.top"
|
||||
completionUrl = "https://copilot-proxy.githubusercontent.com/v1/engines/copilot-codex/completions"
|
||||
telemetryUrl = "https://copilot-telemetry.githubusercontent.com/telemetry"
|
||||
isModMsg = false
|
||||
)
|
||||
|
@ -2,6 +2,15 @@ package main
|
||||
|
||||
// Routes 自定义代理服务器路由 附加中间件(域名验证和请求验证)
|
||||
func Routes() {
|
||||
// 定义根路由
|
||||
copilotApi := copilotGinEngine.Group("/copilot_internal", DomainMiddleware(configFile.Server.Domain), VerifyRequestMiddleware())
|
||||
|
||||
// 定义代理github token的路由
|
||||
copilotApi.GET("/v2/token", getCopilotToken())
|
||||
|
||||
// 定义 completions路由的反向代理
|
||||
registerProxyRoute(copilotGinEngine, "/v1/engines/copilot-codex/completions", completionUrl)
|
||||
|
||||
// 定义 telemetry路由的反向代理 ,
|
||||
registerProxyRoute(copilotGinEngine, "/telemetry", telemetryUrl)
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -76,3 +81,61 @@ func diyBadRequest(c *gin.Context, code int, errorMessage string) {
|
||||
"documentation_url": "https://docs.github.com/rest",
|
||||
})
|
||||
}
|
||||
|
||||
// registerProxyRoute 反向代理路由
|
||||
func registerProxyRoute(r *gin.Engine, routePath, targetURL string) {
|
||||
target, err := url.Parse(targetURL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Scheme = "https"
|
||||
req.Host = target.Host
|
||||
},
|
||||
ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
},
|
||||
}
|
||||
r.Any(routePath, func(c *gin.Context) {
|
||||
proxy.Director = func(req *http.Request) {
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Scheme = "https"
|
||||
req.Host = target.Host
|
||||
}
|
||||
if isModMsg {
|
||||
modProxyResp(c, proxy)
|
||||
}
|
||||
proxy.ServeHTTP(c.Writer, c.Request)
|
||||
})
|
||||
}
|
||||
|
||||
// 修改代码提示内容
|
||||
func modProxyResp(c *gin.Context, proxy *httputil.ReverseProxy) {
|
||||
proxy.ModifyResponse = func(response *http.Response) error {
|
||||
responseBuffer := new(bytes.Buffer)
|
||||
_, readErr := responseBuffer.ReadFrom(response.Body)
|
||||
if readErr != nil {
|
||||
return readErr
|
||||
}
|
||||
responseData := responseBuffer.Bytes()
|
||||
pattern := `(.*?)data:`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
match := regex.FindStringSubmatch(string(responseData))
|
||||
var replacedData = ""
|
||||
if len(match) >= 2 {
|
||||
replacedData = match[1]
|
||||
} else {
|
||||
fmt.Println("No match found.")
|
||||
}
|
||||
runes := []rune(diyMsg)
|
||||
newStr := ""
|
||||
for _, r := range runes {
|
||||
newStr += fmt.Sprintf("data: {\"id\":\"cmpl-7xy1GLgssjHEubVrPyt534VRYVF0t\",\"model\":\"cushman-ml\",\"created\":1694526422,\"choices\":[{\"text\":\"%c\",\"index\":0,\"finish_reason\":null,\"logprobs\":null}]}\n", r)
|
||||
}
|
||||
newStr = replacedData + newStr + "data: [DONE]\n"
|
||||
fmt.Println(newStr)
|
||||
c.Data(response.StatusCode, response.Header.Get("Content-Type"), []byte(newStr))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user