-
Notifications
You must be signed in to change notification settings - Fork 22
/
spongebob-cli
234 lines (178 loc) · 8.41 KB
/
spongebob-cli
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/usr/bin/env python3
# This code is licensed under GNU General Public License v3.0. I encouruage you to do the same to the software you write!
# TODO: queee {1-10} this will play first to tenth episode | queee {1 2 3} This will play first, second and third episode
try:
from bs4 import BeautifulSoup
import requests, subprocess, sys, random, time, os
from termcolor import colored
from prettytable import PrettyTable
from urllib.error import HTTPError
from halo import Halo
# local file, func.py
from func import httperror_assess
except ImportError or ModuleNotFoundError:
# Using python color codes instead of termcolor if it isn't found
raise SystemExit("\033[1;31;40mOne or more library is missing! Check the list of libraries!")
def ListEpisodes(limit_real):
counter = 0
table = PrettyTable()
episode_number = []
episode_title = []
for data in soup.find_all("a", class_ = "btn btn-sm btn-default", limit = limit_real):
counter += 1
episode_title.append(data.get("title"))
episode_number.append(colored(counter, "cyan" ))
table.add_column("Title", episode_title)
table.add_column("Episode", episode_number)
table.align["Title"] = "l"
print(table)
# This function get the direct mp4 link
@Halo(text="Getting video source", spinner="shark", color="green")
def VideoSource(source):
raw = requests.get(source).text
soup = BeautifulSoup(raw, "html.parser")
# This took me way to long to figure out, DONT TOUCH
link = soup.find("input", {"name":"main_video_url"})["value"]
return link
# It used to just void the output of MPV but since that was introduces half of the episdoes failed to play. Thats why its no longer voiding the MPV output
# This function for some reason randomly fails and need to be fixed ASAP
def Play(DirectLink):
try:
subprocess.run(["mpv", DirectLink])
except subprocess.CalledProcessError:
print(colored("\nAn error occured while tying to play the video! Make sure you have mpv or youtube-dl installed.", "red"))
def Download(source, args3=False):
try:
if args3 is False:
with Halo(text="Downloading episode.", spinner="shark", color="green"):
subprocess.run(["youtube-dl", source],
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
else:
subprocess.run(["youtube-dl", source])
print(colored("\nDownload complete!", "green"))
except ImportError or subprocess.CalledProcessError:
print(colored("Downloading the video failed. Be sure to have youtube-dl installed.", "red"))
episodes = []
counter = 0
# It fetches the episodes from this link, So that episode is not avaliable.
# Historically this used to be help wanted episode, but since it was the first episode it was changed to the last
try:
link = "https://www.megacartoons.net/truth-or-square/"
raw = requests.get(link).text
soup = BeautifulSoup(raw, "html.parser")
except HTTPError as e:
httperror_assess(e.code)
# This is to fetch all the episodes links
for data in soup.find_all("a", class_ = "btn btn-sm btn-default"):
counter += 1
episodes.append(data.get("href"))
try:
args = sys.argv[1]
except IndexError:
args = ''
try:
args2 = sys.argv[2]
except:
pass
try:
# Download Function
if args.replace(' ', '') in ["--download", "-d"]:
try:
try:
args3 = sys.argv[3]
except:
args3 = False
else:
args3 = True
print(f"Downloading episode {colored(args2, 'cyan')}")
Download(VideoSource(episodes[int(args2) - 1]), args3)
except IndexError or ValueError:
print(colored("No arguments passed with download function or the index is out of range, aborting...!", "red"))
# Dowload all
elif args.replace(' ', '') in ["--download-all", "-da"]:
dled = 0
try:
try:
args3 = sys.argv[2]
except:
args3 = False
else:
args3 = True
print(colored(f"Downloading all fetched episodes : {len(episodes)}", "green"))
for x in range(len(episodes)):
print(f"Downloading episode {colored(x+1, 'cyan')}")
Download(VideoSource(episodes[x+1]), args3)
print(f"Episode {x+1} downloaded!", end="") ; time.sleep(2) ; print("\r", end="")
dled += 1
continue
print(colored(f"All {len(episodes)} are downloaded!", "green"))
except HTTPError as e:
httperror_assess(e.code)
finally:
print(colored(f"{dled} episodes were downloaded."))
elif args.replace(' ', '') in ["--binge", "-b"]:
try:
print("Playing every episode from beggining")
for x in range(len(episodes)):
print(f"Playing episode {x + 1}", end = "")
Play(VideoSource(episodes[x + 1]))
time.sleep(2) ; print("\r", end="")
continue
except HTTPError as e:
httperror_assess(e.code)
# List function
elif args.replace(' ', '') in ["--list", "-l"]:
try:
ListEpisodes(int(args2))
except:
# 3xx is replaced with len(episodes) to avoid error, if ever the fetched episodes if
# less than 3xx (it is 399 or 339 I think, if I remember correctly)
ListEpisodes(len(episodes))
# Play function
elif args.replace(' ', '') in ["--play", "-p"]:
try:
Play(VideoSource(episodes[int(args2) - 1]))
except ValueError or IndexError:
print(colored("No arguments were passed with the play function or the index is out of range, aborting...", "red"))
elif args.replace(' ', '') in ['--update', "-u"]:
print(colored("This is higly experimental and only works if you have installed spongebob-cli with git clone command!", "red"))
sys.subprocess(["git", "fetch"])
elif args.replace(' ', '') in ["--random", "-r"]:
real = VideoSource(episodes[random.randint(1, len(episodes))])
print(colored("You are now watching: ", "green"), real)
Play(real)
elif args.replace(' ', '') in ["--help", "-h"]:
print("""
--download | -d, usage --download {a number of a episode}, This will download that video under a directory the command was run
--download-all | -da, usage --download-all, This will download every video spongebob video it scrapes
--binge | -b , usage spongebob-cli --binge, This is used to start the first episode to the last
--list | -l, usage --list, this will list all the episodes and then exit the programm
--list | -l, usage --list {number} this will show the number of episodes with the limit you provided.
--play | -p, usage --play {a number of a episode}, This will play the episode without listing the episodes
--random | -r, usage spongebob-cli --random, This will play a random episode
--help | -h, usage --help this will print what each argument does
""")
# This is if no arguments were passed.
else:
while True:
os.system("clear")
ListEpisodes(len(episodes))
print(colored("No arguments were passed. Default settings applied.\n", "green"))
try:
video_input = input("What episode do you want to watch? (type a number by the right side): ").replace(' ', '')
video_input = int(video_input)
except ValueError or AttributeError:
if video_input in ["exit", "quit", "close", 'q']:
raise SystemExit("Quitting the program!")
print(colored("You need to type a number!", "red"))
continue
except IndexError:
print("The video you chose is out of range or doesnt exist")
continue
else:
real = VideoSource(episodes[video_input - 1])
print(colored(f"Now playing: {real}\n", "green"))
Play(real)
except KeyboardInterrupt:
raise SystemExit(colored("\nUser interruped with the operation, aborting.", "red"))