initial commit
This commit is contained in:
23
.github/copilot-instructions.md
vendored
Normal file
23
.github/copilot-instructions.md
vendored
Normal 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
117
.gitignore
vendored
Normal 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
37
README.md
Normal 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
112
main.py
Normal 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
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
requests
|
||||||
|
python-dotenv
|
||||||
|
schedule
|
||||||
Reference in New Issue
Block a user