Added 'imdb_api_access'

This commit is contained in:
ayxan 2022-12-11 04:54:22 +04:00
parent 7bfad1a5cb
commit 939f8ad578
8 changed files with 135 additions and 66 deletions

3
.gitignore vendored
View File

@ -8,5 +8,4 @@ Backup-codes-series.notification.txt
celerybeat-schedule
databasepostgresql_env
SeriesRobot.pem
certbot
imdb_api_access
certbot

View File

@ -0,0 +1,2 @@
from .series_counter import SeriesCounter
from .exceptions import *

View File

@ -0,0 +1,18 @@
from requests import get
from typing import (Union,
Dict)
from .exceptions import *
def get_request(url: str) -> Union[StatusCodeError, APIError, MaximumUsageError, Dict]:
raw_data = get(url)
if raw_data.status_code != 200:
raise StatusCodeError(raw_data.status_code)
data = raw_data.json()
if data['errorMessage']:
if 'Maximum usage' in data['errorMessage']:
raise MaximumUsageError()
raise APIError(data['errorMessage'])
return data

View File

@ -0,0 +1,23 @@
from typing import Union
class StatusCodeError(Exception):
def __init__(self, status_code: Union[int, str] = 404) -> None:
self.status_code = status_code
def __str__(self) -> str:
return f"request response status code: {self.status_code}"
class APIError(Exception):
def __init__(self, message: str = 'Unknown Error') -> None:
self.message = message
def __str__(self) -> str:
return f"IMDB API: {self.message}"
class MaximumUsageError(Exception):
def __init__(self, message: str):
self.message = message
def __str__(self) -> str:
return self.message

View File

@ -0,0 +1,11 @@
from dataclasses import dataclass
from series.models import SeriesModel
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

View File

@ -0,0 +1,63 @@
from ._requests import get_request
from datetime import datetime
from .exceptions import *
from .new_series_model import NewSeries
from series.models import SeriesModel
from typing import (List,
Tuple,
Dict,
Union)
class SeriesCounter:
def __init__(self, api_key: str) -> None:
self.api_key = api_key
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]:
# sourcery skip: aware-datetime-for-utc
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
new_episodes_count = 0
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}")
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
return new_episodes_count, n, i+1 if new_episodes_count > 0 else 0, 0, 0
def find_new_series(self, series: List[NewSeries]) -> 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]
)
)

View File

@ -17,31 +17,31 @@
</tr>
</thead>
<tbody>
{% for s, d in data %}
{% for d in data %}
<tr>
<th scope="row">
<a href="https://www.imdb.com/title/{{s.imdb_id}}/" style="text-decoration: none;" target="_blank">
{{s.title}}
{{d.series.title}}
</a>
<br>
<a class="btn mr-1 update-btn" style="padding: 0;" href="{% url 'update-series' s.slug %}">
<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' s.slug %}">
<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/{{s.imdb_id}}/episodes?season={{s.last_season}}" style="text-decoration: none;" target="_blank">
{{s.last_season}} - {{s.last_episode}}
<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/{{s.imdb_id}}/episodes?season={{d.last_season}}" style="text-decoration: none;" target="_blank">
<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.count}}</td>
<td>{{d.new_episodes_count}}</td>
</tr>
{% endfor %}
</tbody>

View File

@ -3,68 +3,21 @@ from django.shortcuts import (render,
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from account.models import User
from requests import get
from datetime import datetime
from imdb_api_access import SeriesCounter
from imdb_api_access import MaximumUsageError
def get_request(request, link):
raw_data = get(link)
if raw_data.status_code != 200:
messages.info(request, "Can't search for TV Series. Please try again.")
return redirect('homepage')
data = raw_data.json()
if data['errorMessage']:
messages.info(request, f"IMDB API: {data['errorMessage']}")
return redirect('homepage')
return data
def episode_counter(request, s, data):
now_date = datetime.strptime(datetime.strftime(datetime.utcnow(),'%d %b %Y'), '%d %b %Y')
new_episodes_count = 0
for n in data['tvSeriesInfo']['seasons'][data['tvSeriesInfo']['seasons'].index(str(s.last_season)):]:
data = get_request(request, f"https://imdb-api.com/en/API/SeasonEpisodes/{request.user.imdb_api_key}/{s.imdb_id}/{n}")
if type(data) is not dict: return data
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
@login_required(login_url='/account/login')
def new_episodes_view(request):
series = User.objects.get(id=request.user.id).series.filter(show=True).order_by('-id')
series_new_episodes = []
for s in series:
data = get_request(request, f"https://imdb-api.com/en/API/Title/{request.user.imdb_api_key}/{s.imdb_id}")
if type(data) is not dict: return data
data = episode_counter(request, s, data)
if type(data) is not tuple: return data
if data[0]:
series_new_episodes.append([s,
{'count': data[0],
'last_season': data[1],
'last_episode': data[2]}
])
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)")
if series_new_episodes:
return render(request, 'new_episodes.html', context={'data': series_new_episodes})
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 :(")
return redirect('homepage')