Skip to content
This repository has been archived by the owner on Mar 22, 2024. It is now read-only.

Feature/add cli #1

Merged
merged 2 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Build
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY . .
RUN go build -o copi

# Deploy
FROM debian:stretch-slim

WORKDIR /app
COPY --from=builder /app/copi .

# Copy all system certificates from the builder stage
COPY --from=builder /etc/ssl/certs /etc/ssl/certs

EXPOSE 8081
CMD ["./copi"]

116 changes: 116 additions & 0 deletions copilot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package main

import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path"
"sync"
"time"

"github.com/mitchellh/go-homedir"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)

var (
caches = new(cache.Cache)
copilotCFG = new(copilot)
)

func getCopilot() copiloter {
return copilotCFG
}

type copilot struct {
GithubCom struct {
User string `json:"user"`
OauthToken string `json:"oauth_token"`
DevOverride struct {
CopilotTokenURL string `json:"copilot_token_url"`
} `json:"dev_override"`
} `json:"github.com"`
}

func Init() {
// init cache
one := &sync.Once{}
one.Do(func() {
caches = cache.New(15*time.Minute, 20*time.Minute)
})

// ~/.config/github-copilot/hosts.json
// get user home directory
dir, err := homedir.Dir()
if err != nil {
log.Fatal(err)
}
hostsJson := path.Join(dir, ".config", "github-copilot", "hosts.json")
_, err = os.Stat(hostsJson)

if !os.IsNotExist(err) {
bts, err := os.ReadFile(hostsJson)
if err != nil {
log.Fatal(err)
}
if err := json.Unmarshal(bts, copilotCFG); err != nil {
log.Fatal(err)
}
log.Printf("read config file path: %s", hostsJson)
} else {
if copilotToken == "" {
log.Fatal("no token and no hosts.json found, please set token or create hosts.json file in ~/.config/github-copilot/hosts.json")
}
}
if copilotToken != "" {
copilotCFG.GithubCom.OauthToken = copilotToken
}
if copilotTokenURL != "" {
copilotCFG.GithubCom.DevOverride.CopilotTokenURL = copilotTokenURL
}
}

// Copiloter is the interface that wraps the token method.
// token return the access token for github copilot
type copiloter interface {
token() (string, error)
}

func (c *copilot) token() (string, error) {
if cacheToken, ok := caches.Get(c.GithubCom.OauthToken); ok {
return cacheToken.(string), nil
}
tokenURL := c.GithubCom.DevOverride.CopilotTokenURL
if tokenURL == "" {
tokenURL = "https://api.github.com/copilot_internal/v2/token"
}

req, err := http.NewRequest(http.MethodGet, tokenURL, nil)
if err != nil {
return "", err
}
req.Header.Set("Authorization", fmt.Sprintf("token %s", c.GithubCom.OauthToken))

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("get token error: %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
if token := gjson.GetBytes(body, "token").String(); token != "" {
caches.Set(c.GithubCom.OauthToken, token, 14*time.Minute)
return token, nil
}

return "", fmt.Errorf("get token error")
}
17 changes: 16 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
package main

import "net/http"
import (
"flag"
"fmt"
"net/http"
)

var (
copilotToken string
copilotTokenURL string
)

func main() {
flag.StringVar(&copilotToken, "token", "", "token to get copilot token")
flag.StringVar(&copilotTokenURL, "token_url", "", "url to get copilot token")
flag.Parse()
fmt.Printf("copilotToken: %s\n", copilotToken)
fmt.Printf("copilotTokenURL: %s\n", copilotTokenURL)
Init()
http.HandleFunc("/", handleProxy)
http.ListenAndServe(":8081", nil)
}
2 changes: 1 addition & 1 deletion proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func handleProxy(w http.ResponseWriter, r *http.Request) {
// remove /v1/ from req.URL.Path
req.URL.Path = strings.ReplaceAll(req.URL.Path, "/v1/", "/")

accToken, err := getAccToken()
accToken, err := getCopilot().token()
if accToken == "" {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "get acc token error: %v", err)
Expand Down
78 changes: 0 additions & 78 deletions utilis.go

This file was deleted.