mirror of
https://github.com/aykhans/series-robot-web.git
synced 2025-04-21 22:28:57 +00:00
Added 'imdb_api_access' app
removed 'new_episodes' page changed series_count algorithm
This commit is contained in:
parent
939f8ad578
commit
8ec01acc4c
@ -6,7 +6,7 @@ class User(AbstractUser):
|
|||||||
first_name = None
|
first_name = None
|
||||||
last_name = None
|
last_name = None
|
||||||
email = models.EmailField('email', null=True, blank=True, unique=True)
|
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)
|
email_is_verified = models.BooleanField(default=False)
|
||||||
send_email = models.BooleanField(default=False)
|
send_email = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ from django.shortcuts import (render,
|
|||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from account.forms import ProfileEditingForm
|
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
|
from .send_otp import send_otp_view
|
||||||
|
|
||||||
|
|
||||||
@ -13,22 +14,19 @@ def profile_editing_view(request):
|
|||||||
form = ProfileEditingForm(request.POST, instance=request.user)
|
form = ProfileEditingForm(request.POST, instance=request.user)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
if 'imdb_api_key' in form.changed_data:
|
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")
|
try:
|
||||||
|
get_request(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413")
|
||||||
if raw_data.status_code != 200:
|
except StatusCodeError:
|
||||||
messages.info(request, 'Account not created. Please try again later')
|
messages.info(request, 'Account not created. Please try again later')
|
||||||
return redirect('profile-editing')
|
return redirect('profile-editing')
|
||||||
data = raw_data.json()
|
except MaximumUsageError as e:
|
||||||
|
messages.info(request, str(e))
|
||||||
if data['errorMessage']:
|
return redirect('profile-editing')
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError as e:
|
||||||
messages.info(request, f"IMDB API: {data['errorMessage']}")
|
if e.message == 'Invalid API Key':
|
||||||
return redirect('profile-editing')
|
|
||||||
|
|
||||||
elif data['errorMessage'] == 'Invalid API Key':
|
|
||||||
form.add_error('imdb_api_key', 'Invalid API Key')
|
form.add_error('imdb_api_key', 'Invalid API Key')
|
||||||
return render(request, 'profile_editing.html', context={"form": form})
|
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')
|
return redirect('profile-editing')
|
||||||
|
|
||||||
if 'email' in form.changed_data:
|
if 'email' in form.changed_data:
|
||||||
|
@ -4,7 +4,8 @@ from django.contrib import messages
|
|||||||
from account.forms import RegisterForm
|
from account.forms import RegisterForm
|
||||||
from django.contrib.auth import (login,
|
from django.contrib.auth import (login,
|
||||||
authenticate)
|
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 django.shortcuts import render
|
||||||
from .send_otp import send_otp_view
|
from .send_otp import send_otp_view
|
||||||
|
|
||||||
@ -13,22 +14,19 @@ def register_view(request): # sourcery skip: extract-method
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = RegisterForm(request.POST)
|
form = RegisterForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
raw_data = get(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413")
|
try:
|
||||||
|
get_request(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413")
|
||||||
if raw_data.status_code != 200:
|
except StatusCodeError:
|
||||||
messages.info(request, 'Account not created. Please try again later')
|
messages.info(request, 'Account not created. Please try again later')
|
||||||
return redirect('register')
|
return redirect('register')
|
||||||
data = raw_data.json()
|
except MaximumUsageError as e:
|
||||||
|
messages.info(request, str(e))
|
||||||
if data['errorMessage']:
|
return redirect('register')
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError as e:
|
||||||
messages.info(request, f"IMDB API: {data['errorMessage']}")
|
if e.message == 'Invalid API Key':
|
||||||
return redirect('register')
|
|
||||||
|
|
||||||
elif data['errorMessage'] == 'Invalid API Key':
|
|
||||||
form.add_error('imdb_api_key', 'Invalid API Key')
|
form.add_error('imdb_api_key', 'Invalid API Key')
|
||||||
return render(request, 'register.html', context={"form": form})
|
return render(request, 'register.html', context={"form": form})
|
||||||
messages.info(request, f"IMDB API: {data['errorMessage']}")
|
messages.info(request, str(e))
|
||||||
return redirect('register')
|
return redirect('register')
|
||||||
|
|
||||||
to_email = form.cleaned_data.get('email')
|
to_email = form.cleaned_data.get('email')
|
||||||
|
@ -13,6 +13,6 @@ def get_request(url: str) -> Union[StatusCodeError, APIError, MaximumUsageError,
|
|||||||
|
|
||||||
if data['errorMessage']:
|
if data['errorMessage']:
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
if 'Maximum usage' in data['errorMessage']:
|
||||||
raise MaximumUsageError()
|
raise MaximumUsageError(data['errorMessage'])
|
||||||
raise APIError(data['errorMessage'])
|
raise APIError(data['errorMessage'])
|
||||||
return data
|
return data
|
@ -20,4 +20,4 @@ class MaximumUsageError(Exception):
|
|||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.message
|
return f"IMDB API: {self.message}"
|
@ -6,6 +6,6 @@ from typing import Optional
|
|||||||
@dataclass
|
@dataclass
|
||||||
class NewSeries:
|
class NewSeries:
|
||||||
series: SeriesModel
|
series: SeriesModel
|
||||||
new_episodes_count: Optional[int] = None
|
new_episodes_count: int
|
||||||
last_season: Optional[int] = None
|
last_season: int
|
||||||
last_episode: Optional[int] = None
|
last_episode: int
|
@ -4,7 +4,6 @@ from .exceptions import *
|
|||||||
from .new_series_model import NewSeries
|
from .new_series_model import NewSeries
|
||||||
from series.models import SeriesModel
|
from series.models import SeriesModel
|
||||||
from typing import (List,
|
from typing import (List,
|
||||||
Tuple,
|
|
||||||
Dict,
|
Dict,
|
||||||
Union)
|
Union)
|
||||||
|
|
||||||
@ -15,49 +14,60 @@ class SeriesCounter:
|
|||||||
self.new_series_list: List[NewSeries] = []
|
self.new_series_list: List[NewSeries] = []
|
||||||
self.error_series: List[SeriesModel] = []
|
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
|
# sourcery skip: aware-datetime-for-utc
|
||||||
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
|
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)):]:
|
for season_number in seasons[seasons.index(str(series.watched_season)):]:
|
||||||
data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{self.api_key}/{series.imdb_id}/{n}")
|
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:
|
try:
|
||||||
episode_date = datetime.strptime(released_date, '%d %b %Y')
|
episode_date = datetime.strptime(released_date, '%d %b %Y')
|
||||||
if (episode_date - now_date).days > 0:
|
if (episode_date - now_date).days > 0:
|
||||||
raise ValueError
|
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
|
data_return['last_season'] = int(season_number)
|
||||||
new_episodes_count += 1
|
data_return['last_episode'] = episode_number+1
|
||||||
last_n = n
|
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:
|
for s in series:
|
||||||
try:
|
try:
|
||||||
data = get_request(f"https://imdb-api.com/en/API/Title/{self.api_key}/{s.imdb_id}")
|
data = get_request(f"https://imdb-api.com/en/API/Title/{self.api_key}/{s.imdb_id}")
|
||||||
|
|
||||||
except (StatusCodeError, APIError):
|
except (StatusCodeError, APIError):
|
||||||
self.error_series.append(s)
|
self.error_series.append(s)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
data = self.get_episode_count(s, data)
|
try:
|
||||||
if data[0]:
|
data = self.get_episode_count(s, data)
|
||||||
self.new_series_list.append(
|
if data['new_episodes_count'] != s.new_episodes_count:
|
||||||
NewSeries(
|
self.new_series_list.append(
|
||||||
series=s,
|
NewSeries(series=s, **data)
|
||||||
new_episodes_count=data[0],
|
|
||||||
last_season=data[1],
|
|
||||||
last_episode=data[2]
|
|
||||||
)
|
)
|
||||||
)
|
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)
|
@ -10,14 +10,26 @@ class SeriesModel(models.Model):
|
|||||||
title = models.CharField(max_length=35, blank=False, null=False)
|
title = models.CharField(max_length=35, blank=False, null=False)
|
||||||
imdb_id = models.CharField(max_length=10, validators=[MinLengthValidator(9)],
|
imdb_id = models.CharField(max_length=10, validators=[MinLengthValidator(9)],
|
||||||
blank=False, null=False)
|
blank=False, null=False)
|
||||||
last_season = models.IntegerField(validators=[
|
watched_season = models.IntegerField(validators=[
|
||||||
MaxValueValidator(30),
|
MaxValueValidator(30),
|
||||||
MinValueValidator(1)
|
MinValueValidator(1)
|
||||||
], blank=False, null=False)
|
], blank=False, null=False)
|
||||||
last_episode = models.IntegerField(validators=[
|
watched_episode = models.IntegerField(validators=[
|
||||||
MaxValueValidator(60),
|
MaxValueValidator(60),
|
||||||
MinValueValidator(1)
|
MinValueValidator(1)
|
||||||
], blank=False, null=False)
|
], 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)
|
show = models.BooleanField(default=True)
|
||||||
slug = AutoSlugField(populate_from='title', unique=True)
|
slug = AutoSlugField(populate_from='title', unique=True)
|
||||||
|
|
||||||
|
@ -5,78 +5,61 @@ from datetime import datetime
|
|||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from celery.utils.log import get_task_logger
|
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:
|
def update_series(updated_series):
|
||||||
data = raw_data.json()
|
updated_series.series.last_season = updated_series.last_season
|
||||||
if not data['errorMessage']:
|
updated_series.series.last_episode = updated_series.last_episode
|
||||||
return data
|
updated_series.series.new_episodes_count = updated_series.new_episodes_count
|
||||||
logger.info(f"error message: {data['errorMessage']}\nlink: {link}")
|
|
||||||
return None
|
|
||||||
logger.info(f"status code: {raw_data.status_code}\nlink: {link}")
|
|
||||||
|
|
||||||
def episode_counter(imdb_api_key, s, data):
|
def send_email(user):
|
||||||
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
|
series = user.series.filter(show=True).order_by('-id')
|
||||||
new_episodes_count = 0
|
|
||||||
|
|
||||||
for n in data['tvSeriesInfo']['seasons'][data['tvSeriesInfo']['seasons'].index(str(s.last_season)):]:
|
series_counter = SeriesCounter(user.imdb_api_key)
|
||||||
data = get_request(f"https://imdb-api.com/en/API/SeasonEpisodes/{imdb_api_key}/{s.imdb_id}/{n}")
|
try:
|
||||||
if data is None: return None
|
series_counter.find_new_series(series)
|
||||||
|
series_len = len(series_counter.new_series_list)
|
||||||
episodes = data['episodes']
|
except MaximumUsageError as e:
|
||||||
for i in range(int(s.last_episode) if n == str(s.last_season) else 0, len(episodes)):
|
if series_len := len(series_counter.new_series_list):
|
||||||
released_date = episodes[i]['released'].replace('.', '')
|
for updated_series in series_counter.new_series_list:
|
||||||
try:
|
update_series(updated_series)
|
||||||
episode_date = datetime.strptime(released_date, '%d %b %Y')
|
updated_series.save()
|
||||||
if (episode_date - now_date).days > 0:
|
message = render_to_string('new_episodes_notification.html', {
|
||||||
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', {
|
|
||||||
'user': user,
|
'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(
|
email = EmailMessage(
|
||||||
'New Episodes!', message, to=[user.email]
|
'New Episodes!', message, to=[user.email]
|
||||||
)
|
)
|
||||||
email.send()
|
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)
|
@ -12,7 +12,9 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Title ({{series.paginator.count}})</th>
|
<th scope="col">Title ({{series.paginator.count}})</th>
|
||||||
<th scope="col">Season - Episode</th>
|
<th scope="col">Watched</th>
|
||||||
|
<th scope="col">Last</th>
|
||||||
|
<th scope="col">Unwatched</th>
|
||||||
<th scope="col">Show</th>
|
<th scope="col">Show</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -31,11 +33,19 @@
|
|||||||
<img class="trash-icon" src="{% static 'icons/trash.png' %}" width="24px" height="24px">
|
<img class="trash-icon" src="{% static 'icons/trash.png' %}" width="24px" height="24px">
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
|
<td>
|
||||||
|
<a href="https://www.imdb.com/title/{{s.imdb_id}}/episodes?season={{s.last_season}}" style="text-decoration: none;" target="_blank">
|
||||||
|
{{s.watched_season}} - {{s.watched_episode}}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://www.imdb.com/title/{{s.imdb_id}}/episodes?season={{s.last_season}}" style="text-decoration: none;" target="_blank">
|
<a href="https://www.imdb.com/title/{{s.imdb_id}}/episodes?season={{s.last_season}}" style="text-decoration: none;" target="_blank">
|
||||||
{{s.last_season}} - {{s.last_episode}}
|
{{s.last_season}} - {{s.last_episode}}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{s.new_episodes_count}}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if s.show %}
|
{% if s.show %}
|
||||||
<img src="{% static 'icons/true-check-button.png' %}" width="22px" height="22px">
|
<img src="{% static 'icons/true-check-button.png' %}" width="22px" height="22px">
|
||||||
@ -51,7 +61,13 @@
|
|||||||
<div style="margin-bottom: 8.5rem;">
|
<div style="margin-bottom: 8.5rem;">
|
||||||
<div class="btn-new-episode">
|
<div class="btn-new-episode">
|
||||||
<button type="button" class="btn btn-outline-primary">
|
<button type="button" class="btn btn-outline-primary">
|
||||||
<a href="/series/new-episodes/" style="text-decoration: none; color: inherit;">New Episodes</a>
|
<a href="/" style="text-decoration: none; color: inherit;">All</a>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary" style="margin-left: 4px;">
|
||||||
|
<a href="?new=true" style="text-decoration: none; color: inherit;">Unwatched</a>
|
||||||
|
</button> <br>
|
||||||
|
<button type="button" class="btn btn-outline-primary" style="margin-top: 4.7%; margin-bottom: 77%;">
|
||||||
|
<a href="/series/new-episodes/" style="text-decoration: none; color: inherit;">Update</a>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %} New Episodes of The Series {% endblock title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<link rel="stylesheet" href="{% static 'css/new_episodes.css' %}">
|
|
||||||
|
|
||||||
<div class="table-div">
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Title</th>
|
|
||||||
<th scope="col">Watched Season - Episode</th>
|
|
||||||
<th scope="col">Last Season - Episode</th>
|
|
||||||
<th scope="col">Number of New Episodes</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for d in data %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
<a href="https://www.imdb.com/title/{{s.imdb_id}}/" style="text-decoration: none;" target="_blank">
|
|
||||||
{{d.series.title}}
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
<a class="btn mr-1 update-btn" style="padding: 0;" href="{% url 'update-series' d.series.slug %}">
|
|
||||||
<img class="edit-icon" src="{% static 'icons/edit.png' %}" width="21px" height="21px">
|
|
||||||
</a>
|
|
||||||
<a class="btn delete-btn" href="{% url 'delete-series' d.series.slug %}">
|
|
||||||
<img class="trash-icon" src="{% static 'icons/trash.png' %}" width="24px" height="24px">
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<a href="https://www.imdb.com/title/{{d.series.imdb_id}}/episodes?season={{d.series.last_season}}" style="text-decoration: none;" target="_blank">
|
|
||||||
{{d.series.last_season}} - {{d.series.last_episode}}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://www.imdb.com/title/{{d.series.imdb_id}}/episodes?season={{d.last_season}}" style="text-decoration: none;" target="_blank">
|
|
||||||
{{d.last_season}} - {{d.last_episode}}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>{{d.new_episodes_count}}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
36
src/series/templates/new_episodes_notification.html
Normal file
36
src/series/templates/new_episodes_notification.html
Normal file
@ -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 %}
|
@ -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 %}
|
|
@ -4,15 +4,17 @@ from django.urls import reverse_lazy, reverse
|
|||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from requests import get
|
|
||||||
from datetime import datetime
|
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):
|
class AddSeriesView(LoginRequiredMixin, CreateView):
|
||||||
login_url = reverse_lazy('login')
|
login_url = reverse_lazy('login')
|
||||||
template_name = 'add_series.html'
|
template_name = 'add_series.html'
|
||||||
model = SeriesModel
|
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):
|
def get_success_url(self):
|
||||||
messages.success(self.request, 'Series Added')
|
messages.success(self.request, 'Series Added')
|
||||||
@ -22,58 +24,73 @@ class AddSeriesView(LoginRequiredMixin, CreateView):
|
|||||||
series = form.save(commit=False)
|
series = form.save(commit=False)
|
||||||
series.user = self.request.user
|
series.user = self.request.user
|
||||||
|
|
||||||
raw_data = get(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}")
|
try:
|
||||||
|
data = get_request(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}")
|
||||||
if raw_data.status_code != 200:
|
except StatusCodeError:
|
||||||
messages.info(self.request, 'TV Series can not added. Please try again.')
|
messages.info(self.request, 'TV Series can not added. Please try again.')
|
||||||
return redirect('add-series')
|
return redirect('add-series')
|
||||||
data = raw_data.json()
|
except MaximumUsageError:
|
||||||
|
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
||||||
if data['errorMessage']:
|
return redirect('add-series')
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError:
|
||||||
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
|
||||||
return redirect('add-series')
|
|
||||||
form.add_error('imdb_id', 'ID is not correct.')
|
form.add_error('imdb_id', 'ID is not correct.')
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
if not data['tvSeriesInfo']:
|
if not data['tvSeriesInfo']:
|
||||||
form.add_error('imdb_id', 'This is not a TV series id.')
|
form.add_error('imdb_id', 'This is not a TV series id.')
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
seasons = data['tvSeriesInfo']['seasons']
|
seasons = data['tvSeriesInfo']['seasons']
|
||||||
|
|
||||||
if str(series.last_season) not in seasons:
|
if str(series.watched_season) not in seasons:
|
||||||
form.add_error('last_season', 'The season number is not correct.')
|
form.add_error('watched_season', 'The season number is not correct.')
|
||||||
return self.form_invalid(form)
|
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}")
|
try:
|
||||||
if raw_data.status_code != 200:
|
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.')
|
messages.info(self.request, 'TV Series can not added. Please try again.')
|
||||||
return redirect('add-series')
|
return redirect('add-series')
|
||||||
data = raw_data.json()
|
except MaximumUsageError:
|
||||||
|
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
||||||
if data['errorMessage']:
|
return redirect('add-series')
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError:
|
||||||
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
|
||||||
return redirect('add-series')
|
|
||||||
form.add_error('imdb_id', 'ID is not correct.')
|
form.add_error('imdb_id', 'ID is not correct.')
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
episodes = data['episodes']
|
|
||||||
|
|
||||||
|
episodes = data['episodes']
|
||||||
episodes_count = len(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)
|
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')
|
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
last_episode_date = datetime.strptime(released_date, '%d %b %Y')
|
watched_episode_date = datetime.strptime(released_date, '%d %b %Y')
|
||||||
if (last_episode_date - now_date).days > 0:
|
if (watched_episode_date - now_date).days > 0:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except 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)
|
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()
|
series.save()
|
||||||
form.save_m2m()
|
form.save_m2m()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
@ -7,7 +7,7 @@ from django.contrib import messages
|
|||||||
|
|
||||||
class SeriesDeleteView(LoginRequiredMixin, DeleteView):
|
class SeriesDeleteView(LoginRequiredMixin, DeleteView):
|
||||||
login_url = reverse_lazy('login')
|
login_url = reverse_lazy('login')
|
||||||
template_name = 'article_deletion_confirmation.html'
|
template_name = 'series_deletion_confirmation.html'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
messages.success(self.request, 'Series Deleted')
|
messages.success(self.request, 'Series Deleted')
|
||||||
|
@ -2,13 +2,19 @@ from django.shortcuts import render
|
|||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from account.models import User
|
from account.models import User
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
|
||||||
@login_required(login_url='/account/login')
|
@login_required(login_url='/account/login')
|
||||||
def homepage_view(request):
|
def homepage_view(request):
|
||||||
user = User.objects.get(id=request.user.id)
|
user = User.objects.get(id=request.user.id)
|
||||||
series_true = user.series.filter(show=True).order_by('-id')
|
if request.GET.get('new') == 'true':
|
||||||
series_false = user.series.filter(show=False).order_by('-id')
|
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')
|
page = request.GET.get('page')
|
||||||
paginator = Paginator(list(series_true) + list(series_false), 5)
|
paginator = Paginator(list(series_true) + list(series_false), 5)
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django.shortcuts import (render,
|
from django.shortcuts import redirect
|
||||||
redirect)
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from account.models import User
|
from account.models import User
|
||||||
@ -14,10 +13,41 @@ def new_episodes_view(request):
|
|||||||
series_counter = SeriesCounter(request.user.imdb_api_key)
|
series_counter = SeriesCounter(request.user.imdb_api_key)
|
||||||
try:
|
try:
|
||||||
series_counter.find_new_series(series)
|
series_counter.find_new_series(series)
|
||||||
except MaximumUsageError as e: ...
|
series_len = len(series_counter.new_series_list)
|
||||||
# messages.warning(request, f"{e} (some series could not be updated)")
|
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:
|
messages.warning(request,
|
||||||
return render(request, 'new_episodes.html', context={'data': series_counter.new_series_list})
|
f"Series could not be updated. {str(e)}")
|
||||||
messages.warning(request, "There are no new episodes of any series :(")
|
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')
|
return redirect('homepage')
|
@ -5,14 +5,16 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.shortcuts import (get_object_or_404,
|
from django.shortcuts import (get_object_or_404,
|
||||||
redirect)
|
redirect)
|
||||||
from requests import get
|
|
||||||
from datetime import datetime
|
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):
|
class UpdateSeriesView(LoginRequiredMixin, UpdateView):
|
||||||
login_url = reverse_lazy('login')
|
login_url = reverse_lazy('login')
|
||||||
template_name = 'update_series.html'
|
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):
|
def get_object(self):
|
||||||
return get_object_or_404(SeriesModel, slug=self.kwargs.get('slug'), user=self.request.user)
|
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 = form.save(commit=False)
|
||||||
series.user = self.request.user
|
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()
|
series.save()
|
||||||
form.save_m2m()
|
form.save_m2m()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
raw_data = get(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}")
|
try:
|
||||||
|
data = get_request(f"https://imdb-api.com/en/API/Title/{series.user.imdb_api_key}/{series.imdb_id}")
|
||||||
if raw_data.status_code != 200:
|
except StatusCodeError:
|
||||||
messages.info(self.request, 'TV Series can not updated. Please try again.')
|
messages.info(self.request, 'TV Series can not added. Please try again.')
|
||||||
return redirect('update-series', self.kwargs.get('slug'))
|
return redirect('update-series', self.kwargs.get('slug'))
|
||||||
data = raw_data.json()
|
except MaximumUsageError:
|
||||||
|
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
||||||
if data['errorMessage']:
|
return redirect('update-series', self.kwargs.get('slug'))
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError:
|
||||||
messages.info(self.request, f"IMDB Key: {data['errorMessage']}")
|
|
||||||
return redirect("update-series", self.kwargs.get('slug'))
|
|
||||||
form.add_error('imdb_id', 'ID is not correct.')
|
form.add_error('imdb_id', 'ID is not correct.')
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
@ -49,39 +49,55 @@ class UpdateSeriesView(LoginRequiredMixin, UpdateView):
|
|||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
seasons = data['tvSeriesInfo']['seasons']
|
seasons = data['tvSeriesInfo']['seasons']
|
||||||
|
|
||||||
if str(series.last_season) not in seasons:
|
if str(series.watched_season) not in seasons:
|
||||||
form.add_error('last_season', 'The season number is not correct.')
|
form.add_error('watched_season', 'The season number is not correct.')
|
||||||
return self.form_invalid(form)
|
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}")
|
try:
|
||||||
if raw_data.status_code != 200:
|
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.')
|
messages.info(self.request, 'TV Series can not added. Please try again.')
|
||||||
return redirect('update-series', self.kwargs.get('slug'))
|
return redirect('update-series', self.kwargs.get('slug'))
|
||||||
data = raw_data.json()
|
except MaximumUsageError:
|
||||||
|
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
||||||
if data['errorMessage']:
|
return redirect('update-series', self.kwargs.get('slug'))
|
||||||
if 'Maximum usage' in data['errorMessage']:
|
except APIError:
|
||||||
messages.info(self.request, f"IMDB API: {data['errorMessage']}")
|
|
||||||
return redirect('update-series', self.kwargs.get('slug'))
|
|
||||||
form.add_error('imdb_id', 'ID is not correct.')
|
form.add_error('imdb_id', 'ID is not correct.')
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
episodes = data['episodes']
|
|
||||||
|
|
||||||
|
episodes = data['episodes']
|
||||||
episodes_count = len(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)
|
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')
|
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
last_episode_date = datetime.strptime(released_date, '%d %b %Y')
|
last_episode_date = datetime.strptime(released_date, '%d %b %Y')
|
||||||
if (last_episode_date - now_date).days > 0:
|
if (last_episode_date - now_date).days > 0:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except 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)
|
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()
|
series.save()
|
||||||
form.save_m2m()
|
form.save_m2m()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
@ -14,7 +14,7 @@
|
|||||||
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 2px 4px 2px 4px;" target="_blank" href="https://github.com/Ayxan-z" role="button">
|
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 2px 4px 2px 4px;" target="_blank" href="https://github.com/Ayxan-z" role="button">
|
||||||
<img class="contact-img" src="{% static 'icons/github.png' %}">
|
<img class="contact-img" src="{% static 'icons/github.png' %}">
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 5px 6px 5px 6px;" target="_blank" href="https://www.linkedin.com/in/ayxan-shahsuvarov-59a314187" role="button">
|
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 5px 6px 5px 6px;" target="_blank" href="https://www.linkedin.com/in/aykhan-shahsuvarov-59a314187/" role="button">
|
||||||
<img class="contact-img" src="{% static 'icons/linkedin.png' %}" style="background-color: white;">
|
<img class="contact-img" src="{% static 'icons/linkedin.png' %}" style="background-color: white;">
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 6px 7px 6px 7px;" target="_blank" href="mailto:ayxan.shahsuvarov1@gmail.com" role="button">
|
<a class="btn btn-outline-light btn-floating m-1 contact-links" style="padding: 6px 7px 6px 7px;" target="_blank" href="mailto:ayxan.shahsuvarov1@gmail.com" role="button">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user