initial commit

This commit is contained in:
georg.sinn-schirwitz
2025-09-06 14:01:06 +02:00
commit fbe4e2f487
5 changed files with 292 additions and 0 deletions

23
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,23 @@
<!-- Use this file to provide workspace-specific custom instructions to Copilot. For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file -->
- [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.

117
.gitignore vendored Normal file
View File

@@ -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

37
README.md Normal file
View File

@@ -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

112
main.py Normal file
View File

@@ -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()

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
requests
python-dotenv
schedule