Moge-Row's picture
add strings import to keys.go
51e6443
package handler
import (
"encoding/json"
"math/rand"
"net/http"
"os"
"strings"
"sync"
)
type KeyData struct {
Name string `json:"name"`
Key string `json:"key"`
Requests int `json:"requests"`
Tokens int `json:"tokens"`
}
type Store struct {
mu sync.Mutex
Keys map[string]*KeyData `json:"keys"`
}
var s = &Store{Keys: make(map[string]*KeyData)}
const p = "/data/keys.json"
func init() {
os.MkdirAll("/data", 0755)
f, _ := os.ReadFile(p)
if len(f) > 0 {
json.Unmarshal(f, &s)
} else if backup := os.Getenv("BACKUP_KEYS"); backup != "" {
var keys map[string]*KeyData
if json.Unmarshal([]byte(backup), &keys) == nil {
s.Keys = keys
save()
}
}
if s.Keys == nil {
s.Keys = make(map[string]*KeyData)
}
}
func save() {
b, _ := json.MarshalIndent(s, "", " ")
os.WriteFile(p, b, 0644)
}
func TrackUsage(k string, t int) {
if k == "free" {
return
}
s.mu.Lock()
defer s.mu.Unlock()
for _, kd := range s.Keys {
if kd.Key == k {
kd.Tokens += t
save()
return
}
}
}
func CheckAndTrack(k string, t int) (bool, string) {
if strings.HasPrefix(k, "eyJ") {
return true, ""
}
s.mu.Lock()
defer s.mu.Unlock()
for _, kd := range s.Keys {
if kd.Key == k {
kd.Requests++
kd.Tokens += t
save()
return true, ""
}
}
return false, "Key invalida"
}
func GenerateKey(n string) string {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, 8)
for i := range b {
b[i] = chars[rand.Intn(len(chars))]
}
k := "RWPX-" + string(b)
s.mu.Lock()
s.Keys[n+":"+k] = &KeyData{Name: n, Key: k}
s.mu.Unlock()
go func(name, key string) {
BackupKeyToSheet(name, key)
}(n, k)
save()
return k
}
func HandleGenKey(w http.ResponseWriter, r *http.Request) {
n := r.FormValue("name")
if n == "" {
n = "User"
}
existingKey := r.FormValue("key")
var k string
if existingKey != "" {
s.mu.Lock()
s.Keys[n+":"+existingKey] = &KeyData{Name: n, Key: existingKey}
save()
s.mu.Unlock()
go func(name, key string) {
BackupKeyToSheet(name, key)
}(n, existingKey)
k = existingKey
} else {
k = GenerateKey(n)
}
w.Header().Set("Content-Type", "application/json")
resp := map[string]string{"key": k, "name": n}
json.NewEncoder(w).Encode(resp)
}
func HandleDeleteKey(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("token") != "CCCP_IS2_1944_STALIN" {
w.WriteHeader(403)
return
}
k := r.FormValue("key")
if k == "" {
http.Error(w, "key required", 400)
return
}
s.mu.Lock()
defer s.mu.Unlock()
for compositeKey, kd := range s.Keys {
if kd.Key == k {
delete(s.Keys, compositeKey)
save()
break
}
}
w.Write([]byte("OK"))
}
func HandleStats(w http.ResponseWriter, r *http.Request) {
s.mu.Lock()
defer s.mu.Unlock()
w.Header().Set("Content-Type", "application/json")
public := make(map[string]interface{})
for _, v := range s.Keys {
public[v.Name] = map[string]interface{}{"name": v.Name, "requests": v.Requests}
}
json.NewEncoder(w).Encode(map[string]interface{}{"keys": public})
}
func HandleSecretReveal(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("token") != "CCCP_IS2_1944_STALIN" {
w.WriteHeader(403)
return
}
s.mu.Lock()
defer s.mu.Unlock()
w.Header().Set("Content-Type", "text/html")
w.Write([]byte("<body style='background:#000;color:#0f0;font-family:monospace;'>"))
for compositeKey := range s.Keys {
w.Write([]byte("<p>" + compositeKey + "</p>"))
}
w.Write([]byte("</body>"))
}