mirror of
https://github.com/aykhans/series-robot-web.git
synced 2025-04-16 04:53:11 +00:00
Added 'imdb_api_access'
This commit is contained in:
parent
7bfad1a5cb
commit
939f8ad578
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,5 +8,4 @@ Backup-codes-series.notification.txt
|
||||
celerybeat-schedule
|
||||
databasepostgresql_env
|
||||
SeriesRobot.pem
|
||||
certbot
|
||||
imdb_api_access
|
||||
certbot
|
2
src/imdb_api_access/__init__.py
Normal file
2
src/imdb_api_access/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .series_counter import SeriesCounter
|
||||
from .exceptions import *
|
18
src/imdb_api_access/_requests.py
Normal file
18
src/imdb_api_access/_requests.py
Normal 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
|
23
src/imdb_api_access/exceptions.py
Normal file
23
src/imdb_api_access/exceptions.py
Normal 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
|
11
src/imdb_api_access/new_series_model.py
Normal file
11
src/imdb_api_access/new_series_model.py
Normal 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
|
63
src/imdb_api_access/series_counter.py
Normal file
63
src/imdb_api_access/series_counter.py
Normal 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]
|
||||
)
|
||||
)
|
@ -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>
|
||||
|
@ -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')
|
Loading…
x
Reference in New Issue
Block a user