# Buggy code
def search(self, search_strings, age=0, ep_obj=None, **kwargs):
    """
    Search a provider and parse the results.

    :param search_strings: A dict with mode (key) and the search value (value)
    :param age: Not used
    :param ep_obj: Informations about the episode being searched (when not RSS)

    :returns: A list of search results (structure)
    """
    results = []
    if not self.login():
        return results

    manual_search = kwargs.get("manual_search")
    if manual_search:
        self.max_back_pages = 20

    anime = False
    if ep_obj and ep_obj.series:
        anime = ep_obj.series.anime == 1

    search_params = {
        "order_by": "time",
        "order_way": "desc",
        "group_results": 0,
        "action": "basic",
        "searchsubmit": 1,
    }

    if "RSS" in search_strings.keys():
        search_params["filter_cat[14]"] = 1  # anime
        search_params["filter_cat[2]"] = 1  # tv shows
    elif anime:
        search_params["filter_cat[14]"] = 1  # anime
    else:
        search_params["filter_cat[2]"] = 1  # tv shows

    for mode in search_strings:
        items = []
        log.debug("Search mode: {0}".format(mode))

        # if looking for season, look for more pages
        if mode == "Season" and not manual_search:
            self.max_back_pages = 10

        for search_string in search_strings[mode]:
            if mode != "RSS":
                log.debug("Search string: {0}".format(search_string.decode("utf-8")))

            # Remove season / episode from search (not supported by tracker)
            search_str = re.sub(
                r"\d+$" if anime else r"[S|E]\d\d", "", search_string
            ).strip()
            search_params["searchstr"] = search_str
            next_page = 1
            has_next_page = True

            while has_next_page and next_page <= self.max_back_pages:
                search_params["page"] = next_page
                log.debug("Searching page: {0}".format(next_page))
                next_page += 1

                response = self.session.get(self.urls["search"], params=search_params)
                if not response or not response.content:
                    log.debug("No data returned from provider")
                    continue

                result = self.parse(response.content, mode)
                has_next_page = result["has_next_page"]
                items += result["items"]

            results += items

    return results


