148 lines
4.5 KiB
Go
148 lines
4.5 KiB
Go
package copilot
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gofrs/uuid"
|
|
"log"
|
|
"math/rand"
|
|
"net/http"
|
|
"os"
|
|
"ripper/internal/app/github_auth"
|
|
"ripper/internal/cache"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// GetDisguiseCopilotInternalV2Token 返回伪装的token
|
|
func GetDisguiseCopilotInternalV2Token(ctx *gin.Context) {
|
|
requestID := uuid.Must(uuid.NewV4()).String()
|
|
ctx.Header("x-github-request-id", requestID)
|
|
|
|
trackingId, _ := uuid.NewV4()
|
|
now := time.Now().Unix()
|
|
dcAt, _ := strconv.Atoi(os.Getenv("DISGUISE_COPILOT_TOKEN_EXPIRES_AT"))
|
|
expiresAt := now + int64(dcAt)
|
|
sku := "copilot_for_business_seat"
|
|
|
|
copilotToken := github_auth.JsonMap2SignToken(map[string]interface{}{
|
|
"tid": trackingId,
|
|
"exp": expiresAt,
|
|
"sku": sku,
|
|
"st": "dotcom",
|
|
"chat": 1,
|
|
"u": "github",
|
|
})
|
|
|
|
endpoints := make(map[string]interface{})
|
|
endpoints["api"] = os.Getenv("API_BASE_URL")
|
|
endpoints["origin-tracker"] = "https://origin-tracker.individual.githubcopilot.com"
|
|
endpoints["proxy"] = os.Getenv("PROXY_BASE_URL")
|
|
endpoints["telemetry"] = os.Getenv("TELEMETRY_BASE_URL")
|
|
|
|
gout := gin.H{
|
|
"annotations_enabled": true,
|
|
"chat_enabled": true,
|
|
"chat_jetbrains_enabled": true,
|
|
"code_quote_enabled": true,
|
|
"code_review_enabled": false,
|
|
"codesearch": true,
|
|
"copilot_ide_agent_chat_gpt4_small_prompt": false,
|
|
"copilotignore_enabled": false,
|
|
"endpoints": endpoints,
|
|
"expires_at": expiresAt,
|
|
"individual": true,
|
|
"nes_enabled": false,
|
|
"prompt_8k": true,
|
|
"public_suggestions": "disabled",
|
|
"refresh_in": 1500,
|
|
"sku": sku,
|
|
"snippy_load_test_enabled": false,
|
|
"telemetry": "disabled",
|
|
"token": copilotToken,
|
|
"tracking_id": trackingId,
|
|
"intellij_editor_fetcher": false,
|
|
"vsc_electron_fetcher": false,
|
|
"vs_editor_fetcher": false,
|
|
"vsc_panel_v2": false,
|
|
"xcode": true,
|
|
"xcode_chat": true,
|
|
"limited_user_quotas": nil,
|
|
"limited_user_reset_date": nil,
|
|
"vsc_electron_fetcher_v2": false,
|
|
}
|
|
ctx.JSON(http.StatusOK, gout)
|
|
}
|
|
|
|
// GetCopilotInternalV2Token 获取github copilot官方token
|
|
func GetCopilotInternalV2Token(c *gin.Context) {
|
|
ghuTokens := strings.Split(os.Getenv("COPILOT_GHU_TOKEN"), ",")
|
|
if len(ghuTokens) == 0 {
|
|
return
|
|
}
|
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
ghu := ghuTokens[rand.Intn(len(ghuTokens))]
|
|
if ghu == "" {
|
|
log.Println("ghu token is empty")
|
|
c.JSON(http.StatusUnprocessableEntity, gin.H{
|
|
"message": "ghu token is empty",
|
|
})
|
|
return
|
|
}
|
|
|
|
cacheKey := "copilot_internal_v2_token"
|
|
token, err := cache.Get(cacheKey)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
|
cache.Del(cacheKey)
|
|
return
|
|
}
|
|
|
|
if token != nil {
|
|
c.JSON(http.StatusOK, token)
|
|
return
|
|
}
|
|
|
|
url := "https://api.github.com/copilot_internal/v2/token"
|
|
req, err := http.NewRequestWithContext(c, "GET", url, nil)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
req.Header.Set("authorization", "token "+ghu)
|
|
req.Header.Set("editor-plugin-version", "copilot-intellij/1.5.21.6667")
|
|
req.Header.Set("editor-version", "JetBrains-IU/242.21829.142")
|
|
req.Header.Set("user-agent", "GithubCopilot/1.228.0")
|
|
|
|
client := &http.Client{Timeout: 30 * time.Second}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
c.JSON(resp.StatusCode, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
errorMsg := "获取 Token 失败, 当前 ghu_token 账户可能并未订阅 github copilot 服务!" + ghu
|
|
c.JSON(resp.StatusCode, gin.H{"error": errorMsg})
|
|
log.Println(errorMsg)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var result interface{}
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
cache.Set(cacheKey, result, 1500)
|
|
c.JSON(resp.StatusCode, result)
|
|
}
|