From fbe4e2f487695c65bde9b4bb43a5bfb3c0c4ebf5 Mon Sep 17 00:00:00 2001 From: "georg.sinn-schirwitz" Date: Sat, 6 Sep 2025 14:01:06 +0200 Subject: [PATCH] initial commit --- .github/copilot-instructions.md | 23 +++++++ .gitignore | 117 ++++++++++++++++++++++++++++++++ README.md | 37 ++++++++++ main.py | 112 ++++++++++++++++++++++++++++++ requirements.txt | 3 + 5 files changed, 292 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .gitignore create mode 100644 README.md create mode 100644 main.py create mode 100644 requirements.txt diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..15c52b5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,23 @@ + + +- [x] Verify that the copilot-instructions.md file in the .github directory is created. + +- [x] Clarify Project Requirements + +- [x] Scaffold the Project + +- [x] Customize the Project + +- [x] Install Required Extensions + +- [x] Compile the Project + +- [x] Create and Run Task + +- [x] Launch the Project + +- [x] Ensure Documentation is Complete + +- Work through each checklist item systematically. +- Keep communication concise and focused. +- Follow development best practices. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f11988 --- /dev/null +++ b/.gitignore @@ -0,0 +1,117 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..84a863c --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# Discord Webhook 420 Notification App + +This Python application sends notifications to a Discord channel via webhook every hour at HH:15 (5 minute reminder) and at HH:20. + +## Setup + +1. Install dependencies: + + ```bash + pip install -r requirements.txt + ``` + +2. Set up your Discord webhook: + + - Go to your Discord server settings > Integrations > Webhooks + - Create a new webhook and copy the URL + +3. Update the `.env` file with your webhook URL: + + ```text + DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your_webhook_id/your_webhook_token + ``` + +## Running the App + +Run the application: + +```bash +python main.py +``` + +The app will run continuously and send notifications at the scheduled times. + +## Requirements + +- Python 3.6+ +- Discord webhook URL diff --git a/main.py b/main.py new file mode 100644 index 0000000..98fa319 --- /dev/null +++ b/main.py @@ -0,0 +1,112 @@ +import os +import time +import logging +import requests +import schedule +from dotenv import load_dotenv + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' +) + +# Load environment variables +load_dotenv() + +WEBHOOK_URL = os.getenv('DISCORD_WEBHOOK_URL') + +MSG_TEST = "Discord 420 timer activated. This is a test notification." +MSG_REMINDER = "5 minute reminder!" +MSG_NOTIFICATION = "420!" +COL_BLUE = 0x3498db +COL_ORANGE = 0xe67e22 +COL_GREEN = 0x2ecc71 +COL_UNKNOWN = 0x95a5a6 + +messages = { + "test": {"text": MSG_TEST, "color": COL_BLUE}, + "reminder": {"text": MSG_REMINDER, "color": COL_ORANGE}, + "notification": {"text": MSG_NOTIFICATION, "color": COL_GREEN}, + "unknown": {"text": "Unknown notification type", "color": COL_UNKNOWN} +} + + +def get_message(type: str) -> dict[str, int]: + """ + Get the notification message based on the type. + """ + if type in messages: + return messages[type] + else: + return messages["unknown"] + + +def send_notification(message: dict[str, int]) -> None: + """ + Send a notification to the Discord webhook as an embed. + + Args: + message (dict[str, int]): The message to send. + """ + if not WEBHOOK_URL: + logging.error("WEBHOOK_URL not set") + return + + embed = { + "title": "Notification", + "description": message["text"], + "color": message["color"], + "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), + "footer": { + "text": "Discord Webhook App" + } + } + + data = {"embeds": [embed]} + try: + response = requests.post(WEBHOOK_URL, json=data, timeout=10) + if response.status_code == 204: + logging.info(f"Notification sent: {message}") + else: + logging.error( + f"Failed to send notification: {response.status_code} - " + f"{response.text}" + ) + except requests.RequestException as e: + logging.error(f"Error sending notification: {e}") + + +def test_notification() -> None: + """ + Send a test notification to verify the webhook. + """ + send_notification(get_message("test")) + + +def main() -> None: + """ + Main function to run the scheduler. + """ + # Schedule notifications + schedule.every().hour.at(":15").do(send_notification, get_message("reminder")) + schedule.every().hour.at(":20").do(send_notification, get_message("notification")) + + logging.info( + "Scheduler started. Notifications will be sent every hour at :15 and :20") + + # Test the notification on startup + test_notification() + + try: + while True: + schedule.run_pending() + time.sleep(60) # Check every minute + except KeyboardInterrupt: + logging.info("Scheduler stopped by user") + except Exception as e: + logging.error(f"Unexpected error: {e}") + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..20f6d74 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +requests +python-dotenv +schedule