Skip to content

Commit

Permalink
Merge pull request #15 from marhoy/mester-fix
Browse files Browse the repository at this point in the history
Index seasons by season_id, not number
  • Loading branch information
marhoy committed Jan 23, 2020
2 parents 3ed1afb + e8e5027 commit 39fc07d
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 46 deletions.
18 changes: 10 additions & 8 deletions src/nrkdownload/parse_nrk_url.py
Expand Up @@ -86,22 +86,24 @@ def parse_url(url):
# We know the season and episode number, but not the media id
# https://tv.nrk.no/serie/oppfinneren/sesong/2/episode/2/avspiller
series_id = series_match.group(1)
season_number = int(season_match.group(1))
season_name = season_match.group(1)
episode_number = int(episode_match.group(1))
series = tv.series_from_series_id(series_id)
episode = series.seasons[season_number - 1].episodes[episode_number - 1]
LOG.info("URL matches episode %d, season %d of series %s",
episode_number, season_number, series_id)
season_id = series.get_season_id_from_season_name(season_name)
episode = series.seasons[season_id].episodes[episode_number - 1]
LOG.info("URL matches episode %d, season %s of series %s",
episode_number, season_name, series_id)
return [episode]

if series_match and season_match:
# A season of a series
# https://tv.nrk.no/serie/oppfinneren/sesong/2
season_number = int(season_match.group(1))
season_name = season_match.group(1)
series_id = series_match.group(1)
LOG.info("URL matches season number %d of series %s", season_number, series_id)
LOG.info("URL matches season %s of series %s", season_name, series_id)
series = tv.series_from_series_id(series_id)
episodes = series.seasons[season_number - 1].episodes
season_id = series.get_season_id_from_season_name(season_name)
episodes = series.seasons[season_id].episodes
return episodes

if series_match and not season_match:
Expand All @@ -110,7 +112,7 @@ def parse_url(url):
series_id = series_match.group(1)
series = tv.series_from_series_id(series_id)
episodes = []
for season in series.seasons:
for season in series.seasons.values():
for episode in season.episodes:
episodes.append(episode)
LOG.info("URL matches series %s", series_id)
Expand Down
78 changes: 48 additions & 30 deletions src/nrkdownload/tv.py
Expand Up @@ -4,6 +4,8 @@
import logging
import os.path
import re
from collections import OrderedDict


# The urllib has changed from Python 2 to 3, and thus requires some extra handling

Expand Down Expand Up @@ -57,25 +59,37 @@ def __init__(self, program_id, title, description, image_url,
self.subtitle_urls = subtitle_urls
self.duration = duration
self._series = series_from_series_id(self.series_id)
self._season_number = None
self._season_name = None
self._season_id = None
self._episode_number = None
self._filename = None

@property
def season_number(self):
def season_name(self):
if not self.series_id:
LOG.debug("%s is not part of a series", self.title)
return None
return self._series.seasons[self.season_id].name

@property
def season_id(self):
"""
Loop over the seasons of the series and find the one which contains our program_id
:return: Season number: int
Returns:
Season ID (str)
"""
if not self.series_id:
LOG.debug("%s is not part of a series", self.title)
return None
if not self._season_number:
for i, season in enumerate(self._series.seasons):
if self.program_id in season.episode_ids:
self._season_number = i
return self._season_number
return ""
if self._season_id:
return self._season_id
for season_id, season in self._series.seasons.items():
if self.program_id in season.episode_ids:
self._season_id = season_id
return self._season_id
raise IndexError("program_id {} not found in any seasons of "
"series {}".format(self.program_id, self.series_id))

@property
def episode_number(self):
Expand All @@ -88,7 +102,7 @@ def episode_number(self):
LOG.warning("%s is not part of a series", self.title)
return None
if not self._episode_number:
self._episode_number = self._series.seasons[self.season_number].\
self._episode_number = self._series.seasons[self.season_id].\
episode_ids.index(self.program_id)
return self._episode_number

Expand All @@ -107,11 +121,13 @@ def filename(self):
LOG.debug("Making filename for program %s", self.title)

basedir = os.path.join(config.DOWNLOAD_DIR, self._series.dir_name,
self._series.seasons[self.season_number].dir_name)
self._series.seasons[
self.season_id].dir_name)

filename = self._series.title
filename += ' - S{:02}E{:02}'.format(self.season_number + 1,
self.episode_number + 1)

filename += ' - S{}E{:02}'.format(utils.zero_pad(self.season_name),
self.episode_number + 1)

if not self.title.lower().startswith(self._series.title.lower()):
filename += ' - {}'.format(self.title)
Expand All @@ -133,8 +149,8 @@ def __str__(self):
string = ''
if self._series:
string += "{} - ".format(self._series.title)
if self.season_number:
string += "Sesong {} - ".format(self.season_number + 1)
if self.season_name:
string += "Sesong {} - ".format(self.season_name)
string += self.title
if self.episode_number_or_date and not string.endswith(self.episode_number_or_date):
string += ': ' + self.episode_number_or_date
Expand All @@ -144,11 +160,10 @@ def __str__(self):


