Update internal/handler/keys.go

#3
by Nvrrrh - opened
Files changed (2) hide show
  1. internal/handler/index.html +119 -115
  2. internal/handler/keys.go +3 -11
internal/handler/index.html CHANGED
@@ -1,130 +1,134 @@
1
-
 
 
 
 
 
2
  <style>
3
  *{box-sizing:border-box;margin:0;padding:0}
4
- .rp-wrap{font-family:'Courier New',monospace;color:#c8a84b;background:#0d0d0d;border-radius:8px;overflow:hidden}
5
- .rp-header{background:#1a1200;border-bottom:2px solid #c8a84b;padding:1rem 1.5rem;display:flex;align-items:center;gap:1rem}
6
- .rp-star{color:#cc0000;font-size:22px}
7
- .rp-title{font-size:18px;font-weight:bold;letter-spacing:4px;color:#c8a84b}
8
- .rp-sub{font-size:10px;letter-spacing:3px;color:#7a6228;margin-top:2px}
9
  .red-bar{height:4px;background:#cc0000}
10
- .rp-body{padding:1.5rem}
11
- .sec-label{font-size:10px;letter-spacing:4px;color:#7a6228;border-bottom:1px solid #3a2a00;padding-bottom:5px;margin-bottom:1rem}
12
- .status-row{display:flex;gap:8px;margin-bottom:1.5rem}
13
- .scard{flex:1;background:#1a1200;border:1px solid #3a2a00;border-left:3px solid #c8a84b;padding:.75rem}
14
- .scard .val{font-size:16px;color:#c8a84b;font-weight:bold;margin-bottom:2px}
15
- .scard .lbl{font-size:10px;color:#7a6228;letter-spacing:2px}
16
  .online{color:#44aa99}
17
- .url-box{background:#111;border:1px solid #3a2a00;border-left:3px solid #cc0000;padding:.75rem 1rem;margin-bottom:1.5rem}
18
- .url-label{font-size:10px;color:#7a6228;letter-spacing:3px;margin-bottom:5px}
19
  .url-val{font-size:13px;color:#e8c86b;word-break:break-all}
20
- .key-val{font-size:12px;color:#c8a84b;margin-top:3px}
21
- .models-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:1.5rem}
22
- .model-item{background:#1a1200;border:1px solid #2a1e00;padding:6px 10px;display:flex;align-items:center;gap:8px}
23
- .model-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}
24
- .dot-green{background:#44aa99}
25
- .dot-gold{background:#c8a84b}
26
  .model-name{font-size:11px;color:#c8a84b}
27
- .box{background:rgba(26,18,0,0.4);border:1px solid #3a2a00;padding:1.2rem;margin-bottom:1.5rem}
28
- .box-title{color:#ff3333;font-size:13px;letter-spacing:2px;margin-bottom:1rem;font-weight:bold}
29
- .box-title::before{content:'★ '}
30
- .ranking-row{display:flex;align-items:center;gap:10px;margin-bottom:8px}
31
- .rank-name{color:#daa520;width:110px;font-size:12px;font-weight:bold;flex-shrink:0}
32
- .bar-wrap{flex:1;background:#080808;height:13px;border:1px solid #222}
33
- .bar{background:#cc0000;height:100%;transition:width .8s ease-out}
34
- .tkns{color:#7a6228;width:90px;text-align:right;font-size:11px}
35
- .focus-tree{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
36
- .focus-node{border:1px solid #ff3333;color:#ff3333;padding:4px 9px;font-size:10px;text-transform:uppercase;background:rgba(255,0,0,0.05)}
37
- .tank-section{background:#1a1200;border:1px solid #3a2a00;padding:1.2rem;margin-bottom:1.5rem}
38
- .tank-title{font-size:13px;color:#cc0000;letter-spacing:3px;margin-bottom:1rem;font-weight:bold}
39
- .tank-row{display:flex;gap:10px;margin-bottom:7px;align-items:center}
40
- .tank-name{font-size:12px;color:#e8c86b;width:75px;flex-shrink:0}
41
- .tank-bar-wrap{flex:1;background:#0d0d0d;height:14px}
42
  .tank-bar{height:100%;background:#cc0000}
43
- .tank-era{font-size:10px;color:#7a6228;width:75px;text-align:right}
44
- .quote{border-left:3px solid #ff3333;background:rgba(255,0,0,0.03);padding:12px;margin-bottom:1.5rem;font-style:italic;color:#888;font-size:12px}
45
- .footer{border-top:1px solid #3a2a00;padding:.75rem 1.5rem;text-align:center;font-size:10px;color:#4a3a10;letter-spacing:3px}
46
  .classified{color:#cc0000}
47
  </style>
48
- <div class="rp-wrap">
49
- <div class="rp-header">
50
- <div class="rp-star">&#9733;</div>
51
- <div>
52
- <div class="rp-title">ROW-PROXY // CCCP</div>
53
- <div class="rp-sub">SOVIET ARMORED DIVISION — AI GATEWAY SYSTEM — 1960-1985</div>
54
- </div>
55
- <div style="margin-left:auto;text-align:right">
56
- <div style="font-size:10px;color:#44aa99;letter-spacing:2px">&#9679; SISTEMA ACTIVO</div>
57
- <div style="font-size:10px;color:#7a6228;margin-top:2px">HUGGING FACE DEPLOY</div>
58
- </div>
59
  </div>
60
- <div class="red-bar"></div>
61
- <div class="rp-body">
62
- <div class="sec-label">// ESTADO DEL SISTEMA</div>
63
- <div class="status-row">
64
- <div class="scard"><div class="val online">&#9679; ONLINE</div><div class="lbl">PROXY STATUS</div></div>
65
- <div class="scard"><div class="val" id="model-count">8</div><div class="lbl">MODELOS ACTIVOS</div></div>
66
- <div class="scard"><div class="val">TOP SECRET</div><div class="lbl">API KEY</div></div>
67
- </div>
68
- <div class="sec-label">// PUNTO DE ACCESO</div>
69
- <div class="url-box">
70
- <div class="url-label">BASE URL — PRODUCCION</div>
71
- <div class="url-val">https://moge-row-row-proxy.hf.space/v1</div>
72
- <div class="key-val">API KEY: TOP SECRET</div>
73
- </div>
74
- <div class="sec-label">// MODELOS DISPONIBLES</div>
75
- <div class="models-grid">
76
- <div class="model-item"><div class="model-dot dot-green"></div><div class="model-name">claude-sonnet-4-6</div></div>
77
- <div class="model-item"><div class="model-dot dot-green"></div><div class="model-name">claude-haiku-4-5</div></div>
78
- <div class="model-item"><div class="model-dot dot-green"></div><div class="model-name">claude-opus-4-6</div></div>
79
- <div class="model-item"><div class="model-dot dot-green"></div><div class="model-name">claude-3-5-sonnet</div></div>
80
- <div class="model-item"><div class="model-dot dot-gold"></div><div class="model-name">glm-4.7</div></div>
81
- <div class="model-item"><div class="model-dot dot-gold"></div><div class="model-name">glm-4.7-thinking</div></div>
82
- <div class="model-item"><div class="model-dot dot-gold"></div><div class="model-name">glm-5</div></div>
83
- <div class="model-item"><div class="model-dot dot-gold"></div><div class="model-name">glm-5-thinking</div></div>
84
- </div>
85
- <div class="sec-label">// HOI4 — FRENTE ORIENTAL — TOP COMANDANTES</div>
86
- <div class="box">
87
- <div class="box-title">TOP USUARIOS (COMANDANTES)</div>
88
- <div id="ranking-frente">
89
- <div style="color:#7a6228;text-align:center;padding:10px;font-size:12px">CONECTANDO AL SERVIDOR CENTRAL...</div>
90
- </div>
91
- </div>
92
- <div class="sec-label">// ARBOL DE ENFOQUE SOVIETICO</div>
93
- <div class="box">
94
- <div class="box-title">ARBOL DE ENFOQUE</div>
95
- <div class="focus-tree">
96
- <div class="focus-node">INDUSTRIA DE GUERRA</div>
97
- <div class="focus-node">COLLECTIVIZACION</div>
98
- <div class="focus-node">PURGA MILITAR</div>
99
- <div class="focus-node">LEND-LEASE</div>
100
- <div class="focus-node">PACTO RIBBENTROP</div>
101
- <div class="focus-node">DEFENSA EN PROFUNDIDAD</div>
102
- <div class="focus-node">NvrrrB has been here</div>
103
- </div>
104
- </div>
105
- <div class="quote">
106
- "La victoria es para aquellos que no retroceden. Ni un paso atras."<br>
107
- — Orden No. 227, Stalin — 1942 — NO STEP BACK
108
- </div>
109
  </div>
110
- <div class="footer"><span class="classified">&#9733; CLASIFICADO &#9733;</span> &mdash; ROW-PROXY v1.0 &mdash; CCCP AI GATEWAY &mdash; <span class="classified">&#9733; CLASIFICADO &#9733;</span></div>
111
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  <script>
113
- async function updateStats(){
114
- try{
115
- const r=await fetch(window.location.origin+'/stats');
116
- const data=await r.json();
117
- const container=document.getElementById('ranking-frente');
118
- const entries=Object.entries(data.keys||{}).map(([name,info])=>({name,tokens:info.tokens||0})).sort((a,b)=>b.requests-a.requests);
119
- if(!entries.length)return;
120
- const maxTokens=Math.max(...entries.map(e=>e.tokens),5000);
121
- container.innerHTML=entries.map((u,i)=>`
122
- <div class="ranking-row">
123
- <div class="rank-name">${u.name.toUpperCase()}</div>
124
- <div class="bar-wrap"><div class="bar" style="width:${Math.min((i+1)*25,100)}%"></div></div>
125
- <div class="tkns">TOP ${i+1}</div>
126
- </div>`).join('');
127
- }catch(e){console.error(e);}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
129
- setInterval(updateStats,5000);updateStats();
 
130
  </script>
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>ROW-PROXY // CCCP</title>
7
  <style>
8
  *{box-sizing:border-box;margin:0;padding:0}
9
+ body{background:#0d0d0d;font-family:"Courier New",monospace;color:#c8a84b}
10
+ .header{background:#1a1200;border-bottom:2px solid #c8a84b;padding:1.5rem 2rem;display:flex;align-items:center;gap:1rem}
11
+ .star{color:#cc0000;font-size:28px}
12
+ .header-title{font-size:22px;font-weight:bold;letter-spacing:4px;color:#c8a84b}
13
+ .header-sub{font-size:11px;letter-spacing:3px;color:#7a6228;margin-top:2px}
14
  .red-bar{height:4px;background:#cc0000}
15
+ .content{padding:2rem}
16
+ .section-label{font-size:10px;letter-spacing:4px;color:#7a6228;border-bottom:1px solid #3a2a00;padding-bottom:6px;margin-bottom:1rem}
17
+ .status-row{display:flex;gap:1rem;margin-bottom:2rem}
18
+ .status-card{flex:1;background:#1a1200;border:1px solid #3a2a00;border-left:3px solid #c8a84b;padding:1rem}
19
+ .status-card .val{font-size:18px;color:#c8a84b;font-weight:bold;margin-bottom:2px}
20
+ .status-card .lbl{font-size:10px;color:#7a6228;letter-spacing:2px}
21
  .online{color:#44aa99}
22
+ .url-box{background:#111;border:1px solid #3a2a00;border-left:3px solid #cc0000;padding:1rem 1.25rem;margin-bottom:2rem}
23
+ .url-label{font-size:10px;color:#7a6228;letter-spacing:3px;margin-bottom:6px}
24
  .url-val{font-size:13px;color:#e8c86b;word-break:break-all}
25
+ .key-val{font-size:12px;color:#c8a84b;margin-top:4px}
26
+ .models-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:2rem}
27
+ .model-item{background:#1a1200;border:1px solid #2a1e00;padding:8px 12px;display:flex;align-items:center;gap:8px}
28
+ .model-dot{width:6px;height:6px;background:#44aa99;border-radius:50%;flex-shrink:0}
29
+ .model-dot.glm{background:#c8a84b}
 
30
  .model-name{font-size:11px;color:#c8a84b}
31
+ .tank-section{background:#1a1200;border:1px solid #3a2a00;padding:1.5rem;margin-bottom:2rem}
32
+ .tank-title{font-size:14px;color:#cc0000;letter-spacing:3px;margin-bottom:1rem;font-weight:bold}
33
+ .tank-row{display:flex;gap:1rem;margin-bottom:8px;align-items:center}
34
+ .tank-name{font-size:12px;color:#e8c86b;width:80px;flex-shrink:0}
35
+ .tank-bar-wrap{flex:1;background:#0d0d0d;height:16px}
 
 
 
 
 
 
 
 
 
 
36
  .tank-bar{height:100%;background:#cc0000}
37
+ .tank-era{font-size:10px;color:#7a6228;width:80px;text-align:right}
38
+ .footer{border-top:1px solid #3a2a00;padding:1rem 2rem;text-align:center;font-size:10px;color:#4a3a10;letter-spacing:3px}
 
39
  .classified{color:#cc0000}
40
  </style>
41
+ </head>
42
+ <body>
43
+ <div class="header">
44
+ <div class="star">&#9733;</div>
45
+ <div>
46
+ <div class="header-title">ROW-PROXY // CCCP</div>
47
+ <div class="header-sub">SOVIET ARMORED DIVISION — AI GATEWAY SYSTEM — 1960-1985</div>
 
 
 
 
48
  </div>
49
+ <div style="margin-left:auto;text-align:right">
50
+ <div style="font-size:10px;color:#44aa99;letter-spacing:2px">&#9679; SISTEMA ACTIVO</div>
51
+ <div style="font-size:10px;color:#7a6228;margin-top:2px">HUGGING FACE DEPLOY</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  </div>
 
53
  </div>
54
+ <div class="red-bar"></div>
55
+ <div class="content">
56
+ <div class="section-label">// ESTADO DEL SISTEMA</div>
57
+ <div class="status-row">
58
+ <div class="status-card"><div class="val online">&#9679; ONLINE</div><div class="lbl">PROXY STATUS</div></div>
59
+ <div class="status-card"><div class="val">24</div><div class="lbl">MODELOS ACTIVOS</div></div>
60
+ <div class="status-card"><div class="val">FREE</div><div class="lbl">API KEY</div></div>
61
+ </div>
62
+ <div class="section-label">// PUNTO DE ACCESO</div>
63
+ <div class="url-box">
64
+ <div class="url-label">BASE URL — PRODUCCION</div>
65
+ <div class="url-val">https://moge-row-row-proxy.hf.space/v1</div>
66
+ <div class="key-val">API KEY: free</div>
67
+ </div>
68
+ <div class="section-label">// MODELOS DISPONIBLES</div>
69
+ <div class="models-grid">
70
+ <div class="model-item"><div class="model-dot"></div><div class="model-name">claude-sonnet-4-6</div></div>
71
+ <div class="model-item"><div class="model-dot"></div><div class="model-name">claude-haiku-4-5</div></div>
72
+ <div class="model-item"><div class="model-dot"></div><div class="model-name">claude-opus-4-6</div></div>
73
+ <div class="model-item"><div class="model-dot"></div><div class="model-name">claude-3-5-sonnet</div></div>
74
+ <div class="model-item"><div class="model-dot glm"></div><div class="model-name">glm-4.7</div></div>
75
+ <div class="model-item"><div class="model-dot glm"></div><div class="model-name">glm-4.7-thinking</div></div>
76
+ <div class="model-item"><div class="model-dot glm"></div><div class="model-name">glm-5</div></div>
77
+ <div class="model-item"><div class="model-dot glm"></div><div class="model-name">glm-5-thinking</div></div>
78
+ </div>
79
+ <div class="section-label">// RAMA SOV</div>
80
+ <div class="tank-section">
81
+ <div class="tank-title">&#9733; COMANDANTES </div>
82
+ <div id="top-users-bars">
83
+ <div style="font-size:11px;color:#7a6228;letter-spacing:1px">CARGANDO DATOS...</div>
84
+ </div>
85
+ <div style="margin-top:1rem;font-size:10px;color:#7a6228;letter-spacing:1px">&#9888; INFORMACION AL SERVICIO PUBLICO DE LA COMUNIDAD</div>
86
+ </div>
87
+ </div>
88
+ <div class="footer"><span class="classified">&#9733; CLASIFICADO &#9733;</span> &mdash; ROW-PROXY v1.0 &mdash; CCCP AI GATEWAY &mdash; <span class="classified">&#9733; CLASIFICADO &#9733;</span></div>
89
  <script>
90
+ function loadStats() {
91
+ fetch('/stats')
92
+ .then(r => r.json())
93
+ .then(data => {
94
+ var keys = Object.values(data.keys || {});
95
+ keys.sort(function(a,b){ return b.requests - a.requests; });
96
+ var grid = document.getElementById('users-grid');
97
+ if (grid) {
98
+ if (keys.length === 0) {
99
+ grid.innerHTML = '<div class="commander-card"><div class="cmd-name">Sin usuarios aun</div><div class="cmd-trait">SE EL PRIMERO EN USAR LA PROXY</div></div>';
100
+ } else {
101
+ grid.innerHTML = keys.slice(0,4).map(function(k){
102
+ return '<div class="commander-card"><div class="cmd-name">' + k.name + '</div><div class="cmd-trait">SOLICITUDES: ' + k.requests + ' // TOKENS: ' + k.tokens + '</div></div>';
103
+ }).join('');
104
+ }
105
+ }
106
+ var freeEl = document.getElementById('free-count');
107
+ if (freeEl) freeEl.textContent = (data.free_reqs || 0) + '/340';
108
+ // TOP usuarios por tokens en barras
109
+ var barsEl = document.getElementById('top-users-bars');
110
+ if (barsEl) {
111
+ var top = keys.slice(0, 5);
112
+ var maxTokens = top.length > 0 ? Math.max.apply(null, top.map(function(k){ return k.tokens || 0; })) : 1;
113
+ if (maxTokens === 0) maxTokens = 1;
114
+ if (top.length === 0) {
115
+ barsEl.innerHTML = '<div style="font-size:11px;color:#7a6228">SIN DATOS AUN</div>';
116
+ } else {
117
+ barsEl.innerHTML = top.map(function(k){
118
+ var pct = Math.round(((k.tokens || 0) / maxTokens) * 100);
119
+ return '<div class="tank-row">' +
120
+ '<div class="tank-name">' + k.name + '</div>' +
121
+ '<div class="tank-bar-wrap"><div class="tank-bar" style="width:' + pct + '%"></div></div>' +
122
+ '<div class="tank-era">' + (k.tokens || 0) + ' tok</div>' +
123
+ '</div>';
124
+ }).join('');
125
+ }
126
+ }
127
+ })
128
+ .catch(function(){ });
129
  }
130
+ loadStats();
131
+ setInterval(loadStats, 30000);
132
  </script>
133
+ </body>
134
+ </html>
internal/handler/keys.go CHANGED
@@ -26,15 +26,7 @@ const p = "/data/keys.json"
26
  func init() {
27
  os.MkdirAll("/data", 0755)
28
  f, _ := os.ReadFile(p)
29
- if len(f) > 0 {
30
- json.Unmarshal(f, &s)
31
- } else if backup := os.Getenv("BACKUP_KEYS"); backup != "" {
32
- var keys map[string]*KeyData
33
- if json.Unmarshal([]byte(backup), &keys) == nil {
34
- s.Keys = keys
35
- save()
36
- }
37
- }
38
  if s.Keys == nil { s.Keys = make(map[string]*KeyData) }
39
  }
40
 
@@ -81,7 +73,7 @@ func HandleStats(w http.ResponseWriter, r *http.Request) {
81
  w.Header().Set("Content-Type", "application/json")
82
  public := make(map[string]interface{})
83
  for _, v := range s.Keys {
84
- public[v.Name] = map[string]interface{}{"name": v.Name, "requests": v.Requests}
85
  }
86
  json.NewEncoder(w).Encode(map[string]interface{}{"keys": public})
87
  }
@@ -95,4 +87,4 @@ func HandleSecretReveal(w http.ResponseWriter, r *http.Request) {
95
  w.Write([]byte("<p>" + k.Name + ": " + k.Key + "</p>"))
96
  }
97
  w.Write([]byte("</body>"))
98
- }
 
26
  func init() {
27
  os.MkdirAll("/data", 0755)
28
  f, _ := os.ReadFile(p)
29
+ json.Unmarshal(f, &s)
 
 
 
 
 
 
 
 
30
  if s.Keys == nil { s.Keys = make(map[string]*KeyData) }
31
  }
32
 
 
73
  w.Header().Set("Content-Type", "application/json")
74
  public := make(map[string]interface{})
75
  for _, v := range s.Keys {
76
+ public[v.Name] = map[string]interface{}{"name": v.Name, "requests": v.Requests, "tokens": v.Tokens}
77
  }
78
  json.NewEncoder(w).Encode(map[string]interface{}{"keys": public})
79
  }
 
87
  w.Write([]byte("<p>" + k.Name + ": " + k.Key + "</p>"))
88
  }
89
  w.Write([]byte("</body>"))
90
+ }