feedvault.se/cli/update_feeds.py

92 lines
2.5 KiB
Python

import sys
import traceback
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from typing import TYPE_CHECKING
from reader import (
Feed,
ParseError,
Reader,
StorageError,
UpdatedFeed,
UpdateError,
UpdateResult,
)
from rich import print
from app.dependencies import get_reader
from cli.cli import app
if TYPE_CHECKING:
from collections.abc import Iterable
def _add_broken_feed_to_csv(feed: Feed | UpdateResult | None) -> None:
"""Add a broken feed to a CSV file."""
if feed is None:
print("Feed is None.")
return
with Path("broken_feeds.csv").open("a", encoding="utf-8") as f:
f.write(f"{feed.url}\n")
@app.command(
name="update_feeds",
help="Update all the feeds.",
)
def update_feeds() -> None:
"""Update all the feeds."""
reader: Reader = get_reader()
print("Updating feeds...")
feeds: Iterable[Feed] = reader.get_feeds(
broken=False,
updates_enabled=True,
new=True,
)
total_feeds: int | None = reader.get_feed_counts(
broken=False,
updates_enabled=True,
).total
if not total_feeds:
print("[bold red]No feeds to update[/bold red]")
return
print(f"Feeds to update: {total_feeds}")
def update_feed(feed: Feed) -> None:
try:
updated_feed: UpdatedFeed | None = reader.update_feed(feed)
if updated_feed is not None:
print(
f"New: [green]{updated_feed.new}[/green], modified: [yellow]{updated_feed.modified}[/yellow], unmodified: {updated_feed.unmodified} - {feed.url}", # noqa: E501
)
except ParseError as e:
print(f"[bold red]Error parsing feed[/bold red]: {feed.url} ({e})")
except UpdateError as e:
print(f"[bold red]Error updating feed[/bold red]: {feed.url} ({e})")
except StorageError as e:
print(f"[bold red]Error updating feed[/bold red]: {feed.url}")
print(f"[bold red]Storage error[/bold red]: {e}")
except AssertionError:
print(f"[bold red]Assertion error[/bold red]: {feed.url}")
traceback.print_exc(file=sys.stderr)
reader.disable_feed_updates(feed)
_add_broken_feed_to_csv(feed)
except KeyboardInterrupt:
print("[bold red]Keyboard interrupt[/bold red]")
reader.close()
sys.exit(1)
with ThreadPoolExecutor(max_workers=50) as executor:
executor.map(update_feed, feeds)
print(f"Updated {total_feeds} feeds.")