├── .gitignore ├── requirements.txt ├── README.md └── check.py /.gitignore: -------------------------------------------------------------------------------- 1 | SECRETS.py 2 | news_data.json 3 | __pycache__ -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | discord_webhook==0.15.0 2 | requests==2.27.1 3 | xmltodict==0.12.0 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # distrowatch-checker 2 | 3 | A small python script that checks distrowatch.com for news and sends discord 4 | webhook notifications for new ones. 5 | 6 | # IMPORTANT 7 | 8 | This is no longer maintained, use 9 | [rss-discord](https://github.com/Gobidev/rss-discord) instead. 10 | 11 | ## How to Run 12 | 13 | 1. Install the requirements 14 | 2. Create a SECRETS.py file containing a variable called `WEBHOOK_URL` that is 15 | set to the discord webhook you want to use for notifications. 16 | 3. Run the script periodically, I recommend cron for automation. 17 | -------------------------------------------------------------------------------- /check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import xmltodict 4 | import requests 5 | import json 6 | import time 7 | import os.path 8 | from discord_webhook import DiscordWebhook, DiscordEmbed 9 | import SECRETS 10 | 11 | 12 | class NewsEvent: 13 | 14 | def __init__(self, title: str, time: str, description: str, link: str) -> None: 15 | self.title = title 16 | self.time = time 17 | self.description = description 18 | self.link = link 19 | 20 | def __repr__(self) -> str: 21 | return f"{self.time}\n--\n{self.title}\n--\n{self.description}\n--\n{self.link}" 22 | 23 | def __eq__(self, other: object) -> bool: 24 | if not isinstance(other, NewsEvent): 25 | return False 26 | return other.title == self.title 27 | 28 | 29 | def fetch_current_distro_news() -> dict: 30 | return xmltodict.parse(requests.get(r"https://distrowatch.com/news/dw.xml").text) 31 | 32 | 33 | def filter_news_entries(news_dict: dict) -> list: 34 | return news_dict["rdf:RDF"]["item"] 35 | 36 | 37 | def convert_dicts_to_objects(news: list) -> list: 38 | object_list = [] 39 | for entry in news: 40 | object_list.append(NewsEvent(entry["title"], entry["dc:date"], entry["description"], entry["link"])) 41 | return object_list 42 | 43 | 44 | def get_events() -> list: 45 | return list(reversed(convert_dicts_to_objects(filter_news_entries(fetch_current_distro_news())))) 46 | 47 | 48 | def send_webhook(news_event: NewsEvent): 49 | webhook = DiscordWebhook(url=SECRETS.WEBHOOK_URL) 50 | embed = DiscordEmbed(title=news_event.title, description=news_event.description, color="7f0304", url=news_event.link) 51 | embed.set_footer(text=news_event.time) 52 | webhook.add_embed(embed) 53 | webhook.execute() 54 | time.sleep(1) 55 | 56 | 57 | def save_events_to_file(news_events: list): 58 | with open("news_data.json", "w") as news_data_file: 59 | json.dump([e.__dict__ for e in news_events], news_data_file, indent=2) 60 | 61 | 62 | def load_events_from_file() -> list: 63 | if not os.path.isfile("news_data.json"): 64 | return [] 65 | with open("news_data.json", "r") as news_data_file: 66 | return [NewsEvent(**e) for e in json.load(news_data_file)] 67 | 68 | 69 | if __name__ == "__main__": 70 | current_events = get_events() 71 | saved_events = load_events_from_file() 72 | 73 | print("Sending notifications for news..") 74 | for new_event in current_events: 75 | if new_event not in saved_events: 76 | print(f"New event:\n{new_event}") 77 | send_webhook(new_event) 78 | print("..done") 79 | 80 | save_events_to_file(current_events) 81 | --------------------------------------------------------------------------------