class Season:
def __init__(self, series_id, idx, season_id, name):
def __init__(self, series_id, season_id, name):
LOG.debug('Creating new season of %s: %s: %s: %s',
series_id, idx, season_id, name)
series_id, season_id, name)
self.series_id = series_id
self.idx = idx
self.season_id = season_id
self.name = name
self._dir_name = None
Expand All @@ -158,7 +173,8 @@ def __init__(self, series_id, idx, season_id, name):
@property
def dir_name(self):
if not self._dir_name:
self._dir_name = utils.valid_filename('Season {:02}'.format(self.idx + 1))
self._dir_name = utils.valid_filename('Season {}'.format(
utils.zero_pad(self.name)))
# if not self.name.startswith('Sesong'):
# self._dir_name = utils.valid_filename(self._dir_name + '- {}'.format(self.name))
return self._dir_name
Expand All @@ -183,8 +199,7 @@ def episodes(self):
return self._episodes

def __str__(self):
string = '{}: {} ({} episoder)'.format(self.idx + 1, self.name, len(self.episode_ids))
return string
return '{} ({} episoder)'.format(self.name, len(self.episode_ids))


class Series:
Expand Down Expand Up @@ -212,9 +227,13 @@ def known_series(cls):
def add_known_series(cls, series_id, series_obj):
cls._known_series[series_id] = series_obj

# @property
# def seasonId2Idx(self):
# return {season.id: season.number for season in self.seasons}
def get_season_id_from_season_name(self, season_name):
for season_id, season in self.seasons.items():
if season.name == season_name:
return season_id
raise IndexError("No season in series {} with name {}".format(
self.series_id, season_name
))

def __str__(self):
string = '{} : {} Sesong'.format(self.title, len(self.seasons))
Expand Down Expand Up @@ -267,14 +286,13 @@ def series_from_series_id(series_id, image_size=960):
if image['pixelWidth'] == image_size:
image_url = image['imageUrl']

seasons = []
for idx, season in enumerate(json['seasons']):
seasons = OrderedDict()
for season in json['seasons']:
season_name = re.sub(r'\s+', ' ', season['name'])
season_id = season['id']
seasons.append(Season(series_id=series_id,
idx=idx,
season_id=season_id,
name=season_name))
seasons[season_id] = Season(series_id=series_id,
season_id=season_id,
name=season_name)

series = Series(series_id=series_id, title=title, description=description,
image_url=image_url, seasons=seasons)
Expand Down
7 changes: 7 additions & 0 deletions src/nrkdownload/utils.py
Expand Up @@ -33,6 +33,13 @@ def parse_datetime(string):
return dateutil.parser.parse(string)


def zero_pad(value):
try:
return "{:02d}".format(int(value))
except ValueError:
return value


def parse_duration(string):
# PT28M39S : 28m39s
# PT3H12M41.6S : 3h12m41.6s
Expand Down
9 changes: 6 additions & 3 deletions tests/test_parse_nrk_url.py
Expand Up @@ -14,14 +14,17 @@ def test_parse_url():
'https://tv.nrk.no/serie/oppfinneren/sesong/2/episode/2/avspiller')
assert len(programs) == 1
assert programs[0].title == 'Oppfinneren'
assert programs[0].season_number == 1
assert programs[0].season_name == '2'
assert programs[0].episode_number == 1
assert programs[0].filename == nrkdownload.config.DOWNLOAD_DIR + \
'/Oppfinneren/Season 02/Oppfinneren - S02E02 - 2of8'
assert programs[0].filename == nrkdownload.config.DOWNLOAD_DIR + \
'/Oppfinneren/Season 02/Oppfinneren - S02E02 - 2of8'
assert programs[0].__str__() == 'Oppfinneren - Sesong 2 - Oppfinneren: 2:8'
assert programs[0]._series.seasons[0].__str__() == '1: 1 (8 episoder)'

first_season = list(programs[0]._series.seasons.values())[0]
assert first_season.__str__() == '1 (8 episoder)'

assert programs[0]._series.__str__() == 'Oppfinneren : 3 Sesonger'
nrkdownload.config.MAX_OUTPUT_STRING_LENGTH = 10
assert programs[0].__str__() == 'Oppfinn...'
Expand All @@ -39,7 +42,7 @@ def test_parse_url():
assert len(programs) == 1
assert programs[0].title == 'Arif og Unge Ferrari med Stavanger Symfoniorkester'
assert programs[0].series_id is None
assert programs[0].season_number is None
assert programs[0].season_name is None
assert programs[0].episode_number is None
assert programs[0].filename == nrkdownload.config.DOWNLOAD_DIR + \
'/Arif og Unge Ferrari med Stavanger Symfoniorkester'
Expand Down
10 changes: 5 additions & 5 deletions tox.ini
Expand Up @@ -9,11 +9,11 @@ envlist = py27, py35, py36, py37, flake8
[testenv]
extras = testing
commands = pytest {posargs}
basepython =
py27: {homedir}/miniconda3/envs/python27/bin/python
py35: {homedir}/miniconda3/envs/python35/bin/python
py36: {homedir}/miniconda3/envs/python36/bin/python
py37: {homedir}/miniconda3/envs/python37/bin/python
# basepython =
# py27: {homedir}/miniconda3/envs/python27/bin/python
# py35: {homedir}/miniconda3/envs/python35/bin/python
# py36: {homedir}/miniconda3/envs/python36/bin/python
# py37: {homedir}/miniconda3/envs/python37/bin/python

[testenv:flake8]
basepython = python
Expand Down

0 comments on commit 39fc07d

Please sign in to comment.