Files
copilot-app/internal/controller/copilot/get_copilot_internal_v2_token.go
2025-08-13 19:03:20 +08:00

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