mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-05 02:55:25 +00:00
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
This commit is contained in:
parent
306377a7be
commit
1c5f960b16
@ -26,37 +26,40 @@ video_source = VideoSource()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def download_episode(index_select: int):
|
def download_episode(index_select: int, custom_video_source: VideoSource = None):
|
||||||
"""
|
"""
|
||||||
Downloads the selected episode.
|
Downloads the selected episode.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
- index_select (int): Index of the episode to download.
|
- index_select (int): Index of the episode to download.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
active_video_source = custom_video_source if custom_video_source is not None else video_source
|
||||||
|
|
||||||
|
|
||||||
# Get information about the selected episode
|
# Get information about the selected episode
|
||||||
obj_episode = video_source.get_info_episode(index_select)
|
obj_episode = active_video_source.get_info_episode(index_select)
|
||||||
|
|
||||||
start_message()
|
start_message()
|
||||||
console.print(f"[yellow]Download: [red]EP_{obj_episode.number} \n")
|
console.print(f"[yellow]Download: [red]EP_{obj_episode.number} \n")
|
||||||
|
|
||||||
# Get the embed URL for the episode
|
# Get the embed URL for the episode
|
||||||
embed_url = video_source.get_embed(obj_episode.id)
|
embed_url = active_video_source.get_embed(obj_episode.id)
|
||||||
|
|
||||||
# Parse parameter in embed text
|
# Parse parameter in embed text
|
||||||
video_source.parse_script(embed_url)
|
active_video_source.parse_script(embed_url)
|
||||||
|
|
||||||
# Create output path
|
# Create output path
|
||||||
mp4_path = None
|
mp4_path = None
|
||||||
mp4_name = f"{index_select + 1}.mp4"
|
mp4_name = f"{index_select + 1}.mp4"
|
||||||
if video_source.is_series:
|
if active_video_source.is_series:
|
||||||
mp4_path = os.path.join(ROOT_PATH, ANIME_FOLDER, SERIES_FOLDER, video_source.series_name)
|
mp4_path = os.path.join(ROOT_PATH, ANIME_FOLDER, SERIES_FOLDER, active_video_source.series_name)
|
||||||
else:
|
else:
|
||||||
mp4_path = os.path.join(ROOT_PATH, ANIME_FOLDER, MOVIE_FOLDER, video_source.series_name)
|
mp4_path = os.path.join(ROOT_PATH, ANIME_FOLDER, MOVIE_FOLDER, active_video_source.series_name)
|
||||||
|
|
||||||
# Crete downloader
|
# Crete downloader
|
||||||
obj_download = Downloader(
|
obj_download = Downloader(
|
||||||
m3u8_playlist = video_source.get_playlist(),
|
m3u8_playlist = active_video_source.get_playlist(),
|
||||||
output_filename = os.path.join(mp4_path, mp4_name)
|
output_filename = os.path.join(mp4_path, mp4_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ def display_episodes_list() -> str:
|
|||||||
return last_command
|
return last_command
|
||||||
|
|
||||||
|
|
||||||
def donwload_video(tv_name: str, index_season_selected: int, index_episode_selected: int) -> None:
|
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.
|
Download a single episode video.
|
||||||
|
|
||||||
@ -76,10 +76,12 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec
|
|||||||
- index_episode_selected (int): Index of the selected episode.
|
- 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()
|
start_message()
|
||||||
|
|
||||||
# Get info about episode
|
# Get info about episode
|
||||||
obj_episode = video_source.obj_episode_manager.episodes[index_episode_selected - 1]
|
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}")
|
console.print(f"[yellow]Download: [red]{index_season_selected}:{index_episode_selected} {obj_episode.name}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@ -88,9 +90,9 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec
|
|||||||
mp4_path = os.path.join(ROOT_PATH, STREAMING_FOLDER, SERIES_FOLDER, tv_name, f"S{index_season_selected}")
|
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
|
# Retrieve scws and if available master playlist
|
||||||
video_source.get_iframe(obj_episode.id)
|
active_video_source.get_iframe(obj_episode.id)
|
||||||
video_source.get_content()
|
active_video_source.get_content()
|
||||||
master_playlist = video_source.get_playlist()
|
master_playlist = active_video_source.get_playlist()
|
||||||
|
|
||||||
# Download the episode
|
# Download the episode
|
||||||
Downloader(
|
Downloader(
|
||||||
@ -99,7 +101,7 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec
|
|||||||
).start(SERVER_IP)
|
).start(SERVER_IP)
|
||||||
|
|
||||||
|
|
||||||
def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: bool = False) -> None:
|
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.
|
Download all episodes of a season.
|
||||||
|
|
||||||
@ -109,19 +111,21 @@ def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: boo
|
|||||||
- donwload_all (bool): Donwload all seasons episodes
|
- 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]).
|
# 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]).
|
||||||
video_source.obj_episode_manager.clear()
|
active_video_source.obj_episode_manager.clear()
|
||||||
season_number = (video_source.obj_title_manager.titles[index_season_selected-1].number)
|
season_number = (active_video_source.obj_title_manager.titles[index_season_selected-1].number)
|
||||||
|
|
||||||
# Start message and collect information about episodes
|
# Start message and collect information about episodes
|
||||||
start_message()
|
start_message()
|
||||||
video_source.collect_title_season(season_number)
|
active_video_source.collect_title_season(season_number)
|
||||||
episodes_count = video_source.obj_episode_manager.get_length()
|
episodes_count = active_video_source.obj_episode_manager.get_length()
|
||||||
|
|
||||||
# Download all episodes wihtout ask
|
# Download all episodes wihtout ask
|
||||||
if donwload_all:
|
if donwload_all:
|
||||||
for i_episode in range(1, episodes_count+1):
|
for i_episode in range(1, episodes_count+1):
|
||||||
donwload_video(tv_name, index_season_selected, i_episode)
|
donwload_video(tv_name, index_season_selected, i_episode, active_video_source)
|
||||||
|
|
||||||
console.print(f"\n[red]Download [yellow]season: [red]{index_season_selected}.")
|
console.print(f"\n[red]Download [yellow]season: [red]{index_season_selected}.")
|
||||||
|
|
||||||
@ -134,12 +138,12 @@ def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: boo
|
|||||||
|
|
||||||
# Download selected episodes
|
# Download selected episodes
|
||||||
if len(list_episode_select) == 1 and last_command != "*":
|
if len(list_episode_select) == 1 and last_command != "*":
|
||||||
donwload_video(tv_name, index_season_selected, list_episode_select[0])
|
donwload_video(tv_name, index_season_selected, list_episode_select[0],active_video_source)
|
||||||
|
|
||||||
# Download all other episodes selecter
|
# Download all other episodes selecter
|
||||||
else:
|
else:
|
||||||
for i_episode in list_episode_select:
|
for i_episode in list_episode_select:
|
||||||
donwload_video(tv_name, index_season_selected, i_episode)
|
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:
|
def download_series(tv_id: str, tv_name: str, version: str, domain: str) -> None:
|
||||||
|
@ -319,7 +319,11 @@ class M3U8_Segments:
|
|||||||
self.condition.notify_all() # Wake up the writer thread if it's waiting
|
self.condition.notify_all() # Wake up the writer thread if it's waiting
|
||||||
|
|
||||||
# Register the signal handler for Ctrl+C
|
# Register the signal handler for Ctrl+C
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
try:
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Failed to register signal handler: {e}")
|
||||||
|
logging.error("Ctrl+C detection may not work.")
|
||||||
|
|
||||||
with ThreadPoolExecutor(max_workers=TQDM_MAX_WORKER) as executor:
|
with ThreadPoolExecutor(max_workers=TQDM_MAX_WORKER) as executor:
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
from .views import SearchView#, DownloadView
|
from .views import SearchView, DownloadView
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
|
|
||||||
router.register(r"search", SearchView, basename="search")
|
router.register(r"search", SearchView, basename="search")
|
||||||
#router.register(r"download", DownloadView, basename="download")
|
router.register(r"download", DownloadView, basename="download")
|
||||||
|
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -7,10 +7,16 @@ from rest_framework import viewsets
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
|
||||||
|
from Src.Api.Animeunity.anime import donwload_film
|
||||||
|
from Src.Api.Animeunity.anime import download_episode as donwload_anime_episode
|
||||||
from Src.Api.Animeunity import title_search as anime_search
|
from Src.Api.Animeunity import title_search as anime_search
|
||||||
from Src.Api.Animeunity.Core.Vix_player.player import VideoSource as anime_source
|
from Src.Api.Animeunity.Core.Vix_player.player import VideoSource as anime_source
|
||||||
from Src.Api.Animeunity.site import media_search_manager as anime_media_manager
|
from Src.Api.Animeunity.site import media_search_manager as anime_media_manager
|
||||||
|
|
||||||
|
|
||||||
|
from Src.Api.Streamingcommunity.film import download_film
|
||||||
|
from Src.Api.Streamingcommunity.series import donwload_episode as download_tv_episode
|
||||||
from Src.Api.Streamingcommunity import title_search as sc_search, get_version_and_domain
|
from Src.Api.Streamingcommunity import title_search as sc_search, get_version_and_domain
|
||||||
from Src.Api.Streamingcommunity.Core.Vix_player.player import VideoSource as film_video_source
|
from Src.Api.Streamingcommunity.Core.Vix_player.player import VideoSource as film_video_source
|
||||||
from Src.Api.Streamingcommunity.site import media_search_manager as film_media_manager
|
from Src.Api.Streamingcommunity.site import media_search_manager as film_media_manager
|
||||||
@ -151,7 +157,7 @@ class SearchView(viewsets.ViewSet):
|
|||||||
return Response({"error": "No media found with that search query"})
|
return Response({"error": "No media found with that search query"})
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
class DownloadView(viewsets.ViewSet):
|
class DownloadView(viewsets.ViewSet):
|
||||||
|
|
||||||
def create(self, request):
|
def create(self, request):
|
||||||
@ -171,59 +177,36 @@ class DownloadView(viewsets.ViewSet):
|
|||||||
case "MOVIE":
|
case "MOVIE":
|
||||||
download_film(self.media_id, self.media_slug, self.domain)
|
download_film(self.media_id, self.media_slug, self.domain)
|
||||||
case "TV":
|
case "TV":
|
||||||
video_source = VideoSource()
|
video_source = film_video_source()
|
||||||
video_source.set_url_base_name(STREAM_SITE_NAME)
|
video_source.setup(
|
||||||
video_source.set_version(self.site_version)
|
version = self.site_version,
|
||||||
video_source.set_domain(self.domain)
|
domain = self.domain,
|
||||||
video_source.set_series_name(self.media_slug)
|
media_id = self.media_id,
|
||||||
video_source.set_media_id(self.media_id)
|
series_name = self.media_slug
|
||||||
|
)
|
||||||
|
|
||||||
video_source.collect_info_seasons()
|
video_source.collect_info_seasons()
|
||||||
video_source.obj_episode_manager.clear()
|
video_source.obj_episode_manager.clear()
|
||||||
|
|
||||||
video_source.collect_title_season(self.download_id)
|
seasons_count = video_source.obj_title_manager.get_length()
|
||||||
episodes_count = video_source.obj_episode_manager.get_length()
|
|
||||||
for i_episode in range(1, episodes_count + 1):
|
|
||||||
episode_id = video_source.obj_episode_manager.episodes[
|
|
||||||
i_episode - 1
|
|
||||||
].id
|
|
||||||
|
|
||||||
# Define filename and path for the downloaded video
|
for i_season in range(1, seasons_count + 1):
|
||||||
mp4_name = remove_special_characters(
|
download_tv_episode(self.media_slug, i_season, True, video_source)
|
||||||
f"{map_episode_title(self.media_slug,video_source.obj_episode_manager.episodes[i_episode - 1],self.download_id)}.mp4"
|
|
||||||
)
|
|
||||||
mp4_path = remove_special_characters(
|
|
||||||
os.path.join(
|
|
||||||
ROOT_PATH,
|
|
||||||
SERIES_FOLDER,
|
|
||||||
self.media_slug,
|
|
||||||
f"S{self.download_id}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
os.makedirs(mp4_path, exist_ok=True)
|
|
||||||
|
|
||||||
# Get iframe and content for the episode
|
|
||||||
video_source.get_iframe(episode_id)
|
|
||||||
video_source.get_content()
|
|
||||||
video_source.set_url_base_name(STREAM_SITE_NAME)
|
|
||||||
|
|
||||||
# Download the episode
|
|
||||||
obj_download = Downloader(
|
|
||||||
m3u8_playlist=video_source.get_playlist(),
|
|
||||||
key=video_source.get_key(),
|
|
||||||
output_filename=os.path.join(mp4_path, mp4_name),
|
|
||||||
)
|
|
||||||
|
|
||||||
obj_download.download_m3u8()
|
|
||||||
|
|
||||||
case "TV_ANIME":
|
case "TV_ANIME":
|
||||||
episodes_downloader = EpisodeDownloader(
|
video_source = anime_source()
|
||||||
self.media_id, self.media_slug
|
video_source.setup(
|
||||||
|
media_id = self.media_id,
|
||||||
|
series_name = self.media_slug
|
||||||
)
|
)
|
||||||
episodes_downloader.download_episode(self.download_id)
|
episoded_count = video_source.get_count_episodes()
|
||||||
|
for i in range(episoded_count):
|
||||||
|
donwload_anime_episode(i, video_source)
|
||||||
case "OVA" | "SPECIAL":
|
case "OVA" | "SPECIAL":
|
||||||
anime_download_film(
|
donwload_film(
|
||||||
id_film=self.media_id, title_name=self.media_slug
|
id_film=self.media_id,
|
||||||
|
title_name=self.media_slug
|
||||||
|
|
||||||
)
|
)
|
||||||
case _:
|
case _:
|
||||||
raise Exception("Type media not supported")
|
raise Exception("Type media not supported")
|
||||||
@ -238,4 +221,3 @@ class DownloadView(viewsets.ViewSet):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Response(response_dict)
|
return Response(response_dict)
|
||||||
'''
|
|
||||||
|
@ -148,7 +148,7 @@ const downloadAllItems = async () => {
|
|||||||
@click.prevent="downloadAllItems">
|
@click.prevent="downloadAllItems">
|
||||||
Scarica {{['TV_ANIME', 'TV'].includes(item.type)? 'tutto' : ''}}
|
Scarica {{['TV_ANIME', 'TV'].includes(item.type)? 'tutto' : ''}}
|
||||||
</button>
|
</button>
|
||||||
<template v-if="!loading && ['TV_ANIME', 'TV'].includes(item.type)">
|
<!--<template v-if="!loading && ['TV_ANIME', 'TV'].includes(item.type)">
|
||||||
<button @click="toggleEpisodeSelection">
|
<button @click="toggleEpisodeSelection">
|
||||||
{{selectingEpisodes ? 'Disattiva' : 'Attiva'}} selezione episodi
|
{{selectingEpisodes ? 'Disattiva' : 'Attiva'}} selezione episodi
|
||||||
</button>
|
</button>
|
||||||
@ -156,7 +156,7 @@ const downloadAllItems = async () => {
|
|||||||
@click="downloadSelectedEpisodes">
|
@click="downloadSelectedEpisodes">
|
||||||
Download episodi selezionati
|
Download episodi selezionati
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -194,7 +194,7 @@ const downloadAllItems = async () => {
|
|||||||
|
|
||||||
<!--MOVIES SECTION-->
|
<!--MOVIES SECTION-->
|
||||||
<div v-else-if="!loading && ['MOVIE', 'OVA', 'SPECIAL'].includes(item.type)">
|
<div v-else-if="!loading && ['MOVIE', 'OVA', 'SPECIAL'].includes(item.type)">
|
||||||
<p>Questo è un {{item.type}} (QUESTO TESTO E' A SCOPO DI TEST)</p>
|
<!-- WILL BE POPULATED WITH HYPOTETICAL MOVIES CONTENT -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--LOADING SECTION-->
|
<!--LOADING SECTION-->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user