aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2024-09-04 00:55:20 -0400
committerBobby <[email protected]>2024-09-04 00:55:20 -0400
commitb73b047452ba47141a96cf000333fc9a7211aa91 (patch)
treec1a306d9afb5f6ecf260f56d64280847588878db
parent763308caf9442b9b636a14ae0fb4b0659e2a0c8c (diff)
downloadyugen-b73b047452ba47141a96cf000333fc9a7211aa91.tar.xz
yugen-b73b047452ba47141a96cf000333fc9a7211aa91.zip
small fixes
-rw-r--r--detail/views.py5
-rw-r--r--static/css/main.css24
-rw-r--r--templates/user_profile/single_anime_update.html6
-rw-r--r--templates/watch/watch.html73
-rw-r--r--watch/models.py4
-rw-r--r--watch/views.py6
6 files changed, 105 insertions, 13 deletions
diff --git a/detail/views.py b/detail/views.py
index 4b247e6..a3495ad 100644
--- a/detail/views.py
+++ b/detail/views.py
@@ -33,7 +33,10 @@ def get_anime_data(anime_id):
response = requests.get(base_url, timeout=10)
response.raise_for_status()
anime_data = response.json()
- store_in_redis_cache(cache_key, json.dumps(anime_data), 86400) # Cache for 24 hours
+ 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
except requests.RequestException as e:
print(f"Error fetching anime data for ID {anime_id}: {e}")
return None
diff --git a/static/css/main.css b/static/css/main.css
index 08cbce2..d85407a 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -858,6 +858,10 @@ video {
height: 100%;
}
+.h-64 {
+ height: 16rem;
+}
+
.max-h-24 {
max-height: 6rem;
}
@@ -935,10 +939,18 @@ video {
width: max-content;
}
+.w-52 {
+ width: 13rem;
+}
+
.min-w-32 {
min-width: 8rem;
}
+.min-w-56 {
+ min-width: 14rem;
+}
+
.max-w-4xl {
max-width: 56rem;
}
@@ -968,6 +980,10 @@ video {
max-width: max-content;
}
+.max-w-56 {
+ max-width: 14rem;
+}
+
.flex-1 {
flex: 1 1 0%;
}
@@ -1110,6 +1126,10 @@ video {
overflow: hidden;
}
+.overflow-scroll {
+ overflow: scroll;
+}
+
.overflow-x-auto {
overflow-x: auto;
}
@@ -1118,6 +1138,10 @@ video {
overflow-y: auto;
}
+.overflow-y-scroll {
+ overflow-y: scroll;
+}
+
.truncate {
overflow: hidden;
text-overflow: ellipsis;
diff --git a/templates/user_profile/single_anime_update.html b/templates/user_profile/single_anime_update.html
index 3f055c7..eaba0d6 100644
--- a/templates/user_profile/single_anime_update.html
+++ b/templates/user_profile/single_anime_update.html
@@ -169,7 +169,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="status_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="status_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600 capitalize" data-value="watching">watching</div>
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600 capitalize" data-value="completed">completed</div>
@@ -195,7 +195,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="score_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="score_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="10">10</div>
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="9">9</div>
@@ -227,7 +227,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="episodes_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="episodes_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="Episodes">0</div>
{% for i in mal_episode_range %}
diff --git a/templates/watch/watch.html b/templates/watch/watch.html
index b11cb42..04e4f13 100644
--- a/templates/watch/watch.html
+++ b/templates/watch/watch.html
@@ -109,14 +109,73 @@
<p class="my-4">
{{ current_episode.description }}
</p>
+ {% if nextAiringEpisode %}
+ <p id="nextAiringEpisodeMessage"></p>
+ <script>
+ const nextAiringEpisode = {
+ airingTime: {{ nextAiringEpisode.airingTime }},
+ timeUntilAiring: {{ nextAiringEpisode.timeUntilAiring }},
+ episode: {{ nextAiringEpisode.episode }}
+ };
+
+ function formatNextEpisode(nextAiringEpisode) {
+ const airingTime = nextAiringEpisode.airingTime * 1000; // Convert to milliseconds
+ const episodeNumber = nextAiringEpisode.episode;
+
+ function updateCountdown() {
+ const now = new Date().getTime();
+ const timeUntilAiring = airingTime - now;
+
+ if (timeUntilAiring <= 0) {
+ return `Episode ${episodeNumber} has aired.`;
+ }
+
+ const days = Math.floor(timeUntilAiring / (1000 * 60 * 60 * 24));
+ const hours = Math.floor((timeUntilAiring % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
+ const minutes = Math.floor((timeUntilAiring % (1000 * 60 * 60)) / (1000 * 60));
+ const seconds = Math.floor((timeUntilAiring % (1000 * 60)) / 1000);
+
+ const airingDate = new Date(airingTime);
+ const formattedDate = airingDate.toLocaleDateString('en-US', {
+ weekday: 'short',
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ });
+ const formattedTime = airingDate.toLocaleTimeString('en-US', {
+ hour: 'numeric',
+ minute: '2-digit',
+ second: '2-digit',
+ hour12: true
+ });
+
+ return `Episode <strong>${episodeNumber}</strong> will air on ${formattedDate} at ${formattedTime} ` +
+ `<strong class="text-{{ user.preferences.accent_colour }}-600">(${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds)</strong>`;
+ }
+
+ const countdownElement = document.getElementById('nextAiringEpisodeMessage');
+ countdownElement.innerHTML = updateCountdown();
+
+ // Update countdown every second
+ setInterval(() => {
+ countdownElement.innerHTML = updateCountdown();
+ }, 1000);
+ }
+
+ // Call the function when the page loads
+ document.addEventListener('DOMContentLoaded', function() {
+ formatNextEpisode(nextAiringEpisode);
+ });
+ </script>
+ {% endif %}
<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.image }}" alt="{{ anime.title.english }}" class="rounded-lg w-48 h-72 object-cover"/>
- <div class="flex flex-row gap-2">
- <a href="https://anilist.co/anime/{{ anime.id }}" target="_blank" class="text-xs font-bold bg-white bg-opacity-10 rounded px-2 py-1">
+ <img src="{{ anime.image }}" alt="{{ anime.title.english }}" class="rounded-lg w-56 h-72 object-cover"/>
+ <div class="flex flex-row gap-2 w-full">
+ <a href="https://anilist.co/anime/{{ anime.id }}" target="_blank" class="text-xs font-bold bg-{{ user.preferences.accent_colour }}-400 bg-opacity-30 flex-1 justify-center flex hover:bg-opacity-50 rounded px-2 py-1">
<svg stroke="currentColor" fill="currentColor" stroke-width="0" role="img" viewBox="0 0 24 24" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg"><path d="M24 17.53v2.421c0 .71-.391 1.101-1.1 1.101h-5l-.057-.165L11.84 3.736c.106-.502.46-.788 1.053-.788h2.422c.71 0 1.1.391 1.1 1.1v12.38H22.9c.71 0 1.1.392 1.1 1.101zM11.034 2.947l6.337 18.104h-4.918l-1.052-3.131H6.019l-1.077 3.131H0L6.361 2.948h4.673zm-.66 10.96-1.69-5.014-1.541 5.015h3.23z"></path></svg>
</a>
- <a href="https://myanimelist.net/anime/{{ anime.malId }}" target="_blank" class="ext-xs font-bold bg-white bg-opacity-10 rounded px-2 py-1">
+ <a href="https://myanimelist.net/anime/{{ anime.malId }}" target="_blank" class="ext-xs font-bold bg-{{ user.preferences.accent_colour }}-400 bg-opacity-30 flex-1 justify-center flex hover:bg-opacity-50 rounded px-2 py-1">
<svg stroke="currentColor" fill="currentColor" stroke-width="0" role="img" viewBox="0 0 24 24" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg"><path d="M8.273 7.247v8.423l-2.103-.003v-5.216l-2.03 2.404-1.989-2.458-.02 5.285H.001L0 7.247h2.203l1.865 2.545 2.015-2.546 2.19.001zm8.628 2.069l.025 6.335h-2.365l-.008-2.871h-2.8c.07.499.21 1.266.417 1.779.155.381.298.751.583 1.128l-1.705 1.125c-.349-.636-.622-1.337-.878-2.082a9.296 9.296 0 0 1-.507-2.179c-.085-.75-.097-1.471.107-2.212a3.908 3.908 0 0 1 1.161-1.866c.313-.293.749-.5 1.1-.687.351-.187.743-.264 1.107-.359a7.405 7.405 0 0 1 1.191-.183c.398-.034 1.107-.066 2.39-.028l.545 1.749H14.51c-.593.008-.878.001-1.341.209a2.236 2.236 0 0 0-1.278 1.92l2.663.033.038-1.81h2.309zm3.992-2.099v6.627l3.107.032-.43 1.775h-4.807V7.187l2.13.03z"></path></svg>
</a>
</div>
@@ -309,7 +368,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="status_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="status_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600 capitalize" data-value="watching">watching</div>
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600 capitalize" data-value="completed">completed</div>
@@ -335,7 +394,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="score_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="score_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="10">10</div>
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="9">9</div>
@@ -367,7 +426,7 @@
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/>
</svg>
</div>
- <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden" id="episodes_options">
+ <div class="absolute z-10 w-full mt-1 bg-neutral-900 rounded shadow-lg hidden max-h-96 overflow-y-scroll no-scrollbar" id="episodes_options">
<div class="py-1">
<div class="cursor-pointer px-4 py-2 text-white hover:bg-{{ user.preferences.accent_colour }}-600" data-value="Episodes">0</div>
{% for i in mal_episode_range %}
diff --git a/watch/models.py b/watch/models.py
index c35b3bb..edde8e5 100644
--- a/watch/models.py
+++ b/watch/models.py
@@ -66,8 +66,8 @@ class Anime(models.Model):
return self.title.english if self.title.english else self.title.romaji
def needs_update(self):
- # Always update if the anime is ongoing and last updated was more than 1 day ago
- if self.status == "Ongoing" and (timezone.now() - self.last_updated) > datetime.timedelta(days=1):
+ # Always update if the anime is ongoing and last updated was more than 12 hours ago
+ if self.status == "Ongoing" and (timezone.now() - self.last_updated) > datetime.timedelta(hours=12):
return True
if self.status == "Not yet aired":
diff --git a/watch/views.py b/watch/views.py
index 0839721..a8a5232 100644
--- a/watch/views.py
+++ b/watch/views.py
@@ -253,6 +253,9 @@ def watch(request, anime_id, episode=None):
return redirect("detail:detail", anime_id=anime_id)
anime_fetched = get_anime_by_id(anime_id)
+ if anime_fetched["status"] == "Not yet aired":
+ return redirect("detail:detail", anime_id=anime_id)
+
try:
anime = Anime.objects.get(id=anime_id)
if anime.needs_update():
@@ -313,6 +316,9 @@ def watch(request, anime_id, episode=None):
"mal_episode_range": range(1, mal_data["num_episodes"] + 1) if mal_data else None,
}
+ if "nextAiringEpisode" in anime_fetched:
+ context["nextAiringEpisode"] = anime_fetched["nextAiringEpisode"]
+
return render(request, "watch/watch.html", context)
def update_episode_watch_time(request):