mirror of
https://github.com/zgs225/cliproxy-plugin-commandcode.git
synced 2026-09-26 03:32:50 +08:00
feat: initial implementation of CLIProxyAPI Command Code plugin (stage 1)
This commit is contained in:
+166
@@ -0,0 +1,166 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var cookieRegex = regexp.MustCompile(`(?:^|;\s*)__Secure-commandcode_prod_\.session_token=([^;]+)`)
|
||||
|
||||
// RawAuthContent represents possible structures inside a commandcode credential JSON file.
|
||||
type RawAuthContent struct {
|
||||
Type string `json:"type"`
|
||||
Provider string `json:"provider"`
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
SessionToken string `json:"session_token"`
|
||||
CommandCodeSession string `json:"commandcode_session_token"`
|
||||
Cookie string `json:"cookie"`
|
||||
Token string `json:"token"`
|
||||
UpstreamBase string `json:"api_base"`
|
||||
}
|
||||
|
||||
// ExtractSessionToken extracts the clean session token from a raw string or cookie string.
|
||||
func ExtractSessionToken(raw string) string {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return ""
|
||||
}
|
||||
if matches := cookieRegex.FindStringSubmatch(raw); len(matches) > 1 {
|
||||
return strings.TrimSpace(matches[1])
|
||||
}
|
||||
if strings.HasPrefix(raw, "__Secure-commandcode_prod_.session_token=") {
|
||||
trimmed := strings.TrimPrefix(raw, "__Secure-commandcode_prod_.session_token=")
|
||||
if idx := strings.Index(trimmed, ";"); idx != -1 {
|
||||
trimmed = trimmed[:idx]
|
||||
}
|
||||
return strings.TrimSpace(trimmed)
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
// FormatSessionCookie ensures the token is formatted as the upstream Cookie header value.
|
||||
func FormatSessionCookie(token string) string {
|
||||
clean := ExtractSessionToken(token)
|
||||
if clean == "" {
|
||||
return ""
|
||||
}
|
||||
return "__Secure-commandcode_prod_.session_token=" + clean
|
||||
}
|
||||
|
||||
// ParseAuth handles auth.parse requests for Command Code credentials.
|
||||
func ParseAuth(req AuthParseRequest) (AuthParseResponse, error) {
|
||||
lowerFileName := strings.ToLower(req.FileName)
|
||||
isCommandCodeFile := strings.HasPrefix(lowerFileName, "commandcode") && strings.HasSuffix(lowerFileName, ".json")
|
||||
isCommandCodeProvider := strings.EqualFold(req.Provider, PluginID)
|
||||
|
||||
var content RawAuthContent
|
||||
var rawMap map[string]any
|
||||
if len(req.RawJSON) > 0 {
|
||||
if err := json.Unmarshal(req.RawJSON, &content); err == nil {
|
||||
_ = json.Unmarshal(req.RawJSON, &rawMap)
|
||||
}
|
||||
}
|
||||
|
||||
isExplicitCommandCode := strings.EqualFold(content.Type, PluginID) ||
|
||||
strings.EqualFold(content.Provider, PluginID) ||
|
||||
content.SessionToken != "" ||
|
||||
content.CommandCodeSession != "" ||
|
||||
strings.Contains(content.Cookie, "__Secure-commandcode_prod_.session_token")
|
||||
|
||||
if !isCommandCodeFile && !isCommandCodeProvider && !isExplicitCommandCode {
|
||||
return AuthParseResponse{Handled: false}, nil
|
||||
}
|
||||
|
||||
// Extract session token
|
||||
token := content.SessionToken
|
||||
if token == "" {
|
||||
token = content.CommandCodeSession
|
||||
}
|
||||
if token == "" && content.Cookie != "" {
|
||||
token = ExtractSessionToken(content.Cookie)
|
||||
}
|
||||
if token == "" && (isCommandCodeFile || isCommandCodeProvider || isExplicitCommandCode) {
|
||||
token = content.Token
|
||||
}
|
||||
token = ExtractSessionToken(token)
|
||||
|
||||
// Determine ID
|
||||
authID := content.ID
|
||||
if authID == "" && req.FileName != "" {
|
||||
base := filepath.Base(req.FileName)
|
||||
authID = strings.TrimSuffix(base, filepath.Ext(base))
|
||||
}
|
||||
if authID == "" {
|
||||
authID = "commandcode-default"
|
||||
}
|
||||
|
||||
// Determine Label
|
||||
label := content.Label
|
||||
if label == "" {
|
||||
label = content.Name
|
||||
}
|
||||
if label == "" && content.Email != "" {
|
||||
label = fmt.Sprintf("Command Code (%s)", content.Email)
|
||||
}
|
||||
if label == "" {
|
||||
label = fmt.Sprintf("Command Code (%s)", authID)
|
||||
}
|
||||
|
||||
// Build clean StorageJSON
|
||||
storageMap := map[string]any{
|
||||
"type": PluginID,
|
||||
"provider": PluginID,
|
||||
"session_token": token,
|
||||
}
|
||||
if content.Email != "" {
|
||||
storageMap["email"] = content.Email
|
||||
}
|
||||
if content.Label != "" {
|
||||
storageMap["label"] = content.Label
|
||||
}
|
||||
if content.UpstreamBase != "" {
|
||||
storageMap["api_base"] = content.UpstreamBase
|
||||
}
|
||||
for k, v := range rawMap {
|
||||
if _, exists := storageMap[k]; !exists {
|
||||
storageMap[k] = v
|
||||
}
|
||||
}
|
||||
storageJSON, _ := json.Marshal(storageMap)
|
||||
|
||||
metadata := map[string]any{
|
||||
"type": PluginID,
|
||||
"session_token": token,
|
||||
}
|
||||
if content.Email != "" {
|
||||
metadata["email"] = content.Email
|
||||
}
|
||||
|
||||
attributes := map[string]string{
|
||||
"provider": PluginID,
|
||||
}
|
||||
|
||||
authData := AuthData{
|
||||
Provider: PluginID,
|
||||
ID: authID,
|
||||
FileName: req.FileName,
|
||||
Label: label,
|
||||
Disabled: false,
|
||||
StorageJSON: storageJSON,
|
||||
Metadata: metadata,
|
||||
Attributes: attributes,
|
||||
NextRefreshAfter: time.Now().Add(24 * time.Hour).UTC(),
|
||||
}
|
||||
|
||||
return AuthParseResponse{
|
||||
Handled: true,
|
||||
Auth: authData,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user