Deployables / refresh_task.py
skander101's picture
fix: extract dates from article pages via trafilatura instead of homepage HTML
623f05d
Raw
History Blame Contribute Delete
4.78 kB
#!/usr/bin/env python3
"""
Standalone script for PythonAnywhere scheduled tasks.
Run daily at 3:00 UTC (4:00 AM Tunisian time).
Usage:
python3 /home/YOUR_USER/newsapp/refresh_task.py
"""
import json
import logging
import os
import sys
from collections import defaultdict
from datetime import datetime, timezone
logging.basicConfig(level=logging.INFO, format="%(levelname).1s %(message)s", stream=sys.stderr)
logger = logging.getLogger(__name__)
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from config import Config
from main import run_pipeline
from src.models import NewsItem
from src.rss_feed_scraper import RSSFeedScraper
cfg = Config()
CACHE_FILE = os.getenv("CACHE_FILE", "/tmp/cache_data.json")
CATEGORIES = ["Geopolitical", "World Health", "Tech", "Cybersecurity", "Funny/Weird", "Gaming", "Movies", "Arab World", "Tunisia"]
def serialize_clusters(clusters):
by_cat = defaultdict(list)
results = []
for c in clusters:
cat = "General"
if c.articles and c.articles[0].analysis:
ca = c.articles[0].analysis.category
cat = ca if ca in CATEGORIES else "General"
html = {
"category": cat,
"topic": c.topic,
"score": round(c.final_score, 2),
"trust": f"{c.avg_trustworthiness:.0%}",
"coverage": c.total_coverage,
"image_url": c.image_url,
"top_post_url": c.top_post_url,
"articles": [
{
"title": a.article.title or a.post.title,
"summary": a.analysis.summary if a.analysis else "",
"topics": a.analysis.topics if a.analysis else [],
"trust": f"{a.analysis.trustworthiness_score:.0%}" if a.analysis else "",
"sponsor": a.analysis.sponsor.get("display", "") if a.analysis else "",
"sponsor_info": a.analysis.sponsor if a.analysis else {},
"sourcing_penalty": a.analysis.sourcing_penalty if a.analysis else 0,
"score": a.post.score,
"comments": a.post.num_comments,
"url": a.post.url,
"image": a.article.image_url if a.article else a.post.image_url,
"published": a.article.published or a.post.published,
"published_iso": a.article.published_iso or a.post.published_iso,
}
for a in c.articles[:5]
],
}
by_cat[cat].append(html)
api = {
"id": f"cluster-{id(c)}",
"topic": c.topic,
"category": cat,
"final_score": round(c.final_score, 2),
"avg_trustworthiness": round(c.avg_trustworthiness, 2),
"total_coverage": c.total_coverage,
"image_url": c.image_url,
"top_post_url": c.top_post_url,
"articles": [
{
"title": a.article.title or a.post.title,
"url": a.post.url,
"domain": a.article.source_domain if a.article else "",
"summary": a.analysis.summary if a.analysis else "",
"topics": a.analysis.topics if a.analysis else [],
"trust": round(a.analysis.trustworthiness_score, 2) if a.analysis else 0,
"sponsor": a.analysis.sponsor.get("display", "") if a.analysis else "",
"sponsor_info": a.analysis.sponsor if a.analysis else {},
"sourcing_penalty": a.analysis.sourcing_penalty if a.analysis else 0,
"score": a.post.score,
"comments": a.post.num_comments,
"image": a.article.image_url if a.article else a.post.image_url,
"published": a.article.published or a.post.published,
"published_iso": a.article.published_iso or a.post.published_iso,
}
for a in c.articles[:5]
],
}
results.append(api)
data = {
"by_cat": dict(by_cat),
"results": results,
"status": f"ok — {len(clusters)} clusters",
"last_refresh": datetime.now(timezone.utc).isoformat(),
}
with open(CACHE_FILE, "w") as f:
json.dump(data, f)
logger.info("Cache written to %s (%d clusters)", CACHE_FILE, len(clusters))
def main():
logger.info("Starting refresh task...")
scraper = RSSFeedScraper(cfg)
posts = scraper.fetch_posts()
items = [NewsItem(post=p) for p in posts]
clusters = run_pipeline(items, cfg)
serialize_clusters(clusters)
logger.info("Refresh task done — %d clusters", len(clusters))
if __name__ == "__main__":
main()