Created
December 7, 2025 07:40
-
-
Save omarkurt/ff9c44e3d7731504c610f854b3a5a482 to your computer and use it in GitHub Desktop.
GitHub Following to OPML Converter - Export GitHub following list as RSS/Atom feeds for feed readers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| GitHub Following to OPML Converter | |
| Exports your GitHub following list as an OPML file containing Atom feeds | |
| for each user. Import into your favorite feed reader (Feedly, Inoreader, etc.) | |
| to track activity from developers you follow. | |
| Usage: | |
| python github_following_to_opml.py <username> | |
| python github_following_to_opml.py omarkurt | |
| Output: | |
| Creates <username>_following.opml in the current directory | |
| Requirements: | |
| pip install requests | |
| uv pip install requests | |
| """ | |
| import requests | |
| import xml.etree.ElementTree as ET | |
| from xml.dom import minidom | |
| import sys | |
| def generate_opml(username): | |
| """Fetch GitHub following list and generate OPML file with Atom feeds.""" | |
| base_url = f"https://api.github.com/users/{username}/following" | |
| following_list = [] | |
| page = 1 | |
| print(f"Fetching following list for '{username}', please wait...") | |
| while True: | |
| try: | |
| response = requests.get(f"{base_url}?per_page=100&page={page}") | |
| if response.status_code != 200: | |
| print(f"Error: {response.status_code}") | |
| break | |
| data = response.json() | |
| if not data: | |
| break | |
| for user in data: | |
| following_list.append(user['login']) | |
| page += 1 | |
| except Exception as e: | |
| print(f"An error occurred: {e}") | |
| break | |
| # Build OPML structure | |
| opml = ET.Element('opml', version="1.0") | |
| head = ET.SubElement(opml, 'head') | |
| ET.SubElement(head, 'title').text = f"{username} GitHub Following List" | |
| body = ET.SubElement(opml, 'body') | |
| main_outline = ET.SubElement( | |
| body, 'outline', | |
| text=f"Following by {username}", | |
| title=f"{username} Following" | |
| ) | |
| for user in following_list: | |
| feed_url = f"https://github.com/{user}.atom" | |
| profile_url = f"https://github.com/{user}" | |
| ET.SubElement( | |
| main_outline, 'outline', | |
| type="rss", | |
| text=user, | |
| title=user, | |
| xmlUrl=feed_url, | |
| htmlUrl=profile_url | |
| ) | |
| # Pretty print XML | |
| xmlstr = minidom.parseString(ET.tostring(opml)).toprettyxml(indent=" ") | |
| filename = f"{username}_following.opml" | |
| with open(filename, "w", encoding="utf-8") as f: | |
| f.write(xmlstr) | |
| print(f"\nSuccess! Found {len(following_list)} users.") | |
| print(f"File created: {filename}") | |
| if __name__ == "__main__": | |
| if len(sys.argv) > 1: | |
| target_user = sys.argv[1] | |
| else: | |
| print("No username provided, using default...") | |
| target_user = 'infosec-au' | |
| generate_opml(target_user) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment