Francesco Grazioso 1c5f960b16
Feat/app api and frontend (#140)
* minor fixes

* created basic django app

* add django dependency

* created basic search endpoint

* created retrieve method for search

* remove retrieve

* start implementing download endpoint (only movie for now)

* start implementing episode info for series

* finished get_episodes_info

* minor fixes

* add download anime episode

* start implementing download for tv series

* refactor methods

* finished download endpoint (will implement possibility to download single episodes of season in tv series)

* new domain and black on project

* start

* add cors

* add start gui command

* add gui for search

* edited .gitignore

* create component for media details

* better UX/UI

* edited anime episode to stream response (better experience)

* implemented UI for media details (TODO add download capabilities)

* fix poster fetching

* minor fixes

* fix cors error

* start implementing download

* fix typing on anime movies

* refactor

* refactor + add download OVA

* add plot for all anime types

* add download for all anime episodes

* add download all tv series episodes

* fix crach if localStorage is undefined

* moved download logic in separeted file

* fix wrong index passed while downloading tv series

* fix style searchbar

* add loader to search button and add enter listener while searching

* remove dependency from loading episodes to download all in anime series

* add function to download selected episodes for anime

* add sh command to kill gui

* fix messages in kill_gui.sh

* start implementing download select episodes for tv series (to be tested) + run black and eslint

* start  refactoring  to version 2.0

* start implementing preview endpoint

* finish reimplement version 2.0
2024-06-01 13:13:09 +02:00

194 lines
6.5 KiB
Python

# 3.12.23
import os
import sys
import logging
# Internal utilities
from Src.Util.console import console, msg
from Src.Util._jsonConfig import config_manager
from Src.Util.table import TVShowManager
from Src.Util.message import start_message
from Src.Lib.Hls.downloader import Downloader
# Logic class
from .Core.Vix_player.player import VideoSource
from .Core.Util import manage_selection, map_episode_title
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
from .costant import STREAMING_FOLDER, SERIES_FOLDER, SERVER_IP
# Variable
video_source = VideoSource()
table_show_manager = TVShowManager()
def display_episodes_list() -> str:
"""
Display episodes list and handle user input.
Returns:
last_command (str): Last command entered by the user.
"""
# Set up table for displaying episodes
table_show_manager.set_slice_end(10)
# Add columns to the table
column_info = {
"Index": {'color': 'red'},
"Name": {'color': 'magenta'},
"Duration": {'color': 'green'}
}
table_show_manager.add_column(column_info)
# Populate the table with episodes information
for i, media in enumerate(video_source.obj_episode_manager.episodes):
table_show_manager.add_tv_show({
'Index': str(media.number),
'Name': media.name,
'Duration': str(media.duration)
})
# Run the table and handle user input
last_command = table_show_manager.run()
if last_command == "q":
console.print("\n[red]Quit [white]...")
sys.exit(0)
return last_command
def donwload_video(tv_name: str, index_season_selected: int, index_episode_selected: int, custom_video_source: VideoSource = None) -> None:
"""
Download a single episode video.
Args:
- tv_name (str): Name of the TV series.
- index_season_selected (int): Index of the selected season.
- index_episode_selected (int): Index of the selected episode.
"""
active_video_source = custom_video_source if custom_video_source is not None else video_source
start_message()
# Get info about episode
obj_episode = active_video_source.obj_episode_manager.episodes[index_episode_selected - 1]
console.print(f"[yellow]Download: [red]{index_season_selected}:{index_episode_selected} {obj_episode.name}")
print()
# Define filename and path for the downloaded video
mp4_name = f"{map_episode_title(tv_name, obj_episode, index_season_selected)}.mp4"
mp4_path = os.path.join(ROOT_PATH, STREAMING_FOLDER, SERIES_FOLDER, tv_name, f"S{index_season_selected}")
# Retrieve scws and if available master playlist
active_video_source.get_iframe(obj_episode.id)
active_video_source.get_content()
master_playlist = active_video_source.get_playlist()
# Download the episode
Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_name)
).start(SERVER_IP)
def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: bool = False, custom_video_source: VideoSource = None) -> None:
"""
Download all episodes of a season.
Args:
- tv_name (str): Name of the TV series.
- index_season_selected (int): Index of the selected season.
- donwload_all (bool): Donwload all seasons episodes
"""
active_video_source = custom_video_source if custom_video_source is not None else video_source
# Clean memory of all episodes and get the number of the season (some dont follow rule of [1,2,3,4,5] but [1,2,3,145,5,6,7]).
active_video_source.obj_episode_manager.clear()
season_number = (active_video_source.obj_title_manager.titles[index_season_selected-1].number)
# Start message and collect information about episodes
start_message()
active_video_source.collect_title_season(season_number)
episodes_count = active_video_source.obj_episode_manager.get_length()
# Download all episodes wihtout ask
if donwload_all:
for i_episode in range(1, episodes_count+1):
donwload_video(tv_name, index_season_selected, i_episode, active_video_source)
console.print(f"\n[red]Download [yellow]season: [red]{index_season_selected}.")
# If not download all episode but a single season
if not donwload_all:
# Display episodes list and manage user selection
last_command = display_episodes_list()
list_episode_select = manage_selection(last_command, episodes_count)
# Download selected episodes
if len(list_episode_select) == 1 and last_command != "*":
donwload_video(tv_name, index_season_selected, list_episode_select[0],active_video_source)
# Download all other episodes selecter
else:
for i_episode in list_episode_select:
donwload_video(tv_name, index_season_selected, i_episode, active_video_source)
def download_series(tv_id: str, tv_name: str, version: str, domain: str) -> None:
"""
Download all episodes of a TV series.
Args:
- tv_id (str): ID of the TV series.
- tv_name (str): Name of the TV series.
- version (str): Version of the TV series.
- domain (str): Domain from which to download.
"""
# Start message and set up video source
start_message()
# Setup video source
video_source.setup(
version = version,
domain = domain,
media_id = tv_id,
series_name = tv_name
)
# Collect information about seasons
video_source.collect_info_seasons()
seasons_count = video_source.obj_title_manager.get_length()
# Prompt user for season selection and download episodes
console.print(f"\n[green]Season find: [red]{seasons_count}")
index_season_selected = str(msg.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]for a range of media"))
list_season_select = manage_selection(index_season_selected, seasons_count)
# Download selected episodes
if len(list_season_select) == 1 and index_season_selected != "*":
if 1 <= int(index_season_selected) <= seasons_count:
donwload_episode(tv_name, list_season_select[0])
# Dowload all seasons and episodes
elif index_season_selected == "*":
for i_season in list_season_select:
donwload_episode(tv_name, i_season, True)
# Download all other season selecter
else:
for i_season in list_season_select:
donwload_episode(tv_name, i_season)