===== 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("", 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()