feat: top přispěvatel, nový účet, milník v reportu
This commit is contained in:
+27
-2
@@ -66,12 +66,13 @@ def fetch_daily_timeline(base_url, token):
|
|||||||
def main():
|
def main():
|
||||||
env = {**load_env(), **os.environ}
|
env = {**load_env(), **os.environ}
|
||||||
|
|
||||||
for var in ("NOVINKY_TOKEN", "INSTANCE_URL"):
|
for var in ("NOVINKY_TOKEN", "INSTANCE_URL", "STATS_TOKEN"):
|
||||||
if not env.get(var):
|
if not env.get(var):
|
||||||
print(f"Chybí proměnná prostředí: {var}", file=sys.stderr)
|
print(f"Chybí proměnná prostředí: {var}", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
token = env["NOVINKY_TOKEN"]
|
token = env["NOVINKY_TOKEN"]
|
||||||
|
stats_token = env["STATS_TOKEN"]
|
||||||
base_url = env["INSTANCE_URL"].rstrip("/")
|
base_url = env["INSTANCE_URL"].rstrip("/")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -107,12 +108,36 @@ def main():
|
|||||||
top = candidates[:3]
|
top = candidates[:3]
|
||||||
tags = [t for t, _ in sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:5]]
|
tags = [t for t, _ in sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:5]]
|
||||||
|
|
||||||
|
authors_count = {}
|
||||||
|
for c in candidates:
|
||||||
|
authors_count[c["acct"]] = authors_count.get(c["acct"], 0) + 1
|
||||||
|
|
||||||
|
newest_account = None
|
||||||
|
try:
|
||||||
|
accounts = api_get(
|
||||||
|
f"{base_url}/api/v1/admin/accounts?order=newest&limit=1", stats_token
|
||||||
|
)
|
||||||
|
if accounts and accounts[0].get("account", {}).get("discoverable"):
|
||||||
|
newest_account = {
|
||||||
|
"acct": accounts[0]["account"]["acct"],
|
||||||
|
"created_at": accounts[0]["created_at"],
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
out_path = os.path.join("data", f"{today}.json")
|
out_path = os.path.join("data", f"{today}.json")
|
||||||
|
|
||||||
with open(out_path, "w", encoding="utf-8") as f:
|
with open(out_path, "w", encoding="utf-8") as f:
|
||||||
json.dump({"date": today, "total_count": len(timeline), "top": top, "tags": tags}, f, ensure_ascii=False, indent=2)
|
json.dump({
|
||||||
|
"date": today,
|
||||||
|
"total_count": len(timeline),
|
||||||
|
"authors_count": authors_count,
|
||||||
|
"newest_account": newest_account,
|
||||||
|
"top": top,
|
||||||
|
"tags": tags,
|
||||||
|
}, 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ů)")
|
||||||
|
|
||||||
|
|||||||
+72
-6
@@ -126,7 +126,8 @@ def format_month_cs(dt):
|
|||||||
]
|
]
|
||||||
return f"{months[dt.month - 1]} {dt.year}"
|
return f"{months[dt.month - 1]} {dt.year}"
|
||||||
|
|
||||||
def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, instance_info, total_count=0):
|
def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
||||||
|
total_count=0, top_author=None, newest_account=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)
|
||||||
@@ -142,9 +143,18 @@ def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, inst
|
|||||||
hashtags = " ".join(f"#{t['name']}" for t in tags[:5]) if tags else "(žádné)"
|
hashtags = " ".join(f"#{t['name']}" for t in tags[:5]) if tags else "(žádné)"
|
||||||
|
|
||||||
inst_stats = instance_info.get("stats", {}) if instance_info else {}
|
inst_stats = instance_info.get("stats", {}) if instance_info else {}
|
||||||
user_count = inst_stats.get("user_count", "?")
|
user_count_val = inst_stats.get("user_count", 0)
|
||||||
|
user_count = user_count_val if user_count_val else "?"
|
||||||
domain_count = inst_stats.get("domain_count", "?")
|
domain_count = inst_stats.get("domain_count", "?")
|
||||||
|
|
||||||
|
author_line = f"✍️ Top přispěvatel: @{top_author['acct']} ({top_author['count']} tootů)\n" if top_author else ""
|
||||||
|
newest_line = f"👋 Nový účet: @{newest_account['acct']}\n" if newest_account else ""
|
||||||
|
milestone_line = (
|
||||||
|
f"🎉 Milník: Mamutovo dosáhlo {user_count_val} uživatelů!\n"
|
||||||
|
if user_count_val and user_count_val % 10 == 0 else ""
|
||||||
|
)
|
||||||
|
extra = author_line + newest_line + milestone_line
|
||||||
|
|
||||||
if top_tooty:
|
if top_tooty:
|
||||||
blocks = "\n\n".join(
|
blocks = "\n\n".join(
|
||||||
f"🐘 @{s['acct']}\n\"{truncate(s['text'], 80).replace(chr(10), ' ')}\"\n🔁 {s['reblogs']} ⭐ {s['favourites']}\n🔗 {s.get('url', '')}"
|
f"🐘 @{s['acct']}\n\"{truncate(s['text'], 80).replace(chr(10), ' ')}\"\n🔁 {s['reblogs']} ⭐ {s['favourites']}\n🔗 {s.get('url', '')}"
|
||||||
@@ -167,11 +177,14 @@ def build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, inst
|
|||||||
f"🌐 Federovaných instancí: {domain_count}\n"
|
f"🌐 Federovaných instancí: {domain_count}\n"
|
||||||
f"\n"
|
f"\n"
|
||||||
f"🔥 Top hashtagy měsíce:\n"
|
f"🔥 Top hashtagy měsíce:\n"
|
||||||
f"{hashtags}"
|
f"{hashtags}\n"
|
||||||
|
f"\n"
|
||||||
|
f"{extra}"
|
||||||
f"{tooty_sekce}"
|
f"{tooty_sekce}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number, total_count=0):
|
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):
|
||||||
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)
|
||||||
@@ -190,6 +203,11 @@ def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
|||||||
else:
|
else:
|
||||||
toot_tyden = ""
|
toot_tyden = ""
|
||||||
|
|
||||||
|
author_line = f"✍️ Top přispěvatel: @{top_author['acct']} ({top_author['count']} tootů)\n" if top_author else ""
|
||||||
|
newest_line = f"👋 Nový účet: @{newest_account['acct']}\n" if newest_account else ""
|
||||||
|
milestone_line = f"🎉 Milník: Mamutovo dosáhlo {user_count} uživatelů!\n" if user_count and user_count % 10 == 0 else ""
|
||||||
|
extra = author_line + newest_line + milestone_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
|
||||||
@@ -207,6 +225,7 @@ def build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number,
|
|||||||
f"{hashtags}\n"
|
f"{hashtags}\n"
|
||||||
f"\n"
|
f"\n"
|
||||||
f"{toot_tyden}"
|
f"{toot_tyden}"
|
||||||
|
f"{extra}"
|
||||||
f"💡 Tip týdne: {tip}"
|
f"💡 Tip týdne: {tip}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -262,6 +281,37 @@ def load_total_count_from_data(date_to, days):
|
|||||||
pass
|
pass
|
||||||
return total
|
return total
|
||||||
|
|
||||||
|
def load_top_author_from_data(date_to, days):
|
||||||
|
counts = Counter()
|
||||||
|
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)
|
||||||
|
for acct, n in file_data.get("authors_count", {}).items():
|
||||||
|
counts[acct] += n
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
if not counts:
|
||||||
|
return None
|
||||||
|
acct, n = counts.most_common(1)[0]
|
||||||
|
return {"acct": acct, "count": n}
|
||||||
|
|
||||||
|
def load_newest_account_from_data(date_to, days):
|
||||||
|
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)
|
||||||
|
acc = file_data.get("newest_account")
|
||||||
|
if acc:
|
||||||
|
return acc
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Statistiky Mamutovo.cz")
|
parser = argparse.ArgumentParser(description="Statistiky Mamutovo.cz")
|
||||||
parser.add_argument("--dry-run", action="store_true", help="Pouze vypíše toot, neodešle")
|
parser.add_argument("--dry-run", action="store_true", help="Pouze vypíše toot, neodešle")
|
||||||
@@ -315,7 +365,12 @@ def main():
|
|||||||
|
|
||||||
top_tooty = load_tooty_from_data(date_to, 30)
|
top_tooty = load_tooty_from_data(date_to, 30)
|
||||||
total_count = load_total_count_from_data(date_to, 30)
|
total_count = load_total_count_from_data(date_to, 30)
|
||||||
toot = build_monthly_toot(measures_data, tags, top_tooty, date_to, prev_stats, instance_info, total_count)
|
top_author = load_top_author_from_data(date_to, 30)
|
||||||
|
newest_account = load_newest_account_from_data(date_to, 30)
|
||||||
|
toot = build_monthly_toot(
|
||||||
|
measures_data, tags, top_tooty, date_to, prev_stats, instance_info,
|
||||||
|
total_count, top_author, newest_account,
|
||||||
|
)
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
print(toot)
|
print(toot)
|
||||||
@@ -359,9 +414,20 @@ def main():
|
|||||||
except Exception:
|
except Exception:
|
||||||
tags = []
|
tags = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
instance_info = api_get(f"{base_url}/api/v1/instance")
|
||||||
|
except Exception:
|
||||||
|
instance_info = {}
|
||||||
|
user_count = instance_info.get("stats", {}).get("user_count", 0)
|
||||||
|
|
||||||
top_tooty = load_tooty_from_data(date_to, 7)
|
top_tooty = load_tooty_from_data(date_to, 7)
|
||||||
total_count = load_total_count_from_data(date_to, 7)
|
total_count = load_total_count_from_data(date_to, 7)
|
||||||
toot = build_toot(measures_data, tags, top_tooty, date_from, date_to, week_number, total_count)
|
top_author = load_top_author_from_data(date_to, 7)
|
||||||
|
newest_account = load_newest_account_from_data(date_to, 7)
|
||||||
|
toot = build_toot(
|
||||||
|
measures_data, tags, top_tooty, date_from, date_to, week_number,
|
||||||
|
total_count, top_author, newest_account, user_count,
|
||||||
|
)
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
print(toot)
|
print(toot)
|
||||||
|
|||||||
Reference in New Issue
Block a user