aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2024-09-01 21:09:06 -0400
committerBobby <[email protected]>2024-09-01 21:09:06 -0400
commit562d0172688fc81c2134a31692c0da4b2b2e9501 (patch)
tree736266a24770d0d80d3b166ec3a7a24443bb3f77
parentaff11dfbab143a177ba320b93359e862d5217a88 (diff)
downloadyugen-562d0172688fc81c2134a31692c0da4b2b2e9501.tar.xz
yugen-562d0172688fc81c2134a31692c0da4b2b2e9501.zip
episode metadata
-rw-r--r--static/css/main.css127
-rw-r--r--templates/watch/watch.html7
-rw-r--r--watch/tmdbmapper.py424
-rw-r--r--watch/views.py38
4 files changed, 480 insertions, 116 deletions
diff --git a/static/css/main.css b/static/css/main.css
index c6ee6a9..a0ea458 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -673,16 +673,12 @@ video {
z-index: 10;
}
-.z-50 {
- z-index: 50;
-}
-
.z-20 {
z-index: 20;
}
-.z-30 {
- z-index: 30;
+.z-50 {
+ z-index: 50;
}
.-mx-4 {
@@ -705,11 +701,6 @@ video {
margin-bottom: 2rem;
}
-.-mx-2 {
- margin-left: -0.5rem;
- margin-right: -0.5rem;
-}
-
.mb-2 {
margin-bottom: 0.5rem;
}
@@ -750,14 +741,6 @@ video {
margin-top: 2rem;
}
-.mt-\[0\.35rem\] {
- margin-top: 0.35rem;
-}
-
-.ml-1 {
- margin-left: 0.25rem;
-}
-
.block {
display: block;
}
@@ -802,9 +785,8 @@ video {
height: 1.5rem;
}
-.size-5 {
- width: 1.25rem;
- height: 1.25rem;
+.h-16 {
+ height: 4rem;
}
.h-24 {
@@ -847,18 +829,10 @@ video {
height: 100%;
}
-.h-16 {
- height: 4rem;
-}
-
.max-h-24 {
max-height: 6rem;
}
-.max-h-screen {
- max-height: 100vh;
-}
-
.max-h-96 {
max-height: 24rem;
}
@@ -871,6 +845,10 @@ video {
width: 2.5rem;
}
+.w-12 {
+ width: 3rem;
+}
+
.w-16 {
width: 4rem;
}
@@ -887,6 +865,10 @@ video {
width: 1rem;
}
+.w-48 {
+ width: 12rem;
+}
+
.w-5 {
width: 1.25rem;
}
@@ -916,32 +898,20 @@ video {
width: max-content;
}
-.w-48 {
- width: 12rem;
-}
-
-.w-12 {
- width: 3rem;
-}
-
.min-w-32 {
min-width: 8rem;
}
-.min-w-96 {
- min-width: 24rem;
-}
-
-.min-w-80 {
- min-width: 20rem;
+.max-w-7xl {
+ max-width: 80rem;
}
-.min-w-72 {
- min-width: 18rem;
+.max-w-\[calc\(100\%-10rem\)\] {
+ max-width: calc(100% - 10rem);
}
-.max-w-7xl {
- max-width: 80rem;
+.max-w-\[calc\(100\%-4rem\)\] {
+ max-width: calc(100% - 4rem);
}
.max-w-\[calc\(100\%-6rem\)\] {
@@ -957,23 +927,6 @@ video {
max-width: max-content;
}
-.max-w-\[calc\(100\%-10rem\)\] {
- max-width: calc(100% - 10rem);
-}
-
-.max-w-fit {
- max-width: -moz-fit-content;
- max-width: fit-content;
-}
-
-.max-w-\[calc\(100\%-4rem\)\] {
- max-width: calc(100% - 4rem);
-}
-
-.max-w-0\.5 {
- max-width: 0.125rem;
-}
-
.flex-1 {
flex: 1 1 0%;
}
@@ -1078,10 +1031,6 @@ video {
justify-content: space-around;
}
-.justify-evenly {
- justify-content: space-evenly;
-}
-
.gap-1 {
gap: 0.25rem;
}
@@ -1098,10 +1047,6 @@ video {
gap: 2rem;
}
-.gap-11 {
- gap: 2.75rem;
-}
-
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
@@ -2301,18 +2246,6 @@ main {
height: 1rem;
}
- .sm\:flex-wrap {
- flex-wrap: wrap;
- }
-
- .sm\:place-content-center {
- place-content: center;
- }
-
- .sm\:items-center {
- align-items: center;
- }
-
.sm\:gap-2 {
gap: 0.5rem;
}
@@ -2360,18 +2293,10 @@ main {
height: 4rem;
}
- .lg\:h-\[42vw\] {
- height: 42vw;
- }
-
.lg\:h-\[39vw\] {
height: 39vw;
}
- .lg\:max-h-\[806px\] {
- max-height: 806px;
- }
-
.lg\:max-h-\[761px\] {
max-height: 761px;
}
@@ -2396,10 +2321,6 @@ main {
width: 15rem;
}
- .lg\:w-1\/3 {
- width: 33.333333%;
- }
-
.lg\:flex-row {
flex-direction: row;
}
@@ -2420,18 +2341,6 @@ main {
justify-content: flex-end;
}
- .lg\:justify-between {
- justify-content: space-between;
- }
-
- .lg\:justify-around {
- justify-content: space-around;
- }
-
- .lg\:justify-evenly {
- justify-content: space-evenly;
- }
-
.lg\:bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
diff --git a/templates/watch/watch.html b/templates/watch/watch.html
index 910f0e6..8b9a688 100644
--- a/templates/watch/watch.html
+++ b/templates/watch/watch.html
@@ -106,6 +106,9 @@
<a href="{% url "watch:watch_episode" anime_id current_episode_data.number %}?mode=dub" 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>
</div>
</div>
+ <p class="my-4">
+ {{ current_episode_metadata.description }}
+ </p>
<div class="flex flex-col lg:flex-row w-full my-4 bg-neutral-950 rounded p-2 gap-4">
<div class="flex flex-col items-center lg:items-start gap-2 min-w-32">
<img src="{{ anime_data.image }}" alt="{{ anime_data.title.english }}" class="rounded-lg w-48 h-72 object-cover"/>
@@ -569,7 +572,8 @@
<span>Recommendations</span>
</div>
<div class="flex flex-col gap-2">
- {% for recommendation in anime_data.recommendations %}
+ {% for recommendation in anime_data.recommendations|slice:":10" %}
+ {% if recommendation.id %}
<a href="{% url 'watch:watch' recommendation.id %}" class="flex flex-row w-full gap-4 bg-white bg-opacity-10 p-2 rounded hover:bg-{{ user.preferences.accent_colour }}-600 hover:bg-opacity-30">
<img src="{{ recommendation.image }}" alt="{{ recommendation.title.english }}" class="rounded-lg w-12 h-16 object-cover"/>
<div class="flex flex-col gap-2 max-w-[calc(100%-4rem)]">
@@ -632,6 +636,7 @@
{% endif %}
</div>
</a>
+ {% endif %}
{% endfor %}
</div>
{% endif %}
diff --git a/watch/tmdbmapper.py b/watch/tmdbmapper.py
new file mode 100644
index 0000000..0f23c2e
--- /dev/null
+++ b/watch/tmdbmapper.py
@@ -0,0 +1,424 @@
+import os
+import re
+import requests
+from dotenv import load_dotenv
+from datetime import datetime
+
+load_dotenv()
+
+API_KEY = os.getenv("TMDB_API_KEY")
+API_READ_ACCESS_TOKEN = os.getenv("TMDB_READ_ACCESS_TOKEN")
+BASE_URL = "https://api.themoviedb.org/3"
+IMAGE_URL = "https://image.tmdb.org/t/p/original"
+
+def get_headers():
+ return {
+ "Authorization": f"Bearer {API_READ_ACCESS_TOKEN}",
+ "accept": "application/json"
+ }
+
+def compare_two_strings(str1, str2):
+ str1 = re.sub(r'\s+', '', str1)
+ str2 = re.sub(r'\s+', '', str2)
+ if str1 == str2:
+ return 1
+ if len(str1) < 2 or len(str2) < 2:
+ return 0
+ bigrams = {}
+ for i in range(len(str1) - 1):
+ bigram = str1[i:i+2]
+ bigrams[bigram] = bigrams.get(bigram, 0) + 1
+
+ intersections = 0
+ for i in range(len(str2) - 1):
+ bigram = str2[i:i+2]
+ if bigram in bigrams and bigrams[bigram] > 0:
+ bigrams[bigram] -= 1
+ intersections += 1
+
+ return 2.0 * intersections / (len(str1) + len(str2) - 2)
+
+def roman_to_decimal(roman):
+ values = {
+ 'I': 1, 'V': 5, 'X': 10, 'L': 50,
+ 'C': 100, 'D': 500, 'M': 1000
+ }
+ total = 0
+ prev_value = 0
+ for char in reversed(roman.upper()):
+ current_value = values[char]
+ if current_value >= prev_value:
+ total += current_value
+ else:
+ total -= current_value
+ prev_value = current_value
+ return total
+
+def parse_title_and_season(title):
+ media_types = ["TV", "TV_SHORT", "OVA", "ONA", "MOVIE", "SPECIAL", "MUSIC"]
+ pattern = re.compile(r'\s*(' + '|'.join(media_types) + r')\s*$', re.IGNORECASE)
+ title = pattern.sub('', title).strip()
+
+ match = re.search(r'(.*?)(Season \d+|Cour \d+|Part \d+|Series \d+|Level \d+|(\bI{1,3}\b|\bIV\b|\bV\b|\bVI\b|\bVII\b|\bVIII\b|\bIX\b|\bX\b)( Part \d+)?|\bI{1,3}\b|\bIV\b|\bV\b|\bVI\b|\bVII\b|\bVIII\b|\bIX\b|\bX\b)$', title, re.IGNORECASE)
+
+ if not match:
+ return {"show_name": title, "season_info": ""}
+
+ show_name = match.group(1).strip()
+ season_info = match.group(2).strip()
+
+ roman_match = re.search(r'(\bI{1,3}\b|\bIV\b|\bV\b|\bVI\b|\bVII\b|\bVIII\b|\bIX\b|\bX\b)', season_info, re.IGNORECASE)
+ if roman_match:
+ season_info = f"Season {roman_to_decimal(roman_match.group(1))}"
+
+ return {"show_name": show_name, "season_info": season_info}
+
+def search_tv_shows_by_title(title, alternative_title=None, is_adult=None, country_priority=None, max_year=None):
+ try:
+ query = title.split(':')[0].strip()
+ if ' ' not in query and alternative_title:
+ query += f" {alternative_title}"
+
+ response = requests.get(f"{BASE_URL}/search/tv", headers=get_headers(), params={"query": query})
+ results = response.json().get('results', [])
+
+ if not results:
+ response = requests.get(f"{BASE_URL}/search/tv", headers=get_headers(), params={"query": title})
+ results = response.json().get('results', [])
+
+ if not results:
+ pattern = re.compile(r'\s*\([A-Z_]+\)\s*$', re.IGNORECASE)
+ if pattern.search(title):
+ clean_title = pattern.sub('', title).strip()
+ response = requests.get(f"{BASE_URL}/search/tv", headers=get_headers(), params={"query": clean_title})
+ results = response.json().get('results', [])
+
+ if results:
+ if is_adult is not None:
+ results = [r for r in results if r.get('adult', False) == is_adult]
+
+ if country_priority:
+ results.sort(key=lambda x: int(country_priority in x.get('origin_country', [])), reverse=True)
+
+ if max_year:
+ try:
+ max_year = int(max_year)
+ results = [r for r in results if r.get('first_air_date') and int(r['first_air_date'].split('-')[0]) <= max_year]
+ except ValueError:
+ # If max_year is not a valid integer, we'll skip this filter
+ pass
+
+ return results
+ except Exception as e:
+ print(f"Error in search_tv_shows_by_title: {str(e)}")
+ return []
+
+def get_tv_show_details(show_id):
+ try:
+ response = requests.get(f"{BASE_URL}/tv/{show_id}", headers=get_headers())
+ data = response.json()
+ return {"show": data, "seasons": data.get("seasons", [])}
+ except Exception as e:
+ print(f"Error in get_tv_show_details: {str(e)}")
+ return None
+
+def get_image_url(path):
+ return f"https://image.tmdb.org/t/p/original{path}" if path else None
+
+def get_tv_season_details(show_id, season_number):
+ try:
+ response = requests.get(f"{BASE_URL}/tv/{show_id}/season/{season_number}", headers=get_headers())
+ episodes = response.json().get('episodes', [])
+
+ if not episodes:
+ return []
+
+ return [
+ {
+ "id": f"{show_id}-S{season_number}E{ep['episode_number']}",
+ "lastVisited": None,
+ "episodeId": str(ep['id']),
+ "title": ep['name'],
+ "description": ep['overview'] or "No Description.",
+ "number": ep['episode_number'],
+ "image": get_image_url(ep.get('still_path')),
+ "airDate": ep.get('air_date'),
+ "isFiller": False
+ }
+ for ep in episodes
+ ]
+ except Exception as e:
+ print(f"Error in get_tv_season_details: {str(e)}")
+ return None
+
+def get_tv_episode_groups(show_id):
+ try:
+ response = requests.get(f"{BASE_URL}/tv/{show_id}/episode_groups", headers=get_headers())
+ return response.json().get('results', [])
+ except Exception as e:
+ print(f"Error in get_tv_episode_groups: {str(e)}")
+ return []
+
+def get_tv_episode_group_details(group_id):
+ try:
+ response = requests.get(f"{BASE_URL}/tv/episode_group/{group_id}", headers=get_headers())
+ data = response.json()
+
+ if not data or 'groups' not in data:
+ return []
+
+ return [
+ {
+ "id": f"{group_id}-E{ep['episode_number']}",
+ "lastVisited": None,
+ "episodeId": str(ep['id']),
+ "title": ep['name'],
+ "description": ep['overview'],
+ "number": ep['episode_number'],
+ "image": get_image_url(ep.get('still_path')),
+ "airDate": ep.get('air_date'),
+ "isFiller": False
+ }
+ for group in data['groups']
+ for ep in group.get('episodes', [])
+ ]
+ except Exception as e:
+ print(f"Error in get_tv_episode_group_details: {str(e)}")
+ return []
+
+def filter_episodes_by_year(episodes, episode_count=None, start_date=None, start_year=None, duration=None, media_type=None):
+ start_date = datetime.strptime(start_date, "%Y-%m-%d") if start_date else None
+ start_year = int(start_year) if start_year else None
+
+ filtered_episodes = [
+ ep for ep in episodes
+ if ep['airDate'] and (
+ (not start_date or datetime.strptime(ep['airDate'], "%Y-%m-%d") >= start_date) and
+ (not start_year or int(ep['airDate'].split('-')[0]) >= start_year)
+ )
+ ]
+
+ if media_type in ['OVA', 'ONA', 'SPECIAL']:
+ excluded_keywords = ['chibi', 'live', 'event', 'recap', 'summary']
+ filtered_episodes = [
+ ep for ep in filtered_episodes
+ if not any(keyword in ep['title'].lower() for keyword in excluded_keywords) and
+ (not ep.get('runtime') or ep['runtime'] >= 20)
+ ]
+
+ filtered_episodes.sort(key=lambda ep: (
+ abs((datetime.strptime(ep['airDate'], "%Y-%m-%d") - start_date).total_seconds()) if start_date else 0,
+ abs(int(ep['airDate'].split('-')[0]) - start_year) if start_year else 0,
+ abs((ep.get('runtime') or 0) - (duration or 0))
+ ))
+
+ return filtered_episodes[:episode_count] if episode_count else filtered_episodes
+
+def search_movies_by_title(title, alternative_title=None, year=None):
+ try:
+ if alternative_title:
+ response = requests.get(f"{BASE_URL}/search/movie", headers=get_headers(), params={"query": alternative_title, "year": year})
+ results = response.json().get('results', [])
+ if len(results) == 1 and compare_two_strings((results[0].get('original_title') or '').lower(), alternative_title.lower()) >= 0.9:
+ return results
+
+ response = requests.get(f"{BASE_URL}/search/movie", headers=get_headers(), params={"query": title, "year": year})
+ results = response.json().get('results', [])
+
+ if not results:
+ pattern = re.compile(r'\s*\([A-Z_]+\)\s*$', re.IGNORECASE)
+ if pattern.search(title):
+ clean_title = pattern.sub('', title).strip()
+ response = requests.get(f"{BASE_URL}/search/movie", headers=get_headers(), params={"query": clean_title, "year": year})
+ results = response.json().get('results', [])
+
+ return results
+ except Exception as e:
+ print(f"Error in search_movies_by_title: {str(e)}")
+ return None
+
+def get_movie_details(movie_id):
+ try:
+ response = requests.get(f"{BASE_URL}/movie/{movie_id}", headers=get_headers())
+ movie = response.json()
+
+ return {
+ "id": str(movie['id']),
+ "lastVisited": None,
+ "episodeId": str(movie['id']),
+ "title": movie['title'],
+ "description": movie['overview'],
+ "number": 1,
+ "image": get_image_url(movie.get('poster_path')),
+ "airDate": movie.get('release_date'),
+ "isFiller": False
+ }
+ except Exception as e:
+ print(f"Error in get_movie_details: {str(e)}")
+ return None
+
+def fetch_and_filter_episodes(show_id, season, start_date, year, episode_count, media_type):
+ episodes = get_tv_season_details(show_id, season['season_number'])
+ return filter_episodes_by_year(episodes, episode_count or season['episode_count'], start_date, year, None, media_type) if episodes else []
+
+def find_best_matching_season(seasons, season_info, episode_count, year, date):
+ matching_seasons = [
+ s for s in seasons
+ if (season_info and f"Season {s['season_number']}".lower() == season_info.lower()) or
+ (s['episode_count'] == episode_count and
+ (not s.get('air_date') or
+ (s.get('air_date') and str(s['air_date']).startswith(str(year or '')))))
+ ]
+
+ if len(matching_seasons) > 1 and date:
+ matching_seasons = [
+ s for s in matching_seasons
+ if s.get('air_date') and datetime.strptime(s['air_date'], "%Y-%m-%d").month == date.month
+ ]
+
+ if len(matching_seasons) > 1 and date:
+ matching_seasons = [
+ s for s in matching_seasons
+ if s.get('air_date') and datetime.strptime(s['air_date'], "%Y-%m-%d").day == date.day
+ ]
+
+ return matching_seasons[0] if matching_seasons else None
+
+def search_and_fetch_all_episodes(title, media_type, alternative_title, year, episode_count, date, is_adult, country_priority, duration):
+ parsed_title = parse_title_and_season(title)
+ show_name, season_info = parsed_title['show_name'], parsed_title['season_info']
+
+ if media_type == "MOVIE":
+ movies = search_movies_by_title(title, alternative_title, year)
+ if movies and len(movies) > 0:
+ movie = max(movies, key=lambda m: m['popularity'])
+ movie_details = get_movie_details(movie['id'])
+ return [movie_details] if movie_details else []
+ return []
+
+ start_date = f"{year}-{date.month:02d}-{date.day:02d}" if date else None
+ tv_shows = search_tv_shows_by_title(show_name, alternative_title, is_adult, country_priority, year)
+
+ if not tv_shows:
+ print(f"No TV shows found for title: {show_name}")
+ return []
+
+ best_match = next(
+ (show for show in tv_shows if (
+ show['name'].lower() == show_name.lower() or
+ show.get('original_name', '').lower() == show_name.lower()
+ ) and (not year or show['first_air_date'].startswith(str(year)))),
+ tv_shows[0]
+ )
+
+ show_details = get_tv_show_details(best_match['id'])
+ if not show_details:
+ return []
+
+ seasons = show_details['seasons']
+ if media_type == "TV":
+ seasons = [s for s in seasons if s['season_number'] != 0]
+
+ best_season = find_best_matching_season(seasons, season_info, episode_count, year, date)
+
+ if best_season:
+ return fetch_and_filter_episodes(best_match['id'], best_season, start_date, year, episode_count, media_type)
+ else:
+ print(f"No matching season found for {show_name}")
+ # You might want to implement a fallback strategy here, such as:
+ # 1. Try to fetch episodes from the latest season
+ # 2. Generate placeholder episodes
+ # 3. Or simply return an empty list
+ # return [] <- removed this early return to avoid breaking the code
+
+ if media_type in ["OVA", "ONA", "SPECIAL"]:
+ episode_groups = get_tv_episode_groups(best_match['id'])
+ if episode_groups and len(episode_groups) > 0:
+ absolute_order_group = next((g for g in episode_groups if "absolute order" in g['name'].lower()), None)
+ if absolute_order_group:
+ episodes = get_tv_episode_group_details(absolute_order_group['id'])
+ filtered_episodes = filter_episodes_by_year(episodes, episode_count, start_date, year, duration, media_type)
+ if filtered_episodes:
+ return filtered_episodes
+
+ special_season = next((s for s in seasons if s['season_number'] == 0), None)
+ if special_season:
+ episodes = fetch_and_filter_episodes(best_match['id'], special_season, start_date, year, episode_count, media_type)
+ if episodes:
+ return episodes
+
+ if season_info:
+ matching_season = next((s for s in seasons if f"Season {s['season_number']}".lower() == season_info.lower()), None)
+ if matching_season:
+ return fetch_and_filter_episodes(best_match['id'], matching_season, start_date, year, episode_count, media_type)
+
+ episode_groups = get_tv_episode_groups(best_match['id'])
+ if episode_groups and len(episode_groups) > 0:
+ all_episodes_group = next(
+ (g for g in episode_groups if any(keyword in g['name'].lower() for keyword in
+ ['all episodes', 'absolute order', 'absolute', 'correct order', 'bluray order'])),
+ None
+ )
+ if all_episodes_group:
+ episodes = get_tv_episode_group_details(all_episodes_group['id'])
+ return filter_episodes_by_year(episodes, episode_count, start_date, year, duration, media_type)
+
+ best_match = max(tv_shows, key=lambda show: compare_two_strings(show_name.lower(), (show['name'] or '').lower()))
+ show_details = get_tv_show_details(best_match['id'])
+ if show_details:
+ seasons = show_details['seasons']
+ if media_type == "TV":
+ seasons = [s for s in seasons if s['season_number'] != 0]
+
+ best_season = next(
+ (s for s in seasons if s['episode_count'] == episode_count and
+ (s['air_date'] and s['air_date'].startswith(str(year)))),
+ None
+ )
+
+ if not best_season:
+ possible_seasons = [s for s in seasons if s['episode_count'] > episode_count and
+ (s['air_date'] and int(s['air_date'].split('-')[0]) <= int(year))]
+ if possible_seasons:
+ best_season = min(
+ possible_seasons,
+ key=lambda s: (
+ abs(int(s['air_date'].split('-')[0]) - int(year)),
+ abs(s['episode_count'] - episode_count)
+ )
+ )
+
+ if best_season:
+ return fetch_and_filter_episodes(best_match['id'], best_season, start_date, year, episode_count, media_type)
+
+ return []
+
+# Usage example
+def get_anime_episodes(anime_data):
+ title = anime_data['title']['english'] or anime_data['title']['romaji']
+ alternative_title = anime_data['title']['native']
+ media_type = anime_data['type']
+ year = anime_data['startDate']['year']
+ episode_count = anime_data['totalEpisodes']
+ date = datetime(
+ year=anime_data['startDate']['year'],
+ month=anime_data['startDate']['month'],
+ day=anime_data['startDate']['day']
+ )
+ is_adult = anime_data.get('isAdult', False)
+ country_priority = anime_data['countryOfOrigin']
+ duration = anime_data['duration']
+
+ episodes = search_and_fetch_all_episodes(
+ title=title,
+ media_type=media_type,
+ alternative_title=alternative_title,
+ year=year,
+ episode_count=episode_count,
+ date=date,
+ is_adult=is_adult,
+ country_priority=country_priority,
+ duration=duration
+ )
+
+ return episodes
diff --git a/watch/views.py b/watch/views.py
index 9eadb30..9ed390d 100644
--- a/watch/views.py
+++ b/watch/views.py
@@ -6,6 +6,7 @@ from authentication.utils import get_single_anime_mal
from watch.utils import update_anime_user_history, get_anime_user_history, get_from_redis_cache, store_in_redis_cache
import requests
import json
+from watch.tmdbmapper import get_anime_episodes
dotenv.load_dotenv()
@@ -27,13 +28,29 @@ def watch(request, anime_id, episode=None):
anime_selected_cached = get_from_redis_cache(f"anime_{anime_id}_anime_selected")
anime_episodes_cached = get_from_redis_cache(f"anime_{anime_id}_anime_episodes")
+ if anime_data_cached:
+ try:
+ anime_data = json.loads(anime_data_cached)
+ except:
+ anime_data = None
+
+ if anime_selected_cached:
+ try:
+ anime_selected = json.loads(anime_selected_cached)
+ except:
+ anime_selected = None
+
+ if anime_episodes_cached:
+ try:
+ anime_episodes = json.loads(anime_episodes_cached)
+ except:
+ anime_episodes = None
+
if not anime_data_cached:
base_url = f"{os.getenv("CONSUMET_URL")}/meta/anilist/info/{anime_id}?provider=zoro"
response = requests.get(base_url)
anime_data = response.json()
store_in_redis_cache(f"anime_{anime_id}_anime_data", json.dumps(anime_data))
- else:
- anime_data = json.loads(anime_data_cached)
if not anime_selected_cached:
z_anime_id = anime_data["episodes"][0]["id"].split("$")[0]
@@ -41,16 +58,12 @@ def watch(request, anime_id, episode=None):
response = requests.get(base_url)
anime_selected = response.json()
store_in_redis_cache(f"anime_{anime_id}_anime_selected", json.dumps(anime_selected))
- else:
- anime_selected = json.loads(anime_selected_cached)
if not anime_episodes_cached:
base_url = f"{os.getenv("ZORO_URL")}/anime/episodes/{anime_selected["anime"]["info"]["id"]}"
response = requests.get(base_url)
anime_episodes = response.json()
store_in_redis_cache(f"anime_{anime_id}_anime_episodes", json.dumps(anime_episodes))
- else:
- anime_episodes = json.loads(anime_episodes_cached)
if not anime_selected["anime"]["info"]["stats"]["episodes"][mode] or anime_selected["anime"]["info"]["stats"]["episodes"][mode] < episode:
mode = "sub"
@@ -83,6 +96,18 @@ def watch(request, anime_id, episode=None):
current_episode_data = [e for e in anime_episodes["episodes"] if e["number"] == episode][0]
+ episode_metadata = get_from_redis_cache(f"anime_{anime_id}_episode_metadata")
+ try:
+ episode_metadata = json.loads(episode_metadata)
+ except:
+ episode_metadata = None
+
+ if not episode_metadata:
+ episode_metadata = get_anime_episodes(anime_data)
+ store_in_redis_cache(f"anime_{anime_id}_episode_metadata", json.dumps(episode_metadata))
+
+ current_episode_metadata = episode_metadata[episode - 1] if episode_metadata else None
+
context = {
"anime_data": anime_data,
"anime_selected": anime_selected,
@@ -96,6 +121,7 @@ def watch(request, anime_id, episode=None):
"anime_history": anime_history,
"watched_episodes": watched_episodes,
"current_watched_time": current_watched_time,
+ "current_episode_metadata": current_episode_metadata,
"mode": mode,
}