import requests
import os
from datetime import datetime
from feedgen.feed import FeedGenerator
from feedgen.entry import FeedEntry
API_BASE_URL = "https://repebblesearch.com/api/v1/apps"
OUTPUT_FOLDER = "feeds"
def format_description(text):
"""Convert release notes text to HTML with paragraph and list support."""
if not text:
return ""
html = ""
lines = text.split("\n")
in_list = False
for line in lines:
line = line.strip()
if not line:
if in_list:
html += ""
in_list = False
continue
# Check if line is a list item (starts with -, *, or •)
if line.startswith(("-", "*", "•")):
if not in_list:
html += "
"
in_list = True
item_text = line[1:].strip()
html += f"- {item_text}
"
else:
if in_list:
html += "
"
in_list = False
html += f"{line}
"
if in_list:
html += ""
return html
def create_description_with_screenshots(app_data):
"""Build description with screenshots on a single line, then release notes."""
description = ""
# Add screenshots on a single line at the top
screenshots = app_data.get("screenshots", [])
if screenshots:
screenshot_html = ''
for idx, screenshot in enumerate(screenshots, 1):
url = screenshot.get("url", "")
width = screenshot.get("width", "auto")
height = screenshot.get("height", "auto")
hardware = screenshot.get("hardware", "")
label = f"Screenshot {idx}"
if hardware:
label += f" ({hardware})"
screenshot_html += f'

'
screenshot_html += '
'
description += screenshot_html
# Add release notes below screenshots
changelog = app_data.get("changelog", [])
if changelog:
for entry in changelog:
version = entry.get("version", "Unknown")
published_date = entry.get("published_date", "")
release_notes = entry.get("release_notes", "")
# Format the date
if published_date:
try:
date_obj = datetime.fromisoformat(published_date.replace('Z', '+00:00'))
formatted_date = date_obj.strftime("%Y-%m-%d %H:%M UTC")
except:
formatted_date = published_date
else:
formatted_date = "Unknown"
description += f"Version {version}
"
description += f"Released: {formatted_date}
"
description += format_description(release_notes)
else:
# Fallback to latest_release_notes
latest_notes = app_data.get("latest_release_notes", "")
if latest_notes:
description += format_description(latest_notes)
return description
def fetch_apps(query, platform="basalt"):
"""Fetch apps from the Pebble Search API."""
params = {
"query": query,
"platform": platform,
"limit": 100
}
try:
response = requests.get(API_BASE_URL, params=params)
response.raise_for_status()
data = response.json()
return data.get("apps", [])
except requests.exceptions.RequestException as e:
print(f"Error fetching apps for query '{query}': {e}")
return []
def create_rss_feed(filename, title, description, apps):
"""Create an RSS feed from app data."""
fg = FeedGenerator()
fg.title(title)
fg.link(href="https://repebblesearch.com", rel="alternate")
fg.description(description)
fg.language("en")
for app in apps:
fe = fg.add_entry()
app_title = app.get("title", "Unknown App")
app_id = app.get("uuid", "")
app_url = f"https://repebblesearch.com/app/{app_id}" if app_id else "https://repebblesearch.com"
fe.title(app_title)
fe.link(href=app_url)
fe.guid(app_url)
# Build description with screenshots and release notes
description_html = create_description_with_screenshots(app)
fe.description(description_html)
# Add enclosures for screenshots (for readers that support them)
screenshots = app.get("screenshots", [])
for screenshot in screenshots:
url = screenshot.get("url", "")
if url:
fe.enclosure(url=url, type="image/png")
# Set publication date from latest changelog entry or fallback
pub_date = None
changelog = app.get("changelog", [])
if changelog and len(changelog) > 0:
pub_date_str = changelog[0].get("published_date", "")
if pub_date_str:
try:
pub_date = datetime.fromisoformat(pub_date_str.replace('Z', '+00:00'))
except:
pub_date = datetime.now()
else:
pub_date = datetime.now()
if pub_date:
fe.pubDate(pub_date)
# Ensure output folder exists
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
# Write RSS feed to file
output_path = os.path.join(OUTPUT_FOLDER, filename)
fg.rss_file(output_path, pretty=True)
print(f"Feed created: {output_path}")
def main():
"""Main function to generate RSS feeds."""
print("Fetching Pebble apps and generating RSS feeds...")
# Fetch new apps
print("Fetching new apps...")
new_apps = fetch_apps("*", platform="basalt")
# Fetch updated apps (you might want to adjust the query)
print("Fetching updated apps...")
updated_apps = fetch_apps("*", platform="basalt")
# Create RSS feeds
create_rss_feed(
"new_apps.xml",
"New Pebble Apps",
"Recently released Pebble apps from the Pebble Search database",
new_apps[:20] # Limit to 20 most recent
)
create_rss_feed(
"updated_apps.xml",
"Updated Pebble Apps",
"Recently updated Pebble apps from the Pebble Search database",
updated_apps[:20] # Limit to 20 most recent
)
print("Done!")
if __name__ == "__main__":
main()