All checks were successful
Build and Deploy Docker Container / build-and-deploy (push) Successful in 44s
198 lines
6.1 KiB
Python
198 lines
6.1 KiB
Python
import os
|
|
import pytz
|
|
from datetime import datetime
|
|
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_FOOTER = "THC - Toke Hash Coordinated"
|
|
|
|
MSG_REMINDER = "This is your 5 minute reminder to 420!"
|
|
MSG_HALFTIME_REMINDER = "Half-time in 5 minutes!"
|
|
MSG_HALFTIME = "Half-time!"
|
|
MSG_NOTIFICATION = "Blaze it!"
|
|
|
|
COL_BLUE = 0x3498db
|
|
COL_ORANGE = 0xe67e22
|
|
COL_GREEN = 0x2ecc71
|
|
COL_UNKNOWN = 0x95a5a6
|
|
|
|
messages = {
|
|
"reminder_halftime": {"text": MSG_HALFTIME_REMINDER, "color": COL_ORANGE},
|
|
"halftime": {"text": MSG_HALFTIME, "color": COL_GREEN},
|
|
"reminder": {"text": MSG_REMINDER, "color": COL_ORANGE},
|
|
"420": {"text": MSG_NOTIFICATION, "color": COL_GREEN},
|
|
"unknown": {"text": "Unknown notification type", "color": COL_UNKNOWN}
|
|
}
|
|
|
|
|
|
def load_timezones() -> list[dict]:
|
|
"""Load timezones from csv file."""
|
|
# Read the CSV file and return a list of timezones
|
|
with open("tzdb/TimeZoneDB.csv/time_zone.csv", "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
# Fields: zone_name,country_code,abbreviation,time_start,gmt_offset,dst
|
|
timezones = []
|
|
for line in lines:
|
|
fields = line.strip().split(",")
|
|
if len(fields) >= 5:
|
|
timezones.append({
|
|
"zone_name": fields[0],
|
|
"country_code": fields[1],
|
|
"abbreviation": fields[2],
|
|
"time_start": fields[3],
|
|
"gmt_offset": int(fields[4]),
|
|
"dst": fields[5] == '1'
|
|
})
|
|
return timezones
|
|
|
|
|
|
def load_countries() -> list[dict]:
|
|
"""Load countries from csv file."""
|
|
# Read the CSV file and return a list of countries
|
|
with open("tzdb/TimeZoneDB.csv/country.csv", "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
# Fields: country_code,country_name
|
|
countries = []
|
|
for line in lines:
|
|
fields = line.strip().split(",")
|
|
if len(fields) >= 2:
|
|
countries.append({
|
|
"country_code": fields[0],
|
|
"country_name": fields[1]
|
|
})
|
|
return countries
|
|
|
|
|
|
timezones = load_timezones()
|
|
countries = load_countries()
|
|
|
|
|
|
def get_message(type: str) -> dict[str, int]:
|
|
"""
|
|
Get the notification message based on the type.
|
|
"""
|
|
msg = messages["unknown"]
|
|
if type in messages:
|
|
msg = messages[type]
|
|
if type in ["halftime", "420"]:
|
|
msg["image"] = {
|
|
"url": "https://www.freepnglogos.com/uploads/weed-leaf-png/cannabis-weed-leaf-png-clipart-images-24.png"}
|
|
if type == "420":
|
|
tz_list = where_is_it_420(timezones, countries)
|
|
if tz_list:
|
|
tz_str = "\n".join(tz_list)
|
|
msg["text"] += f"\nIt's 4:20 in:\n{tz_str}"
|
|
else:
|
|
msg["text"] += " It's not 4:20 anywhere right now."
|
|
return msg
|
|
|
|
|
|
def create_embed(message: str) -> dict:
|
|
"""
|
|
Create a Discord embed message.
|
|
"""
|
|
msg = get_message(message)
|
|
embed = {
|
|
"title": message.replace("_", " ").capitalize(),
|
|
"description": msg["text"],
|
|
"image": msg.get("image"),
|
|
"color": msg["color"],
|
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
"footer": {"text": MSG_FOOTER}
|
|
}
|
|
return embed
|
|
|
|
|
|
def send_notification(message: str) -> None:
|
|
"""
|
|
Send a notification to the Discord webhook.
|
|
"""
|
|
if not WEBHOOK_URL:
|
|
logging.error("WEBHOOK_URL not set")
|
|
return
|
|
embed = create_embed(message)
|
|
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 get_tz_info(tz_name: str, timezones: list[dict]) -> dict | None:
|
|
"""Get timezone info by name."""
|
|
return next((tz for tz in timezones if tz["zone_name"] == tz_name), None)
|
|
|
|
|
|
def get_country_info(country_code: str, countries: list[dict]) -> dict | None:
|
|
"""Get country info by country code."""
|
|
return next((c for c in countries if c["country_code"] == country_code), None)
|
|
|
|
|
|
def where_is_it_420(timezones: list[dict], countries: list[dict]) -> list[str]:
|
|
"""Get timezones where the current hour is 4 or 16, indicating it's 4:20 there.
|
|
|
|
Returns:
|
|
list[str]: A list of timezones where it's currently 4:20 PM or AM.
|
|
"""
|
|
tz_list = []
|
|
for tz in pytz.all_timezones:
|
|
now = datetime.now(pytz.timezone(tz))
|
|
if now.hour == 4 or now.hour == 16:
|
|
# Find the timezone in the loaded timezones
|
|
tz_info = get_tz_info(tz, timezones)
|
|
if tz_info:
|
|
country = get_country_info(tz_info["country_code"], countries)
|
|
if country and country["country_name"] not in tz_list:
|
|
country_name = country["country_name"].strip().strip('"')
|
|
tz_list.append(country_name)
|
|
return tz_list
|
|
|
|
|
|
def main() -> None:
|
|
"""
|
|
Main function to run the scheduler.
|
|
"""
|
|
# Schedule notifications
|
|
schedule.every().hour.at(":15").do(send_notification, "reminder")
|
|
schedule.every().hour.at(":20").do(send_notification, "420")
|
|
schedule.every().hour.at(":45").do(send_notification, "reminder_halftime")
|
|
schedule.every().hour.at(":50").do(send_notification, "halftime")
|
|
logging.info("Scheduler started.")
|
|
|
|
# Test the notification on startup
|
|
send_notification("420")
|
|
|
|
try:
|
|
while True:
|
|
schedule.run_pending()
|
|
time.sleep(1) # Check every second
|
|
except KeyboardInterrupt:
|
|
logging.info("Scheduler stopped by user")
|
|
except Exception as e:
|
|
logging.error(f"Unexpected error: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|