增加代码提示修改功能

This commit is contained in:
luyoyu 2023-09-20 23:51:23 +08:00
parent f166316c6f
commit 465426e4e1
4 changed files with 103 additions and 10 deletions

View File

@ -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请求并没有破解插件"
```
![软件系统网络架构.png](https://img1.imgtp.com/2023/09/10/qTL8A2u9.png)
------
```xml
| 文件名 | 说明
| -------------- | -------------------
| config.json | 配置文件
| copilot_api | guh_token和co_token相关逻辑
| global | 全局变量、常量或配置
| main | 主要入口文件
| middleware | 中间件,验证域名,验证自定义请求头
| routers | 路由信息,定义不同请求路径的处理逻辑。
| server | 服务端的代码或相关配置,用于启动和运行服务器。
| show_msg | 用于显示消息或信息的函数,展示内容。
```
***
# 一、自行编译:

View File

@ -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
)

View File

@ -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)
}

View File

@ -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
}
}