diff --git a/src/main.py b/src/main.py
index b34136a..5130b6f 100644
--- a/src/main.py
+++ b/src/main.py
@@ -8,8 +8,8 @@
import logging
import json
from .models import initialize_database, close_database
-from .schemas import BadgeParams, UrlStatsResponse, SystemStatsResponse
-from .services import update_visit_count, get_url_visit_count, get_system_statistics, get_app_info, load_template
+from .schemas import BadgeParams, TagStatsResponse, SystemStatsResponse
+from .services import update_visit_count, get_tag_visit_count, get_system_statistics, get_app_info, load_template
from .utils import build_shields_url, get_security_headers
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
@@ -71,48 +71,48 @@ def get_app_version():
async def badge(
request: Request,
response: Response,
- url: str,
+ tag: str,
label: str = "visits",
color: str = "4ade80",
style: str = "flat",
logo: str = "",
):
try:
- params = BadgeParams(url=url, label=label, color=color, style=style, logo=logo)
+ params = BadgeParams(tag=tag, label=label, color=color, style=style, logo=logo)
except Exception:
raise HTTPException(status_code=400, detail="Invalid parameters.")
cookie_id = request.cookies.get("visitor_id")
try:
- count, was_incremented, new_cookie_id = update_visit_count(cookie_id, params.url)
+ count, was_incremented, new_cookie_id = update_visit_count(cookie_id, params.tag)
if new_cookie_id:
response.set_cookie(key="visitor_id", value=new_cookie_id, max_age=31536000, httponly=True, samesite="Lax")
except ValueError as e:
raise HTTPException(status_code=429, detail=str(e))
except Exception as e:
logger.error(f"Error updating visit count: {e}")
- count = get_url_visit_count(params.url)
+ count = get_tag_visit_count(params.tag)
shields_url = build_shields_url(params.label, count, params.color, params.style, params.logo)
headers = get_security_headers()
return RedirectResponse(shields_url, headers=headers)
-@app.get("/api/stats/{url}", response_model=UrlStatsResponse)
-async def get_url_stats_endpoint(url: str):
+@app.get("/api/stats/{tag}", response_model=TagStatsResponse)
+async def get_tag_stats_endpoint(tag: str):
try:
- if not url or len(url) > 200:
- raise HTTPException(status_code=400, detail="Invalid URL parameter")
+ if not tag or len(tag) > 200:
+ raise HTTPException(status_code=400, detail="Invalid tag parameter")
- count = get_url_visit_count(url)
- return UrlStatsResponse(
- url=url,
+ count = get_tag_visit_count(tag)
+ return TagStatsResponse(
+ tag=tag,
visit_count=count,
last_updated=int(time.time())
)
except Exception as e:
- logger.error(f"Error getting URL stats: {e}")
+ logger.error(f"Error getting tag stats: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
@app.get("/api/stats", response_model=SystemStatsResponse)
@@ -121,10 +121,9 @@ async def get_system_stats_endpoint():
stats = get_system_statistics()
return SystemStatsResponse(
- total_tracked_urls=stats["total_tracked_urls"],
+ total_tracked_tags=stats["total_tracked_tags"],
total_visits=stats["total_visits"],
- new_badges_today=stats["new_badges_today"],
- rate_limit_window_hours=0
+ new_badges_today=stats["new_badges_today"]
)
except Exception as e:
logger.error(f"Error getting system stats: {e}")
diff --git a/src/models.py b/src/models.py
index 05c3206..3588f4e 100644
--- a/src/models.py
+++ b/src/models.py
@@ -18,8 +18,8 @@ class Meta:
database = db
class Badge(BaseModel):
- """Badge URLs with their total visit counts"""
- url = CharField(max_length=200, unique=True)
+ """Badge tags with their total visit counts"""
+ tag = CharField(max_length=200, unique=True)
visits = IntegerField(default=0)
created = IntegerField() # When first created
diff --git a/src/schemas.py b/src/schemas.py
index 78fd6e0..3a51c86 100644
--- a/src/schemas.py
+++ b/src/schemas.py
@@ -2,22 +2,21 @@
from typing import Annotated
class BadgeParams(BaseModel):
- url: Annotated[str, Field(strip_whitespace=True, min_length=1, max_length=200)]
+ tag: Annotated[str, Field(strip_whitespace=True, min_length=1, max_length=200)]
label: Annotated[str, Field(strip_whitespace=True, min_length=1, max_length=20)] = "visits"
color: Annotated[str, Field(strip_whitespace=True, min_length=3, max_length=10)] = "4ade80"
style: Annotated[str, Field(strip_whitespace=True, min_length=2, max_length=10)] = "flat"
logo: Annotated[str, Field(strip_whitespace=True, max_length=20)] = ""
-class UrlStatsResponse(BaseModel):
- url: str
+class TagStatsResponse(BaseModel):
+ tag: str
visit_count: int
last_updated: int
class SystemStatsResponse(BaseModel):
- total_tracked_urls: int
+ total_tracked_tags: int
total_visits: int
new_badges_today: int
- rate_limit_window_hours: int
class AppInfoResponse(BaseModel):
version: str
diff --git a/src/services.py b/src/services.py
index 63e570e..d0587ac 100644
--- a/src/services.py
+++ b/src/services.py
@@ -9,15 +9,15 @@
logger = logging.getLogger(__name__)
-def update_visit_count(cookie_id: str, url_str: str) -> Tuple[int, bool, str]:
- """Update visit count for a URL and cookie combination"""
+def update_visit_count(cookie_id: str, tag_str: str) -> Tuple[int, bool, str]:
+ """Update visit count for a tag and cookie combination"""
current_time = int(time.time())
new_cookie_id = None
try:
with db.atomic():
badge, badge_created = Badge.get_or_create(
- url=url_str,
+ tag=tag_str,
defaults={'created': current_time}
)
@@ -41,15 +41,15 @@ def update_visit_count(cookie_id: str, url_str: str) -> Tuple[int, bool, str]:
except Exception as e:
logger.error(f"Error updating visit count: {e}")
try:
- badge = Badge.get(Badge.url == url_str)
+ badge = Badge.get(Badge.tag == tag_str)
return badge.visits, False, new_cookie_id
except Badge.DoesNotExist:
return 0, False, new_cookie_id
-def get_url_visit_count(url_str: str) -> int:
- """Get total visit count for a URL"""
+def get_tag_visit_count(tag_str: str) -> int:
+ """Get total visit count for a tag"""
try:
- badge = Badge.get(Badge.url == url_str)
+ badge = Badge.get(Badge.tag == tag_str)
return badge.visits
except Badge.DoesNotExist:
return 0
@@ -57,7 +57,7 @@ def get_url_visit_count(url_str: str) -> int:
def get_system_statistics() -> dict:
"""Get system-wide statistics"""
try:
- total_urls = Badge.select().count()
+ total_tags = Badge.select().count()
total_visits = Badge.select(fn.SUM(Badge.visits)).scalar() or 0
# Count badges created in last 24 hours
@@ -67,14 +67,14 @@ def get_system_statistics() -> dict:
).count()
return {
- "total_tracked_urls": total_urls,
+ "total_tracked_tags": total_tags,
"total_visits": total_visits,
"new_badges_today": recent_badges,
}
except Exception as e:
logger.error(f"Error getting system statistics: {e}")
return {
- "total_tracked_urls": 0,
+ "total_tracked_tags": 0,
"total_visits": 0,
"new_badges_today": 0,
}
diff --git a/static/script.js b/static/script.js
index d3b8c24..1dae0cc 100644
--- a/static/script.js
+++ b/static/script.js
@@ -6,7 +6,7 @@ class BadgeGenerator {
}
initializeElements() {
this.form = document.getElementById('badge-form');
- this.urlInput = document.getElementById('url');
+ this.tagInput = document.getElementById('tag');
this.labelInput = document.getElementById('label');
this.colorInput = document.getElementById('color');
this.colorPicker = document.getElementById('color-picker');
@@ -33,16 +33,9 @@ class BadgeGenerator {
option.addEventListener('click', () => {
this.selectColor(option);
});
- });
-
- // Copy button events
- document.querySelectorAll('.copy-btn').forEach((btn) => {
- btn.addEventListener('click', (e) => {
- this.copyToClipboard(e.target);
- });
}); // Real-time preview
[
- this.urlInput,
+ this.tagInput,
this.labelInput,
this.colorInput,
this.styleSelect,
@@ -127,8 +120,8 @@ class BadgeGenerator {
updatePreview() {
if (!this.badgePreview) return;
- const url = this.urlInput.value.trim();
- if (!url) return;
+ const tag = this.tagInput.value.trim();
+ if (!tag) return;
const badgeUrl = this.buildBadgeUrl();
this.badgePreview.innerHTML = ``;
@@ -137,7 +130,7 @@ class BadgeGenerator {
buildBadgeUrl() {
const baseUrl = window.location.origin;
const params = new URLSearchParams({
- url: this.urlInput.value.trim(),
+ tag: this.tagInput.value.trim(),
label: this.labelInput.value.trim() || 'visits',
color: this.colorInput.value.trim() || '247e62',
style: this.styleSelect.value || 'flat',
@@ -151,17 +144,9 @@ class BadgeGenerator {
}
generateBadge() {
- const url = this.urlInput.value.trim();
- if (!url) {
- this.showToast('Please enter a URL');
- return;
- }
-
- // Validate URL format
- try {
- new URL(url.startsWith('http') ? url : `https://${url}`);
- } catch {
- this.showToast('Please enter a valid URL');
+ const tag = this.tagInput.value.trim();
+ if (!tag) {
+ this.showToast('Please enter a tracking tag');
return;
}
@@ -173,11 +158,11 @@ class BadgeGenerator {
this.badgeUrl.textContent = badgeUrl;
// Generate markdown
- const markdown = `[](${url})`;
+ const markdown = ``;
this.markdownCode.textContent = markdown;
// Generate HTML
- const html = `
`;
+ const html = `
`;
this.htmlCode.textContent = html;
// Show results
diff --git a/templates/index.html b/templates/index.html
index 85e773b..5ef2358 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -41,9 +41,9 @@