From 9c4fe7a0be57ba85582f39a684b0a471ee33f82e Mon Sep 17 00:00:00 2001 From: cottongin Date: Mon, 6 Apr 2026 19:27:49 -0400 Subject: [PATCH] feat: pass image paths to cover generator in scheduler Made-with: Cursor --- src/scheduler.py | 10 +++--- tests/test_scheduler.py | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/scheduler.py b/src/scheduler.py index 8bf08a5..f509ad6 100644 --- a/src/scheduler.py +++ b/src/scheduler.py @@ -8,7 +8,7 @@ from apscheduler.triggers.interval import IntervalTrigger import config from app import db -from src.models import Article, Issue, Setting +from src.models import Article, Image, Issue, Setting logger = logging.getLogger(__name__) @@ -81,16 +81,18 @@ class SchedulerManager: if "Obituaries" not in json.loads(a.categories) ] - categories_list = [] + image_paths = [] for a in articles: - categories_list.extend(json.loads(a.categories)) + first_image = Image.query.filter_by(article_id=a.id).first() + if first_image: + image_paths.append(first_image.local_path) auto_pub = Setting.get("auto_publish", {}) method = auto_pub.get("cover_method", "text") cover_path = generate_cover( method, config.ISSUES_DIR, week_start, week_end, - headlines, categories_list + headlines, image_paths ) epub_path = build_epub( week_start, week_end, article_ids, cover_path, config.ISSUES_DIR diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index d3e3edc..8c8096a 100644 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -1,3 +1,11 @@ +import json +import os +from datetime import date, datetime +from unittest.mock import MagicMock, patch + +from PIL import Image as PILImage + +from src.models import Article, Image from src.scheduler import SchedulerManager @@ -53,3 +61,69 @@ def test_scheduler_get_status(app): assert status["running"] is True assert "rss_fetch" in status mgr.shutdown() + + +def test_auto_publish_passes_ordered_image_paths_to_generate_cover(app, tmp_path, db): + """First image per article in pub_date order passed to generate_cover.""" + os.makedirs(tmp_path, exist_ok=True) + img1 = str(tmp_path / "a1.jpg") + img2 = str(tmp_path / "a2.jpg") + for p in (img1, img2): + PILImage.new("RGB", (100, 100), color="blue").save(p, format="JPEG") + + with app.app_context(): + a1 = Article( + guid="g1", + title="Earlier Article", + author="A", + pub_date=datetime(2026, 4, 6, 10, 0), + categories=json.dumps(["Government"]), + link="http://example.com/1", + content_html="

x

", + ) + a2 = Article( + guid="g2", + title="Later Article", + author="B", + pub_date=datetime(2026, 4, 7, 10, 0), + categories=json.dumps(["Culture"]), + link="http://example.com/2", + content_html="

y

", + ) + db.session.add_all([a1, a2]) + db.session.flush() + db.session.add_all( + [ + Image( + article_id=a1.id, + original_url="https://example.com/1.jpg", + local_path=img1, + width=100, + height=100, + ), + Image( + article_id=a2.id, + original_url="https://example.com/2.jpg", + local_path=img2, + width=100, + height=100, + ), + ] + ) + db.session.commit() + + mock_cover = MagicMock(return_value="/fake/cover.jpg") + mock_epub = MagicMock(return_value="/fake/issue.epub") + + with patch("src.scheduler.date") as mock_date, patch( + "src.cover.generate_cover", mock_cover + ), patch("src.epub_builder.build_epub", mock_epub): + mock_date.today.return_value = date(2026, 4, 6) + mgr = SchedulerManager(app) + mgr._run_auto_publish() + + mock_cover.assert_called_once() + args = mock_cover.call_args[0] + assert args[0] == "text" + assert args[4] == ["Earlier Article", "Later Article"] + assert args[5] == [img1, img2]