-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwakeCast.py
156 lines (127 loc) · 6.71 KB
/
wakeCast.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import sys
import time
import re
import pychromecast
import typer
from pychromecast.controllers import youtube
# Define colors for formatting
class bcolors:
HEADER = '\033[95m' # Pink
OKBLUE = '\033[94m' # Blue
OKCYAN = '\033[96m' # Cyan
OKGREEN = '\033[92m' # Green
WARNING = '\033[93m' # Yellow
FAIL = '\033[91m' # Red
ENDC = '\033[0m' # Reset color
BOLD = '\033[1m' # Bold
UNDERLINE = '\033[4m' # Underline
# Default YouTube video ID
DEFAULT_YOUTUBE_VIDEO_ID = "PWn-Wh9O3N8"
# Banner
BANNER = f"""
{bcolors.BOLD} Made by @tzero86
██ ██ █████ ██ ██ ███████ ██████ █████ ███████ ████████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ █ ██ ███████ █████ █████ ██ ███████ ███████ ██
██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███ ███ ██ ██ ██ ██ ███████ ██████ ██ ██ ███████ ██
A Chromecast Video-alarm using YouTube app, apparently expecting
a native alarm app is too much for a Chromecast device these days...
"""
app = typer.Typer()
def choose_device() -> pychromecast.Chromecast:
print(f"{bcolors.OKBLUE}[INF] WakeCast is looking for Online Chromecast devices on the network...{bcolors.ENDC}")
chromecasts, _ = pychromecast.get_chromecasts()
if not chromecasts:
print(f"{bcolors.FAIL}[ERR] Sorry I was unable to find any Chromecast devices on the network. Make sure you "
f"are connected to the same network as the Chromecast device.{bcolors.ENDC}")
sys.exit(1)
print(
f"{bcolors.OKGREEN}[INF] A total of {len(chromecasts)} Chromecast devices were found active on the network.{bcolors.ENDC}")
# Display available devices for selection
for i, cc in enumerate(chromecasts):
print(f"[{i}] {cc.name}")
print(
f"{bcolors.OKBLUE}[INP] Please specify the Chromecast device you want to compensate the lack of functionality "
f"for (Enter its Index, e.g. 1):{bcolors.ENDC}")
while True:
try:
index = int(input())
if index < 0 or index >= len(chromecasts):
raise ValueError
break
except ValueError:
print(f"{bcolors.FAIL}[ERR] ERROR: Invalid device index number. Please Try again:{bcolors.ENDC}")
return chromecasts[index]
def play_youtube_video(chromecast_device: pychromecast.Chromecast, video_id: str, wait_time: int):
try:
print(
f"{bcolors.OKBLUE}[INF] WakeCast is connecting to Chromecast device now. '{chromecast_device.name}'...{bcolors.ENDC}")
chromecast_device.wait()
print(f"{bcolors.OKGREEN}[INF] WakeCast is Connected to '{chromecast_device.name}.'.{bcolors.ENDC}")
for remaining in range(wait_time, 0, -1):
sys.stdout.write(f"\r{bcolors.OKBLUE}[INF] Let's wait a bit for that timer to go off: {remaining} seconds "
f"remaining...{bcolors.ENDC}")
sys.stdout.flush()
time.sleep(1)
print(f"\r{bcolors.OKGREEN}[INF] The wait is over. Starting video...{bcolors.ENDC}")
print(f"{bcolors.OKBLUE}[INF] Ok we are playing the YouTube video with ID '{video_id}'.{bcolors.ENDC}")
yt = pychromecast.controllers.youtube.YouTubeController()
chromecast_device.register_handler(yt)
yt.play_video(video_id)
except Exception as e:
print(
f"{bcolors.FAIL}[ERR] Well... Something went south. Let's try that again from the top, shall we?: {e}{bcolors.ENDC}")
sys.exit(1)
def is_valid_youtube_url(url: str) -> bool:
# Regular expression to validate YouTube URL
pattern = r'^(https?://)?(www\.)?(youtube\.com|youtu\.?be)/.+$'
return bool(re.match(pattern, url))
def extract_video_id(url: str) -> str:
# Regular expression to extract video ID from YouTube URL
video_id_match = re.search(
r'(?:v=|youtu\.be/|/embed/|/v/|/e/|/watch\?v=|/watch\?v%3D|/watch\?.+&v=)([^#\&\?]{11})', url)
if video_id_match:
return video_id_match.group(1)
else:
raise ValueError(
f"{bcolors.FAIL}[ERR] As per our top engineering ferrets team, {url} is not a valid YouTube video URL we can use.\n The "
f"high council recommends trying a different one.{bcolors.ENDC}")
@app.command()
def main(wait_time: int = typer.Option(..., help="The time to wait before triggering the alarm (in seconds)"),
video: str = typer.Option(None, "--video", "-v", help="The YouTube video URL to play"),
device: str = typer.Option(None, "--device", "-d", help="The Chromecast device name")):
print(BANNER) # Print the banner when the script starts
chromecast_device = None
if device:
try:
chromecast_device = next(cc for cc in pychromecast.get_chromecasts()[0] if cc.name == device)
if not chromecast_device:
raise ValueError(
f"{bcolors.FAIL}[ERR] The Device '{device}' was not found, Did you type the name correctly?.{bcolors.ENDC}")
except Exception as e:
print(
f"{bcolors.WARNING}[WARN] Warning: Something failed when trying to use the device {device}. We need to try manual selection instead...{e}{bcolors.ENDC}")
if not chromecast_device:
chromecast_device = choose_device()
video_id = DEFAULT_YOUTUBE_VIDEO_ID
if video:
while True:
if is_valid_youtube_url(video):
try:
video_id = extract_video_id(video)
print(f"{bcolors.OKGREEN}[INF] Extracted video ID: {video_id}{bcolors.ENDC}")
break
except ValueError as e:
print(f"{bcolors.FAIL}{e}{bcolors.ENDC}")
else:
print(f"{bcolors.FAIL}[ERR] The provided URL '{video}' is not a valid YouTube URL.{bcolors.ENDC}")
video = input(
f"{bcolors.OKBLUE}[INP] Please enter a valid YouTube video URL or type 'default' to use the default video:{bcolors.ENDC} ")
if video.lower() == 'default':
video_id = DEFAULT_YOUTUBE_VIDEO_ID
break
play_youtube_video(chromecast_device, video_id, wait_time)
print(f"{bcolors.OKGREEN}[INF] All Done, shutting down WakeCast.{bcolors.ENDC}")
if __name__ == "__main__":
app()