Spaces:
Paused
Paused
add key system with RWPX prefix
Browse files- internal/handler/keys.go +108 -0
- main.go +2 -0
internal/handler/keys.go
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package handler
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"encoding/json"
|
| 5 |
+
"fmt"
|
| 6 |
+
"math/rand"
|
| 7 |
+
"net/http"
|
| 8 |
+
"os"
|
| 9 |
+
"sync"
|
| 10 |
+
"time"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type KeyData struct {
|
| 14 |
+
Name string \`json:"name"\`
|
| 15 |
+
Key string \`json:"key"\`
|
| 16 |
+
Requests int \`json:"requests"\`
|
| 17 |
+
Tokens int \`json:"tokens"\`
|
| 18 |
+
Created time.Time \`json:"created"\`
|
| 19 |
+
LastUsed time.Time \`json:"last_used"\`
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
type KeyStore struct {
|
| 23 |
+
mu sync.Mutex
|
| 24 |
+
Keys map[string]*KeyData \`json:"keys"\`
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
var store = &KeyStore{Keys: make(map[string]*KeyData)}
|
| 28 |
+
var storePath = "/data/keys.json"
|
| 29 |
+
|
| 30 |
+
func init() {
|
| 31 |
+
os.MkdirAll("/data", 0755)
|
| 32 |
+
data, err := os.ReadFile(storePath)
|
| 33 |
+
if err == nil {
|
| 34 |
+
json.Unmarshal(data, store)
|
| 35 |
+
}
|
| 36 |
+
if store.Keys == nil {
|
| 37 |
+
store.Keys = make(map[string]*KeyData)
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
func saveStore() {
|
| 42 |
+
data, _ := json.MarshalIndent(store, "", " ")
|
| 43 |
+
os.WriteFile(storePath, data, 0644)
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
func GenerateKey(name string) string {
|
| 47 |
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
| 48 |
+
b := make([]byte, 8)
|
| 49 |
+
for i := range b {
|
| 50 |
+
b[i] = chars[rand.Intn(len(chars))]
|
| 51 |
+
}
|
| 52 |
+
key := "RWPX-" + string(b)
|
| 53 |
+
store.mu.Lock()
|
| 54 |
+
store.Keys[key] = &KeyData{
|
| 55 |
+
Name: name,
|
| 56 |
+
Key: key,
|
| 57 |
+
Created: time.Now(),
|
| 58 |
+
}
|
| 59 |
+
saveStore()
|
| 60 |
+
store.mu.Unlock()
|
| 61 |
+
return key
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
func ValidateKey(key string) (bool, *KeyData) {
|
| 65 |
+
if key == "free" {
|
| 66 |
+
return true, &KeyData{Name: "guest"}
|
| 67 |
+
}
|
| 68 |
+
store.mu.Lock()
|
| 69 |
+
defer store.mu.Unlock()
|
| 70 |
+
kd, ok := store.Keys[key]
|
| 71 |
+
return ok, kd
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
func TrackUsage(key string, tokens int) {
|
| 75 |
+
if key == "free" {
|
| 76 |
+
return
|
| 77 |
+
}
|
| 78 |
+
store.mu.Lock()
|
| 79 |
+
defer store.mu.Unlock()
|
| 80 |
+
if kd, ok := store.Keys[key]; ok {
|
| 81 |
+
kd.Requests++
|
| 82 |
+
kd.Tokens += tokens
|
| 83 |
+
kd.LastUsed = time.Now()
|
| 84 |
+
saveStore()
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
func HandleGenKey(w http.ResponseWriter, r *http.Request) {
|
| 89 |
+
if r.Method != "POST" {
|
| 90 |
+
http.Error(w, "Method not allowed", 405)
|
| 91 |
+
return
|
| 92 |
+
}
|
| 93 |
+
name := r.FormValue("name")
|
| 94 |
+
if name == "" {
|
| 95 |
+
name = "usuario"
|
| 96 |
+
}
|
| 97 |
+
key := GenerateKey(name)
|
| 98 |
+
w.Header().Set("Content-Type", "application/json")
|
| 99 |
+
fmt.Fprintf(w, "{"key":"%s","name":"%s"}", key, name)
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
func HandleStats(w http.ResponseWriter, r *http.Request) {
|
| 103 |
+
store.mu.Lock()
|
| 104 |
+
defer store.mu.Unlock()
|
| 105 |
+
w.Header().Set("Content-Type", "application/json")
|
| 106 |
+
data, _ := json.Marshal(store)
|
| 107 |
+
w.Write(data)
|
| 108 |
+
}
|
main.go
CHANGED
|
@@ -17,6 +17,8 @@ func main() {
|
|
| 17 |
version.StartVersionUpdater()
|
| 18 |
|
| 19 |
http.HandleFunc("/", handler.HandleIndex)
|
|
|
|
|
|
|
| 20 |
http.HandleFunc("/v1/models", handler.HandleModels)
|
| 21 |
http.HandleFunc("/v1/chat/completions", handler.HandleChatCompletions)
|
| 22 |
http.HandleFunc("/v1/messages", handler.HandleMessages)
|
|
|
|
| 17 |
version.StartVersionUpdater()
|
| 18 |
|
| 19 |
http.HandleFunc("/", handler.HandleIndex)
|
| 20 |
+
http.HandleFunc("/genkey", handler.HandleGenKey)
|
| 21 |
+
http.HandleFunc("/stats", handler.HandleStats)
|
| 22 |
http.HandleFunc("/v1/models", handler.HandleModels)
|
| 23 |
http.HandleFunc("/v1/chat/completions", handler.HandleChatCompletions)
|
| 24 |
http.HandleFunc("/v1/messages", handler.HandleMessages)
|