Spaces:
Sleeping
Sleeping
$P@D$3RV£R commited on
Commit ·
f50aece
1
Parent(s): 09628c7
Add /stats route for viewing analytics statistics
Browse files
app.py
CHANGED
|
@@ -5,7 +5,7 @@ import argparse
|
|
| 5 |
from flask import Flask, redirect, url_for, request
|
| 6 |
from flask import render_template
|
| 7 |
from flask import send_file
|
| 8 |
-
import os
|
| 9 |
from datasets import load_dataset
|
| 10 |
from huggingface_hub import hf_hub_download
|
| 11 |
from io import BytesIO
|
|
@@ -360,6 +360,154 @@ def bye():
|
|
| 360 |
</html>
|
| 361 |
"""
|
| 362 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
@app.route('/add/<temp_id>')
|
| 364 |
def add(temp_id):
|
| 365 |
image = request.args.get("image")
|
|
@@ -704,7 +852,7 @@ if __name__ == "__main__":
|
|
| 704 |
app.config["FOLDER_SETS"] = []
|
| 705 |
app.config["DATASET_ERROR"] = error_msg
|
| 706 |
else:
|
| 707 |
-
|
| 708 |
app.config["DATASET_ERROR"] = None
|
| 709 |
app.config["HEAD"] = 0
|
| 710 |
app.config["IMAGE_SET_INDEX"] = 0
|
|
|
|
| 5 |
from flask import Flask, redirect, url_for, request
|
| 6 |
from flask import render_template
|
| 7 |
from flask import send_file
|
| 8 |
+
import os
|
| 9 |
from datasets import load_dataset
|
| 10 |
from huggingface_hub import hf_hub_download
|
| 11 |
from io import BytesIO
|
|
|
|
| 360 |
</html>
|
| 361 |
"""
|
| 362 |
|
| 363 |
+
@app.route('/stats')
|
| 364 |
+
def stats():
|
| 365 |
+
"""Display analytics statistics"""
|
| 366 |
+
stats_data = load_stats()
|
| 367 |
+
|
| 368 |
+
# Convert set to list for display
|
| 369 |
+
unique_count = len(stats_data['unique_visitors']) if isinstance(stats_data['unique_visitors'], set) else len(stats_data.get('unique_visitors', []))
|
| 370 |
+
|
| 371 |
+
# Sort countries by visits
|
| 372 |
+
sorted_countries = sorted(stats_data.get('countries', {}).items(), key=lambda x: x[1], reverse=True)
|
| 373 |
+
|
| 374 |
+
# Sort dates
|
| 375 |
+
sorted_dates = sorted(stats_data.get('visits_by_date', {}).items(), reverse=True)[:30] # Last 30 days
|
| 376 |
+
|
| 377 |
+
# Get top user agents
|
| 378 |
+
sorted_user_agents = sorted(stats_data.get('user_agents', {}).items(), key=lambda x: x[1], reverse=True)[:10]
|
| 379 |
+
|
| 380 |
+
html = f"""
|
| 381 |
+
<!DOCTYPE html>
|
| 382 |
+
<html>
|
| 383 |
+
<head>
|
| 384 |
+
<title>Analytics Statistics</title>
|
| 385 |
+
<meta charset="UTF-8">
|
| 386 |
+
<style>
|
| 387 |
+
body {{ font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5; }}
|
| 388 |
+
.container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
|
| 389 |
+
h1 {{ color: #333; border-bottom: 3px solid #007bff; padding-bottom: 10px; }}
|
| 390 |
+
h2 {{ color: #555; margin-top: 30px; }}
|
| 391 |
+
.stat-box {{ background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #007bff; }}
|
| 392 |
+
.stat-number {{ font-size: 36px; font-weight: bold; color: #007bff; }}
|
| 393 |
+
.stat-label {{ font-size: 14px; color: #666; margin-top: 5px; }}
|
| 394 |
+
.table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
|
| 395 |
+
.table th, .table td {{ padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }}
|
| 396 |
+
.table th {{ background-color: #007bff; color: white; }}
|
| 397 |
+
.table tr:hover {{ background-color: #f5f5f5; }}
|
| 398 |
+
.back-link {{ display: inline-block; margin-top: 20px; padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; }}
|
| 399 |
+
.back-link:hover {{ background: #0056b3; }}
|
| 400 |
+
.grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 20px 0; }}
|
| 401 |
+
</style>
|
| 402 |
+
</head>
|
| 403 |
+
<body>
|
| 404 |
+
<div class="container">
|
| 405 |
+
<h1>📊 Analytics Statistics</h1>
|
| 406 |
+
|
| 407 |
+
<div class="grid">
|
| 408 |
+
<div class="stat-box">
|
| 409 |
+
<div class="stat-number">{stats_data.get('total_visits', 0):,}</div>
|
| 410 |
+
<div class="stat-label">Total Visits</div>
|
| 411 |
+
</div>
|
| 412 |
+
<div class="stat-box">
|
| 413 |
+
<div class="stat-number">{unique_count:,}</div>
|
| 414 |
+
<div class="stat-label">Unique Visitors</div>
|
| 415 |
+
</div>
|
| 416 |
+
<div class="stat-box">
|
| 417 |
+
<div class="stat-number">{len(stats_data.get('countries', {}))}</div>
|
| 418 |
+
<div class="stat-label">Countries</div>
|
| 419 |
+
</div>
|
| 420 |
+
<div class="stat-box">
|
| 421 |
+
<div class="stat-number">{stats_data.get('first_visit', 'N/A')[:10] if stats_data.get('first_visit') else 'N/A'}</div>
|
| 422 |
+
<div class="stat-label">First Visit</div>
|
| 423 |
+
</div>
|
| 424 |
+
</div>
|
| 425 |
+
|
| 426 |
+
<h2>🌍 Visits by Country</h2>
|
| 427 |
+
<table class="table">
|
| 428 |
+
<thead>
|
| 429 |
+
<tr>
|
| 430 |
+
<th>Country</th>
|
| 431 |
+
<th>Visits</th>
|
| 432 |
+
<th>Percentage</th>
|
| 433 |
+
</tr>
|
| 434 |
+
</thead>
|
| 435 |
+
<tbody>
|
| 436 |
+
"""
|
| 437 |
+
|
| 438 |
+
total_visits = stats_data.get('total_visits', 1)
|
| 439 |
+
for country, count in sorted_countries:
|
| 440 |
+
percentage = (count / total_visits * 100) if total_visits > 0 else 0
|
| 441 |
+
html += f"""
|
| 442 |
+
<tr>
|
| 443 |
+
<td>{country}</td>
|
| 444 |
+
<td>{count:,}</td>
|
| 445 |
+
<td>{percentage:.1f}%</td>
|
| 446 |
+
</tr>
|
| 447 |
+
"""
|
| 448 |
+
|
| 449 |
+
html += """
|
| 450 |
+
</tbody>
|
| 451 |
+
</table>
|
| 452 |
+
|
| 453 |
+
<h2>📅 Visits by Date (Last 30 Days)</h2>
|
| 454 |
+
<table class="table">
|
| 455 |
+
<thead>
|
| 456 |
+
<tr>
|
| 457 |
+
<th>Date</th>
|
| 458 |
+
<th>Visits</th>
|
| 459 |
+
</tr>
|
| 460 |
+
</thead>
|
| 461 |
+
<tbody>
|
| 462 |
+
"""
|
| 463 |
+
|
| 464 |
+
for date, count in sorted_dates:
|
| 465 |
+
html += f"""
|
| 466 |
+
<tr>
|
| 467 |
+
<td>{date}</td>
|
| 468 |
+
<td>{count:,}</td>
|
| 469 |
+
</tr>
|
| 470 |
+
"""
|
| 471 |
+
|
| 472 |
+
html += """
|
| 473 |
+
</tbody>
|
| 474 |
+
</table>
|
| 475 |
+
|
| 476 |
+
<h2>🖥️ Top User Agents</h2>
|
| 477 |
+
<table class="table">
|
| 478 |
+
<thead>
|
| 479 |
+
<tr>
|
| 480 |
+
<th>User Agent</th>
|
| 481 |
+
<th>Visits</th>
|
| 482 |
+
</tr>
|
| 483 |
+
</thead>
|
| 484 |
+
<tbody>
|
| 485 |
+
"""
|
| 486 |
+
|
| 487 |
+
for ua, count in sorted_user_agents:
|
| 488 |
+
# Truncate long user agents
|
| 489 |
+
ua_display = ua[:80] + '...' if len(ua) > 80 else ua
|
| 490 |
+
html += f"""
|
| 491 |
+
<tr>
|
| 492 |
+
<td>{ua_display}</td>
|
| 493 |
+
<td>{count:,}</td>
|
| 494 |
+
</tr>
|
| 495 |
+
"""
|
| 496 |
+
|
| 497 |
+
html += f"""
|
| 498 |
+
</tbody>
|
| 499 |
+
</table>
|
| 500 |
+
|
| 501 |
+
<p><strong>Last Updated:</strong> {stats_data.get('last_visit', 'N/A')}</p>
|
| 502 |
+
|
| 503 |
+
<a href="/tagger" class="back-link">← Back to Tagger</a>
|
| 504 |
+
</div>
|
| 505 |
+
</body>
|
| 506 |
+
</html>
|
| 507 |
+
"""
|
| 508 |
+
|
| 509 |
+
return html
|
| 510 |
+
|
| 511 |
@app.route('/add/<temp_id>')
|
| 512 |
def add(temp_id):
|
| 513 |
image = request.args.get("image")
|
|
|
|
| 852 |
app.config["FOLDER_SETS"] = []
|
| 853 |
app.config["DATASET_ERROR"] = error_msg
|
| 854 |
else:
|
| 855 |
+
app.config["FOLDER_SETS"] = folder_sets
|
| 856 |
app.config["DATASET_ERROR"] = None
|
| 857 |
app.config["HEAD"] = 0
|
| 858 |
app.config["IMAGE_SET_INDEX"] = 0
|