mirror of
https://gitee.com/chuangxxt/share-copilot
synced 2025-04-18 23:23:27 +00:00
增加代码提示修改功能
This commit is contained in:
parent
f166316c6f
commit
465426e4e1
31
README.md
31
README.md
@ -1,10 +1,9 @@
|
|||||||
|
|
||||||
[中文](README.md) | [English](README-EN.md)
|
[中文](README.md) | [English](README-EN.md)
|
||||||
|
|
||||||
|
|
||||||
# share-copilot
|
# share-copilot
|
||||||
|
|
||||||
- 作为代理服务器,中转copilot插件的API的请求
|
- 作为代理服务器,中转copilot插件的API的请求(也可以代理无良商贩的,自行研究)
|
||||||
- 支持vscode插件和jetbrains插件
|
- 支持vscode插件和jetbrains插件
|
||||||
- 支持多用户共享一个token
|
- 支持多用户共享一个token
|
||||||
- 优化请求逻辑,降低suspended概率(别万人骑基本不会)
|
- 优化请求逻辑,降低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
|
代码提示都是用的co_token
|
||||||
|
|
||||||
3.co_token到期->ghu_token重新请求->获得新的co_token
|
3.co_token到期->ghu_token重新请求->获得新的co_token
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|
||||||
代理服务器的逻辑:
|
代理服务器的逻辑:
|
||||||
|
|
||||||
代理的是"ghu_token请求"这一环节
|
代理的是"ghu_token请求"这一环节
|
||||||
|
|
||||||
1.携ghu_token请求github的API,暂存co_token
|
1.使用ghu_token请求github的API,暂存co_token
|
||||||
|
|
||||||
2.多用户请求时,判断co_token有没有过期,没过期直接返回,
|
2.多用户请求时,判断co_token有没有过期,没过期直接返回co_token,
|
||||||
减少ghu_token的请求次数(大约10-20分钟过期)
|
减少对ghu_token的请求次数(大约10-20分钟过期)
|
||||||
|
|
||||||
3.至于本地co_token,也就是代码提示没有走代理(可以代理,但是要修改插件,jetbrains的插件还要重新build)
|
3.至于本地co_token,也就是代码提示没有走代理(可以代理,但是要修改插件,jetbrains的插件还要重新build)
|
||||||
猜测风控目前也只是停留在请求ghu_token这一层
|
猜测风控目前也只是停留在请求ghu_token这一层
|
||||||
|
|
||||||
"cocopilot也是代理了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
|
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 自定义代理服务器路由 附加中间件(域名验证和请求验证)
|
// Routes 自定义代理服务器路由 附加中间件(域名验证和请求验证)
|
||||||
func Routes() {
|
func Routes() {
|
||||||
|
// 定义根路由
|
||||||
copilotApi := copilotGinEngine.Group("/copilot_internal", DomainMiddleware(configFile.Server.Domain), VerifyRequestMiddleware())
|
copilotApi := copilotGinEngine.Group("/copilot_internal", DomainMiddleware(configFile.Server.Domain), VerifyRequestMiddleware())
|
||||||
|
|
||||||
|
// 定义代理github token的路由
|
||||||
copilotApi.GET("/v2/token", getCopilotToken())
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,3 +81,61 @@ func diyBadRequest(c *gin.Context, code int, errorMessage string) {
|
|||||||
"documentation_url": "https://docs.github.com/rest",
|
"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