Twitch Status

import requests
import tkinter as tk
from tkinter import ttk
import webbrowser
import os
import sys
 
# Try to import plyer notifications
try:
    from plyer import notification
    HAS_NOTIFICATIONS = True
except ImportError:
    HAS_NOTIFICATIONS = False
 
# Get app directory (works for .py and PyInstaller .exe)
def get_app_dir():
    if getattr(sys, 'frozen', False):
        # Running as compiled .exe
        return os.path.dirname(sys.executable)
    else:
        # Running as normal script
        return os.path.dirname(os.path.abspath(__file__))
 
APP_DIR = get_app_dir()
CHANNEL_FILE = os.path.join(APP_DIR, "channels.txt")
 
# Remember live status
live_channels = set()
 
# Ensure the file exists
def ensure_channel_file_exists():
    if not os.path.exists(CHANNEL_FILE):
        with open(CHANNEL_FILE, "w", encoding="utf-8") as f:
            pass
 
# Load channels from file
def load_channels():
    if not os.path.exists(CHANNEL_FILE):
        return []
    with open(CHANNEL_FILE, "r", encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]
 
# Save all channels
def save_channels_to_file(channel_list):
    with open(CHANNEL_FILE, "w", encoding="utf-8") as f:
        for channel in channel_list:
            f.write(channel + "\n")
 
# Add new channel
def add_channel_to_file(channel_name):
    existing = load_channels()
    if channel_name not in existing:
        with open(CHANNEL_FILE, "a", encoding="utf-8") as f:
            f.write(channel_name + "\n")
 
# Check if channel is live
def check_if_live(channel_name):
    url = f'https://www.twitch.tv/{channel_name}'
    try:
        response = requests.get(url)
        response.raise_for_status()
        return 'isLiveBroadcast' in response.text
    except requests.RequestException:
        return None
 
# Status for all channels
def get_channel_statuses(channels):
    results = {}
    for channel in channels:
        status = check_if_live(channel)
        if status is None:
            results[channel] = '❌ Error'
        elif status:
            results[channel] = '🟒 Live'
        else:
            results[channel] = 'βšͺ Offline'
    return results
 
# Open Twitch in browser
def open_channel(channel_name):
    webbrowser.open(f"https://www.twitch.tv/{channel_name}")
 
# Send notification
def notify_live(channel_name):
    if HAS_NOTIFICATIONS:
        notification.notify(
            title="Twitch Channel is Live!",
            message=f"{channel_name} is now live on Twitch.",
            timeout=5
        )
 
# Build GUI
def build_gui():
    root = tk.Tk()
    root.title("Twitch Live Status")
 
    # Input field
    entry_frame = ttk.Frame(root)
    entry_frame.pack(pady=10)
 
    ttk.Label(entry_frame, text="New Channel:").pack(side="left", padx=5)
    channel_entry = ttk.Entry(entry_frame, width=30)
    channel_entry.pack(side="left", padx=5)
 
    def add_channel():
        new_channel = channel_entry.get().strip()
        if new_channel and new_channel not in channels:
            channels.append(new_channel)
            add_channel_to_file(new_channel)
            update_table()
            channel_entry.delete(0, tk.END)
 
    ttk.Button(entry_frame, text="Add", command=add_channel).pack(side="left", padx=5)
 
    # Table with scrollbar
    table_frame = ttk.Frame(root)
    table_frame.pack(padx=20, pady=10, fill="both", expand=True)
 
    tree = ttk.Treeview(table_frame, columns=("Channel", "Status", "Open", "Remove"), show="headings")
    for col, text in zip(("Channel", "Status", "Open", "Remove"), ("Channel", "Status", "Open", "Remove")):
        tree.heading(col, text=text)
        tree.column(col, width=120, anchor="center")
    tree.column("Channel", anchor="w", width=150)
    tree.pack(side="left", fill="both", expand=True)
 
    scrollbar = ttk.Scrollbar(table_frame, orient="vertical", command=tree.yview)
    scrollbar.pack(side="right", fill="y")
    tree.configure(yscrollcommand=scrollbar.set)
 
    def update_table():
        global live_channels
        for row in tree.get_children():
            tree.delete(row)
        statuses = get_channel_statuses(channels)
        for channel, status in statuses.items():
            tree.insert("", "end", iid=channel, values=(channel, status, "Open", "Remove"))
 
            # Notify on new live status
            if status == '🟒 Live' and channel not in live_channels:
                notify_live(channel)
                live_channels.add(channel)
            elif status != '🟒 Live' and channel in live_channels:
                live_channels.remove(channel)
 
    def schedule_refresh():
        update_table()
        root.after(60000, schedule_refresh)
 
    def on_tree_click(event):
        item = tree.identify_row(event.y)
        column = tree.identify_column(event.x)
        if item:
            if column == "#3":  # Open
                open_channel(item)
            elif column == "#4":  # Remove
                channels.remove(item)
                save_channels_to_file(channels)
                update_table()
 
    tree.bind("<Button-1>", on_tree_click)
 
    update_table()
    schedule_refresh()
    root.mainloop()
 
# Start app
ensure_channel_file_exists()
channels = load_channels()
build_gui()

Worldclock

import tkinter as tk
from datetime import datetime
from zoneinfo import ZoneInfo
 
def update_clocks():
    berlin_time = datetime.now(ZoneInfo("Europe/Berlin")).strftime("%H:%M:%S")
    melbourne_time = datetime.now(ZoneInfo("Australia/Melbourne")).strftime("%H:%M:%S")
    victoria_time = datetime.now(ZoneInfo("America/Vancouver")).strftime("%H:%M:%S")
    charleston_time = datetime.now(ZoneInfo("America/New_York")).strftime("%H:%M:%S")
 
    berlin_label.config(text=f"Berlin πŸ‡©πŸ‡ͺ: {berlin_time}")
    melbourne_label.config(text=f"Melbourne πŸ‡¦πŸ‡Ί: {melbourne_time}")
    victoria_label.config(text=f"Victoria πŸ‡¨πŸ‡¦: {victoria_time}")
    charleston_label.config(text=f"Charleston πŸ‡ΊπŸ‡Έ: {charleston_time}")
 
    root.after(1000, update_clocks)
 
root = tk.Tk()
root.title("🌍 Weltzeit-Uhren")
 
berlin_label = tk.Label(root, font=("Helvetica", 20), fg="black")
melbourne_label = tk.Label(root, font=("Helvetica", 20), fg="blue")
victoria_label = tk.Label(root, font=("Helvetica", 20), fg="green")
charleston_label = tk.Label(root, font=("Helvetica", 20), fg="purple")
 
berlin_label.pack(pady=10)
melbourne_label.pack(pady=10)
victoria_label.pack(pady=10)
charleston_label.pack(pady=10)
 
update_clocks()
root.mainloop()