feat: nejaktivnější hodina v týdenním i měsíčním přehledu
This commit is contained in:
@@ -7,6 +7,9 @@ import sys
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.error
|
import urllib.error
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
_TZ_PRAGUE = ZoneInfo("Europe/Prague")
|
||||||
|
|
||||||
def load_env(path=".env"):
|
def load_env(path=".env"):
|
||||||
env = {}
|
env = {}
|
||||||
@@ -83,7 +86,11 @@ def main():
|
|||||||
tag_counts = {}
|
tag_counts = {}
|
||||||
candidates = []
|
candidates = []
|
||||||
media_count = {"image": 0, "video": 0, "gifv": 0, "audio": 0, "total": 0}
|
media_count = {"image": 0, "video": 0, "gifv": 0, "audio": 0, "total": 0}
|
||||||
|
hourly_count = {str(h): 0 for h in range(24)}
|
||||||
for toot in timeline:
|
for toot in timeline:
|
||||||
|
created_at = datetime.fromisoformat(toot["created_at"].replace("Z", "+00:00"))
|
||||||
|
local_hour = str(created_at.astimezone(_TZ_PRAGUE).hour)
|
||||||
|
hourly_count[local_hour] += 1
|
||||||
for att in toot.get("media_attachments", []):
|
for att in toot.get("media_attachments", []):
|
||||||
att_type = att.get("type", "")
|
att_type = att.get("type", "")
|
||||||
media_count["total"] += 1
|
media_count["total"] += 1
|
||||||
@@ -158,6 +165,7 @@ def main():
|
|||||||
"tags": tags,
|
"tags": tags,
|
||||||
"top_links": top_links,
|
"top_links": top_links,
|
||||||
"media_count": media_count,
|
"media_count": media_count,
|
||||||
|
"hourly_count": hourly_count,
|
||||||
}, f, ensure_ascii=False, indent=2)
|
}, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
print(f"Uloženo: {out_path} ({len(timeline)} tootů načteno, {len(top)} top, {len(tags)} hashtagů)")
|
print(f"Uloženo: {out_path} ({len(timeline)} tootů načteno, {len(top)} top, {len(tags)} hashtagů)")
|
||||||
|
|||||||
+35
-3
@@ -128,7 +128,7 @@ def format_month_cs(dt):
|
|||||||
|
|
||||||
def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
||||||
total_count=0, top_author=None, newest_account=None, top_links=None,
|
total_count=0, top_author=None, newest_account=None, top_links=None,
|
||||||
media_count=None):
|
media_count=None, hourly_count=None):
|
||||||
stats = {m["key"]: int(m["total"]) for m in measures_data}
|
stats = {m["key"]: int(m["total"]) for m in measures_data}
|
||||||
new_users = stats.get("new_users", 0)
|
new_users = stats.get("new_users", 0)
|
||||||
active_users = stats.get("active_users", 0)
|
active_users = stats.get("active_users", 0)
|
||||||
@@ -180,6 +180,12 @@ def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, inst
|
|||||||
else:
|
else:
|
||||||
media_line = ""
|
media_line = ""
|
||||||
|
|
||||||
|
if hourly_count and any(hourly_count.values()):
|
||||||
|
peak_h = max(hourly_count, key=lambda h: hourly_count[h])
|
||||||
|
peak_line = f"⏰ Nejaktivnější čas: {int(peak_h):02d}:00–{(int(peak_h) + 1) % 24:02d}:00 ({hourly_count[peak_h]} tootů)\n"
|
||||||
|
else:
|
||||||
|
peak_line = ""
|
||||||
|
|
||||||
return (
|
return (
|
||||||
f"🐘 Měsíční přehled Mamutovo.cz\n"
|
f"🐘 Měsíční přehled Mamutovo.cz\n"
|
||||||
f"📅 {format_month_cs(date_to)}\n"
|
f"📅 {format_month_cs(date_to)}\n"
|
||||||
@@ -189,6 +195,7 @@ def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, inst
|
|||||||
f"📝 Interakce: {interactions}{fmt_diff(interactions, 'interactions')}\n"
|
f"📝 Interakce: {interactions}{fmt_diff(interactions, 'interactions')}\n"
|
||||||
f"📝 Tooty měsíce: {total_count}\n"
|
f"📝 Tooty měsíce: {total_count}\n"
|
||||||
f"{media_line}"
|
f"{media_line}"
|
||||||
|
f"{peak_line}"
|
||||||
f"\n"
|
f"\n"
|
||||||
f"📊 Celkem uživatelů: {user_count}\n"
|
f"📊 Celkem uživatelů: {user_count}\n"
|
||||||
f"🌐 Federovaných instancí: {domain_count}\n"
|
f"🌐 Federovaných instancí: {domain_count}\n"
|
||||||
@@ -203,7 +210,7 @@ def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, inst
|
|||||||
|
|
||||||
def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
||||||
total_count=0, top_author=None, newest_account=None, user_count=0, top_links=None,
|
total_count=0, top_author=None, newest_account=None, user_count=0, top_links=None,
|
||||||
prev_stats=None, media_count=None):
|
prev_stats=None, media_count=None, hourly_count=None):
|
||||||
stats = {m["key"]: int(m["total"]) for m in measures_data}
|
stats = {m["key"]: int(m["total"]) for m in measures_data}
|
||||||
new_users = stats.get("new_users", 0)
|
new_users = stats.get("new_users", 0)
|
||||||
active_users = stats.get("active_users", 0)
|
active_users = stats.get("active_users", 0)
|
||||||
@@ -249,6 +256,12 @@ def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
|||||||
else:
|
else:
|
||||||
media_line = ""
|
media_line = ""
|
||||||
|
|
||||||
|
if hourly_count and any(hourly_count.values()):
|
||||||
|
peak_h = max(hourly_count, key=lambda h: hourly_count[h])
|
||||||
|
peak_line = f"⏰ Nejaktivnější čas: {int(peak_h):02d}:00–{(int(peak_h) + 1) % 24:02d}:00 ({hourly_count[peak_h]} tootů)\n"
|
||||||
|
else:
|
||||||
|
peak_line = ""
|
||||||
|
|
||||||
date_from_str = format_date_cs(date_from)
|
date_from_str = format_date_cs(date_from)
|
||||||
date_to_str = format_date_cs(date_to)
|
date_to_str = format_date_cs(date_to)
|
||||||
year = date_to.year
|
year = date_to.year
|
||||||
@@ -262,6 +275,7 @@ def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
|||||||
f"📝 Interakce: {interactions}{fmt_diff(interactions, 'interactions')}\n"
|
f"📝 Interakce: {interactions}{fmt_diff(interactions, 'interactions')}\n"
|
||||||
f"📝 Tooty týdne: {total_count}\n"
|
f"📝 Tooty týdne: {total_count}\n"
|
||||||
f"{media_line}"
|
f"{media_line}"
|
||||||
|
f"{peak_line}"
|
||||||
f"\n"
|
f"\n"
|
||||||
f"🔥 Populární hashtagy:\n"
|
f"🔥 Populární hashtagy:\n"
|
||||||
f"{hashtags}\n"
|
f"{hashtags}\n"
|
||||||
@@ -376,6 +390,21 @@ def load_media_count_from_data(date_to, days):
|
|||||||
pass
|
pass
|
||||||
return totals
|
return totals
|
||||||
|
|
||||||
|
def load_hourly_count_from_data(date_to, days):
|
||||||
|
totals = {str(h): 0 for h in range(24)}
|
||||||
|
for i in range(days):
|
||||||
|
day = (date_to - timedelta(days=i)).strftime("%Y-%m-%d")
|
||||||
|
path = os.path.join("data", f"{day}.json")
|
||||||
|
try:
|
||||||
|
with open(path, encoding="utf-8") as f:
|
||||||
|
file_data = json.load(f)
|
||||||
|
hc = file_data.get("hourly_count", {})
|
||||||
|
for h in totals:
|
||||||
|
totals[h] += hc.get(h, 0)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
return totals
|
||||||
|
|
||||||
def load_newest_account_from_data(date_to, days):
|
def load_newest_account_from_data(date_to, days):
|
||||||
for i in range(days):
|
for i in range(days):
|
||||||
day = (date_to - timedelta(days=i)).strftime("%Y-%m-%d")
|
day = (date_to - timedelta(days=i)).strftime("%Y-%m-%d")
|
||||||
@@ -447,9 +476,10 @@ def main():
|
|||||||
newest_account = load_newest_account_from_data(date_to, 30)
|
newest_account = load_newest_account_from_data(date_to, 30)
|
||||||
top_links = load_top_links_from_data(date_to, 30)
|
top_links = load_top_links_from_data(date_to, 30)
|
||||||
media_count = load_media_count_from_data(date_to, 30)
|
media_count = load_media_count_from_data(date_to, 30)
|
||||||
|
hourly_count = load_hourly_count_from_data(date_to, 30)
|
||||||
toot = build_monthly_toot(
|
toot = build_monthly_toot(
|
||||||
measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
||||||
total_count, top_author, newest_account, top_links, media_count,
|
total_count, top_author, newest_account, top_links, media_count, hourly_count,
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
@@ -514,9 +544,11 @@ def main():
|
|||||||
newest_account = load_newest_account_from_data(date_to, 7)
|
newest_account = load_newest_account_from_data(date_to, 7)
|
||||||
top_links = load_top_links_from_data(date_to, 7)
|
top_links = load_top_links_from_data(date_to, 7)
|
||||||
media_count = load_media_count_from_data(date_to, 7)
|
media_count = load_media_count_from_data(date_to, 7)
|
||||||
|
hourly_count = load_hourly_count_from_data(date_to, 7)
|
||||||
toot = build_toot(
|
toot = build_toot(
|
||||||
measures_data, tags, top_tooty, date_from, date_to, week_number,
|
measures_data, tags, top_tooty, date_from, date_to, week_number,
|
||||||
total_count, top_author, newest_account, user_count, top_links, prev_stats, media_count,
|
total_count, top_author, newest_account, user_count, top_links, prev_stats, media_count,
|
||||||
|
hourly_count,
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
|
|||||||
Reference in New Issue
Block a user