From 21f8f27d6600110fc028739042128504d7c95a0e Mon Sep 17 00:00:00 2001 From: djib Date: Sun, 30 Aug 2026 12:46:36 +0200 Subject: [PATCH] Initial version --- rss-generator.py | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 rss-generator.py diff --git a/rss-generator.py b/rss-generator.py new file mode 100644 index 0000000..6a14d2b --- /dev/null +++ b/rss-generator.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +""" +Generate an RSS feed from Pebble Search API data. +Requires: feedgen (pip install feedgen) +""" + +import requests +import json +from datetime import datetime, timezone +from feedgen.feed import FeedGenerator + +def fetch_apps_data(url): + """Fetch apps data from the API endpoint.""" + try: + response = requests.get(url) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + print(f"Error fetching data: {e}") + return None + +def fetch_app_description(app_id): + """Fetch the description for a specific app from its detail endpoint.""" + detail_url = f"https://repebblesearch.com/api/v1/apps/{app_id}" + try: + response = requests.get(detail_url) + response.raise_for_status() + + # Try parsing as JSON first + try: + data = response.json() + return data.get('description', '') + except json.JSONDecodeError: + # If not JSON, try to extract from response text + print(f"Warning: Detail endpoint returned non-JSON for {app_id}") + return "" + except requests.exceptions.RequestException as e: + print(f"Error fetching description for {app_id}: {e}") + return "" + +def create_rss_feed(apps_data, output_file="apps_feed.xml"): + """Create an RSS feed from apps data using feedgen.""" + + # Extract the apps list from 'items' key + if not isinstance(apps_data, dict) or 'items' not in apps_data: + print("Unexpected data structure: 'items' key not found") + return False + + apps = apps_data['items'] + + if not isinstance(apps, list): + print("Error: 'items' is not a list") + return False + + print(f"Found {len(apps)} apps to process") + + # Initialize the feed generator + fg = FeedGenerator() + fg.id('https://repebblesearch.com/api/v1/apps') + fg.title('Pebble Apps Feed') + fg.link(href='https://repebblesearch.com', rel='alternate') + fg.description('Latest Pebble apps sorted by release date') + fg.language('en') + + # Process each app + for i, app in enumerate(apps): + # Skip entries without required fields + if not isinstance(app, dict) or 'title' not in app: + continue + + app_id = app.get('id', app['title']) + print(f"Processing app {i+1}/{len(apps)}: {app['title']}") + + # Fetch description from detail endpoint + description = fetch_app_description(app_id) + + # Create a feed entry + fe = fg.add_entry() + fe.id(app_id) + fe.title(app['title']) + fe.description(description) + + # Add screenshot URL as a link with rel='enclosure' (for media) + if 'screenshot_url' in app: + fe.link(href=app['screenshot_url'], rel='enclosure', type='image/png') + + # Set publication date if available + pub_date = None + if 'release_date' in app: + try: + pub_date = datetime.fromisoformat(app['release_date'].replace('Z', '+00:00')) + except (ValueError, AttributeError): + pass + + # If no valid date, use current time with UTC timezone + if pub_date is None: + pub_date = datetime.now(timezone.utc) + + fe.pubDate(pub_date) + + # Add author if available + if 'author' in app: + fe.author(name=app['author']) + + # Write the RSS feed to file + try: + fg.rss_file(output_file, pretty=True) + print(f"RSS feed successfully created: {output_file}") + return True + except Exception as e: + print(f"Error writing RSS file: {e}") + return False + +def main(): + api_url = "https://repebblesearch.com/api/v1/apps?sort=release_date&order=desc" + output_file = "apps_feed.xml" + + print("Fetching apps data...") + apps_data = fetch_apps_data(api_url) + + if apps_data: + print("Creating RSS feed...") + if create_rss_feed(apps_data, output_file): + print(f"Done! Your RSS feed is ready at: {output_file}") + else: + print("Failed to create RSS feed") + else: + print("Failed to fetch apps data") + +if __name__ == "__main__": + main() +