mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-07 12:05:35 +00:00
Improve readability and Conform PEP8 Style Guide (#63)
* style(PEP8): conform to PEP8 guide * style(spell): spelling corrected * Improve examples * refact(audio_extractor): improves code readability refactoring audio_extractor_m3u8 function * Conform to default example * Add .idea
This commit is contained in:
parent
60ffda5163
commit
75b04fc398
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ bin
|
||||
lib64
|
||||
*__pycache__
|
||||
pyvenv.cfg
|
||||
.idea
|
||||
|
||||
# Project specific
|
||||
videos/
|
||||
|
22
README.md
22
README.md
@ -50,8 +50,8 @@ You can change some behaviors by tweaking the configuration file.
|
||||
```json
|
||||
{
|
||||
"root_path": "videos",
|
||||
"movies_folder_name": "Film",
|
||||
"series_folder_name": "Serie",
|
||||
"movies_folder_name": "Movies",
|
||||
"series_folder_name": "Series",
|
||||
"download_subtitles": true,
|
||||
"download_default_language": true,
|
||||
"selected_language": "English",
|
||||
@ -59,15 +59,15 @@ You can change some behaviors by tweaking the configuration file.
|
||||
}
|
||||
```
|
||||
#### Options
|
||||
| Key | Default Value | Description | Value Example |
|
||||
|---------------------------|---------------|------------------------------------------------------------------------------------|--------------------------|
|
||||
| root_path | videos | Path where the script will add movies and tv series. Do not put trailing slash. | media/streamingcommunity |
|
||||
| movies_folder_name | Film | The folder name where all the movies will be placed. Do not put trailing slash. | downloaded-movies |
|
||||
| series_folder_name | Serie | The folder name where all the TV Series will be placed. Do not put trailing slash. | mytvseries |
|
||||
| download_subtitles | true | Whether or not you want all the found subtitles to be downloaded. | false |
|
||||
| download_default_language | true | Whether or not you want to download only the default Italian audio language. | true |
|
||||
| selected_language | English | If "download_default_language" is False the script will download this language | English |
|
||||
| max_worker | 20 | How many workers will cooperate to download .ts file (High value may lag your pc) | 20 |
|
||||
| Key | Default Value | Description | Value Example |
|
||||
|---------------------------|---------------|-----------------------------------------------------------------------------------------|--------------------------|
|
||||
| root_path | videos | Path where the script will add movies and tv series folders. Do not put trailing slash. | media/streamingcommunity |
|
||||
| movies_folder_name | Movies | The folder name where all the movies will be placed. Do not put trailing slash. | downloaded-movies |
|
||||
| series_folder_name | Series | The folder name where all the TV Series will be placed. Do not put trailing slash. | mytvseries |
|
||||
| download_subtitles | true | Whether or not you want all the found subtitles to be downloaded. | false |
|
||||
| download_default_language | true | Whether or not you want to download only the default Italian audio language. | false |
|
||||
| selected_language | English | If `"download_default_language"` is `False` the script will download this language | French |
|
||||
| max_worker | 20 | How many workers will cooperate to download .ts file (High value may slow down your pc) | 30 |
|
||||
|
||||
## Tutorial
|
||||
For a detailed walkthrough, refer to the [video tutorial](https://www.youtube.com/watch?v=Ok7hQCgxqLg&ab_channel=Nothing)
|
||||
|
@ -1,29 +1,35 @@
|
||||
# 3.12.23 -> 10.12.23
|
||||
|
||||
# General import
|
||||
import binascii
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import sys
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
||||
from Src.Util.config import config
|
||||
from Src.Util.console import console
|
||||
# Class import
|
||||
from Src.Util.headers import get_headers
|
||||
from Src.Util.console import console
|
||||
from Src.Util.config import config
|
||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||
|
||||
# General import
|
||||
import requests, os, re, json, sys, binascii
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
# [func]
|
||||
def get_iframe(id_title, domain):
|
||||
req = requests.get(url = f"https://streamingcommunity.{domain}/iframe/{id_title}", headers = {
|
||||
req = requests.get(url=f"https://streamingcommunity.{domain}/iframe/{id_title}", headers={
|
||||
"User-agent": get_headers()
|
||||
})
|
||||
|
||||
if req.ok:
|
||||
url_embed = BeautifulSoup(req.text, "lxml").find("iframe").get("src")
|
||||
req_embed = requests.get(url_embed, headers = {"User-agent": get_headers()}).text
|
||||
req_embed = requests.get(url_embed, headers={"User-agent": get_headers()}).text
|
||||
|
||||
try:
|
||||
return BeautifulSoup(req_embed, "lxml").find("body").find("script").text
|
||||
except:
|
||||
except Exception:
|
||||
console.log("[red]Couldn't play this video file (video not available)")
|
||||
sys.exit(0)
|
||||
|
||||
@ -33,7 +39,6 @@ def get_iframe(id_title, domain):
|
||||
|
||||
|
||||
def select_quality(json_win_param):
|
||||
|
||||
if json_win_param['token1080p']:
|
||||
return "1080p"
|
||||
elif json_win_param['token720p']:
|
||||
@ -45,14 +50,16 @@ def select_quality(json_win_param):
|
||||
|
||||
|
||||
def parse_content(embed_content):
|
||||
|
||||
# Parse parameter from req embed content
|
||||
win_video = re.search(r"window.video = {.*}", str(embed_content)).group()
|
||||
win_param = re.search(r"params: {[\s\S]*}", str(embed_content)).group()
|
||||
|
||||
# Parse parameter to make read for json
|
||||
json_win_video = "{"+win_video.split("{")[1].split("}")[0]+"}"
|
||||
json_win_param = "{"+win_param.split("{")[1].split("}")[0].replace("\n", "").replace(" ", "") + "}"
|
||||
json_win_video = "{" + win_video.split("{")[1].split("}")[0] + "}"
|
||||
json_win_param = ("{" + win_param.split("{")[1]
|
||||
.split("}")[0]
|
||||
.replace("\n", "")
|
||||
.replace(" ", "") + "}")
|
||||
json_win_param = json_win_param.replace(",}", "}").replace("'", '"')
|
||||
return json.loads(json_win_video), json.loads(json_win_param), select_quality(json.loads(json_win_param))
|
||||
|
||||
@ -75,36 +82,25 @@ def get_m3u8_key(json_win_video, json_win_param, title_name, token_render):
|
||||
|
||||
|
||||
def get_m3u8_audio(json_win_video, json_win_param, title_name, token_render):
|
||||
req = requests.get(f'https://vixcloud.co/playlist/{json_win_video["id"]}', params={'token': json_win_param['token'], 'expires': json_win_param["expires"] }, headers={
|
||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={title_name}&referer=1&expires={json_win_param["expires"]}'
|
||||
})
|
||||
req = requests.get(
|
||||
f'https://vixcloud.co/playlist/{json_win_video["id"]}',
|
||||
params={'token': json_win_param['token'],
|
||||
'expires': json_win_param["expires"]},
|
||||
headers={
|
||||
'referer':
|
||||
f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={title_name}&referer=1&expires={json_win_param["expires"]}'
|
||||
})
|
||||
|
||||
if req.ok:
|
||||
m3u8_cont = req.text.split()
|
||||
m3u8_cont_arr = []
|
||||
for row in m3u8_cont:
|
||||
if "audio" in str(row):
|
||||
lang=None
|
||||
default=False
|
||||
for field in row.split(","):
|
||||
if "NAME" in field:
|
||||
lang = field.split('"')[-2]
|
||||
if "DEFAULT" in field:
|
||||
default_str = field.split('=')[1]
|
||||
default = default_str.strip() == "YES"
|
||||
audioobj={"url": row.split(",")[-1].split('"')[-2], "lang": lang, "default": default}
|
||||
if audioobj['lang'] is None:
|
||||
continue
|
||||
m3u8_cont_arr.append(audioobj)
|
||||
return m3u8_cont_arr or None
|
||||
result = audio_extractor_m3u8(req)
|
||||
return result
|
||||
else:
|
||||
console.log(f"[red]Error: {req.status_code}")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
|
||||
# [func \ main]
|
||||
def main_dw_film(id_film, title_name, domain):
|
||||
|
||||
embed_content = get_iframe(id_film, domain)
|
||||
json_win_video, json_win_param, render_quality = parse_content(embed_content)
|
||||
|
||||
@ -123,4 +119,5 @@ def main_dw_film(id_film, title_name, domain):
|
||||
if m3u8_url_audio is not None:
|
||||
console.print("[blue]Using m3u8 audio => [red]True")
|
||||
subtitle_path = os.path.join(config['root_path'], config['series_folder_name'], mp4_name)
|
||||
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_url, key=m3u8_key, output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
||||
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_url, key=m3u8_key,
|
||||
output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
||||
|
@ -12,7 +12,7 @@ from bs4 import BeautifulSoup
|
||||
def domain_version():
|
||||
domain_req = requests.get("https://api.telegra.ph/getPage/Link-Aggiornato-StreamingCommunity-01-17")
|
||||
domain = domain_req.json()['result']['description'].split(".")[1]
|
||||
console.print("[green]Get rules ...")
|
||||
console.print("[green]Getting rules...")
|
||||
|
||||
console.print(f"[blue]Test domain [white]=> [red]{domain}")
|
||||
site_url = f"https://streamingcommunity.{domain}"
|
||||
|
145
Src/Api/tv.py
145
Src/Api/tv.py
@ -1,14 +1,21 @@
|
||||
# 3.12.23 -> 10.12.23
|
||||
|
||||
# General import
|
||||
import binascii
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import sys
|
||||
import urllib
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
||||
from Src.Util.config import config
|
||||
from Src.Util.console import console, msg
|
||||
# Class import
|
||||
from Src.Util.headers import get_headers
|
||||
from Src.Util.console import console, msg
|
||||
from Src.Util.config import config
|
||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||
|
||||
# General import
|
||||
import requests, os, re, json, sys, binascii, urllib
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
# [func]
|
||||
@ -19,9 +26,8 @@ def get_token(id_tv, domain):
|
||||
|
||||
|
||||
def get_info_tv(id_film, title_name, site_version, domain):
|
||||
|
||||
req = requests.get(f"https://streamingcommunity.{domain}/titles/{id_film}-{title_name}", headers={
|
||||
'X-Inertia': 'true',
|
||||
'X-Inertia': 'true',
|
||||
'X-Inertia-Version': site_version,
|
||||
'User-Agent': get_headers()
|
||||
})
|
||||
@ -33,41 +39,53 @@ def get_info_tv(id_film, title_name, site_version, domain):
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def get_info_season(tv_id, tv_name, domain, version, token, n_stagione):
|
||||
req = requests.get(f'https://streamingcommunity.{domain}/titles/{tv_id}-{tv_name}/stagione-{n_stagione}', headers={
|
||||
'authority': f'streamingcommunity.{domain}', 'referer': f'https://streamingcommunity.broker/titles/{tv_id}-{tv_name}',
|
||||
'user-agent': get_headers(), 'x-inertia': 'true', 'x-inertia-version': version, 'x-xsrf-token': token,
|
||||
})
|
||||
def get_info_season(tv_id, tv_name, domain, version, token, n_season):
|
||||
req = requests.get(
|
||||
f'https://streamingcommunity.{domain}/titles/{tv_id}-{tv_name}/stagione-{n_season}',
|
||||
headers={
|
||||
'authority': f'streamingcommunity.{domain}',
|
||||
'referer': f'https://streamingcommunity.broker/titles/{tv_id}-{tv_name}',
|
||||
'user-agent': get_headers(),
|
||||
'x-inertia': 'true',
|
||||
'x-inertia-version': version,
|
||||
'x-xsrf-token': token,
|
||||
})
|
||||
|
||||
if req.ok:
|
||||
return [{'id': ep['id'], 'n': ep['number'], 'name': ep['name']} for ep in req.json()['props']['loadedSeason']['episodes']]
|
||||
return [{'id': ep['id'], 'n': ep['number'], 'name': ep['name']} for ep in
|
||||
req.json()['props']['loadedSeason']['episodes']]
|
||||
else:
|
||||
console.log(f"[red]Error: {req.status_code}")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def get_iframe(tv_id, ep_id, domain, token):
|
||||
req = requests.get(f'https://streamingcommunity.{domain}/iframe/{tv_id}', params={'episode_id': ep_id, 'next_episode': '1'}, cookies={'XSRF-TOKEN': token}, headers={
|
||||
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
|
||||
'user-agent': get_headers()
|
||||
})
|
||||
req = requests.get(f'https://streamingcommunity.{domain}/iframe/{tv_id}',
|
||||
params={'episode_id': ep_id, 'next_episode': '1'},
|
||||
cookies={'XSRF-TOKEN': token},
|
||||
headers={
|
||||
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
|
||||
'user-agent': get_headers()
|
||||
})
|
||||
|
||||
# Change user agent m3u8
|
||||
# Change user agent m3u8 (unused)
|
||||
"""
|
||||
custom_headers_req = {
|
||||
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
|
||||
'user-agent': get_headers()
|
||||
}
|
||||
"""
|
||||
|
||||
if req.ok:
|
||||
url_embed = BeautifulSoup(req.text, "lxml").find("iframe").get("src")
|
||||
req_embed = requests.get(url_embed, headers = {"User-agent": get_headers()}).text
|
||||
req_embed = requests.get(url_embed, headers={"User-agent": get_headers()}).text
|
||||
return BeautifulSoup(req_embed, "lxml").find("body").find("script").text
|
||||
else:
|
||||
console.log(f"[red]Error: {req.status_code}")
|
||||
sys.exit(0)
|
||||
|
||||
def select_quality(json_win_param):
|
||||
|
||||
def select_quality(json_win_param):
|
||||
if json_win_param['token1080p']:
|
||||
return "1080p"
|
||||
elif json_win_param['token720p']:
|
||||
@ -76,16 +94,16 @@ def select_quality(json_win_param):
|
||||
return "480p"
|
||||
else:
|
||||
return "360p"
|
||||
|
||||
def parse_content(embed_content):
|
||||
|
||||
|
||||
def parse_content(embed_content):
|
||||
# Parse parameter from req embed content
|
||||
win_video = re.search(r"window.video = {.*}", str(embed_content)).group()
|
||||
win_param = re.search(r"params: {[\s\S]*}", str(embed_content)).group()
|
||||
|
||||
# Parse parameter to make read for json
|
||||
json_win_video = "{"+win_video.split("{")[1].split("}")[0]+"}"
|
||||
json_win_param = "{"+win_param.split("{")[1].split("}")[0].replace("\n", "").replace(" ", "") + "}"
|
||||
json_win_video = "{" + win_video.split("{")[1].split("}")[0] + "}"
|
||||
json_win_param = "{" + win_param.split("{")[1].split("}")[0].replace("\n", "").replace(" ", "") + "}"
|
||||
json_win_param = json_win_param.replace(",}", "}").replace("'", '"')
|
||||
return json.loads(json_win_video), json.loads(json_win_param), select_quality(json.loads(json_win_param))
|
||||
|
||||
@ -100,9 +118,9 @@ def get_m3u8_url(json_win_video, json_win_param, render_quality):
|
||||
return f"https://vixcloud.co/playlist/{json_win_video['id']}?type=video&rendition={render_quality}&token={json_win_param[token_render]}&expires={json_win_param['expires']}"
|
||||
|
||||
|
||||
def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep_title, token_render):
|
||||
def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_season, n_ep, ep_title, token_render):
|
||||
response = requests.get('https://vixcloud.co/storage/enc.key', headers={
|
||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_stagione}%3AE{n_ep}+{ep_title}&nextEpisode=1',
|
||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_season}%3AE{n_ep}+{ep_title}&nextEpisode=1',
|
||||
})
|
||||
|
||||
if response.ok:
|
||||
@ -111,29 +129,18 @@ def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_stagione, n_ep, e
|
||||
console.log(f"[red]Error: {response.status_code}")
|
||||
sys.exit(0)
|
||||
|
||||
def get_m3u8_audio(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep_title, token_render):
|
||||
req = requests.get(f'https://vixcloud.co/playlist/{json_win_video["id"]}', params={'token': json_win_param['token'], 'expires': json_win_param["expires"] }, headers={
|
||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_stagione}%3AE{n_ep}+{ep_title}&nextEpisode=1'
|
||||
})
|
||||
|
||||
def get_m3u8_audio(json_win_video, json_win_param, tv_name, n_season, n_ep, ep_title, token_render):
|
||||
req = requests.get(f'https://vixcloud.co/playlist/{json_win_video["id"]}',
|
||||
params={'token': json_win_param['token'],
|
||||
'expires': json_win_param["expires"]},
|
||||
headers={
|
||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_season}%3AE{n_ep}+{ep_title}&nextEpisode=1'
|
||||
})
|
||||
|
||||
if req.ok:
|
||||
m3u8_cont = req.text.split()
|
||||
m3u8_cont_arr = []
|
||||
for row in m3u8_cont:
|
||||
if "audio" in str(row):
|
||||
lang=None
|
||||
default=False
|
||||
for field in row.split(","):
|
||||
if "NAME" in field:
|
||||
lang = field.split('"')[-2]
|
||||
if "DEFAULT" in field:
|
||||
default_str = field.split('=')[1]
|
||||
default = default_str.strip() == "YES"
|
||||
audioobj={"url": row.split(",")[-1].split('"')[-2], "lang": lang, "default": default}
|
||||
if audioobj['lang'] is None:
|
||||
continue
|
||||
m3u8_cont_arr.append(audioobj)
|
||||
return m3u8_cont_arr or None
|
||||
result = audio_extractor_m3u8(req)
|
||||
return result
|
||||
else:
|
||||
console.log(f"[red]Error: {req.status_code}")
|
||||
sys.exit(0)
|
||||
@ -141,10 +148,10 @@ def get_m3u8_audio(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep
|
||||
|
||||
# [func \ main]
|
||||
def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_select):
|
||||
|
||||
encoded_name = urllib.parse.quote(eps[index_ep_select]['name'])
|
||||
|
||||
console.print(f"[green]Downloading episode: [blue]{eps[index_ep_select]['n']} [green]=> [purple]{eps[index_ep_select]['name']}")
|
||||
console.print(
|
||||
f"[green]Downloading episode: [blue]{eps[index_ep_select]['n']} [green]=> [purple]{eps[index_ep_select]['name']}")
|
||||
embed_content = get_iframe(tv_id, eps[index_ep_select]['id'], domain, token)
|
||||
json_win_video, json_win_param, render_quality = parse_content(embed_content)
|
||||
|
||||
@ -153,29 +160,31 @@ def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_sel
|
||||
|
||||
m3u8_playlist = get_playlist(json_win_video, json_win_param, render_quality)
|
||||
m3u8_url = get_m3u8_url(json_win_video, json_win_param, render_quality)
|
||||
m3u8_key = get_m3u8_key_ep(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, encoded_name, token_render)
|
||||
m3u8_key = get_m3u8_key_ep(json_win_video, json_win_param, tv_name, season_select, index_ep_select + 1,
|
||||
encoded_name, token_render)
|
||||
|
||||
mp4_name = f"{tv_name.replace('+', '_')}_S{str(season_select).zfill(2)}E{str(index_ep_select+1).zfill(2)}"
|
||||
mp4_name = f"{tv_name.replace('+', '_')}_S{str(season_select).zfill(2)}E{str(index_ep_select + 1).zfill(2)}"
|
||||
mp4_format = f"{mp4_name}.mp4"
|
||||
season = mp4_name.rsplit("E", 1)[0]
|
||||
mp4_path = os.path.join(config['root_path'], config['series_folder_name'], tv_name, season, mp4_format)
|
||||
|
||||
m3u8_url_audio = get_m3u8_audio(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, encoded_name, token_render)
|
||||
m3u8_url_audio = get_m3u8_audio(json_win_video, json_win_param, tv_name, season_select, index_ep_select + 1,
|
||||
encoded_name, token_render)
|
||||
|
||||
if m3u8_url_audio is not None:
|
||||
console.print("[blue]Using m3u8 audio => [red]True")
|
||||
# Movie_Name.[Language_Code].vtt
|
||||
# Movie_Name.[Language_Code].forced.vtt
|
||||
|
||||
subtitle_path = os.path.join(config['root_path'], config['series_folder_name'], tv_name, season)
|
||||
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_playlist, key=m3u8_key, output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
||||
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_playlist, key=m3u8_key,
|
||||
output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
||||
|
||||
|
||||
def main_dw_tv(tv_id, tv_name, version, domain):
|
||||
|
||||
token = get_token(tv_id, domain)
|
||||
|
||||
num_season_find = get_info_tv(tv_id, tv_name, version, domain)
|
||||
console.print("\n[green]Insert season [red]number[green], or [red](*) [green]to download all seasons, or [red][1-2] [green]for a range of seasons")
|
||||
console.print(
|
||||
"\n[green]Insert season [red]number[green], or [red](*) [green]to download all seasons, or [red][1-2] [green]for a range of seasons")
|
||||
console.print(f"\n[blue]Season(s) found: [red]{num_season_find}")
|
||||
season_select = str(msg.ask("\n[green]Insert which season(s) number you'd like to download"))
|
||||
if "[" in season_select:
|
||||
@ -184,7 +193,7 @@ def main_dw_tv(tv_id, tv_name, version, domain):
|
||||
for n_season in result:
|
||||
eps = get_info_season(tv_id, tv_name, domain, version, token, n_season)
|
||||
for ep in eps:
|
||||
dw_single_ep(tv_id, eps, int(ep['n'])-1, domain, token, tv_name, n_season)
|
||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, n_season)
|
||||
print("\n")
|
||||
elif season_select != "*":
|
||||
season_select = int(season_select)
|
||||
@ -193,16 +202,17 @@ def main_dw_tv(tv_id, tv_name, version, domain):
|
||||
|
||||
for ep in eps:
|
||||
console.print(f"[green]Episode: [blue]{ep['n']} [green]=> [purple]{ep['name']}")
|
||||
index_ep_select = str(msg.ask("\n[green]Insert episode [blue]number[green], or [red](*) [green]to download all episodes, or [red][1-2] [green]for a range of episodes"))
|
||||
index_ep_select = str(msg.ask(
|
||||
"\n[green]Insert episode [blue]number[green], or [red](*) [green]to download all episodes, or [red][1-2] [green]for a range of episodes"))
|
||||
|
||||
# Download range []
|
||||
if "[" in index_ep_select:
|
||||
start, end = map(int, index_ep_select[1:-1].split('-'))
|
||||
result = list(range(start, end + 1))
|
||||
|
||||
for n_randge_ep in result:
|
||||
index_ep_select = int(n_randge_ep)
|
||||
dw_single_ep(tv_id, eps, n_randge_ep-1, domain, token, tv_name, season_select)
|
||||
for n_range_ep in result:
|
||||
# index_ep_select = int(n_range_ep) # Unused
|
||||
dw_single_ep(tv_id, eps, n_range_ep - 1, domain, token, tv_name, season_select)
|
||||
|
||||
# Download single ep
|
||||
elif index_ep_select != "*":
|
||||
@ -215,15 +225,14 @@ def main_dw_tv(tv_id, tv_name, version, domain):
|
||||
# Download all
|
||||
else:
|
||||
for ep in eps:
|
||||
dw_single_ep(tv_id, eps, int(ep['n'])-1, domain, token, tv_name, season_select)
|
||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, season_select)
|
||||
print("\n")
|
||||
|
||||
else:
|
||||
console.print("[red]Wrong [yellow]INDEX for the selected Season")
|
||||
else:
|
||||
for n_season in range(1, num_season_find+1):
|
||||
for n_season in range(1, num_season_find + 1):
|
||||
eps = get_info_season(tv_id, tv_name, domain, version, token, n_season)
|
||||
for ep in eps:
|
||||
dw_single_ep(tv_id, eps, int(ep['n'])-1, domain, token, tv_name, n_season)
|
||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, n_season)
|
||||
print("\n")
|
||||
|
||||
|
@ -4,7 +4,8 @@
|
||||
from Src.Util.console import console
|
||||
|
||||
# Import
|
||||
import ffmpeg
|
||||
import ffmpeg
|
||||
|
||||
|
||||
# Variable
|
||||
|
||||
@ -19,14 +20,37 @@ def get_video_duration(file_path):
|
||||
print(f"Error: {e.stderr}")
|
||||
return None
|
||||
|
||||
|
||||
def format_duration(seconds):
|
||||
hours, remainder = divmod(seconds, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
return int(hours), int(minutes), int(seconds)
|
||||
|
||||
|
||||
def print_duration_table(file_path):
|
||||
video_duration = get_video_duration(file_path)
|
||||
|
||||
if video_duration is not None:
|
||||
hours, minutes, seconds = format_duration(video_duration)
|
||||
console.log(f"[cyan]Info [green]'{file_path}': [purple]{int(hours)}[red]h [purple]{int(minutes)}[red]m [purple]{int(seconds)}[red]s")
|
||||
console.log(
|
||||
f"[cyan]Info [green]'{file_path}': [purple]{int(hours)}[red]h [purple]{int(minutes)}[red]m [purple]{int(seconds)}[red]s")
|
||||
|
||||
|
||||
def audio_extractor_m3u8(req):
|
||||
m3u8_cont = req.text.split()
|
||||
m3u8_cont_arr = []
|
||||
for row in m3u8_cont:
|
||||
if "audio" in str(row):
|
||||
lang = None
|
||||
default = False
|
||||
for field in row.split(","):
|
||||
if "NAME" in field:
|
||||
lang = field.split('"')[-2]
|
||||
if "DEFAULT" in field:
|
||||
default_str = field.split('=')[1]
|
||||
default = default_str.strip() == "YES"
|
||||
audioobj = {"url": row.split(",")[-1].split('"')[-2], "lang": lang, "default": default}
|
||||
if audioobj['lang'] is None:
|
||||
continue
|
||||
m3u8_cont_arr.append(audioobj)
|
||||
return m3u8_cont_arr or None
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"root_path": "videos",
|
||||
"movies_folder_name": "Film",
|
||||
"series_folder_name": "Serie",
|
||||
"movies_folder_name": "Movies",
|
||||
"series_folder_name": "Series",
|
||||
"download_subtitles": true,
|
||||
"download_default_language": true,
|
||||
"selected_language": "English",
|
||||
|
6
run.py
6
run.py
@ -26,17 +26,18 @@ def initialize():
|
||||
try:
|
||||
main_update()
|
||||
except Exception as e:
|
||||
console.print(f"[blue]Req github [white]=> [red]Failed: {e}")
|
||||
console.print(f"[blue]Request GitHub [white]=> [red]Failed: {e}")
|
||||
|
||||
check_ffmpeg()
|
||||
print("\n")
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
initialize()
|
||||
domain, site_version = Page.domain_version()
|
||||
|
||||
film_search = msg.ask("\n[blue]Search for any movie or tv series title").strip()
|
||||
film_search = msg.ask("\n[blue]Search for any Movie or TV Series title").strip()
|
||||
db_title = Page.search(film_search, domain)
|
||||
Page.display_search_results(db_title)
|
||||
|
||||
@ -89,5 +90,6 @@ def main():
|
||||
|
||||
console.print("[red]Done!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -42,7 +42,7 @@ def keep_specific_items(directory, keep_folder, keep_file):
|
||||
os.remove(item_path)
|
||||
|
||||
except PermissionError as pe:
|
||||
print(f"PermissionError: {pe}. Check permissions and try running the script as administrator.")
|
||||
print(f"PermissionError: {pe}. Check permissions and try running the script with admin privileges.")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
@ -51,13 +51,13 @@ def download_and_extract_latest_commit(author, repo_name):
|
||||
# Get the latest commit information using GitHub API
|
||||
api_url = f'https://api.github.com/repos/{author}/{repo_name}/commits?per_page=1'
|
||||
response = requests.get(api_url)
|
||||
console.log("[green]Make req repo github")
|
||||
console.log("[green]Making a request to GitHub repository...")
|
||||
|
||||
if response.status_code == 200:
|
||||
commit_info = response.json()[0]
|
||||
commit_sha = commit_info['sha']
|
||||
zipball_url = f'https://github.com/{author}/{repo_name}/archive/{commit_sha}.zip'
|
||||
console.log("[green]Get zip file from repo")
|
||||
console.log("[green]Getting zip file from repository...")
|
||||
|
||||
# Download the zipball
|
||||
response = requests.get(zipball_url)
|
||||
|
Loading…
x
Reference in New Issue
Block a user