#!/usr/bin/env python3 import re import os from xml.dom import minidom from xml.etree import ElementTree as ET from argparse import ArgumentParser def generate_rss(input_file, output_file, feed_url): try: with open(input_file, "r", encoding="utf-8") as f: lines = f.readlines() except FileNotFoundError: print(f'[err] {input_file} not found') exit(1) lines = lines[::-1] feed_file = os.path.basename(output_file) rss = ET.Element('rss', version='2.0') rss.set('xmlns:atom', 'http://www.w3.org/2005/Atom') channel = ET.SubElement(rss, 'channel') ET.SubElement(channel, 'title').text = 'CVE Updates Feed' ET.SubElement(channel, 'link').text = feed_url ET.SubElement(channel, 'description').text = 'RSS feed for recent CVE GitHub repositories' ET.SubElement(channel, 'atom:link', href=f'{feed_url}/{feed_file}', rel='self', type='application/rss+xml') pattern = r'-\s*\[[^\]]+\]\(([^)]+)\)\s*(.*)' for line in lines: match = re.match(pattern, line.strip()) if match: url = match.group(1).strip() description = match.group(2).strip() or 'No description' title = os.path.basename(url) item_elem = ET.SubElement(channel, 'item') ET.SubElement(item_elem, 'title').text = title ET.SubElement(item_elem, 'link').text = url ET.SubElement(item_elem, 'description').text = description rough_string = ET.tostring(rss, 'utf-8') reparsed = minidom.parseString(rough_string) pretty_xml = reparsed.toprettyxml(indent=' ', encoding='utf-8').decode('utf-8') with open(output_file, 'w', encoding='utf-8') as f: f.write(pretty_xml) print(f'[inf] rss feed generated at {output_file}') if __name__ == '__main__': parser = ArgumentParser() parser.add_argument('-i', '--input', required=True, help='path to input markdown file') parser.add_argument('-o', '--output', required=True, help='path to output xml file') parser.add_argument('-u', '--url', required=True, help='feed url') args = parser.parse_args() generate_rss( args.input, args.output, args.url )