Repository: Flexget/Flexget (language: python)

Issue:
Update Sonarr/Radarr to use v3 api
### Motivation for changes:

The latest versions of Sonarr and Radarr have removed the legacy API. We need to start using API v3. I believe it is as simple as changing the URL path. 

I've changed this on my system and ill test for a few days.

#### To Do:

- [ ] Do we need to handle old versions of Sonarr/Radarr?? 



Discussion / hints:
Good question about backward compatibility, we have a similar standing issue with #2906

I think we need some sort of of (soft) policy. It's always annoying if updating software x then requires upgrading bunch of other applications too, but we don't have too many maintainers / testers to keep everything tested to be backwards compatible ....

I'd say we note these upgrade requirements in changelog and support only latest stable releases.

@gazpachoking, any opinions?
@paranoidi i believe Radarr and Sonarr v3 and v4 (latest unstable) both support v3 API. So this may be a non-issue.
I've been running off this brach for 24 hours, so far no errors. 
@gazpachoking @paranoidi been running for a while now. It seems stable.

Thoughts on how we handle legacy? 

NOTE: I do need to look into the current versions of sonarr/radarr to understand what API level they support vs the bleeding edge.
@gazpachoking @paranoidi thoughts on merge? (ill fix the tests)
This PR is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 60 days.
Will this be included into the main branch soon?
This PR is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 60 days.

Fix patch:
diff --git a/flexget/components/imdb/api.py b/flexget/components/imdb/api.py
index e63b929f9e..a8d078f17e 100644
--- a/flexget/components/imdb/api.py
+++ b/flexget/components/imdb/api.py
@@ -1,15 +1,13 @@
-from __future__ import absolute_import, division, unicode_literals
-
 from flask import jsonify
 
 from flexget.api import APIResource, api
 from flexget.api.app import etag
-from flexget.utils.imdb import ImdbSearch
+from flexget.components.imdb.utils import ImdbSearch
 
 imdb_api = api.namespace('imdb', description='IMDB lookup endpoint')
 
 
