diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d62437c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +feeds/ diff --git a/rss-generator.py b/rss-generator.py index 6a14d2b..2121e36 100644 --- a/rss-generator.py +++ b/rss-generator.py @@ -1,14 +1,42 @@ #!/usr/bin/env python3 """ -Generate an RSS feed from Pebble Search API data. +Generate RSS feeds from Pebble Search API data. Requires: feedgen (pip install feedgen) """ import requests import json +import os from datetime import datetime, timezone from feedgen.feed import FeedGenerator +# Define your feeds here +FEEDS = [ + { + 'url': 'https://repebblesearch.com/api/v1/apps?sort=release_date&order=desc&new_only=true', + 'name': 'New Apps', + 'description': 'Latest new Pebble apps' + }, + { + 'url': 'https://repebblesearch.com/api/v1/apps?sort=release_date&order=desc&recently_updated=true', + 'name': 'Updated Apps', + 'description': 'Recently updated Pebble apps' + }, + { + 'url': 'https://repebblesearch.com/api/v1/apps?sort=release_date&order=desc&categories=Games', + 'name': 'Games', + 'description': 'Pebble games' + }, + { + 'url': 'https://repebblesearch.com/api/v1/apps?sort=release_date&order=desc', + 'name': 'All Apps', + 'description': 'All Pebble apps sorted by release date' + } +] + +# Output folder for feeds +FEEDS_FOLDER = 'feeds' + def fetch_apps_data(url): """Fetch apps data from the API endpoint.""" try: @@ -38,28 +66,28 @@ def fetch_app_description(app_id): print(f"Error fetching description for {app_id}: {e}") return "" -def create_rss_feed(apps_data, output_file="apps_feed.xml"): +def create_rss_feed(apps_data, feed_name, feed_description, output_file): """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") + print(f" 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") + print(f" Error: 'items' is not a list") return False - print(f"Found {len(apps)} apps to process") + 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.id(f'https://repebblesearch.com/api/v1/apps') + fg.title(feed_name) fg.link(href='https://repebblesearch.com', rel='alternate') - fg.description('Latest Pebble apps sorted by release date') + fg.description(feed_description) fg.language('en') # Process each app @@ -69,24 +97,32 @@ def create_rss_feed(apps_data, output_file="apps_feed.xml"): continue app_id = app.get('id', app['title']) - print(f"Processing app {i+1}/{len(apps)}: {app['title']}") + print(f" Processing app {i+1}/{len(apps)}: {app['title']}") # Fetch description from detail endpoint description = fetch_app_description(app_id) + # Ensure description is never None or empty string defaults to empty + if description is None: + description = "" # Create a feed entry fe = fg.add_entry() - fe.id(app_id) - fe.title(app['title']) - fe.description(description) + fe.id(str(app_id)) # Ensure ID is a string + fe.title(str(app['title'])) # Ensure title is a string + + # Only set description if it's not empty + if description: + fe.description(description) + else: + fe.description("No description available") # 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') + if 'screenshot_url' in app and app['screenshot_url']: + fe.link(href=str(app['screenshot_url']), rel='enclosure', type='image/png') # Set publication date if available pub_date = None - if 'release_date' in app: + if 'release_date' in app and app['release_date']: try: pub_date = datetime.fromisoformat(app['release_date'].replace('Z', '+00:00')) except (ValueError, AttributeError): @@ -99,33 +135,46 @@ def create_rss_feed(apps_data, output_file="apps_feed.xml"): fe.pubDate(pub_date) # Add author if available - if 'author' in app: - fe.author(name=app['author']) + if 'author' in app and app['author']: + fe.author(name=str(app['author'])) # Write the RSS feed to file try: fg.rss_file(output_file, pretty=True) - print(f"RSS feed successfully created: {output_file}") + print(f" RSS feed successfully created: {output_file}") return True except Exception as e: - print(f"Error writing RSS file: {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" + # Create feeds folder if it doesn't exist + if not os.path.exists(FEEDS_FOLDER): + os.makedirs(FEEDS_FOLDER) + print(f"Created '{FEEDS_FOLDER}' folder\n") - print("Fetching apps data...") - apps_data = fetch_apps_data(api_url) + print("Generating Pebble apps RSS feeds...\n") - 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}") + for feed_config in FEEDS: + feed_name = feed_config['name'] + feed_url = feed_config['url'] + feed_description = feed_config['description'] + output_file = os.path.join(FEEDS_FOLDER, f"{feed_name.lower().replace(' ', '_')}_feed.xml") + + print(f"Processing: {feed_name}") + print(f" Fetching data from API...") + apps_data = fetch_apps_data(feed_url) + + if apps_data: + print(f" Creating RSS feed...") + if create_rss_feed(apps_data, feed_name, feed_description, output_file): + print(f" ✓ Done!\n") + else: + print(f" ✗ Failed to create RSS feed\n") else: - print("Failed to create RSS feed") - else: - print("Failed to fetch apps data") + print(f" ✗ Failed to fetch apps data\n") + + print("All feeds generated!") if __name__ == "__main__": main()