MySafeCode commited on
Commit
3012a78
·
verified ·
1 Parent(s): b1003a9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +315 -0
app.py ADDED
@@ -0,0 +1,315 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import requests
4
+ import gradio as gr
5
+ from datetime import datetime
6
+ from dotenv import load_dotenv
7
+
8
+ # Load environment variables from .env file
9
+ load_dotenv()
10
+
11
+ # API Configuration - Hugging Face Spaces stores secrets in environment variables
12
+ API_KEY = os.getenv('StableCogKey', '')
13
+
14
+
15
+ API_HOST = 'https://api.stablecog.com'
16
+ API_ENDPOINT = '/v1/credits'
17
+ API_URL = f'{API_HOST}{API_ENDPOINT}'
18
+
19
+ headers = {
20
+ 'Authorization': f'Bearer {API_KEY}',
21
+ 'Content-Type': 'application/json'
22
+ }
23
+
24
+ def check_credits():
25
+ """Check StableCog credits and return formatted results"""
26
+ try:
27
+ response = requests.get(API_URL, headers=headers, timeout=10)
28
+
29
+ if response.status_code == 200:
30
+ res_json = response.json()
31
+
32
+ # Extract data
33
+ total_credits = res_json.get('total_credits', 0)
34
+ remaining_credits = res_json.get('remaining_credits', 0)
35
+ used_credits = res_json.get('used_credits', 0)
36
+
37
+ # Calculate percentage used
38
+ if total_credits > 0:
39
+ percentage_used = (used_credits / total_credits * 100)
40
+ else:
41
+ percentage_used = 0
42
+
43
+ # Create formatted output
44
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
45
+
46
+ result = {
47
+ "success": True,
48
+ "total_credits": total_credits,
49
+ "remaining_credits": remaining_credits,
50
+ "used_credits": used_credits,
51
+ "percentage_used": round(percentage_used, 2),
52
+ "timestamp": timestamp,
53
+ "raw_data": json.dumps(res_json, indent=2)
54
+ }
55
+
56
+ return result
57
+
58
+ else:
59
+ return {
60
+ "success": False,
61
+ "error": f"API Error: {response.status_code}",
62
+ "message": response.text if response.text else "No response text",
63
+ "status_code": response.status_code
64
+ }
65
+
66
+ except requests.exceptions.Timeout:
67
+ return {
68
+ "success": False,
69
+ "error": "Timeout Error",
70
+ "message": "The request timed out. Please try again."
71
+ }
72
+ except requests.exceptions.ConnectionError:
73
+ return {
74
+ "success": False,
75
+ "error": "Connection Error",
76
+ "message": "Could not connect to the API. Check your internet connection."
77
+ }
78
+ except Exception as e:
79
+ return {
80
+ "success": False,
81
+ "error": f"Unexpected Error: {type(e).__name__}",
82
+ "message": str(e)
83
+ }
84
+
85
+ def update_display():
86
+ """Update the UI with credit information"""
87
+ result = check_credits()
88
+
89
+ if result["success"]:
90
+ # Create a visual progress bar with color coding
91
+ percentage = result["percentage_used"]
92
+ if percentage < 50:
93
+ bar_color = "#4CAF50" # Green
94
+ status = "🟢 Good"
95
+ status_color = "#4CAF50"
96
+ elif percentage < 80:
97
+ bar_color = "#FF9800" # Orange
98
+ status = "🟡 Moderate"
99
+ status_color = "#FF9800"
100
+ else:
101
+ bar_color = "#F44336" # Red
102
+ status = "🔴 Low"
103
+ status_color = "#F44336"
104
+
105
+ html_content = f"""
106
+ <div style='font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; padding: 25px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; box-shadow: 0 10px 30px rgba(0,0,0,0.2);'>
107
+ <h2 style='text-align: center; margin-bottom: 30px; font-size: 28px; font-weight: 600;'>🎨 StableCog Credit Status</h2>
108
+
109
+ <div style='background: rgba(255,255,255,0.1); backdrop-filter: blur(10px); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 1px solid rgba(255,255,255,0.2);'>
110
+ <div style='display: flex; justify-content: space-between; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid rgba(255,255,255,0.1);'>
111
+ <span style='font-size: 16px; opacity: 0.9;'>Total Credits:</span>
112
+ <span style='font-weight: bold; font-size: 24px;'>{result['total_credits']} ⭐</span>
113
+ </div>
114
+
115
+ <div style='display: flex; justify-content: space-between; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid rgba(255,255,255,0.1);'>
116
+ <span style='font-size: 16px; opacity: 0.9;'>Remaining Credits:</span>
117
+ <span style='font-weight: bold; font-size: 24px; color: #90EE90;'>{result['remaining_credits']} ⭐</span>
118
+ </div>
119
+
120
+ <div style='display: flex; justify-content: space-between; margin-bottom: 20px;'>
121
+ <span style='font-size: 16px; opacity: 0.9;'>Used Credits:</span>
122
+ <span style='font-weight: bold; font-size: 20px;'>{result['used_credits']} ⭐</span>
123
+ </div>
124
+
125
+ <div style='margin-bottom: 20px;'>
126
+ <div style='display: flex; justify-content: space-between; margin-bottom: 8px;'>
127
+ <span style='font-size: 16px; opacity: 0.9;'>Usage Progress:</span>
128
+ <span style='font-weight: bold;'>{result['percentage_used']}%</span>
129
+ </div>
130
+ <div style='height: 22px; background: rgba(255,255,255,0.15); border-radius: 11px; overflow: hidden; position: relative;'>
131
+ <div style='height: 100%; width: {result['percentage_used']}%; background: {bar_color};
132
+ border-radius: 11px; transition: width 0.5s ease-in-out; box-shadow: 0 0 10px {bar_color}80;'></div>
133
+ <div style='position: absolute; right: 10px; top: 50%; transform: translateY(-50%); color: white; font-size: 12px; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.5);'>
134
+ {result['percentage_used']}%
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <div style='display: flex; justify-content: space-between; align-items: center; margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.2);'>
140
+ <span style='font-size: 16px; opacity: 0.9;'>Status:</span>
141
+ <span style='font-weight: bold; font-size: 18px; color: {status_color}; padding: 5px 15px; background: rgba(255,255,255,0.1); border-radius: 20px;'>
142
+ {status}
143
+ </span>
144
+ </div>
145
+ </div>
146
+
147
+ <div style='text-align: center; font-size: 14px; opacity: 0.7; margin-top: 10px;'>
148
+ ⏰ Last checked: {result['timestamp']}
149
+ </div>
150
+ </div>
151
+ """
152
+
153
+ return html_content, result['raw_data'], result['remaining_credits'], result['percentage_used']
154
+
155
+ else:
156
+ # Error display
157
+ html_content = f"""
158
+ <div style='font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; padding: 25px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 15px; color: white; text-align: center; box-shadow: 0 10px 30px rgba(0,0,0,0.2);'>
159
+ <h2 style='margin-bottom: 20px; font-size: 26px;'>⚠️ API Connection Error</h2>
160
+
161
+ <div style='background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 1px solid rgba(255,255,255,0.2);'>
162
+ <p style='margin: 0 0 10px 0; font-size: 18px; font-weight: bold;'>{result.get('error', 'Unknown error')}</p>
163
+ <p style='margin: 0; font-size: 14px; opacity: 0.9;'>{result.get('message', '')}</p>
164
+ {'<p style="margin: 10px 0 0 0; font-size: 14px;">Status Code: ' + str(result.get('status_code', '')) + '</p>' if result.get('status_code') else ''}
165
+ </div>
166
+
167
+ <div style='margin-top: 25px; padding: 15px; background: rgba(255,255,255,0.1); border-radius: 10px;'>
168
+ <h3 style='margin-top: 0;'>🔧 Troubleshooting Tips:</h3>
169
+ <ul style='text-align: left; margin: 10px 0; padding-left: 20px;'>
170
+ <li>Check if your API key is set in Hugging Face Secrets</li>
171
+ <li>Verify the API key has proper permissions</li>
172
+ <li>Ensure StableCog API is currently available</li>
173
+ <li>Check your internet connection</li>
174
+ </ul>
175
+ </div>
176
+ </div>
177
+ """
178
+
179
+ return html_content, f"Error: {result.get('error', 'Unknown error')}\n\nDetails: {result.get('message', '')}", 0, 0
180
+
181
+ def get_recommendation(remaining_credits, percentage_used):
182
+ """Provide recommendations based on credit status"""
183
+ if remaining_credits == 0:
184
+ return "💸 **No credits remaining.** Please add credits to continue using StableCog services."
185
+ elif percentage_used >= 90:
186
+ return "🛑 **Critically low credits!** Consider purchasing more credits before starting new projects."
187
+ elif percentage_used >= 75:
188
+ return "⚠️ **Credits are running low.** You can still do some work, but plan ahead for larger projects."
189
+ elif remaining_credits < 10:
190
+ return "📝 **Limited credits available.** Good for small tasks, testing, or single images."
191
+ elif remaining_credits < 50:
192
+ return "✨ **Credits available!** Suitable for several medium-sized projects or batch processing."
193
+ else:
194
+ return "🚀 **Plenty of credits!** Ready for extensive image generation work and experimentation."
195
+
196
+ # Create Gradio interface with custom theme
197
+ theme = gr.themes.Soft(
198
+ primary_hue="purple",
199
+ secondary_hue="indigo",
200
+ font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"]
201
+ ).set(
202
+ button_primary_background_fill="linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
203
+ button_primary_background_fill_hover="linear-gradient(135deg, #764ba2 0%, #667eea 100%)",
204
+ button_primary_text_color="white",
205
+ button_primary_border_color="rgba(255,255,255,0.2)",
206
+ )
207
+
208
+ with gr.Blocks(theme=theme, title="StableCog Credit Monitor", css="footer {display: none !important;}") as demo:
209
+ gr.Markdown("""
210
+ # 🎯 StableCog Credit Dashboard
211
+
212
+ *Monitor your API credits and plan your image generation projects efficiently.*
213
+ """)
214
+
215
+ # Status row
216
+ with gr.Row():
217
+ with gr.Column(scale=2):
218
+ html_output = gr.HTML(label="Credit Status")
219
+ with gr.Column(scale=1):
220
+ raw_output = gr.Code(
221
+ label="📋 Raw API Response",
222
+ language="json",
223
+ interactive=False,
224
+ lines=15
225
+ )
226
+
227
+ # Stats row
228
+ with gr.Row():
229
+ with gr.Column():
230
+ credits_display = gr.Number(
231
+ label="Remaining Credits",
232
+ interactive=False,
233
+ elem_classes="stat-box"
234
+ )
235
+ with gr.Column():
236
+ usage_display = gr.Number(
237
+ label="Usage Percentage",
238
+ interactive=False,
239
+ elem_classes="stat-box"
240
+ )
241
+
242
+ # Recommendation row
243
+ with gr.Row():
244
+ recommendation_box = gr.Textbox(
245
+ label="🎯 AI Recommendation",
246
+ interactive=False,
247
+ lines=3,
248
+ elem_classes="recommendation-box"
249
+ )
250
+
251
+ # Control row
252
+ with gr.Row():
253
+ check_btn = gr.Button(
254
+ "🔄 Check Credits Now",
255
+ variant="primary",
256
+ size="lg",
257
+ elem_classes="refresh-btn"
258
+ )
259
+
260
+ # Auto-check on load
261
+ demo.load(fn=update_display, inputs=None, outputs=[html_output, raw_output, credits_display, usage_display])
262
+
263
+ # Connect button and update recommendation
264
+ def update_all():
265
+ html, raw, credits, usage = update_display()
266
+ recommendation = get_recommendation(credits, usage)
267
+ return html, raw, credits, usage, recommendation
268
+
269
+ check_btn.click(
270
+ fn=update_all,
271
+ inputs=None,
272
+ outputs=[html_output, raw_output, credits_display, usage_display, recommendation_box]
273
+ )
274
+
275
+ # Instructions and info
276
+ with gr.Accordion("📚 How to Use & Setup", open=False):
277
+ gr.Markdown("""
278
+ ### Setting Up on Hugging Face Spaces:
279
+
280
+ 1. **Add your API key as a Secret:**
281
+ - Go to your Space's Settings → Secrets
282
+ - Add a new secret with:
283
+ - Key: `STABLECOG_API_KEY`
284
+ - Value: `your_actual_api_key_here`
285
+
286
+ 2. **API Key Safety:**
287
+ - Never hardcode your API key in the app
288
+ - Hugging Face Secrets encrypt your key
289
+ - The app will only work with a valid key
290
+
291
+ 3. **Understanding Credits:**
292
+ - **Total Credits**: Lifetime credits purchased
293
+ - **Remaining Credits**: Currently available for use
294
+ - **Used Credits**: Credits spent on generations
295
+ - **Usage %**: Percentage of total credits used
296
+
297
+ 4. **Recommendations are based on:**
298
+ - Remaining credit count
299
+ - Usage percentage
300
+ - Common workload patterns
301
+ """)
302
+
303
+ gr.Markdown("""
304
+ ---
305
+ *Built with ❤️ for StableCog users | [Report Issues](https://github.com/stability-ai/stablecog/issues)*
306
+ """)
307
+
308
+ if __name__ == "__main__":
309
+ # For Hugging Face Spaces
310
+ demo.launch(
311
+ server_name="0.0.0.0",
312
+ server_port=7860,
313
+ share=False,
314
+ show_error=True
315
+ )