# Traceback (AttributeError)
2019-03-15 05:03:02 ERROR    TORNADO :: [94fae84] API :: AttributeError("'str' object has no attribute 'decode'")
Traceback (most recent call last):
File "/Users/matt/Builds/medusa/medusa/server/api/v1/core.py", line 142, in get
out_dict = _call_dispatcher(args, kwargs)
File "/Users/matt/Builds/medusa/medusa/server/api/v1/core.py", line 212, in call_dispatcher
cur_out_dict = func(cur_args, cur_kwargs).run()  # call function and get response
File "/Users/matt/Builds/medusa/medusa/server/api/v1/core.py", line 1308, in run
failed=self.failed, proc_type=self.type
File "/Users/matt/Builds/medusa/medusa/process_tv.py", line 145, in process
ignore_subs=ignore_subs)
File "/Users/matt/Builds/medusa/medusa/process_tv.py", line 335, in process_files
self.process_media(path, self.video_files, force, is_priority, ignore_subs)
File "/Users/matt/Builds/medusa/medusa/process_tv.py", line 556, in process_media
self.result = processor.process()
File "/Users/matt/Builds/medusa/medusa/post_processor.py", line 1289, in process
notifiers.notify_download(ep_obj)
File "/Users/matt/Builds/medusa/medusa/notifiers/__init__.py", line 100, in notify_download
n.notify_download(ep_obj)
File "/Users/matt/Builds/medusa/medusa/notifiers/kodi.py", line 434, in notify_download
self._notify_kodi(common.notifyStrings[common.NOTIFY_DOWNLOAD], ep_obj.pretty_name_with_quality())
File "/Users/matt/Builds/medusa/medusa/notifiers/kodi.py", line 133, in _notify_kodi
result += cur_host + ':' + notify_result['result'].decode('utf-8')
AttributeError: 'str' object has no attribute 'decode'
2019-03-15 05:03:02 INFO     TORNADO :: [94fae84] Selected poster for series 275557 (score=3.3221824253021945, score_bay=5.644364850604389, rating=6.8, votes=20, res=680x1000): https://www.thetvdb.com/banners/posters/275557-6.jpg
2019-03-15 05:03:02 INFO     TORNADO :: [94fae84] Selected fanart for series 275557 (score=3.9240400637751476, score_bay=5.848080127550295, rating=6.9, votes=9, res=1920x1080): https://www.thetvdb.com/banners/fanart/original/275557-8.jpg
2019-03-15 05:03:00 INFO     TORNADO :: [94fae84] 275557: Changed modify date of Broad.City.S05E08.Sleep.No.More.720p.WEB-DL.mkv to series air date Mar 14,2019 (22:00)
2019-03-15 05:02:46 INFO     TORNADO :: [94fae84] Release name (broad.city.s05e08.720p.web.x264-tbs) found from file (broad.city.s05e08.720p.web.x264-tbs.nfo)
2019-03-15 05:02:46 INFO     TORNADO :: [94fae84] This download is marked a priority download so I'm going to replace an existing file if I find one
2019-03-15 05:02:46 INFO     TORNADO :: [94fae84] New size: 432.58 MB
2019-03-15 05:02:46 INFO     TORNADO :: [94fae84] New file: /Volumes/dvorak.8tb/SABnzbd/tv/Broad.City.S05E08.720p.WEB.x264-TBS[TGx]/broad.city.s05e08.720p.web.x264-tbs.mkv
2019-03-15 05:02:46 INFO     TORNADO :: [94fae84] Processing /Volumes/dvorak.8tb/SABnzbd/tv/Broad.City.S05E08.720p.WEB.x264-TBS[TGx]/broad.city.s05e08.720p.web.x264-tbs.mkv

# Fixed code
def search(self, search_strings, age=0, ep_obj=None, **kwargs):
    """
    Search a provider and parse the results.

    :param search_strings: A dict with mode (key) and the search value (value)
    :param age: Not used
    :param ep_obj: Informations about the episode being searched (when not RSS)

    :returns: A list of search results (structure)
    """
    results = []
    if not self.login():
        return results

    manual_search = kwargs.get("manual_search")
    if manual_search:
        self.max_back_pages = 20

    anime = False
    if ep_obj and ep_obj.series:
        anime = ep_obj.series.anime == 1

    search_params = {
        "order_by": "time",
        "order_way": "desc",
        "group_results": 0,
        "action": "basic",
        "searchsubmit": 1,
    }

    if "RSS" in search_strings.keys():
        search_params["filter_cat[14]"] = 1  # anime
        search_params["filter_cat[2]"] = 1  # tv shows
    elif anime:
        search_params["filter_cat[14]"] = 1  # anime
    else:
        search_params["filter_cat[2]"] = 1  # tv shows

    for mode in search_strings:
        items = []
        log.debug("Search mode: {0}".format(mode))

        # if looking for season, look for more pages
        if mode == "Season" and not manual_search:
            self.max_back_pages = 10

        for search_string in search_strings[mode]:
            if mode != "RSS":
                log.debug("Search string: {search}", {"search": search_string})

            # Remove season / episode from search (not supported by tracker)
            search_str = re.sub(
                r"\d+$" if anime else r"[S|E]\d\d", "", search_string
            ).strip()
            search_params["searchstr"] = search_str
            next_page = 1
            has_next_page = True

            while has_next_page and next_page <= self.max_back_pages:
                search_params["page"] = next_page
                log.debug("Searching page: {0}".format(next_page))
                next_page += 1

                response = self.session.get(self.urls["search"], params=search_params)
                if not response or not response.content:
                    log.debug("No data returned from provider")
                    continue

                result = self.parse(response.content, mode)
                has_next_page = result["has_next_page"]
                items += result["items"]

            results += items

    return results