-class ObjectsContainer(object):
+class ObjectsContainer:
     movie_object = {
         'type': 'object',
         'properties': {
@@ -33,6 +31,7 @@ class ObjectsContainer(object):
 @imdb_api.route('/search/<string:title>/')
 @api.doc(params={'title': 'Movie name or IMDB ID'})
 class IMDBMovieSearch(APIResource):
+    # noinspection PyUnusedLocal
     @etag
     @api.response(200, model=return_schema)
     def get(self, title, session=None):
diff --git a/flexget/utils/imdb.py b/flexget/utils/imdb.py
deleted file mode 100644
index 5f8970e3e5..0000000000
--- a/flexget/utils/imdb.py
+++ /dev/null
@@ -1,413 +0,0 @@
-from __future__ import absolute_import, division, unicode_literals
-
-import difflib
-import json
-import logging
-import random
-import re
-from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
-
-from bs4.element import Tag
-from past.builtins import basestring
-
-from flexget.plugin import PluginError, get_plugin_by_name
-from flexget.utils.requests import Session, TimedLimiter
-from flexget.utils.soup import get_soup
-from flexget.utils.tools import str_to_int
-
-log = logging.getLogger('utils.imdb')
-# IMDb delivers a version of the page which is unparsable to unknown (and some known) user agents, such as requests'
-# Spoof the old urllib user agent to keep results consistent
-requests = Session()
-requests.headers.update({'User-Agent': 'Python-urllib/2.6'})
-# requests.headers.update({'User-Agent': random.choice(USERAGENTS)})
-
-# this makes most of the titles to be returned in english translation, but not all of them
-requests.headers.update({'Accept-Language': 'en-US,en;q=0.8'})
-requests.headers.update(
-    {'X-Forwarded-For': '24.110.%d.%d' % (random.randint(0, 254), random.randint(0, 254))}
-)
-
-# give imdb a little break between requests (see: http://flexget.com/ticket/129#comment:1)
-requests.add_domain_limiter(TimedLimiter('imdb.com', '3 seconds'))
-
-
-def is_imdb_url(url):
-    """Tests the url to see if it's for imdb.com."""
-    if not isinstance(url, basestring):
-        return
-    # Probably should use urlparse.
-    return re.match(r'https?://[^/]*imdb\.com/', url)
-
-
-def is_valid_imdb_title_id(value):
-    """
-    Return True if `value` is a valid IMDB ID for titles (movies, series, etc).
-    """
-    if not isinstance(value, basestring):
-        raise TypeError("is_valid_imdb_title_id expects a string but got {0}".format(type(value)))
-    # IMDB IDs for titles have 'tt' followed by 7 digits
-    return re.match('tt[\d]{7}', value) is not None
-
-
-def is_valid_imdb_person_id(value):
-    """
-    Return True if `value` is a valid IMDB ID for a person.
-    """
-    if not isinstance(value, basestring):
-        raise TypeError("is_valid_imdb_person_id expects a string but got {0}".format(type(value)))
-    # An IMDB ID for a person is formed by 'nm' followed by 7 digits
-    return re.match('nm[\d]{7}', value) is not None
-
-
-def extract_id(url):
-    """Return IMDb ID of the given URL. Return None if not valid or if URL is not a string."""
-    if not isinstance(url, basestring):
-        return
-    m = re.search(r'((?:nm|tt)[\d]{7})', url)
-    if m:
-        return m.group(1)
-
-
-def make_url(imdb_id):
-    """Return IMDb URL of the given ID"""
-    return u'https://www.imdb.com/title/%s/' % imdb_id
-
-
-class ImdbSearch(object):
-    def __init__(self):
-        # de-prioritize aka matches a bit
-        self.aka_weight = 0.95
-        # prioritize first
-        self.first_weight = 1.1
-        self.min_match = 0.7
-        self.min_diff = 0.01
-        self.debug = False
-
-        self.max_results = 50
-
-    def ireplace(self, text, old, new, count=0):
-        """Case insensitive string replace"""
-        pattern = re.compile(re.escape(old), re.I)
-        return re.sub(pattern, new, text, count)
-
-    def smart_match(self, raw_name, single_match=True):
-        """Accepts messy name, cleans it and uses information available to make smartest and best match"""
-        parser = get_plugin_by_name('parsing').instance.parse_movie(raw_name)
-        name = parser.name
-        year = parser.year
-        if name == '':
-            log.critical('Failed to parse name from %s', raw_name)
-            return None
-        log.debug('smart_match name=%s year=%s' % (name, str(year)))
-        return self.best_match(name, year, single_match)
-
-    def best_match(self, name, year=None, single_match=True):
-        """Return single movie that best matches name criteria or None"""
-        movies = self.search(name)
-
-        if not movies:
-            log.debug('search did not return any movies')
-            return None
-
-        # remove all movies below min_match, and different year
-        for movie in movies[:]:
-            if year and movie.get('year'):
-                if movie['year'] != year:
-                    log.debug(
-                        'best_match removing %s - %s (wrong year: %s)'
-                        % (movie['name'], movie['url'], str(movie['year']))
-                    )
-                    movies.remove(movie)
-                    continue
-            if movie['match'] < self.min_match:
-                log.debug('best_match removing %s (min_match)', movie['name'])
-                movies.remove(movie)
-                continue
-
-        if not movies:
-            log.debug('FAILURE: no movies remain')
-            return None
-
-        # if only one remains ..
-        if len(movies) == 1:
-            log.debug('SUCCESS: only one movie remains')
-            return movies[0]
-
-        # check min difference between best two hits
-        diff = movies[0]['match'] - movies[1]['match']
-        if diff < self.min_diff:
-            log.debug(
-                'unable to determine correct movie, min_diff too small (`%s` <-?-> `%s`)'
-                % (movies[0], movies[1])
-            )
-            for m in movies:
-                log.debug('remain: %s (match: %s) %s' % (m['name'], m['match'], m['url']))
-            return None
-        else:
-            return movies[0] if single_match else movies
-
-    def search(self, name):
-        """Return array of movie details (dict)"""
-        log.debug('Searching: %s', name)
-        url = u'https://www.imdb.com/find'
-        # This may include Shorts and TV series in the results
-        params = {
-            'q': name,
-            's': 'tt',
-        }
-
-        log.debug('Search query: %s', repr(url))
-        page = requests.get(url, params=params)
-        actual_url = page.url
-
-        movies = []
-        soup = get_soup(page.text)
-        # in case we got redirected to movie page (perfect match)
-        re_m = re.match(r'.*\.imdb\.com/title/tt\d+/', actual_url)
-        if re_m:
-            actual_url = re_m.group(0)
-            imdb_id = extract_id(actual_url)
-            movie_parse = ImdbParser()
-            movie_parse.parse(imdb_id, soup=soup)
-            log.debug('Perfect hit. Search got redirected to %s', actual_url)
-            movie = {
-                'match': 1.0,
-                'name': movie_parse.name,
-                'imdb_id': imdb_id,
-                'url': make_url(imdb_id),
-                'year': movie_parse.year,
-            }
-            movies.append(movie)
-            return movies
-
-        section_table = soup.find('table', 'findList')
-        if not section_table:
-            log.debug('results table not found')
-            return
-
-        rows = section_table.find_all('tr')
-        if not rows:
-            log.debug('Titles section does not have links')
-        for count, row in enumerate(rows):
-            # Title search gives a lot of results, only check the first ones
-            if count > self.max_results:
-                break
-
-            result_text = row.find('td', 'result_text')
-            movie = {}
-            additional = re.findall(r'\((.*?)\)', result_text.text)
-            if len(additional) > 0:
-                if re.match('^\d{4}$', additional[-1]):
-                    movie['year'] = str_to_int(additional[-1])
-                elif len(additional) > 1:
-                    movie['year'] = str_to_int(additional[-2])
-                    if additional[-1] not in ['TV Movie', 'Video']:
-                        log.debug('skipping %s', result_text.text)
-                        continue
-            primary_photo = row.find('td', 'primary_photo')
-            movie['thumbnail'] = primary_photo.find('a').find('img').get('src')
-
-            link = result_text.find_next('a')
-            movie['name'] = link.text
-            movie['imdb_id'] = extract_id(link.get('href'))
-            movie['url'] = make_url(movie['imdb_id'])
-            log.debug('processing name: %s url: %s' % (movie['name'], movie['url']))
-
-            # calc & set best matching ratio
-            seq = difflib.SequenceMatcher(lambda x: x == ' ', movie['name'].title(), name.title())
-            ratio = seq.ratio()
-
-            # check if some of the akas have better ratio
-            for aka in link.parent.find_all('i'):
-                aka = aka.next.string
-                match = re.search(r'".*"', aka)
-                if not match:
-                    log.debug('aka `%s` is invalid' % aka)
-                    continue
-                aka = match.group(0).replace('"', '')
-                log.trace('processing aka %s' % aka)
-                seq = difflib.SequenceMatcher(lambda x: x == ' ', aka.title(), name.title())
-                aka_ratio = seq.ratio()
-                if aka_ratio > ratio:
-                    ratio = aka_ratio * self.aka_weight
-                    log.debug(
-                        '- aka `%s` matches better to `%s` ratio %s (weighted to %s)'
-                        % (aka, name, aka_ratio, ratio)
-                    )
-
-            # prioritize items by position
-            position_ratio = (self.first_weight - 1) / (count + 1) + 1
-            log.debug(
-                '- prioritizing based on position %s `%s`: %s'
-                % (count, movie['url'], position_ratio)
-            )
-            ratio *= position_ratio
-
-            # store ratio
-            movie['match'] = ratio
-            movies.append(movie)
-
-        movies.sort(key=lambda x: x['match'], reverse=True)
-        return movies
-
-
-class ImdbParser(object):
-    """Quick-hack to parse relevant imdb details"""
-
-    def __init__(self):
-        self.genres = []
-        self.languages = []
-        self.actors = {}
-        self.directors = {}
-        self.writers = {}
-        self.score = 0.0
-        self.votes = 0
-        self.meta_score = 0
-        self.year = 0
-        self.plot_outline = None
-        self.name = None
-        self.original_name = None
-        self.url = None
-        self.imdb_id = None
-        self.photo = None
-        self.mpaa_rating = ''
-
-    def __str__(self):
-        return '<ImdbParser(name=%s,imdb_id=%s)>' % (self.name, self.imdb_id)
-
-    def parse(self, imdb_id, soup=None):
-        self.imdb_id = extract_id(imdb_id)
-        url = make_url(self.imdb_id)
-        self.url = url
-
-        if not soup:
-            page = requests.get(url)
-            soup = get_soup(page.text)
-
-        title_wrapper = soup.find('div', attrs={'class': 'title_wrapper'})
-
-        data = json.loads(soup.find('script', {'type': 'application/ld+json'}).text)
-
-        if not data:
-            raise PluginError(
-                'IMDB parser needs updating, imdb format changed. Please report on Github.'
-            )
-
-        # Parse stuff from the title-overview section
-        name_elem = data['name']
-        if name_elem:
-            self.name = name_elem.strip()
-        else:
-            log.error('Possible IMDB parser needs updating, Please report on Github.')
-            raise PluginError('Unable to set imdb_name for %s from %s' % (self.imdb_id, self.url))
-
-        year = soup.find('span', attrs={'id': 'titleYear'})
-        if year:
-            m = re.search(r'([0-9]{4})', year.text)
-            if m:
-                self.year = int(m.group(1))
-
-        if not self.year:
-            log.debug('No year found for %s', self.imdb_id)
-
-        mpaa_rating_elem = data.get('contentRating')
-        if mpaa_rating_elem:
-            self.mpaa_rating = mpaa_rating_elem
-        else:
-            log.debug('No rating found for %s', self.imdb_id)
-
-        photo_elem = data.get('image')
-        if photo_elem:
-            self.photo = photo_elem
-        else:
-            log.debug('No photo found for %s', self.imdb_id)
-
-        original_name_elem = title_wrapper.find('div', {'class': 'originalTitle'})
-        if original_name_elem:
-            self.name = title_wrapper.find('h1', {'class': ''}).contents[0].strip()
-            self.original_name = original_name_elem.contents[0].strip().strip('"')
-        else:
-            log.debug('No original title found for %s', self.imdb_id)
-
-        votes_elem = data.get('aggregateRating', {}).get('ratingCount')
-        if votes_elem:
-            self.votes = str_to_int(votes_elem) if not isinstance(votes_elem, int) else votes_elem
-        else:
-            log.debug('No votes found for %s', self.imdb_id)
-
-        score_elem = data.get('aggregateRating', {}).get('ratingValue')
-        if score_elem:
-            self.score = float(score_elem)
-        else:
-            log.debug('No score found for %s', self.imdb_id)
-
-        meta_score_elem = soup.find(attrs={'class': 'metacriticScore'})
-        if meta_score_elem:
-            self.meta_score = str_to_int(meta_score_elem.text)
-        else:
-            log.debug('No Metacritic score found for %s', self.imdb_id)
-
-        # get director(s)
-        directors = data.get('director', [])
-        if not isinstance(directors, list):
-            directors = [directors]
-
-        for director in directors:
-            if director['@type'] != 'Person':
-                continue
-            director_id = extract_id(director['url'])
-            director_name = director['name']
-            self.directors[director_id] = director_name
-
-        # get writer(s)
-        writers = data.get('creator', [])
-        if not isinstance(writers, list):
-            writers = [writers]
-
-        for writer in writers:
-            if writer['@type'] != 'Person':
-                continue
-            writer_id = extract_id(writer['url'])
-            writer_name = writer['name']
-            self.writers[writer_id] = writer_name
-
-        # Details section
-        title_details = soup.find('div', attrs={'id': 'titleDetails'})
-        if title_details:
-            # get languages
-            for link in title_details.find_all(
-                'a', href=re.compile('^/search/title\?title_type=feature' '&primary_language=')
-            ):
-                lang = link.text.strip().lower()
-                if lang not in self.languages:
-                    self.languages.append(lang.strip())
-
-        # Storyline section
-        storyline = soup.find('div', attrs={'id': 'titleStoryLine'})
-        if storyline:
-            plot_elem = storyline.find('p')
-            if plot_elem:
-                # Remove the "Written By" part.
-                if plot_elem.em:
-                    plot_elem.em.replace_with('')
-                self.plot_outline = plot_elem.text.strip()
-            else:
-                log.debug('No storyline found for %s', self.imdb_id)
-
-        genres = data.get('genre', [])
-        if not isinstance(genres, list):
-            genres = [genres]
-
-        self.genres = [g.strip().lower() for g in genres]
-
-        # Cast section
-        cast = soup.find('table', attrs={'class': 'cast_list'})
-        if cast:
-            for actor in cast.select('tr > td:nth-of-type(2) > a'):
-                actor_id = extract_id(actor['href'])
-                actor_name = actor.text.strip()
-                # tag instead of name
-                if isinstance(actor_name, Tag):
-                    actor_name = None
-                self.actors[actor_id] = actor_name


Test patch:
diff --git a/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_actions b/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_actions
index 796d784b6e..38756b01b9 100644
--- a/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_actions
+++ b/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_actions
@@ -13,7 +13,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -79,7 +79,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -139,7 +139,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: DELETE
-      uri: http://127.0.0.1:7878/api/movie/16
+      uri: http://127.0.0.1:7878/api/v3/movie/16
     response:
       body:
         string: !!binary |
@@ -182,7 +182,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -248,7 +248,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -291,7 +291,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie/lookup/imdb?imdbId=tt1690953
+      uri: http://127.0.0.1:7878/api/v3/movie/lookup/imdb?imdbId=tt1690953
     response:
       body:
         string: !!binary |
@@ -350,7 +350,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/rootfolder
+      uri: http://127.0.0.1:7878/api/v3/rootfolder
     response:
       body:
         string: !!binary |
@@ -395,7 +395,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/tag
+      uri: http://127.0.0.1:7878/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -444,7 +444,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -500,7 +500,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie/lookup/imdb?imdbId=tt2752772
+      uri: http://127.0.0.1:7878/api/v3/movie/lookup/imdb?imdbId=tt2752772
     response:
       body:
         string: !!binary |
@@ -556,7 +556,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/rootfolder
+      uri: http://127.0.0.1:7878/api/v3/rootfolder
     response:
       body:
         string: !!binary |
@@ -606,7 +606,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -661,7 +661,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie/lookup/imdb?imdbId=tt2554274
+      uri: http://127.0.0.1:7878/api/v3/movie/lookup/imdb?imdbId=tt2554274
     response:
       body:
         string: !!binary |
@@ -722,7 +722,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/rootfolder
+      uri: http://127.0.0.1:7878/api/v3/rootfolder
     response:
       body:
         string: !!binary |
@@ -772,7 +772,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -829,7 +829,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie/lookup/imdb?imdbId=tt1431045
+      uri: http://127.0.0.1:7878/api/v3/movie/lookup/imdb?imdbId=tt1431045
     response:
       body:
         string: !!binary |
@@ -888,7 +888,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/rootfolder
+      uri: http://127.0.0.1:7878/api/v3/rootfolder
     response:
       body:
         string: !!binary |
@@ -938,7 +938,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -996,7 +996,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1062,7 +1062,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1151,7 +1151,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1217,7 +1217,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1308,7 +1308,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: DELETE
-      uri: http://127.0.0.1:7878/api/movie/18
+      uri: http://127.0.0.1:7878/api/v3/movie/18
     response:
       body:
         string: !!binary |
@@ -1351,7 +1351,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1417,7 +1417,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1500,7 +1500,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1566,7 +1566,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1649,7 +1649,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1715,7 +1715,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1800,7 +1800,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: DELETE
-      uri: http://127.0.0.1:7878/api/movie/17
+      uri: http://127.0.0.1:7878/api/v3/movie/17
     response:
       body:
         string: !!binary |
@@ -1843,7 +1843,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1909,7 +1909,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -1984,7 +1984,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: DELETE
-      uri: http://127.0.0.1:7878/api/movie/19
+      uri: http://127.0.0.1:7878/api/v3/movie/19
     response:
       body:
         string: !!binary |
@@ -2027,7 +2027,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -2093,7 +2093,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -2153,7 +2153,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: DELETE
-      uri: http://127.0.0.1:7878/api/movie/20
+      uri: http://127.0.0.1:7878/api/v3/movie/20
     response:
       body:
         string: !!binary |
@@ -2196,7 +2196,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -2262,7 +2262,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
diff --git a/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_tags b/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_tags
index 6a1c35c9a6..64ac5daf94 100644
--- a/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_tags
+++ b/flexget/tests/cassettes/test_radarr_list.TestRadarrListActions.test_radarr_list_tags
@@ -15,7 +15,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/tag
+      uri: http://127.0.0.1:7878/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -59,7 +59,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/profile
+      uri: http://127.0.0.1:7878/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -125,7 +125,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -168,7 +168,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie/lookup/imdb?imdbId=tt1431045
+      uri: http://127.0.0.1:7878/api/v3/movie/lookup/imdb?imdbId=tt1431045
     response:
       body:
         string: !!binary |
@@ -227,7 +227,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/rootfolder
+      uri: http://127.0.0.1:7878/api/v3/rootfolder
     response:
       body:
         string: !!binary |
@@ -272,7 +272,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/tag
+      uri: http://127.0.0.1:7878/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -322,7 +322,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: POST
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
@@ -380,7 +380,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/tag
+      uri: http://127.0.0.1:7878/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -424,7 +424,7 @@ interactions:
         X-Api-Key:
           - 65e246ce581a426781e1a8645f0a1f2c
       method: GET
-      uri: http://127.0.0.1:7878/api/movie
+      uri: http://127.0.0.1:7878/api/v3/movie
     response:
       body:
         string: !!binary |
diff --git a/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_actions b/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_actions
index 6843a3e677..9d1e242d5e 100644
--- a/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_actions
+++ b/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_actions
@@ -13,7 +13,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -78,7 +78,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: DELETE
-      uri: http://127.0.0.1:8989/api/series/23
+      uri: http://127.0.0.1:8989/api/v3/series/23
     response:
       body:
         string: !!binary |
@@ -127,7 +127,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: DELETE
-      uri: http://127.0.0.1:8989/api/series/23
+      uri: http://127.0.0.1:8989/api/v3/series/23
     response:
       body:
         string: "{\n  \"message\": \"Series with ID 23 does not exist\",\n  \"description\"\
@@ -190,7 +190,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -237,7 +237,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series/lookup?term=tvdb:81189
+      uri: http://127.0.0.1:8989/api/v3/series/lookup?term=tvdb:81189
     response:
       body:
         string: !!binary |
@@ -297,7 +297,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/Rootfolder
+      uri: http://127.0.0.1:8989/api/v3/Rootfolder
     response:
       body:
         string: !!binary |
@@ -346,7 +346,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/tag
+      uri: http://127.0.0.1:8989/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -418,7 +418,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: POST
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -480,7 +480,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -542,7 +542,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series/lookup?term=tvdb:153021
+      uri: http://127.0.0.1:8989/api/v3/series/lookup?term=tvdb:153021
     response:
       body:
         string: !!binary |
@@ -602,7 +602,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/Rootfolder
+      uri: http://127.0.0.1:8989/api/v3/Rootfolder
     response:
       body:
         string: !!binary |
@@ -677,7 +677,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: POST
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -739,7 +739,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -812,7 +812,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series/lookup?term=tvdb:121361
+      uri: http://127.0.0.1:8989/api/v3/series/lookup?term=tvdb:121361
     response:
       body:
         string: !!binary |
@@ -873,7 +873,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/Rootfolder
+      uri: http://127.0.0.1:8989/api/v3/Rootfolder
     response:
       body:
         string: !!binary |
@@ -948,7 +948,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: POST
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1011,7 +1011,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1094,7 +1094,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/profile
+      uri: http://127.0.0.1:8989/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1156,7 +1156,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1241,7 +1241,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: DELETE
-      uri: http://127.0.0.1:8989/api/series/24
+      uri: http://127.0.0.1:8989/api/v3/series/24
     response:
       body:
         string: !!binary |
@@ -1288,7 +1288,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1363,7 +1363,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/profile
+      uri: http://127.0.0.1:8989/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
@@ -1425,7 +1425,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1500,7 +1500,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1577,7 +1577,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: DELETE
-      uri: http://127.0.0.1:8989/api/series/26
+      uri: http://127.0.0.1:8989/api/v3/series/26
     response:
       body:
         string: !!binary |
@@ -1626,7 +1626,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: DELETE
-      uri: http://127.0.0.1:8989/api/series/25
+      uri: http://127.0.0.1:8989/api/v3/series/25
     response:
       body:
         string: !!binary |
@@ -1673,7 +1673,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -1720,7 +1720,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/profile
+      uri: http://127.0.0.1:8989/api/v3/qualityProfile
     response:
       body:
         string: !!binary |
diff --git a/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_tags b/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_tags
index 4985ee4ae2..1935abf8c6 100644
--- a/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_tags
+++ b/flexget/tests/cassettes/test_sonarr_list.TestSonarrListActions.test_sonarr_list_tags
@@ -17,7 +17,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: POST
-      uri: http://127.0.0.1:8989/api/tag
+      uri: http://127.0.0.1:8989/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -64,7 +64,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -111,7 +111,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -158,7 +158,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series/lookup?term=tvdb:121361
+      uri: http://127.0.0.1:8989/api/v3/series/lookup?term=tvdb:121361
     response:
       body:
         string: !!binary |
@@ -219,7 +219,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/Rootfolder
+      uri: http://127.0.0.1:8989/api/v3/Rootfolder
     response:
       body:
         string: !!binary |
@@ -268,7 +268,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/tag
+      uri: http://127.0.0.1:8989/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -342,7 +342,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: POST
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
@@ -405,7 +405,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/tag
+      uri: http://127.0.0.1:8989/api/v3/tag
     response:
       body:
         string: !!binary |
@@ -453,7 +453,7 @@ interactions:
         X-Api-Key:
           - 7f0a2ce32a3e43c8a7389e9539c487b4
       method: GET
-      uri: http://127.0.0.1:8989/api/series
+      uri: http://127.0.0.1:8989/api/v3/series
     response:
       body:
         string: !!binary |
diff --git a/flexget/tests/test_metainfo.py b/flexget/tests/test_metainfo.py
index 805812f471..f824d793f7 100644
--- a/flexget/tests/test_metainfo.py
+++ b/flexget/tests/test_metainfo.py
@@ -1,11 +1,7 @@
-from __future__ import absolute_import, division, unicode_literals
-
-from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
-
 import pytest
 
 
-class TestMetainfo(object):
+class TestMetainfo:
     config = """
         tasks:
           test_content_size:
@@ -23,7 +19,7 @@ def test_content_size(self, execute_task):
         assert task.find_entry(content_size=1024), 'Content size 1024 MB absent'
 
 
-class TestMetainfoImdb(object):
+class TestMetainfoImdb:
     config = """
         tasks:
           test:
@@ -52,7 +48,7 @@ def test_imdb(self, execute_task):
         ), 'Failed to ignore multiple imdb urls in test 4'
 
 
-class TestMetainfoQuality(object):
+class TestMetainfoQuality:
     config = """
         tasks:
           test:
@@ -84,7 +80,7 @@ def test_quality(self, execute_task):
         )
 
 
-class TestMetainfoSeries(object):
+class TestMetainfoSeries:
     _config = """
         templates:
           global:
@@ -92,6 +88,13 @@ class TestMetainfoSeries(object):
               series: __parser__
             metainfo_series: yes
         tasks:
+          test_jinja_tvdb:
+            thetvdb_lookup: yes
+            mock:
+              - {title: 'Westworld (2016) S01E01', series_name: 'Westworld'}
+            set:
+              title: "{{tvdb_series_name}}"
+            accept_all: yes
           test:
             mock:
               - {title: 'FlexGet.S01E02.TheName.HDTV.xvid'}
@@ -128,21 +131,21 @@ def test_metainfo_series(self, execute_task):
             series_season=1,
             series_episode=2,
             quality='hdtv xvid',
-            id='flexget s01e02',
+            media_id='flexget s01e02',
         ), 'Failed to parse series info'
         assert task.find_entry(
             series_name='Some Series',
             series_season=3,
             series_episode=14,
             quality='720p',
-            id='some series s03e14',
+            media_id='some series s03e14',
         ), 'Failed to parse series info'
         assert task.find_entry(
             series_name='Something',
             series_season=2,
             series_episode=1,
             quality='hdtv',
-            id='something s02e01',
+            media_id='something s02e01',
         ), 'Failed to parse series info'
         # Test unwanted prefixes get stripped from series name
         assert task.find_entry(
@@ -150,14 +153,14 @@ def test_metainfo_series(self, execute_task):
             series_season=3,
             series_episode=15,
             quality='720p',
-            id='some series s03e15',
+            media_id='some series s03e15',
         ), 'Failed to parse series info'
         assert task.find_entry(
             series_name='Some Series',
             series_season=3,
             series_episode=16,
             quality='720p',
-            id='some series s03e16',
+            media_id='some series s03e16',
         ), 'Failed to parse series info'
         # Test episode title and parentheses are stripped from series name
         assert task.find_entry(
@@ -165,14 +168,14 @@ def test_metainfo_series(self, execute_task):
             series_season=2,
             series_episode=9,
             quality='hdtv',
-            id='show-a us s02e09',
+            media_id='show-a us s02e09',
         ), 'Failed to parse series info'
         assert task.find_entry(
             series_name='Jack\'s Show',
             series_season=3,
             series_episode=1,
             quality='1080p',
-            id='jack\'s show s03e01',
+            media_id='jack\'s show s03e01',
         ), 'Failed to parse series info'
         # Test season pack
         assert task.find_entry(
@@ -193,8 +196,13 @@ def test_false_positives(self, execute_task):
             assert 'series_guessed' not in entry, error
             assert 'series_parser' not in entry, error
 
+    @pytest.mark.online
+    def test_jinja_tvdb(self, execute_task):
+        task = execute_task('test_jinja_tvdb')
+        assert task.entries[0]['title'] == 'Westworld'
+
 
-class TestMetainfoMovie(object):
+class TestMetainfoMovie:
     config = """
         templates:
           global: