RSS-to-Rocket/koji rss to rocket json.py

178 lines
5.7 KiB
Python
Raw Normal View History

2025-01-08 17:59:56 +01:00
import time
import feedparser
import requests
import sqlite3
import logging
import os
import requests
from bs4 import BeautifulSoup
import socket
import sys
def join_lines_with_newline(lines):
return "\n".join(lines)
def get_ip_address(domain, retries=10, delay=1):
"""
Resolves the IP address of a domain, retrying up to `retries` times if it fails.
Args:
domain (str): The domain name to resolve.
retries (int): Number of retry attempts (default is 10).
delay (int): Delay between retries in seconds (default is 1 second).
Returns:
str: The IP address if resolved successfully.
Raises:
RuntimeError: If unable to resolve the domain after all attempts.
"""
for attempt in range(1, retries + 1):
try:
ip_address = socket.gethostbyname(domain)
logging.info(f"Successfully resolved {domain} to {ip_address}")
return ip_address
except socket.gaierror:
logging.warning(f"Attempt {attempt} failed. Retrying...")
time.sleep(delay)
raise RuntimeError(f"Unable to resolve domain '{domain}' after {retries} attempts.")
def extract_changelog_top(koji_link, host_header):
try:
response = requests.get(koji_link, headers={'Host': host_header})
except Exception as e:
logging.error(f"Koji link failed: {str(e)}")
return []
soup = BeautifulSoup(response.text, 'html.parser')
changelog_td = soup.find('td', class_='changelog')
if changelog_td:
changelog_text = changelog_td.get_text(strip=False)
lines = changelog_text.split('\n')
result = []
seen = set()
for line in lines:
stripped_line = line.strip()
if not stripped_line:
if result:
break
continue
if stripped_line not in seen:
seen.add(stripped_line)
if not result or stripped_line.startswith('-'):
result.append(stripped_line)
return join_lines_with_newline(result)
else:
return []
2025-01-08 17:59:56 +01:00
# Updated Rocket.Chat webhook URL
2025-01-08 17:59:56 +01:00
ROCKET_CHAT_URL = "https://chat.koozali.org/hooks/66d24441effca216c2ca309f/KJLaNwc5vyHwqz5MhRDpBkKWnQuAfsCX3xZMHxPhpuqmFgBn"
# Set up logging
2025-03-16 08:48:05 +00:00
log_file = "/var/log/Koji2Rocket.log"
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
os.makedirs(os.path.dirname(log_file), exist_ok=True)
# Database setup
def setup_database():
conn = sqlite3.connect('sent_builds.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS sent_builds (
id TEXT PRIMARY KEY
)
''')
conn.commit()
conn.close()
def has_build_been_sent(build_id):
conn = sqlite3.connect('sent_builds.db')
cursor = conn.cursor()
cursor.execute('SELECT * FROM sent_builds WHERE id = ?', (build_id,))
exists = cursor.fetchone() is not None
conn.close()
return exists
def mark_build_as_sent(build_id):
conn = sqlite3.connect('sent_builds.db')
cursor = conn.cursor()
cursor.execute('INSERT OR IGNORE INTO sent_builds (id) VALUES (?)', (build_id,))
conn.commit()
conn.close()
def send_to_rocket_chat(build_title, build_link, build_id, changelog):
2025-01-08 17:59:56 +01:00
payload = {
"alias": "Koji",
"text": f"Build Notification - ID: {build_id}\n{changelog}",
2025-01-08 17:59:56 +01:00
"attachments": [
{
"title": build_title,
"title_link": build_link,
2025-01-08 17:59:56 +01:00
"color": "#764FA5"
}
]
}
response = requests.post(ROCKET_CHAT_URL, json=payload)
if response.status_code == 200:
logging.info(f"Build notification sent successfully: {build_title} (ID: {build_id})")
else:
logging.error(f"Failed to send build notification: {response.status_code} - {response.text}")
def send_startup_message():
payload = {
"alias": "Koji",
"text": "Koji to Rocket.Chat integration started successfully.",
}
response = requests.post(ROCKET_CHAT_URL, json=payload)
if response.status_code == 200:
logging.info("Startup message sent successfully to Rocket.Chat.")
2025-01-08 17:59:56 +01:00
else:
logging.error(f"Failed to send startup message: {response.status_code} - {response.text}")
2025-01-08 17:59:56 +01:00
def fetch_koji_feed(koji_rss_url, host_header):
try:
response = requests.get(koji_rss_url, headers={'Host': host_header})
feed = feedparser.parse(response.content)
return feed.entries
except Exception as e:
logging.error(f"RSS request to koji failed: {str(e)}")
return []
2025-01-08 17:59:56 +01:00
def main():
setup_database()
send_startup_message()
original_domain = "koji.koozali.org"
try:
koji_ip = get_ip_address(original_domain)
except RuntimeError as e:
logging.error(str(e))
sys.exit(1)
# Create IP-based URL and preserve original domain for headers
koji_rss_url = f"http://{koji_ip}/koji/recentbuilds?feed=rss"
logging.info(f"Using Koji RSS URL: {koji_rss_url}")
2025-01-08 17:59:56 +01:00
while True:
entries = fetch_koji_feed(koji_rss_url, original_domain)
2025-01-08 17:59:56 +01:00
for entry in entries:
build_title = entry.title.strip()
original_link = entry.link
build_link = original_link.replace(original_domain, koji_ip)
build_id = build_title.split(':')[1].split(',')[0].strip()
changelog = extract_changelog_top(build_link, original_domain)
if not has_build_been_sent(build_id):
send_to_rocket_chat(build_title, build_link, build_id, changelog)
mark_build_as_sent(build_id)
2025-01-08 17:59:56 +01:00
time.sleep(60)
if __name__ == "__main__":
2025-03-16 08:48:05 +00:00
main()