From 8ec01acc4c4a07e61968019d99ab9edd5a400e1d Mon Sep 17 00:00:00 2001 From: ayxan Date: Fri, 16 Dec 2022 11:27:51 +0400 Subject: [PATCH] Added 'imdb_api_access' app removed 'new_episodes' page changed series_count algorithm --- src/account/models.py | 2 +- src/account/views/profile_editing.py | 24 ++-- src/account/views/register.py | 24 ++-- src/imdb_api_access/_requests.py | 2 +- src/imdb_api_access/exceptions.py | 2 +- src/imdb_api_access/new_series_model.py | 6 +- src/imdb_api_access/series_counter.py | 66 ++++++----- src/series/models.py | 16 ++- src/series/tasks.py | 111 ++++++++---------- src/series/templates/homepage.html | 20 +++- src/series/templates/new_episodes.html | 51 -------- .../templates/new_episodes_notification.html | 36 ++++++ .../templates/new_episodes_verification.html | 9 -- ...html => series_deletion_confirmation.html} | 0 src/series/views/add_series.py | 75 +++++++----- src/series/views/delete_series.py | 2 +- src/series/views/homepage.py | 10 +- src/series/views/new_episodes.py | 44 +++++-- src/series/views/update_series.py | 72 +++++++----- src/templates/components/footer.html | 2 +- 20 files changed, 318 insertions(+), 256 deletions(-) delete mode 100644 src/series/templates/new_episodes.html create mode 100644 src/series/templates/new_episodes_notification.html delete mode 100644 src/series/templates/new_episodes_verification.html rename src/series/templates/{article_deletion_confirmation.html => series_deletion_confirmation.html} (100%) diff --git a/src/account/models.py b/src/account/models.py index b8cee53..dacec53 100644 --- a/src/account/models.py +++ b/src/account/models.py @@ -6,7 +6,7 @@ class User(AbstractUser): first_name = None last_name = None email = models.EmailField('email', null=True, blank=True, unique=True) - imdb_api_key = models.CharField(max_length=15, blank=False, null=False) + imdb_api_key = models.CharField(max_length=15, blank=False, null=False, unique=True) email_is_verified = models.BooleanField(default=False) send_email = models.BooleanField(default=False) diff --git a/src/account/views/profile_editing.py b/src/account/views/profile_editing.py index 0ce34f9..430e53e 100644 --- a/src/account/views/profile_editing.py +++ b/src/account/views/profile_editing.py @@ -3,7 +3,8 @@ from django.shortcuts import (render, from django.contrib.auth.decorators import login_required from django.contrib import messages from account.forms import ProfileEditingForm -from requests import get +from imdb_api_access._requests import get_request +from imdb_api_access.exceptions import * from .send_otp import send_otp_view @@ -13,22 +14,19 @@ def profile_editing_view(request): form = ProfileEditingForm(request.POST, instance=request.user) if form.is_valid(): if 'imdb_api_key' in form.changed_data: - raw_data = get(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413") - - if raw_data.status_code != 200: + try: + get_request(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413") + except StatusCodeError: messages.info(request, 'Account not created. Please try again later') return redirect('profile-editing') - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(request, f"IMDB API: {data['errorMessage']}") - return redirect('profile-editing') - - elif data['errorMessage'] == 'Invalid API Key': + except MaximumUsageError as e: + messages.info(request, str(e)) + return redirect('profile-editing') + except APIError as e: + if e.message == 'Invalid API Key': form.add_error('imdb_api_key', 'Invalid API Key') return render(request, 'profile_editing.html', context={"form": form}) - messages.info(request, f"IMDB API: {data['errorMessage']}") + messages.info(request, str(e)) return redirect('profile-editing') if 'email' in form.changed_data: diff --git a/src/account/views/register.py b/src/account/views/register.py index b877ec6..92b85c8 100644 --- a/src/account/views/register.py +++ b/src/account/views/register.py @@ -4,7 +4,8 @@ from django.contrib import messages from account.forms import RegisterForm from django.contrib.auth import (login, authenticate) -from requests import get +from imdb_api_access._requests import get_request +from imdb_api_access.exceptions import * from django.shortcuts import render from .send_otp import send_otp_view @@ -13,22 +14,19 @@ def register_view(request): # sourcery skip: extract-method if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid(): - raw_data = get(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413") - - if raw_data.status_code != 200: + try: + get_request(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413") + except StatusCodeError: messages.info(request, 'Account not created. Please try again later') return redirect('register') - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(request, f"IMDB API: {data['errorMessage']}") - return redirect('register') - - elif data['errorMessage'] == 'Invalid API Key': + except MaximumUsageError as e: + messages.info(request, str(e)) + return redirect('register') + except APIError as e: + if e.message == 'Invalid API Key': form.add_error('imdb_api_key', 'Invalid API Key') return render(request, 'register.html', context={"form": form}) - messages.info(request, f"IMDB API: {data['errorMessage']}") + messages.info(request, str(e)) return redirect('register') to_email = form.cleaned_data.get('email') diff --git a/src/imdb_api_access/_requests.py b/src/imdb_api_access/_requests.py index e06f593..995581e 100644 --- a/src/imdb_api_access/_requests.py +++ b/src/imdb_api_access/_requests.py @@ -13,6 +13,6 @@ def get_request(url: str) -> Union[StatusCodeError, APIError, MaximumUsageError, if data['errorMessage']: if 'Maximum usage' in data['errorMessage']: - raise MaximumUsageError() + raise MaximumUsageError(data['errorMessage']) raise APIError(data['errorMessage']) return data \ No newline at end of file diff --git a/src/imdb_api_access/exceptions.py b/src/imdb_api_access/exceptions.py index 16704b7..2a2e80a 100644 --- a/src/imdb_api_access/exceptions.py +++ b/src/imdb_api_access/exceptions.py @@ -20,4 +20,4 @@ class MaximumUsageError(Exception): self.message = message def __str__(self) -> str: - return self.message \ No newline at end of file + return f"IMDB API: {self.message}" \ No newline at end of file diff --git a/src/imdb_api_access/new_series_model.py b/src/imdb_api_access/new_series_model.py index 2ce725c..97e3cf0 100644 --- a/src/imdb_api_access/new_series_model.py +++ b/src/imdb_api_access/new_series_model.py @@ -6,6 +6,6 @@ from typing import Optional @dataclass class NewSeries: series: SeriesModel - new_episodes_count: Optional[int] = None - last_season: Optional[int] = None - last_episode: Optional[int] = None \ No newline at end of file + new_episodes_count: int + last_season: int + last_episode: int \ No newline at end of file diff --git a/src/imdb_api_access/series_counter.py b/src/imdb_api_access/series_counter.py index 1e92ceb..9d4e569 100644 --- a/src/imdb_api_access/series_counter.py +++ b/src/imdb_api_access/series_counter.py @@ -4,7 +4,6 @@ from .exceptions import * from .new_series_model import NewSeries from series.models import SeriesModel from typing import (List, - Tuple, Dict, Union) @@ -15,49 +14,60 @@ class SeriesCounter: self.new_series_list: List[NewSeries] = [] self.error_series: List[SeriesModel] = [] - def get_episode_count(self, series: SeriesModel, data: Dict) -> Union[StatusCodeError, APIError, MaximumUsageError, Tuple]: + def get_episode_count(self, series: SeriesModel, data_seasons: Dict) -> Union[StatusCodeError, + APIError, + MaximumUsageError, + Dict]: # sourcery skip: aware-datetime-for-utc now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y') - new_episodes_count = 0 + data_return = { + 'new_episodes_count': 0, + 'last_season': series.watched_season, + 'last_episode': series.watched_episode + } + seasons = data_seasons['tvSeriesInfo']['seasons'] - for n in data['tvSeriesInfo']['seasons'][data['tvSeriesInfo']['seasons'].index(str(series.last_season)):]: - data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{self.api_key}/{series.imdb_id}/{n}") + for season_number in seasons[seasons.index(str(series.watched_season)):]: + data_episodes = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/k_ae700oad/{series.imdb_id}/{season_number}") + episodes = data_episodes['episodes'] + + for episode_number in range(int(series.watched_episode) if season_number == str(series.watched_season) else 0, len(episodes)): + released_date = episodes[episode_number]['released'].replace('.', '') - episodes = data['episodes'] - for i in range(int(series.last_episode) if n == str(series.last_season) else 0, len(episodes)): - released_date = episodes[i]['released'].replace('.', '') try: episode_date = datetime.strptime(released_date, '%d %b %Y') if (episode_date - now_date).days > 0: raise ValueError - except ValueError: - try: - return new_episodes_count, int(last_n)+1, last_i+1 if new_episodes_count > 0 else 0, 0, 0 - except UnboundLocalError: - return new_episodes_count, int(n), last_i+1 if new_episodes_count > 0 else 0, 0, 0 - last_i = i - new_episodes_count += 1 - last_n = n + data_return['last_season'] = int(season_number) + data_return['last_episode'] = episode_number+1 + data_return['new_episodes_count'] += 1 - return new_episodes_count, n, i+1 if new_episodes_count > 0 else 0, 0, 0 + except ValueError: return data_return + return data_return - def find_new_series(self, series: List[NewSeries]) -> Union[MaximumUsageError, None]: + def find_new_series(self, series: List[SeriesModel]) -> Union[MaximumUsageError, None]: for s in series: try: data = get_request(f"https://imdb-api.com/en/API/Title/{self.api_key}/{s.imdb_id}") - except (StatusCodeError, APIError): self.error_series.append(s) else: - data = self.get_episode_count(s, data) - if data[0]: - self.new_series_list.append( - NewSeries( - series=s, - new_episodes_count=data[0], - last_season=data[1], - last_episode=data[2] + try: + data = self.get_episode_count(s, data) + if data['new_episodes_count'] != s.new_episodes_count: + self.new_series_list.append( + NewSeries(series=s, **data) ) - ) \ No newline at end of file + except (StatusCodeError, APIError): + self.error_series.append(s) + + def find_last_episode(self, series: SeriesModel) -> Union[MaximumUsageError, + StatusCodeError, + APIError, + NewSeries]: + + data = get_request(f"https://imdb-api.com/en/API/Title/{self.api_key}/{series.imdb_id}") + data = self.get_episode_count(series, data) + return NewSeries(series=series, **data) \ No newline at end of file diff --git a/src/series/models.py b/src/series/models.py index 6f9c87e..b7fdc89 100644 --- a/src/series/models.py +++ b/src/series/models.py @@ -10,14 +10,26 @@ class SeriesModel(models.Model): title = models.CharField(max_length=35, blank=False, null=False) imdb_id = models.CharField(max_length=10, validators=[MinLengthValidator(9)], blank=False, null=False) - last_season = models.IntegerField(validators=[ + watched_season = models.IntegerField(validators=[ MaxValueValidator(30), MinValueValidator(1) ], blank=False, null=False) - last_episode = models.IntegerField(validators=[ + watched_episode = models.IntegerField(validators=[ MaxValueValidator(60), MinValueValidator(1) ], blank=False, null=False) + last_season = models.IntegerField(validators=[ + MaxValueValidator(30), + MinValueValidator(1)], + default=1) + last_episode = models.IntegerField(validators=[ + MaxValueValidator(60), + MinValueValidator(1)], + default=1) + new_episodes_count = models.IntegerField(validators=[ + MaxValueValidator(200), + MinValueValidator(0)], + default=0) show = models.BooleanField(default=True) slug = AutoSlugField(populate_from='title', unique=True) diff --git a/src/series/tasks.py b/src/series/tasks.py index f022224..6309bb8 100644 --- a/src/series/tasks.py +++ b/src/series/tasks.py @@ -5,78 +5,61 @@ from datetime import datetime from django.template.loader import render_to_string from django.core.mail import EmailMessage from celery.utils.log import get_task_logger +from imdb_api_access import SeriesCounter +from imdb_api_access import MaximumUsageError -logger = get_task_logger(__name__) +# logger = get_task_logger(__name__) -def get_request(link): - raw_data = get(link) - if raw_data.status_code == 200: - data = raw_data.json() - if not data['errorMessage']: - return data - logger.info(f"error message: {data['errorMessage']}\nlink: {link}") - return None - logger.info(f"status code: {raw_data.status_code}\nlink: {link}") +def update_series(updated_series): + updated_series.series.last_season = updated_series.last_season + updated_series.series.last_episode = updated_series.last_episode + updated_series.series.new_episodes_count = updated_series.new_episodes_count -def episode_counter(imdb_api_key, s, data): - now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y') - new_episodes_count = 0 +def send_email(user): + series = user.series.filter(show=True).order_by('-id') - for n in data['tvSeriesInfo']['seasons'][data['tvSeriesInfo']['seasons'].index(str(s.last_season)):]: - data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{imdb_api_key}/{s.imdb_id}/{n}") - if data is None: return None - - episodes = data['episodes'] - for i in range(int(s.last_episode) if n == str(s.last_season) else 0, len(episodes)): - released_date = episodes[i]['released'].replace('.', '') - try: - episode_date = datetime.strptime(released_date, '%d %b %Y') - if (episode_date - now_date).days > 0: - raise ValueError - except ValueError: - try: - return new_episodes_count, int(last_n)+1, last_i+1 if new_episodes_count > 0 else 0, 0, 0 - except UnboundLocalError: - return new_episodes_count, int(n), last_i+1 if new_episodes_count > 0 else 0, 0, 0 - last_i = i - new_episodes_count += 1 - last_n = n - - return new_episodes_count, n, i+1 if new_episodes_count > 0 else 0, 0, 0 - -@shared_task(name='send_emails') -def send_feedback_email_task(): - users = User.objects.filter(send_email=True) - for user in users: - series = user.series.filter(show=True).order_by('-id') - series_new_episodes = [] - - for s in series: - data = get_request(f"https://imdb-api.com/en/API/Title/{user.imdb_api_key}/{s.imdb_id}") - - if data is None: - series_new_episodes = [] - break - data = episode_counter(user.imdb_api_key, s, data) - if data is None: - series_new_episodes = [] - break - - if data[0]: - series_new_episodes.append([s, - {'count': data[0], - 'last_season': data[1], - 'last_episode': data[2]} - ]) - - if series_new_episodes: - message = render_to_string('new_episodes_verification.html', { + series_counter = SeriesCounter(user.imdb_api_key) + try: + series_counter.find_new_series(series) + series_len = len(series_counter.new_series_list) + except MaximumUsageError as e: + if series_len := len(series_counter.new_series_list): + for updated_series in series_counter.new_series_list: + update_series(updated_series) + updated_series.save() + message = render_to_string('new_episodes_notification.html', { 'user': user, - 'data': series_new_episodes + 'new_series_list': series_counter.new_series_list, + 'error_series_list': series_counter.error_series, + 'maximum_usage': str(e) }) email = EmailMessage( 'New Episodes!', message, to=[user.email] ) - email.send() \ No newline at end of file + email.send() + return + return + + if series_len: + for updated_series in series_counter.new_series_list: + update_series(updated_series) + updated_series.series.save() + + message = render_to_string('new_episodes_notification.html', { + 'user': user, + 'new_series_list': series_counter.new_series_list, + 'error_series_list': series_counter.error_series, + 'maximum_usage': '' + }) + email = EmailMessage( + 'New Episodes!', message, to=[user.email] + ) + email.send() + return + +@shared_task(name='send_emails') +def send_feedback_email_task(): + users = User.objects.filter(send_email=True) + for user in users: send_email(user) \ No newline at end of file diff --git a/src/series/templates/homepage.html b/src/series/templates/homepage.html index f94c678..806eaef 100644 --- a/src/series/templates/homepage.html +++ b/src/series/templates/homepage.html @@ -12,7 +12,9 @@ Title ({{series.paginator.count}}) - Season - Episode + Watched + Last + Unwatched Show @@ -31,11 +33,19 @@ + + + {{s.watched_season}} - {{s.watched_episode}} + + {{s.last_season}} - {{s.last_episode}} + + {{s.new_episodes_count}} + {% if s.show %} @@ -51,7 +61,13 @@
+
+
diff --git a/src/series/templates/new_episodes.html b/src/series/templates/new_episodes.html deleted file mode 100644 index 67600a7..0000000 --- a/src/series/templates/new_episodes.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends 'base.html' %} -{% load static %} - -{% block title %} New Episodes of The Series {% endblock title %} - -{% block content %} - - -
- - - - - - - - - - - {% for d in data %} - - - - - - - {% endfor %} - -
TitleWatched Season - EpisodeLast Season - EpisodeNumber of New Episodes
- - {{d.series.title}} - -
- - - - - - -
- - {{d.series.last_season}} - {{d.series.last_episode}} - - - - {{d.last_season}} - {{d.last_episode}} - - {{d.new_episodes_count}}
-
- -{% endblock content %} \ No newline at end of file diff --git a/src/series/templates/new_episodes_notification.html b/src/series/templates/new_episodes_notification.html new file mode 100644 index 0000000..aea0f8c --- /dev/null +++ b/src/series/templates/new_episodes_notification.html @@ -0,0 +1,36 @@ +{% autoescape off %} + +Hi {{ user.username }}, +There are new episodes of the series you recorded. + +{% if maximum_usage %} +Some series could not be updated ({{maximum_usage}}) + +{% for s in new_series_list %} +{{s.series.title}}: watched - {{s.series.watched_season}}-{{s.series.watched_episode}} + last - {{s.last_season}}-{{s.last_episode}} + new episodes count - {{s.new_episodes_count}} +{% endfor %} + +{% else %} + {% if error_series_list %} +Some series could not be updated: + {% for e in error_series_list %} +e.title + {% endfor %} + + {% for s in new_series_list %} +{{s.series.title}}: watched - {{s.series.watched_season}}-{{s.series.watched_episode}} + last - {{s.last_season}}-{{s.last_episode}} + new episodes count - {{s.new_episodes_count}} + {% endfor %} + {% else %} + {% for s in new_series_list %} +{{s.series.title}}: watched - {{s.series.watched_season}}-{{s.series.watched_episode}} + last - {{s.last_season}}-{{s.last_episode}} + new episodes count - {{s.new_episodes_count}} + {% endfor %} + {% endif %} +{% endif %} + +{% endautoescape %} \ No newline at end of file diff --git a/src/series/templates/new_episodes_verification.html b/src/series/templates/new_episodes_verification.html deleted file mode 100644 index d2ea670..0000000 --- a/src/series/templates/new_episodes_verification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% autoescape off %} - -Hi {{ user.username }}, -There are new episodes of the series you recorded. -{% for s, d in data %} -{{d.count}} episodes of {{s.title}} you haven't watched (watched episode: {{s.last_season}} - {{s.last_episode}}). -{% endfor %} - -{% endautoescape %} \ No newline at end of file diff --git a/src/series/templates/article_deletion_confirmation.html b/src/series/templates/series_deletion_confirmation.html similarity index 100% rename from src/series/templates/article_deletion_confirmation.html rename to src/series/templates/series_deletion_confirmation.html diff --git a/src/series/views/add_series.py b/src/series/views/add_series.py index b7ef9c5..65f585e 100644 --- a/src/series/views/add_series.py +++ b/src/series/views/add_series.py @@ -4,15 +4,17 @@ from django.urls import reverse_lazy, reverse from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages from django.shortcuts import redirect -from requests import get from datetime import datetime +from imdb_api_access import SeriesCounter +from imdb_api_access._requests import get_request +from imdb_api_access.exceptions import * class AddSeriesView(LoginRequiredMixin, CreateView): login_url = reverse_lazy('login') template_name = 'add_series.html' model = SeriesModel - fields = ('title', 'imdb_id', 'last_season', 'last_episode', 'show') + fields = ('title', 'imdb_id', 'watched_season', 'watched_episode', 'show') def get_success_url(self): messages.success(self.request, 'Series Added') @@ -22,58 +24,73 @@ class AddSeriesView(LoginRequiredMixin, CreateView): series = form.save(commit=False) series.user = self.request.user - raw_data = get(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}") - - if raw_data.status_code != 200: + try: + data = get_request(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}") + except StatusCodeError: messages.info(self.request, 'TV Series can not added. Please try again.') return redirect('add-series') - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(self.request, f"IMDB API: {data['errorMessage']}") - return redirect('add-series') + except MaximumUsageError: + messages.info(self.request, f"IMDB API: {data['errorMessage']}") + return redirect('add-series') + except APIError: form.add_error('imdb_id', 'ID is not correct.') return self.form_invalid(form) if not data['tvSeriesInfo']: form.add_error('imdb_id', 'This is not a TV series id.') return self.form_invalid(form) + seasons = data['tvSeriesInfo']['seasons'] - if str(series.last_season) not in seasons: - form.add_error('last_season', 'The season number is not correct.') + if str(series.watched_season) not in seasons: + form.add_error('watched_season', 'The season number is not correct.') return self.form_invalid(form) - raw_data = get(f"https://imdb-api.com/en/API/SeasonEpisodes/{series.user.imdb_api_key}/{series.imdb_id}/{series.last_season}") - if raw_data.status_code != 200: + try: + data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{series.user.imdb_api_key}/{series.imdb_id}/{series.watched_season}") + except StatusCodeError: messages.info(self.request, 'TV Series can not added. Please try again.') return redirect('add-series') - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(self.request, f"IMDB API: {data['errorMessage']}") - return redirect('add-series') + except MaximumUsageError: + messages.info(self.request, f"IMDB API: {data['errorMessage']}") + return redirect('add-series') + except APIError: form.add_error('imdb_id', 'ID is not correct.') return self.form_invalid(form) - episodes = data['episodes'] + episodes = data['episodes'] episodes_count = len(episodes) - if series.last_episode > episodes_count: - form.add_error('last_episode', 'The episode number is not correct.') + + if series.watched_episode > episodes_count: + form.add_error('watched_episode', 'The episode number is not correct.') return self.form_invalid(form) - released_date = episodes[int(series.last_episode) - 1]['released'].replace('.', '') + released_date = episodes[int(series.watched_episode) - 1]['released'].replace('.', '') now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y') + try: - last_episode_date = datetime.strptime(released_date, '%d %b %Y') - if (last_episode_date - now_date).days > 0: + watched_episode_date = datetime.strptime(released_date, '%d %b %Y') + if (watched_episode_date - now_date).days > 0: raise ValueError except ValueError: - form.add_error('last_episode', 'This episode has not been published yet.') + form.add_error('watched_episode', 'This episode has not been published yet.') return self.form_invalid(form) + series_counter = SeriesCounter(self.request.user.imdb_api_key) + try: + new_series = series_counter.find_last_episode(series) + series.last_season = new_series.last_season + series.last_episode = new_series.last_episode + series.new_episodes_count = new_series.new_episodes_count + + except (StatusCodeError, APIError): + messages.info(self.request, 'TV Series can not added. Please try again later.') + return redirect('add-series') + + except MaximumUsageError as e: + messages.info(self.request, str(e)) + return redirect('homepage') + series.save() form.save_m2m() - return super().form_valid(form) + return super().form_valid(form) \ No newline at end of file diff --git a/src/series/views/delete_series.py b/src/series/views/delete_series.py index f5f69c6..1714c4b 100644 --- a/src/series/views/delete_series.py +++ b/src/series/views/delete_series.py @@ -7,7 +7,7 @@ from django.contrib import messages class SeriesDeleteView(LoginRequiredMixin, DeleteView): login_url = reverse_lazy('login') - template_name = 'article_deletion_confirmation.html' + template_name = 'series_deletion_confirmation.html' def get_success_url(self): messages.success(self.request, 'Series Deleted') diff --git a/src/series/views/homepage.py b/src/series/views/homepage.py index d3056cd..1d171e7 100644 --- a/src/series/views/homepage.py +++ b/src/series/views/homepage.py @@ -2,13 +2,19 @@ from django.shortcuts import render from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from account.models import User +from django.db.models import Q @login_required(login_url='/account/login') def homepage_view(request): user = User.objects.get(id=request.user.id) - series_true = user.series.filter(show=True).order_by('-id') - series_false = user.series.filter(show=False).order_by('-id') + if request.GET.get('new') == 'true': + series_true = user.series.filter(~Q(new_episodes_count=0), show=True).order_by('-id') + series_false = user.series.filter(~Q(new_episodes_count=0), show=False).order_by('-id') + else: + series_true = user.series.filter(show=True).order_by('-id') + series_false = user.series.filter(show=False).order_by('-id') + page = request.GET.get('page') paginator = Paginator(list(series_true) + list(series_false), 5) diff --git a/src/series/views/new_episodes.py b/src/series/views/new_episodes.py index d6274fa..8d8d548 100644 --- a/src/series/views/new_episodes.py +++ b/src/series/views/new_episodes.py @@ -1,5 +1,4 @@ -from django.shortcuts import (render, - redirect) +from django.shortcuts import redirect from django.contrib.auth.decorators import login_required from django.contrib import messages from account.models import User @@ -14,10 +13,41 @@ def new_episodes_view(request): series_counter = SeriesCounter(request.user.imdb_api_key) try: series_counter.find_new_series(series) - except MaximumUsageError as e: ... - # messages.warning(request, f"{e} (some series could not be updated)") + series_len = len(series_counter.new_series_list) + error_series_len = len(series_counter.error_series) + except MaximumUsageError as e: + if series_len := len(series_counter.new_series_list): + for updated_series in series_counter.new_series_list: + updated_series.series.last_season = updated_series.last_season + updated_series.series.last_episode = updated_series.last_episode + updated_series.series.new_episodes_count = updated_series.new_episodes_count + updated_series.save() + messages.warning(request, + f"{series_len} series updated (some series could not be updated). {str(e)}") + return redirect('homepage') - if series_counter.new_series_list: - return render(request, 'new_episodes.html', context={'data': series_counter.new_series_list}) - messages.warning(request, "There are no new episodes of any series :(") + messages.warning(request, + f"Series could not be updated. {str(e)}") + return redirect('homepage') + + if series_len: + for updated_series in series_counter.new_series_list: + updated_series.series.last_season = updated_series.last_season + updated_series.series.last_episode = updated_series.last_episode + updated_series.series.new_episodes_count = updated_series.new_episodes_count + updated_series.series.save() + if error_series_len: + messages.warning(request, + f"{series_len} series updated ({error_series_len} series could not be updated).") + return redirect('homepage') + messages.warning(request, + f"{series_len} series updated.") + return redirect('homepage') + + if error_series_len: + messages.warning(request, + f"{error_series_len} series could not be updated.") + return redirect('homepage') + + messages.warning(request, "0 series updated :(") return redirect('homepage') \ No newline at end of file diff --git a/src/series/views/update_series.py b/src/series/views/update_series.py index 54f8545..f06bc52 100644 --- a/src/series/views/update_series.py +++ b/src/series/views/update_series.py @@ -5,14 +5,16 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages from django.shortcuts import (get_object_or_404, redirect) -from requests import get from datetime import datetime +from imdb_api_access._requests import get_request +from imdb_api_access import SeriesCounter +from imdb_api_access.exceptions import * class UpdateSeriesView(LoginRequiredMixin, UpdateView): login_url = reverse_lazy('login') template_name = 'update_series.html' - fields = ('title', 'imdb_id', 'last_season', 'last_episode', 'show') + fields = ('title', 'imdb_id', 'watched_season', 'watched_episode', 'show') def get_object(self): return get_object_or_404(SeriesModel, slug=self.kwargs.get('slug'), user=self.request.user) @@ -25,22 +27,20 @@ class UpdateSeriesView(LoginRequiredMixin, UpdateView): series = form.save(commit=False) series.user = self.request.user - if not {'imdb_id', 'last_season', 'last_episode'} & set(form.changed_data): + if not {'imdb_id', 'watched_season', 'watched_episode'} & set(form.changed_data): series.save() form.save_m2m() return super().form_valid(form) - raw_data = get(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}") - - if raw_data.status_code != 200: - messages.info(self.request, 'TV Series can not updated. Please try again.') + try: + data = get_request(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}") + except StatusCodeError: + messages.info(self.request, 'TV Series can not added. Please try again.') return redirect('update-series', self.kwargs.get('slug')) - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(self.request, f"IMDB Key: {data['errorMessage']}") - return redirect("update-series", self.kwargs.get('slug')) + except MaximumUsageError: + messages.info(self.request, f"IMDB API: {data['errorMessage']}") + return redirect('update-series', self.kwargs.get('slug')) + except APIError: form.add_error('imdb_id', 'ID is not correct.') return self.form_invalid(form) @@ -49,39 +49,55 @@ class UpdateSeriesView(LoginRequiredMixin, UpdateView): return self.form_invalid(form) seasons = data['tvSeriesInfo']['seasons'] - if str(series.last_season) not in seasons: - form.add_error('last_season', 'The season number is not correct.') + if str(series.watched_season) not in seasons: + form.add_error('watched_season', 'The season number is not correct.') return self.form_invalid(form) - raw_data = get(f"https://imdb-api.com/en/API/SeasonEpisodes/{series.user.imdb_api_key}/{series.imdb_id}/{series.last_season}") - if raw_data.status_code != 200: + try: + data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{series.user.imdb_api_key}/{series.imdb_id}/{series.watched_season}") + except StatusCodeError: messages.info(self.request, 'TV Series can not added. Please try again.') return redirect('update-series', self.kwargs.get('slug')) - data = raw_data.json() - - if data['errorMessage']: - if 'Maximum usage' in data['errorMessage']: - messages.info(self.request, f"IMDB API: {data['errorMessage']}") - return redirect('update-series', self.kwargs.get('slug')) + except MaximumUsageError: + messages.info(self.request, f"IMDB API: {data['errorMessage']}") + return redirect('update-series', self.kwargs.get('slug')) + except APIError: form.add_error('imdb_id', 'ID is not correct.') return self.form_invalid(form) - episodes = data['episodes'] + episodes = data['episodes'] episodes_count = len(episodes) - if series.last_episode > episodes_count: - form.add_error('last_episode', 'The episode number is not correct.') + + if series.watched_episode > episodes_count: + form.add_error('watched_episode', 'The episode number is not correct.') return self.form_invalid(form) - released_date = episodes[int(series.last_episode) - 1]['released'].replace('.', '') + released_date = episodes[int(series.watched_episode) - 1]['released'].replace('.', '') now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y') + try: last_episode_date = datetime.strptime(released_date, '%d %b %Y') if (last_episode_date - now_date).days > 0: raise ValueError except ValueError: - form.add_error('last_episode', 'This episode has not been published yet.') + form.add_error('watched_episode', 'This episode has not been published yet.') return self.form_invalid(form) + series_counter = SeriesCounter(self.request.user.imdb_api_key) + try: + new_series = series_counter.find_last_episode(series) + series.last_season = new_series.last_season + series.last_episode = new_series.last_episode + series.new_episodes_count = new_series.new_episodes_count + + except (StatusCodeError, APIError): + messages.info(self.request, 'TV Series can not updated. Please try again later.') + return redirect('update-series', self.kwargs.get('slug')) + + except MaximumUsageError as e: + messages.info(self.request, str(e)) + return redirect('homepage') + series.save() form.save_m2m() return super().form_valid(form) \ No newline at end of file diff --git a/src/templates/components/footer.html b/src/templates/components/footer.html index 38f55a1..a415155 100644 --- a/src/templates/components/footer.html +++ b/src/templates/components/footer.html @@ -14,7 +14,7 @@ - +