Spaces:
Running
Running
Update admin.py
Browse files
admin.py
CHANGED
|
@@ -292,7 +292,23 @@ INDEX_TEMPLATE = """
|
|
| 292 |
</form>
|
| 293 |
</div>
|
| 294 |
</div>
|
| 295 |
-
<div class="col-md-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
<div class="table-container mt-0 h-100">
|
| 297 |
<h5 class="fw-bold mb-4">Broadcast Results</h5>
|
| 298 |
<div id="broadcastStatus" class="p-3 rounded bg-dark border border-secondary" style="height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; color: #10b981;">
|
|
@@ -771,6 +787,69 @@ def api_broadcast():
|
|
| 771 |
"failed_count": failed_count
|
| 772 |
})
|
| 773 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 774 |
# Health check endpoint for Space
|
| 775 |
@app.route('/health')
|
| 776 |
def health():
|
|
|
|
| 292 |
</form>
|
| 293 |
</div>
|
| 294 |
</div>
|
| 295 |
+
<div class="col-md-4">
|
| 296 |
+
<div class="table-container mt-0">
|
| 297 |
+
<h5 class="fw-bold mb-3"><i class="bi bi-info-circle me-2"></i>Formatting Guide</h5>
|
| 298 |
+
<div class="small text-secondary mb-3">The broadcast supports standard Markdown syntax:</div>
|
| 299 |
+
<ul class="list-unstyled small">
|
| 300 |
+
<li class="mb-2"><code class="text-accent">**text**</code> or <code class="text-accent">*text*</code> <br> <span class="text-white-50">→</span> <strong>Bold Text</strong></li>
|
| 301 |
+
<li class="mb-2"><code class="text-accent">__text__</code> or <code class="text-accent">_text_</code> <br> <span class="text-white-50">→</span> <em>Italic Text</em></li>
|
| 302 |
+
<li class="mb-2"><code class="text-accent">[google](https://google.com)</code> <br> <span class="text-white-50">→</span> <a href="#" class="text-accent" style="pointer-events: none;">Hyperlink</a></li>
|
| 303 |
+
<li class="mb-2"><code class="text-accent">`code`</code> <br> <span class="text-white-50">→</span> <code>Monospaced Code</code></li>
|
| 304 |
+
</ul>
|
| 305 |
+
<hr class="opacity-10">
|
| 306 |
+
<div class="alert alert-info py-2" style="background: rgba(59, 130, 246, 0.1); border: none; font-size: 11px; color: #60a5fa;">
|
| 307 |
+
<i class="bi bi-exclamation-triangle-fill me-1"></i> Ensure all tags are properly closed to avoid delivery failure.
|
| 308 |
+
</div>
|
| 309 |
+
</div>
|
| 310 |
+
</div>
|
| 311 |
+
<div class="col-md-4">
|
| 312 |
<div class="table-container mt-0 h-100">
|
| 313 |
<h5 class="fw-bold mb-4">Broadcast Results</h5>
|
| 314 |
<div id="broadcastStatus" class="p-3 rounded bg-dark border border-secondary" style="height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; color: #10b981;">
|
|
|
|
| 787 |
"failed_count": failed_count
|
| 788 |
})
|
| 789 |
|
| 790 |
+
@app.route('/api/cron/reset-coins', methods=['GET', 'POST'])
|
| 791 |
+
def cron_reset_coins():
|
| 792 |
+
# Basic security check: You can add a CRON_SECRET if needed
|
| 793 |
+
# secret = request.args.get('secret')
|
| 794 |
+
# if secret != os.getenv("CRON_SECRET"): return "Unauthorized", 401
|
| 795 |
+
|
| 796 |
+
try:
|
| 797 |
+
# 1. Reset database counter in Supabase
|
| 798 |
+
# Set daily_images_generated to 0 for all free users
|
| 799 |
+
res = supabase.table("telegram_users").update({
|
| 800 |
+
"daily_images_generated": 0
|
| 801 |
+
}).eq("tier", "free").execute()
|
| 802 |
+
|
| 803 |
+
updated_count = len(res.data) if res.data else 0
|
| 804 |
+
|
| 805 |
+
# 2. Get tokens for broadcast
|
| 806 |
+
token = os.getenv("TELEGRAM_BOT_TOKEN")
|
| 807 |
+
if not token:
|
| 808 |
+
return jsonify({"status": "partial_success", "message": "DB Reset OK, but BOT_TOKEN missing", "reset_count": updated_count}), 200
|
| 809 |
+
|
| 810 |
+
# 3. Fetch all active users to notify
|
| 811 |
+
users_res = supabase.table("telegram_users").select("chat_id").eq("tier", "free").execute()
|
| 812 |
+
users = users_res.data or []
|
| 813 |
+
|
| 814 |
+
# 4. Notification Message
|
| 815 |
+
message = (
|
| 816 |
+
"🚀 **Daily Coins Reset!**\n\n"
|
| 817 |
+
"Your daily generation coins have been successfully reset. You now have **60 fresh coins** to create amazing AI art today!\n\n"
|
| 818 |
+
"👉 Start generating now: /start"
|
| 819 |
+
)
|
| 820 |
+
formatted_message = format_message_to_html(message)
|
| 821 |
+
|
| 822 |
+
# 5. Send notifications (Non-blocking or simple loop)
|
| 823 |
+
sent_count = 0
|
| 824 |
+
base_url = os.getenv("TELEGRAM_API_BASE_URL", "https://api.telegram.org").rstrip('/')
|
| 825 |
+
|
| 826 |
+
for user in users:
|
| 827 |
+
chat_id = user.get('chat_id')
|
| 828 |
+
if not chat_id: continue
|
| 829 |
+
try:
|
| 830 |
+
# Construct URL
|
| 831 |
+
if "/bot" in base_url.lower(): url = f"{base_url}{token}/sendMessage"
|
| 832 |
+
else: url = f"{base_url}/bot{token}/sendMessage"
|
| 833 |
+
|
| 834 |
+
requests.post(url, json={
|
| 835 |
+
"chat_id": chat_id,
|
| 836 |
+
"text": formatted_message,
|
| 837 |
+
"parse_mode": "HTML"
|
| 838 |
+
}, timeout=5)
|
| 839 |
+
sent_count += 1
|
| 840 |
+
except:
|
| 841 |
+
continue
|
| 842 |
+
|
| 843 |
+
return jsonify({
|
| 844 |
+
"status": "success",
|
| 845 |
+
"db_reset_count": updated_count,
|
| 846 |
+
"notifications_sent": sent_count,
|
| 847 |
+
"time": datetime.now().isoformat()
|
| 848 |
+
}), 200
|
| 849 |
+
|
| 850 |
+
except Exception as e:
|
| 851 |
+
return jsonify({"status": "error", "message": str(e)}), 500
|
| 852 |
+
|
| 853 |
# Health check endpoint for Space
|
| 854 |
@app.route('/health')
|
| 855 |
def health():
|