Initial untested implementation
This commit is contained in:
parent
24200b899a
commit
193a50dd3b
8 changed files with 917 additions and 11 deletions
161
src/rss2newsletter/__main__.py
Normal file
161
src/rss2newsletter/__main__.py
Normal file
|
@ -0,0 +1,161 @@
|
|||
"""Main entry point for rss2newsletter."""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
from typing import List, Dict
|
||||
|
||||
from .config import get_config_from_env, setup_logging
|
||||
from .rss_fetcher import get_todays_articles
|
||||
from .ollama_client import create_ollama_client, summarize_articles
|
||||
from .html_generator import generate_newsletter_html, save_newsletter_html
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_argument_parser() -> argparse.ArgumentParser:
|
||||
"""Create command line argument parser."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate HTML newsletter from RSS feed using Ollama AI summaries",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
python -m rss2newsletter https://feeds.example.com/rss
|
||||
python -m rss2newsletter https://blog.example.com/feed.xml --output my_newsletter.html
|
||||
python -m rss2newsletter https://news.example.com/rss --model llama3.1
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument("rss_url", help="RSS feed URL to process")
|
||||
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
"-o",
|
||||
default=None,
|
||||
help="Output HTML filename (default: newsletter.html)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
"-m",
|
||||
default=None,
|
||||
help="Ollama model to use for summaries (default: llama3.2)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--ollama-url",
|
||||
default=None,
|
||||
help="Ollama server URL (default: http://localhost:11434)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--title", "-t", default=None, help="Newsletter title (default: RSS Newsletter)"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--verbose", "-v", action="store_true", help="Enable verbose logging"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Fetch articles but don't generate summaries or save HTML",
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def merge_config_with_args(config: Dict, args: argparse.Namespace) -> Dict:
|
||||
"""Merge configuration with command line arguments."""
|
||||
if args.output:
|
||||
config["output"]["filename"] = args.output
|
||||
|
||||
if args.model:
|
||||
config["ollama"]["model"] = args.model
|
||||
|
||||
if args.ollama_url:
|
||||
config["ollama"]["base_url"] = args.ollama_url
|
||||
|
||||
if args.title:
|
||||
config["output"]["feed_title"] = args.title
|
||||
|
||||
if args.verbose:
|
||||
config["logging"]["level"] = "DEBUG"
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def process_rss_to_newsletter(rss_url: str, config: Dict, dry_run: bool = False) -> str:
|
||||
"""Main processing pipeline for RSS to newsletter conversion."""
|
||||
logger.info(f"Starting RSS newsletter generation for: {rss_url}")
|
||||
|
||||
# Step 1: Fetch today's articles
|
||||
logger.info("Fetching articles from RSS feed...")
|
||||
articles = get_todays_articles(rss_url)
|
||||
|
||||
if not articles:
|
||||
logger.warning("No articles found for today")
|
||||
return generate_newsletter_html([], config["output"]["feed_title"])
|
||||
|
||||
logger.info(f"Found {len(articles)} articles from today")
|
||||
|
||||
if dry_run:
|
||||
logger.info("Dry run mode - stopping before summarization")
|
||||
for i, article in enumerate(articles, 1):
|
||||
logger.info(f"Article {i}: {article['title']}")
|
||||
return ""
|
||||
|
||||
# Step 2: Create Ollama client and summarize articles
|
||||
logger.info("Generating AI summaries...")
|
||||
ollama_client = create_ollama_client(config["ollama"]["base_url"])
|
||||
|
||||
summarized_articles = summarize_articles(
|
||||
ollama_client, articles, config["ollama"]["model"]
|
||||
)
|
||||
|
||||
# Step 3: Generate HTML newsletter
|
||||
logger.info("Generating HTML newsletter...")
|
||||
html_content = generate_newsletter_html(
|
||||
summarized_articles, config["output"]["feed_title"]
|
||||
)
|
||||
|
||||
return html_content
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Main entry point."""
|
||||
parser = create_argument_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load and merge configuration
|
||||
config = get_config_from_env()
|
||||
config = merge_config_with_args(config, args)
|
||||
|
||||
# Setup logging
|
||||
setup_logging(config)
|
||||
|
||||
try:
|
||||
# Process RSS feed to newsletter
|
||||
html_content = process_rss_to_newsletter(args.rss_url, config, args.dry_run)
|
||||
|
||||
if not args.dry_run and html_content:
|
||||
# Save HTML file
|
||||
output_filename = save_newsletter_html(
|
||||
html_content, config["output"]["filename"]
|
||||
)
|
||||
print(f"Newsletter saved to: {output_filename}")
|
||||
|
||||
return 0
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Process interrupted by user")
|
||||
return 1
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating newsletter: {e}")
|
||||
if config["logging"]["level"] == "DEBUG":
|
||||
logger.exception("Full error details:")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
Loading…
Add table
Add a link
Reference in a new issue