diff options
| author | Bobby <[email protected]> | 2024-09-21 02:38:06 -0400 |
|---|---|---|
| committer | Bobby <[email protected]> | 2024-09-21 02:38:06 -0400 |
| commit | 12f85fd1fcb223bd3e62c7b352ccb57d4922fc0b (patch) | |
| tree | 8ac25c738a029de64bde2f5e31902061153849b6 | |
| parent | aa6bd3d74961a4950dab9167159540939bef45f2 (diff) | |
| download | yugen-12f85fd1fcb223bd3e62c7b352ccb57d4922fc0b.tar.xz yugen-12f85fd1fcb223bd3e62c7b352ccb57d4922fc0b.zip | |
Provider Selection
| -rw-r--r-- | detail/views.py | 7 | ||||
| -rw-r--r-- | static/css/main.css | 4 | ||||
| -rw-r--r-- | templates/watch/watch.html | 23 | ||||
| -rw-r--r-- | watch/utils.py | 162 | ||||
| -rw-r--r-- | watch/views.py | 15 |
5 files changed, 147 insertions, 64 deletions
diff --git a/detail/views.py b/detail/views.py index b38471c..fdbb5a5 100644 --- a/detail/views.py +++ b/detail/views.py @@ -1,6 +1,6 @@ from django.shortcuts import redirect, render from authentication.utils import get_single_anime_mal -from watch.utils import attach_episode_metadata, get_anime_data, get_anime_episodes +from watch.utils import attach_episode_metadata, get_anime_data, get_anime_episodes, get_anime_episodes_gogo from watch.views import get_seasons_by_zid @@ -8,11 +8,14 @@ def index(request): return redirect("home:index") def detail(request, anime_id): - anime_data, provider = get_anime_data(anime_id) + anime_data, provider, gd = get_anime_data(anime_id) if not anime_data: return render(request, "detail/detail.html", {"error": "Anime not found"}, status=404) anime_episodes = get_anime_episodes(anime_id) + if "message" in anime_episodes: + anime_data, provider, gd = get_anime_data(anime_id, provider="gogo") + anime_episodes, _ = get_anime_episodes_gogo(anime_id) if anime_episodes: attach_episode_metadata(anime_data, anime_episodes) diff --git a/static/css/main.css b/static/css/main.css index b45f803..3c8ae82 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -759,6 +759,10 @@ video { margin-left: 1rem; } +.ml-8 { + margin-left: 2rem; +} + .mr-1 { margin-right: 0.25rem; } diff --git a/templates/watch/watch.html b/templates/watch/watch.html index 0d086c3..20d0ce3 100644 --- a/templates/watch/watch.html +++ b/templates/watch/watch.html @@ -28,7 +28,7 @@ <div class="flex flex-col gap-2 h-full max-h-96 lg:h-[39vw] lg:max-h-[761px] overflow-y-auto"> {% for episode in all_episodes %} {% if not viaMal and episode.number == current_episode_number or viaMal and episode.episode.number == current_episode_number %} - <a id="selected-episode" href="{% if not viaMal %}{% url "watch:watch_episode" anime.id episode.number %}{% if request.GET.mode %}?mode={{ request.GET.mode }}{% endif %}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ episode.episode.identifier }}{% if request.GET.mode %}&mode={{ request.GET.mode }}{% endif %}{% endif %}" class="flex flex-row gap-4 justify-between items-center w-full bg-{{ user.preferences.accent_colour }}-600 p-2 rounded hover:bg-{{ user.preferences.accent_colour }}-600 hover:bg-opacity-30"> + <a id="selected-episode" href="{% if not viaMal %}{% url "watch:watch_episode" anime.id episode.number %}{% if request.GET.mode %}?mode={{ request.GET.mode }}{% endif %}{% if request.GET.mode and request.GET.provider %}&provider={{ request.GET.provider }}{% elif request.GET.provider %}?provider={{ request.GET.provider }}{% endif %}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ episode.episode.identifier }}{% if request.GET.mode %}&mode={{ request.GET.mode }}{% endif %}{% if request.GET.mode and request.GET.provider %}&provider={{ request.GET.provider }}{% elif request.GET.provider %}?provider={{ request.GET.provider }}{% endif %}{% endif %}" class="flex flex-row gap-4 justify-between items-center w-full bg-{{ user.preferences.accent_colour }}-600 p-2 rounded hover:bg-{{ user.preferences.accent_colour }}-600 hover:bg-opacity-30"> <span class="truncate max-w-full overflow-hidden text-ellipsis whitespace-nowrap">{{ episode.number }}. {{ episode.title }}</span> <span class="flex flex-row item-center gap-2"> @@ -62,7 +62,7 @@ </a> {% else %} - <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id episode.number %}{% if request.GET.mode %}?mode={{ request.GET.mode }}{% endif %}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ episode.episode.identifier }}{% if request.GET.mode %}&mode={{ request.GET.mode }}{% endif %}{% endif %}" class="flex flex-row justify-between w-full gap-4 {% if episode.number in watched_episodes %}bg-{{ user.preferences.accent_colour }}-600 bg-opacity-20{% else %}bg-white bg-opacity-10{% endif %} p-2 rounded hover:bg-{{ user.preferences.accent_colour }}-600 hover:bg-opacity-30"> + <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id episode.number %}{% if request.GET.mode %}?mode={{ request.GET.mode }}{% endif %}{% if request.GET.mode and request.GET.provider %}&provider={{ request.GET.provider }}{% elif request.GET.provider %}?provider={{ request.GET.provider }}{% endif %}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ episode.episode.identifier }}{% if request.GET.mode %}&mode={{ request.GET.mode }}{% endif %}{% if request.GET.mode and request.GET.provider %}&provider={{ request.GET.provider }}{% elif request.GET.provider %}?provider={{ request.GET.provider }}{% endif %}{% endif %}" class="flex flex-row justify-between w-full gap-4 {% if episode.number in watched_episodes %}bg-{{ user.preferences.accent_colour }}-600 bg-opacity-20{% else %}bg-white bg-opacity-10{% endif %} p-2 rounded hover:bg-{{ user.preferences.accent_colour }}-600 hover:bg-opacity-30"> <span class="truncate max-w-full overflow-hidden text-ellipsis whitespace-nowrap">{{ episode.number }}. {{ episode.title }}</span> <span class="flex flex-row item-center gap-2"> {% if episode.filler %} @@ -106,9 +106,22 @@ <div class="flex flex-row gap-2 items-center justify-between"> {% if current_episode %}<h2 class="text-xl font-bold truncate max-w-full overflow-hidden text-ellipsis whitespace-nowrap">Episode {{ current_episode.number }} — {{ current_episode.title }}</h2>{% endif %} <div class="flex flex-row gap-1 items-center"> + <span class="font-bold">Episode Provider: </span> + <a href="{% if not viaMal %} + {% url "watch:watch_episode" anime.id current_episode.number %}?mode={{ mode }}&provider=zoro + {% else %} + {% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode={{ mode }}&provider=zoro + {% endif %}" class="{% if provider == "zoro" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Zoro</a> + + <a href="{% if not viaMal %} + {% url "watch:watch_episode" anime.id current_episode.number %}?mode={{ mode }}&provider=gogo + {% else %} + {% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode={{ mode }}&provider=gogo + {% endif %}" class="{% if provider == "gogo" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Gogo</a> + <span class="ml-8 font-bold">Mode: </span> {% if current_episode.number %} - <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id current_episode.number %}?mode=sub{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode=sub{% endif %}" class="{% if mode == "sub" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Sub</a> - <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id current_episode.number %}?mode=dub{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode=dub{% endif %}" class="{% if mode == "dub" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Dub</a> + <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id current_episode.number %}?mode=sub&provider={{ provider }}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode=sub&provider={{ provider }}{% endif %}" class="{% if mode == "sub" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Sub</a> + <a href="{% if not viaMal %}{% url "watch:watch_episode" anime.id current_episode.number %}?mode=dub&provider={{ provider }}{% else %}{% url "watch:watch_via_zid_mal_id" anime.id anime.z_anime_id %}?ep={{ current_episode.episode.identifier }}&mode=dub&provider={{ provider }}{% endif %}" class="{% if mode == "dub" %}bg-{{ user.preferences.accent_colour }}-600{% else %}bg-white bg-opacity-10{% endif %} text-white text-sm font-bold px-4 py-2 rounded">Dub</a> {% endif %} </div> </div> @@ -1095,7 +1108,7 @@ }, 30000); {% endif %} - {% if anime.totalEpisodes > current_episode_number and animeId %} + {% if should_preload %} // If current episode is less than total episodes, preload the next episode const nextEpisode = {{ current_episode_number }} + 1; let nextEpisodeUrl = window.location.href.replace(`/watch/{{animeID}}/{{ current_episode_number }}`, `/watch/{{animeID}}/${nextEpisode}`); diff --git a/watch/utils.py b/watch/utils.py index 0a30329..339ef4e 100644 --- a/watch/utils.py +++ b/watch/utils.py @@ -16,8 +16,8 @@ r = redis.Redis( password=os.getenv("REDIS_PASSWORD"), ) -r.flushall() -print("Redis cache flushed") +# r.flushall() +# print("Redis cache flushed") def get_episode_metadata(anime_data, episode): episode_metadata = get_all_episode_metadata(anime_data) @@ -25,75 +25,131 @@ def get_episode_metadata(anime_data, episode): return current_episode_metadata @lru_cache(maxsize=100) -def get_anime_data(anime_id): - cache_key = f"anime_{anime_id}_anime_data" +def get_anime_data(anime_id, provider="zoro", gogodub=False): + cache_key = f"anime_{anime_id}_anime_data_{provider}" anime_data = get_from_redis_cache(cache_key) - provider = get_from_redis_cache(f"anime_{anime_id}_provider") - if not provider: - provider = "zoro" + if provider == "gogo": + provider = "gogoanime" + print("anime data got provider=>", provider) + if gogodub: + print("anime data got dub=>", gogodub) + cache_key = f"anime_{anime_id}_anime_data_{provider}_dub" if not anime_data: - base_url = f"{os.getenv('CONSUMET_URL')}/meta/anilist/info/{anime_id}?provider=zoro" - try: - response = requests.get(base_url, timeout=10) - anime_data = response.json() - if ("message" not in anime_data or response.status_code == 200) and anime_data["episodes"]: - if anime_data["status"] == "Completed": - store_in_redis_cache(cache_key, json.dumps(anime_data), 3600 * 24 * 30) # Cache for 30 days - else: - store_in_redis_cache(cache_key, json.dumps(anime_data), 3600 * 12) # Cache for 12 hours - store_in_redis_cache(f"anime_{anime_id}_provider", "zoro") + base_url = f"{os.getenv('CONSUMET_URL')}/meta/anilist/info/{anime_id}?provider={provider}" + if gogodub: + print("gogodub passed") + base_url += "&dub=true" + print("base_url=>", base_url) + response = requests.get(base_url, timeout=10) + anime_data = response.json() + + print(f"Fetched {len(anime_data["episodes"])} episodes for ID {anime_id} with provider {provider} and dub=>{gogodub}") + + if ("message" not in anime_data or response.status_code == 200) and anime_data["episodes"]: + if anime_data["status"] == "Completed": + store_in_redis_cache(cache_key, json.dumps(anime_data), 3600 * 24 * 30) else: - provider = "gogo" - base_url = f"{os.getenv('CONSUMET_URL')}/meta/anilist/info/{anime_id}" - response = requests.get(base_url, timeout=10) - anime_data = response.json() - store_in_redis_cache(cache_key, json.dumps(anime_data), 3600 * 12) # Cache for 12 hours - store_in_redis_cache(f"anime_{anime_id}_provider", "gogo") - except requests.RequestException as e: - print(f"Error fetching anime data for ID {anime_id}: {e}") - return None + store_in_redis_cache(cache_key, json.dumps(anime_data), 3600 * 12) + print(f"Anime data found for ID {anime_id} with provider {provider}, dub=>{gogodub}, episodes=>{len(anime_data['episodes'])}") + else: + provider = "gogo" + return get_anime_data(anime_id, provider, gogodub) else: anime_data = json.loads(anime_data) if not anime_data: print(f"Anime data not found for ID {anime_id}") - - return anime_data, provider + if provider == "gogoanime": + provider = "gogo" + + return anime_data, provider, gogodub @lru_cache(maxsize=100) -def get_anime_episodes(anime_id): - cache_key = f"anime_{anime_id}_anime_episodes" +def get_anime_episodes(anime_id): #only returns episodes from zoro + cache_key = f"anime_{anime_id}_anime_episodes_zoro" anime_episodes = get_from_redis_cache(cache_key) - + if not anime_episodes: - anime_data, provider = get_anime_data(anime_id) + anime_data, provider, gd = get_anime_data(anime_id, "zoro") if not anime_data or not anime_data.get("episodes"): return None - - if provider == "zoro": - if "mappings" in anime_data: - z_anime_id = next((m["id"] for m in anime_data["mappings"] if m["providerId"] == "zoro"), None) - z_anime_id = z_anime_id.split("/")[-1] if z_anime_id else None - else: - z_anime_id = anime_data["episodes"][0]["id"].split("$")[0] - - print(f"Fetching episodes for ID {anime_id} with Zoro ID {z_anime_id}") - - base_url = f"{os.getenv('ZORO_URL')}/anime/episodes/{z_anime_id}" - try: - response = requests.get(base_url, timeout=10) - anime_episodes = response.json() - store_in_redis_cache(cache_key, json.dumps(anime_episodes), 86400) # Cache for 24 hours - except requests.RequestException as e: - print(f"Error fetching anime episodes for ID {anime_id}: {e}") - return None - else: - return {"episodes": anime_data["episodes"], "totalEpisodes": len(anime_data["episodes"])} + + z_anime_id = anime_data["episodes"][0]["id"].split("$")[0] + + print(f"Fetching episodes for ID {anime_id} with Zoro ID {z_anime_id}") + + base_url = f"{os.getenv('CONSUMET_URL')}/meta/zoro/anime/episodes/{z_anime_id}" + try: + response = requests.get(base_url, timeout=10) + anime_episodes = response.json() + store_in_redis_cache(cache_key, json.dumps(anime_episodes), 86400) # Cache for 24 hours + except requests.RequestException as e: + print(f"Error fetching anime episodes for ID {anime_id}: {e}") + return None else: anime_episodes = json.loads(anime_episodes) - + return anime_episodes +@lru_cache(maxsize=100) +def get_anime_episodes_gogo(anime_id, mode="sub"): + cache_key = f"anime_{anime_id}_anime_episodes_gogo_{mode}" + anime_episodes = get_from_redis_cache(cache_key) + + if not anime_episodes: + gogodub = True if mode == "dub" else False + print(f"Fetching episodes for ID {anime_id} with mode {mode} and dub=>{gogodub}") + anime_data, provider, gd = get_anime_data(anime_id, "gogo", gogodub) + anime_episodes = anime_data["episodes"] + + store_in_redis_cache(cache_key, json.dumps(anime_episodes), 86400) + else: + anime_episodes = json.loads(anime_episodes) + + anime_episode_data = { + "episodes": anime_episodes, + "totalEpisodes": len(anime_episodes) + } + + print(f"Returning {len(anime_episodes)} episodes for ID {anime_id} with mode {mode}") + + return anime_episode_data, mode + + +# @lru_cache(maxsize=100) +# def get_anime_episodes(anime_id, provider="zoro"): +# cache_key = f"anime_{anime_id}_anime_episodes_{provider}" +# anime_episodes = get_from_redis_cache(cache_key) + +# if not anime_episodes: +# anime_data, provider = get_anime_data(anime_id, provider) +# if not anime_data or not anime_data.get("episodes"): +# return None + +# if provider == "zoro": +# if "mappings" in anime_data: +# z_anime_id = next((m["id"] for m in anime_data["mappings"] if m["providerId"] == "zoro"), None) +# z_anime_id = z_anime_id.split("/")[-1] if z_anime_id else None +# else: +# z_anime_id = anime_data["episodes"][0]["id"].split("$")[0] + +# print(f"Fetching episodes for ID {anime_id} with Zoro ID {z_anime_id}") + +# base_url = f"{os.getenv('ZORO_URL')}/anime/episodes/{z_anime_id}" +# try: +# response = requests.get(base_url, timeout=10) +# anime_episodes = response.json() +# store_in_redis_cache(cache_key, json.dumps(anime_episodes), 86400) # Cache for 24 hours +# except requests.RequestException as e: +# print(f"Error fetching anime episodes for ID {anime_id}: {e}") +# return None +# else: +# return {"episodes": anime_data["episodes"], "totalEpisodes": len(anime_data["episodes"])} +# else: +# anime_episodes = json.loads(anime_episodes) + +# return anime_episodes + def attach_episode_metadata(anime_data, anime_episodes): anime_episodes_metadata = get_all_episode_metadata(anime_data) if anime_episodes_metadata: diff --git a/watch/views.py b/watch/views.py index 1864df9..291fe8b 100644 --- a/watch/views.py +++ b/watch/views.py @@ -9,7 +9,7 @@ import requests from authentication.utils import get_single_anime_mal from user_profile.models import UserHistory from watch.tmdbmapper import parse_title_and_season -from watch.utils import attach_episode_metadata, get_anime_episodes, get_all_episode_metadata, get_anime_data, get_episodes_by_zid, get_from_redis_cache, get_info_by_zid, get_seasons_by_zid, store_in_redis_cache, update_anime_user_history, get_anime_user_history +from watch.utils import attach_episode_metadata, get_anime_episodes_gogo, get_all_episode_metadata, get_anime_data, get_episodes_by_zid, get_from_redis_cache, get_info_by_zid, get_seasons_by_zid, store_in_redis_cache, update_anime_user_history, get_anime_user_history from watch.models import Anime, AnimeEpisode, AnimeTitle, AnimeTrailer, AnimeGenre, AnimeStudio from django.db import transaction from authentication.models import User @@ -333,8 +333,10 @@ def watch(request, anime_id, episode=None): if not episode and request.user.preferences.default_watch_page == "detail" and not forward_detail: return redirect("detail:detail", anime_id=anime_id) - anime_fetched, provider = get_anime_data(anime_id) + anime_fetched, provider, gogodub = get_anime_data(anime_id) provider = provider.decode() if isinstance(provider, bytes) else provider + + provider = request.GET.get("provider", provider) if anime_fetched["status"] == "Not yet aired": return redirect("detail:detail", anime_id=anime_id) @@ -408,12 +410,14 @@ def watch(request, anime_id, episode=None): seasons = get_seasons_by_zid(anime.z_anime_id) stream_url = streaming_data["sources"][0]["url"] if streaming_data and "sources" in streaming_data else None else: - episodes = get_anime_episodes(anime_id) + episodes, m = get_anime_episodes_gogo(anime_id, mode) if episodes: attach_episode_metadata(anime_fetched, episodes) + if not gogodub and mode == "dub": + print("Dub not available, fallback to sub") + mode = "sub" episodes = episodes["episodes"] episode_data = next((e for e in episodes if e["number"] == int(episode)), None) - mode = "sub" seasons = [] streaming_data = get_gogo_streaming_data(episode_data["id"]) if episode_data else None streaming_data["anilistID"] = anime_id @@ -423,6 +427,8 @@ def watch(request, anime_id, episode=None): if preload_request: return JsonResponse({"status": f"Preloaded episode {episode}"}) + + should_preload = episode < len(episodes) context = { "anime": anime, @@ -440,6 +446,7 @@ def watch(request, anime_id, episode=None): "current_watched_time": current_watched_time, "seasons": seasons, "provider": provider, + "should_preload": should_preload, } if provider == "zoro" and request.user.mal_access_token and anime.malId: |
