Example #1
0
 def get_total(self, imdb_url, language):
     header = {"Accept-Language": language}
     if imdb_url.startswith(self.urls["keyword"]):
         results = self.send_request(
             imdb_url, header).xpath("//div[@class='desc']/text()")
         total = None
         for result in results:
             if "title" in result:
                 try:
                     total = int(re.findall("(\\d+) title", result)[0])
                     break
                 except IndexError:
                     pass
         if total is None:
             raise Failed(f"IMDb Error: No Results at URL: {imdb_url}")
         return total, 50
     else:
         try:
             results = self.send_request(imdb_url, header).xpath(
                 "//div[@class='desc']/span/text()")[0].replace(",", "")
         except IndexError:
             raise Failed(f"IMDb Error: Failed to parse URL: {imdb_url}")
         try:
             total = int(re.findall("(\\d+) title", results)[0])
         except IndexError:
             raise Failed(f"IMDb Error: No Results at URL: {imdb_url}")
         return total, 250
Example #2
0
 def __init__(self, params):
     self.url = params["url"]
     self.token = params["token"]
     self.version = params["version"]
     self.base_url = f"{self.url}/api{'/v3' if self.version == 'v3' else ''}/"
     try:
         result = requests.get(f"{self.base_url}system/status",
                               params={
                                   "apikey": f"{self.token}"
                               }).json()
     except Exception:
         util.print_stacktrace()
         raise Failed(
             f"Radarr Error: Could not connect to Radarr at {self.url}")
     if "error" in result and result["error"] == "Unauthorized":
         raise Failed("Radarr Error: Invalid API Key")
     if "version" not in result:
         raise Failed("Radarr Error: Unexpected Response Check URL")
     self.add = params["add"]
     self.root_folder_path = params["root_folder_path"]
     self.monitor = params["monitor"]
     self.availability = params["availability"]
     self.quality_profile_id = self.get_profile_id(
         params["quality_profile"])
     self.tag = params["tag"]
     self.tags = self.get_tags()
     self.search = params["search"]
Example #3
0
 def get_tmdb_ids(self, method, data, language):
     if method == "letterboxd_list":
         logger.info(f"Processing Letterboxd List: {data}")
         items = self._parse_list(data, language)
         total_items = len(items)
         if total_items > 0:
             ids = []
             for i, item in enumerate(items, 1):
                 letterboxd_id, slug = item
                 logger.ghost(f"Finding TMDb ID {i}/{total_items}")
                 tmdb_id = None
                 expired = None
                 if self.config.Cache:
                     tmdb_id, expired = self.config.Cache.query_letterboxd_map(
                         letterboxd_id)
                 if not tmdb_id or expired is not False:
                     try:
                         tmdb_id = self._tmdb(f"{base_url}{slug}", language)
                     except Failed as e:
                         logger.error(e)
                         continue
                     if self.config.Cache:
                         self.config.Cache.update_letterboxd_map(
                             expired, letterboxd_id, tmdb_id)
                 ids.append((tmdb_id, "tmdb"))
             logger.info(f"Processed {total_items} TMDb IDs")
             return ids
         else:
             raise Failed(
                 f"Letterboxd Error: No List Items found in {data}")
     else:
         raise Failed(f"Letterboxd Error: Method {method} not supported")
Example #4
0
 def _request(self, imdb_id=None, tmdb_id=None, is_movie=True, ignore_cache=False):
     params = {"apikey": self.apikey}
     if imdb_id:
         params["i"] = imdb_id
         key = imdb_id
     elif tmdb_id:
         params["tm"] = tmdb_id
         params["m"] = "movie" if is_movie else "show"
         key = f"{'tm' if is_movie else 'ts'}{tmdb_id}"
     else:
         raise Failed("MdbList Error: Either IMDb ID or TMDb ID and TMDb Type Required")
     expired = None
     if self.config.Cache and not ignore_cache:
         mdb_dict, expired = self.config.Cache.query_mdb(key, self.expiration)
         if mdb_dict and expired is False:
             return MDbObj(mdb_dict)
     if self.config.trace_mode:
         logger.debug(f"ID: {key}")
     response = self.config.get_json(api_url, params=params)
     if "response" in response and response["response"] is False:
         if response["error"] == "API Limit Reached!":
             self.limit = True
         raise Failed(f"MdbList Error: {response['error']}")
     else:
         mdb = MDbObj(response)
         if self.config.Cache and not ignore_cache:
             self.config.Cache.update_mdb(expired, key, mdb, self.expiration)
         return mdb
Example #5
0
 def check_for_attribute(data, attribute, parent=None, test_list=None, options="", default=None, do_print=True, default_is_none=False, req_default=False, var_type="str", throw=False, save=True):
     message = ""
     endline = ""
     if parent is not None:
         if parent in data:
             data = data[parent]
         else:
             data = None
             do_print = False
             save = False
     text = "{} attribute".format(attribute) if parent is None else "{} sub-attribute {}".format(parent, attribute)
     if data is None or attribute not in data:
         message = "{} not found".format(text)
         if parent and save is True:
             new_config, ind, bsi = yaml.util.load_yaml_guess_indent(open(self.config_path))
             endline = "\n{} sub-attribute {} added to config".format(parent, attribute)
             if parent not in new_config:                                        new_config = {parent: {attribute: default}}
             elif not new_config[parent]:                                        new_config[parent] = {attribute: default}
             elif attribute not in new_config[parent]:                           new_config[parent][attribute] = default
             else:                                                               endLine = ""
             yaml.round_trip_dump(new_config, open(self.config_path, "w"), indent=ind, block_seq_indent=bsi)
     elif not data[attribute] and data[attribute] != False:
         if default_is_none is True:                                         return None
         else:                                                               message = "{} is blank".format(text)
     elif var_type == "bool":
         if isinstance(data[attribute], bool):                               return data[attribute]
         else:                                                               message = "{} must be either true or false".format(text)
     elif var_type == "int":
         if isinstance(data[attribute], int) and data[attribute] > 0:        return data[attribute]
         else:                                                               message = "{} must an integer > 0".format(text)
     elif var_type == "path":
         if os.path.exists(os.path.abspath(data[attribute])):                return data[attribute]
         else:                                                               message = "Path {} does not exist".format(os.path.abspath(data[attribute]))
     elif var_type == "list":                                            return util.get_list(data[attribute])
     elif var_type == "listpath":
         temp_list = [path for path in util.get_list(data[attribute], split=True) if os.path.exists(os.path.abspath(path))]
         if len(temp_list) > 0:                                              return temp_list
         else:                                                               message = "No Paths exist"
     elif var_type == "lowerlist":                                       return util.get_list(data[attribute], lower=True)
     elif test_list is None or data[attribute] in test_list:             return data[attribute]
     else:                                                               message = "{}: {} is an invalid input".format(text, data[attribute])
     if var_type == "path" and default and os.path.exists(os.path.abspath(default)):
         return default
     elif var_type == "path" and default:
         default = None
         message = "neither {} or the default path {} could be found".format(data[attribute], default)
     if default is not None or default_is_none:
         message = message + " using {} as default".format(default)
     message = message + endline
     if req_default and default is None:
         raise Failed("Config Error: {} attribute must be set under {} globally or under this specific Library".format(attribute, parent))
     if (default is None and not default_is_none) or throw:
         if len(options) > 0:
             message = message + "\n" + options
         raise Failed("Config Error: {}".format(message))
     if do_print:
         util.print_multiline("Config Warning: {}".format(message))
         if attribute in data and data[attribute] and test_list is not None and data[attribute] not in test_list:
             util.print_multiline(options)
     return default
Example #6
0
 def get_tvdb_ids_from_url(self, tvdb_url, language):
     show_ids = []
     movie_ids = []
     tvdb_url = tvdb_url.strip()
     if tvdb_url.startswith((self.list_url, self.alt_list_url)):
         try:
             items = self.send_request(tvdb_url, language).xpath("//div[@class='col-xs-12 col-sm-12 col-md-8 col-lg-8 col-md-pull-4']/div[@class='row']")
             for item in items:
                 title = item.xpath(".//div[@class='col-xs-12 col-sm-9 mt-2']//a/text()")[0]
                 item_url = item.xpath(".//div[@class='col-xs-12 col-sm-9 mt-2']//a/@href")[0]
                 if item_url.startswith("/series/"):
                     try:                                                    show_ids.append(self.get_series(language, tvdb_url="{}{}".format(self.site_url, item_url)).id)
                     except Failed as e:                                     logger.error("{} for series {}".format(e, title))
                 elif item_url.startswith("/movies/"):
                     try:
                         tmdb_id = self.get_movie(language, tvdb_url="{}{}".format(self.site_url, item_url)).tmdb_id
                         if tmdb_id:                                             movie_ids.append(tmdb_id)
                         else:                                                   raise Failed("TVDb Error: TMDb ID not found from TVDb URL: {}".format(tvdb_url))
                     except Failed as e:
                         logger.error("{} for series {}".format(e, title))
                 else:
                     logger.error("TVDb Error: Skipping Movie: {}".format(title))
             if len(show_ids) > 0 or len(movie_ids) > 0:
                 return movie_ids, show_ids
             raise Failed("TVDb Error: No TVDb IDs found at {}".format(tvdb_url))
         except requests.exceptions.MissingSchema as e:
             util.print_stacktrace()
             raise Failed("TVDb Error: URL Lookup Failed for {}".format(tvdb_url))
     else:
         raise Failed("TVDb Error: {} must begin with {}".format(tvdb_url, self.list_url))
Example #7
0
 def __init__(self, tmdb, params):
     self.url_params = {"apikey": "{}".format(params["token"])}
     self.base_url = "{}/api{}".format(params["url"], "/v3/" if params["version"] == "v3" else "/")
     try:
         result = requests.get("{}system/status".format(self.base_url), params=self.url_params).json()
     except Exception as e:
         util.print_stacktrace()
         raise Failed("Radarr Error: Could not connect to Radarr at {}".format(params["url"]))
     if "error" in result and result["error"] == "Unauthorized":
         raise Failed("Radarr Error: Invalid API Key")
     if "version" not in result:
         raise Failed("Radarr Error: Unexpected Response Check URL")
     self.quality_profile_id = None
     profiles = ""
     for profile in self.send_get("{}{}".format(self.base_url, "qualityProfile" if params["version"] == "v3" else "profile")):
         if len(profiles) > 0:
             profiles += ", "
         profiles += profile["name"]
         if profile["name"] == params["quality_profile"]:
             self.quality_profile_id = profile["id"]
     if not self.quality_profile_id:
         raise Failed("Radarr Error: quality_profile: {} does not exist in radarr. Profiles available: {}".format(params["quality_profile"], profiles))
     self.tmdb = tmdb
     self.url = params["url"]
     self.version = params["version"]
     self.token = params["token"]
     self.root_folder_path = params["root_folder_path"]
     self.add = params["add"]
     self.search = params["search"]
     self.tag = params["tag"]
Example #8
0
 def _request(self, query, variables, level=1):
     if self.config.trace_mode:
         logger.debug(f"Query: {query}")
         logger.debug(f"Variables: {variables}")
     response = self.config.post(base_url,
                                 json={
                                     "query": query,
                                     "variables": variables
                                 })
     json_obj = response.json()
     if self.config.trace_mode:
         logger.debug(f"Response: {json_obj}")
     if "errors" in json_obj:
         if json_obj['errors'][0]['message'] == "Too Many Requests.":
             wait_time = int(response.headers["Retry-After"]
                             ) if "Retry-After" in response.headers else 0
             time.sleep(wait_time if wait_time > 0 else 10)
             if level < 6:
                 return self._request(query, variables, level=level + 1)
             raise Failed(f"AniList Error: Connection Failed")
         else:
             raise Failed(
                 f"AniList Error: {json_obj['errors'][0]['message']}")
     else:
         time.sleep(60 / 90)
     return json_obj
Example #9
0
 def _request(self, webhooks, json):
     if self.config.trace_mode:
         logger.separator("Webhooks", space=False, border=False)
         logger.debug("")
         logger.debug(f"JSON: {json}")
     for webhook in list(set(webhooks)):
         response = None
         if self.config.trace_mode:
             logger.debug(f"Webhook: {webhook}")
         if webhook == "notifiarr":
             if self.notifiarr:
                 url, params = self.notifiarr.get_url("notification/pmm/")
                 for x in range(6):
                     response = self.config.get(url, json=json, params=params)
                     if response.status_code < 500:
                         break
         else:
             response = self.config.post(webhook, json=json)
         if response:
             try:
                 response_json = response.json()
                 if self.config.trace_mode:
                     logger.debug(f"Response: {response_json}")
                 if "result" in response_json and response_json["result"] == "error" and "details" in response_json and "response" in response_json["details"]:
                     raise Failed(f"Notifiarr Error: {response_json['details']['response']}")
                 if response.status_code >= 400 or ("result" in response_json and response_json["result"] == "error"):
                     raise Failed(f"({response.status_code} [{response.reason}]) {response_json}")
             except JSONDecodeError:
                 if response.status_code >= 400:
                     raise Failed(f"({response.status_code} [{response.reason}])")
Example #10
0
 def _authorization(self):
     url = f"https://trakt.tv/oauth/authorize?response_type=code&client_id={self.client_id}&redirect_uri={redirect_uri_encoded}"
     logger.info(f"Navigate to: {url}")
     logger.info(
         "If you get an OAuth error your client_id or client_secret is invalid"
     )
     webbrowser.open(url, new=2)
     try:
         pin = util.logger_input("Trakt pin (case insensitive)",
                                 timeout=300).strip()
     except TimeoutExpired:
         raise Failed("Input Timeout: Trakt pin required.")
     if not pin: raise Failed("Trakt Error: No input Trakt pin required.")
     json = {
         "code": pin,
         "client_id": self.client_id,
         "client_secret": self.client_secret,
         "redirect_uri": redirect_uri,
         "grant_type": "authorization_code"
     }
     response = self.config.post(
         f"{base_url}/oauth/token",
         json=json,
         headers={"Content-Type": "application/json"})
     if response.status_code != 200:
         raise Failed(
             "Trakt Error: Invalid trakt pin. If you're sure you typed it in correctly your client_id or client_secret may be invalid"
         )
     elif not self._save(response.json()):
         raise Failed("Trakt Error: New Authorization Failed")
Example #11
0
 def _genre(self, genre_id, limit):
     data = self._jiken_request(f"/genre/anime/{genre_id}")
     if "item_count" not in data:
         raise Failed(
             f"MyAnimeList Error: No MyAnimeList IDs for Genre ID: {genre_id}"
         )
     total_items = data["item_count"]
     if total_items < limit or limit <= 0:
         limit = total_items
     mal_ids = []
     num_of_pages = math.ceil(int(limit) / 100)
     current_page = 1
     chances = 0
     while current_page <= num_of_pages:
         if chances > 6:
             logger.debug(data)
             raise Failed("AniList Error: Connection Failed")
         start_num = (current_page - 1) * 100 + 1
         util.print_return(
             f"Parsing Page {current_page}/{num_of_pages} {start_num}-{limit if current_page == num_of_pages else current_page * 100}"
         )
         if current_page > 1:
             data = self._jiken_request(
                 f"/genre/anime/{genre_id}/{current_page}")
         if "anime" in data:
             chances = 0
             mal_ids.extend([anime["mal_id"] for anime in data["anime"]])
             if len(mal_ids) > limit:
                 return mal_ids[:limit]
             current_page += 1
         else:
             chances += 1
     util.print_end()
     return mal_ids
Example #12
0
 def get_authorization(self):
     code_verifier = secrets.token_urlsafe(100)[:128]
     url = f"{self.urls['oauth_authorize']}?response_type=code&client_id={self.client_id}&code_challenge={code_verifier}"
     logger.info("")
     logger.info(f"Navigate to: {url}")
     logger.info("")
     logger.info("Login and click the Allow option. You will then be redirected to a localhost")
     logger.info("url that most likely won't load, which is fine. Copy the URL and paste it below")
     webbrowser.open(url, new=2)
     try:                                url = util.logger_input("URL").strip()
     except TimeoutExpired:              raise Failed("Input Timeout: URL required.")
     if not url:                         raise Failed("MyAnimeList Error: No input MyAnimeList code required.")
     match = re.search("code=([^&]+)", str(url))
     if not match:
         raise Failed("MyAnimeList Error: Invalid URL")
     code = match.group(1)
     data = {
         "client_id": self.client_id,
         "client_secret": self.client_secret,
         "code": code,
         "code_verifier": code_verifier,
         "grant_type": "authorization_code"
     }
     new_authorization = self.oauth_request(data)
     if "error" in new_authorization:
         raise Failed("MyAnimeList Error: Invalid code")
     if not self.save_authorization(new_authorization):
         raise Failed("MyAnimeList Error: New Authorization Failed")
Example #13
0
 def convert_from_tmdb(self, tmdb_id, convert_to, is_movie):
     try:
         id_to_return = self.Movie.external_ids(tmdb_id)[convert_to] if is_movie else self.TV.external_ids(tmdb_id)[convert_to]
         if not id_to_return or (convert_to == "tvdb_id" and id_to_return == 0):
             raise Failed(f"TMDb Error: No {convert_to.upper().replace('B_', 'b ')} found for TMDb ID {tmdb_id}")
         return id_to_return
     except TMDbException:
         raise Failed(f"TMDb Error: {'Movie' if is_movie else 'Show'} TMDb ID: {tmdb_id} not found")
Example #14
0
 def _user_items(self, list_type, data, is_movie):
     try:
         items = self._request(f"/users/{data}/{list_type}/{'movies' if is_movie else 'shows'}")
     except Failed:
         raise Failed(f"Trakt Error: User {data} not found")
     if len(items) == 0:
         raise Failed(f"Trakt Error: {data}'s {list_type.capitalize()} is empty")
     return self._parse(items, item_type="movie" if is_movie else "show")
Example #15
0
 def _user_list(self, data):
     try:
         items = self._request(f"{requests.utils.urlparse(data).path}/items")
     except Failed:
         raise Failed(f"Trakt Error: List {data} not found")
     if len(items) == 0:
         raise Failed(f"Trakt Error: List {data} is empty")
     return self._parse(items)
Example #16
0
    def __init__(self, tvdb_url, language, is_movie, TVDb):
        tvdb_url = tvdb_url.strip()
        if not is_movie and tvdb_url.startswith(
            (TVDb.series_url, TVDb.alt_series_url, TVDb.series_id_url)):
            self.media_type = "Series"
        elif is_movie and tvdb_url.startswith(
            (TVDb.movies_url, TVDb.alt_movies_url, TVDb.movie_id_url)):
            self.media_type = "Movie"
        else:
            raise Failed("TVDb Error: {} must begin with {}".format(
                tvdb_url, TVDb.movies_url if is_movie else TVDb.series_url))

        response = TVDb.send_request(tvdb_url, language)
        results = response.xpath(
            "//*[text()='TheTVDB.com {} ID']/parent::node()/span/text()".
            format(self.media_type))
        if len(results) > 0:
            self.id = int(results[0])
        else:
            raise Failed(
                "TVDb Error: Could not find a TVDb {} ID at the URL {}".format(
                    self.media_type, tvdb_url))

        results = response.xpath(
            "//div[@class='change_translation_text' and @data-language='eng']/@data-title"
        )
        if len(results) > 0 and len(results[0]) > 0:
            self.title = results[0]
        else:
            raise Failed("TVDb Error: Name not found from TVDb URL: {}".format(
                tvdb_url))

        results = response.xpath(
            "//div[@class='row hidden-xs hidden-sm']/div/img/@src")
        self.poster_path = results[0] if len(results) > 0 and len(
            results[0]) > 0 else None

        tmdb_id = None
        if is_movie:
            results = response.xpath("//*[text()='TheMovieDB.com']/@href")
            if len(results) > 0:
                try:
                    tmdb_id = util.regex_first_int(results[0], "TMDb ID")
                except Failed as e:
                    logger.error(e)
            if not tmdb_id:
                results = response.xpath("//*[text()='IMDB']/@href")
                if len(results) > 0:
                    try:
                        tmdb_id = TVDb.convert_from_imdb(
                            util.get_id_from_imdb_url(results[0]), language)
                    except Failed as e:
                        logger.error(e)
        self.tmdb_id = tmdb_id
        self.tvdb_url = tvdb_url
        self.language = language
        self.is_movie = is_movie
        self.TVDb = TVDb
Example #17
0
 def mal_to_anidb(self, mal_id):
     anime_ids = self._arms_ids(mal_ids=mal_id)
     if anime_ids[0] is None:
         raise Failed(
             f"Arms Error: MyAnimeList ID: {mal_id} does not exist")
     if anime_ids[0]["anidb"] is None:
         raise Failed(
             f"Arms Error: No AniDB ID for MyAnimeList ID: {mal_id}")
     return anime_ids[0]["anidb"]
Example #18
0
 def get_item(self, data, year=None):
     if isinstance(data, (int, Movie, Show)):
         try:                                        return self.fetchItem(data.ratingKey if isinstance(data, (Movie, Show)) else data)
         except BadRequest:                          raise Failed("Plex Error: Item {} not found".format(data))
     else:
         item_list = self.search(title=data) if year is None else self.search(data, year=year)
         item = util.choose_from_list(item_list, "movie" if self.is_movie else "show", data)
         if item:                                    return item
         else:                                       raise Failed("Plex Error: Item {} not found".format(data))
Example #19
0
    def get_imdb_ids_from_url(self, imdb_url, language, limit):
        imdb_url = imdb_url.strip()
        if not imdb_url.startswith(
                self.urls["list"]) and not imdb_url.startswith(
                    self.urls["search"]):
            raise Failed(
                f"IMDb Error: {imdb_url} must begin with either:\n| {self.urls['list']} (For Lists)\n| {self.urls['search']} (For Searches)"
            )

        if imdb_url.startswith(self.urls["list"]):
            try:
                list_id = re.search("(\\d+)", str(imdb_url)).group(1)
            except AttributeError:
                raise Failed(
                    f"IMDb Error: Failed to parse List ID from {imdb_url}")
            current_url = f"{self.urls['search']}lists=ls{list_id}"
        else:
            current_url = imdb_url
        header = {"Accept-Language": language}
        length = 0
        imdb_ids = []
        try:
            results = self.send_request(
                current_url,
                header).xpath("//div[@class='desc']/span/text()")[0].replace(
                    ",", "")
        except IndexError:
            raise Failed(f"IMDb Error: Failed to parse URL: {imdb_url}")
        try:
            total = int(re.findall("(\\d+) title", results)[0])
        except IndexError:
            raise Failed(f"IMDb Error: No Results at URL: {imdb_url}")
        if "&start=" in current_url:
            current_url = re.sub("&start=\\d+", "", current_url)
        if "&count=" in current_url:
            current_url = re.sub("&count=\\d+", "", current_url)
        if limit < 1 or total < limit: limit = total
        remainder = limit % 250
        if remainder == 0: remainder = 250
        num_of_pages = math.ceil(int(limit) / 250)
        for i in range(1, num_of_pages + 1):
            start_num = (i - 1) * 250 + 1
            length = util.print_return(
                length,
                f"Parsing Page {i}/{num_of_pages} {start_num}-{limit if i == num_of_pages else i * 250}"
            )
            response = self.send_request(
                f"{current_url}&count={remainder if i == num_of_pages else 250}&start={start_num}",
                header)
            imdb_ids.extend(
                response.xpath(
                    "//div[contains(@class, 'lister-item-image')]//a/img//@data-tconst"
                ))
        util.print_end(length)
        if imdb_ids: return imdb_ids
        else: raise Failed(f"IMDb Error: No Movies Found at {imdb_url}")
Example #20
0
 def __init__(self, params):
     try:
         response = requests.get(f"{params['url']}/api/v2?apikey={params['apikey']}&cmd=get_library_names").json()
     except Exception:
         util.print_stacktrace()
         raise Failed("Tautulli Error: Invalid url")
     if response["response"]["result"] != "success":
         raise Failed(f"Tautulli Error: {response['response']['message']}")
     self.url = params["url"]
     self.apikey = params["apikey"]
Example #21
0
 def get_tmdb(self, letterboxd_url, language):
     response = self.send_request(letterboxd_url, language)
     ids = response.xpath("//a[@data-track-action='TMDb']/@href")
     if len(ids) > 0 and ids[0]:
         if "themoviedb.org/movie" in ids[0]:
             return util.regex_first_int(ids[0], "TMDB Movie ID")
         raise Failed(
             f"Letterboxd Error: TMDb Movie ID not found in {ids[0]}")
     raise Failed(
         f"Letterboxd Error: TMDb Movie ID not found at {letterboxd_url}")
Example #22
0
 def get_items(self, method, data, status_message=True):
     if status_message:
         logger.debug(f"Data: {data}")
     pretty = util.pretty_names[
         method] if method in util.pretty_names else method
     if method == "mal_id":
         mal_ids = [data]
         if status_message:
             logger.info(f"Processing {pretty}: {data}")
     elif method in mal_ranked_name:
         mal_ids = self.get_ranked(mal_ranked_name[method], data)
         if status_message:
             logger.info(f"Processing {pretty}: {data} Anime")
     elif method == "mal_season":
         mal_ids = self.get_season(data["season"], data["year"],
                                   data["sort_by"], data["limit"])
         if status_message:
             logger.info(
                 f"Processing {pretty}: {data['limit']} Anime from {util.pretty_seasons[data['season']]} {data['year']} sorted by {pretty_names[data['sort_by']]}"
             )
     elif method == "mal_suggested":
         mal_ids = self.get_suggestions(data)
         if status_message:
             logger.info(f"Processing {pretty}: {data} Anime")
     elif method == "mal_userlist":
         mal_ids = self.get_userlist(data["username"], data["status"],
                                     data["sort_by"], data["limit"])
         if status_message:
             logger.info(
                 f"Processing {pretty}: {data['limit']} Anime from {self.get_username() if data['username'] == '@me' else data['username']}'s {pretty_names[data['status']]} list sorted by {pretty_names[data['sort_by']]}"
             )
     else:
         raise Failed(f"MyAnimeList Error: Method {method} not supported")
     show_ids = []
     movie_ids = []
     for mal_id in mal_ids:
         try:
             ids = self.MyAnimeListIDList.find_mal_ids(mal_id)
             if "thetvdb_id" in ids and int(ids["thetvdb_id"]) > 0:
                 show_ids.append(int(ids["thetvdb_id"]))
             elif "themoviedb_id" in ids and int(ids["themoviedb_id"]) > 0:
                 movie_ids.append(int(ids["themoviedb_id"]))
             else:
                 raise Failed(
                     f"MyAnimeList Error: MyAnimeList ID: {mal_id} has no other IDs associated with it"
                 )
         except Failed as e:
             if status_message:
                 logger.error(e)
     if status_message:
         logger.debug(f"MyAnimeList IDs Found: {mal_ids}")
         logger.debug(f"Shows Found: {show_ids}")
         logger.debug(f"Movies Found: {movie_ids}")
     return movie_ids, show_ids
 def validate_icheckmovies_lists(self, icheckmovies_lists, language):
     valid_lists = []
     for icheckmovies_list in util.get_list(icheckmovies_lists, split=False):
         list_url = icheckmovies_list.strip()
         if not list_url.startswith(base_url):
             raise Failed(f"ICheckMovies Error: {list_url} must begin with: {base_url}")
         elif len(self._parse_list(list_url, language)) > 0:
             valid_lists.append(list_url)
         else:
             raise Failed(f"ICheckMovies Error: {list_url} failed to parse")
     return valid_lists
Example #24
0
 def get_user_lists(self, data):
     try:
         items = self._request(f"/users/{data}/lists")
     except Failed:
         raise Failed(f"Trakt Error: User {data} not found")
     if len(items) == 0:
         raise Failed(f"Trakt Error: User {data} has no lists")
     return {
         self.build_user_url(data, i["ids"]["slug"]): i["name"]
         for i in items
     }
 def _tmdb(self, flixpatrol_url, language):
     ids = self._request(flixpatrol_url, language,
                         "//script[@type='application/ld+json']/text()")
     if len(ids) > 0 and ids[0]:
         if "https://www.themoviedb.org" in ids[0]:
             return util.regex_first_int(
                 ids[0].split("https://www.themoviedb.org")[1],
                 "TMDB Movie ID")
         raise Failed(
             f"FlixPatrol Error: TMDb Movie ID not found in {ids[0]}")
     raise Failed(
         f"FlixPatrol Error: TMDb Movie ID not found at {flixpatrol_url}")
Example #26
0
 def get_items(self, method, data, status_message=True):
     if status_message:
         logger.debug(f"Data: {data}")
     pretty = util.pretty_names[
         method] if method in util.pretty_names else method
     if method == "anilist_id":
         mal_id, name = self.anilist_id(data)
         mal_ids = [mal_id]
         if status_message:
             logger.info(f"Processing {pretty}: ({data}) {name}")
     elif method in ["anilist_popular", "anilist_top_rated"]:
         mal_ids = self.popular(
             data) if method == "anilist_popular" else self.top_rated(data)
         if status_message:
             logger.info(f"Processing {pretty}: {data} Anime")
     elif method == "anilist_season":
         mal_ids = self.season(data["season"], data["year"],
                               data["sort_by"], data["limit"])
         if status_message:
             logger.info(
                 f"Processing {pretty}: {data['limit']} Anime from {util.pretty_seasons[data['season']]} {data['year']} sorted by {util.anilist_pretty[data['sort_by']]}"
             )
     elif method in ["anilist_studio", "anilist_relations"]:
         if method == "anilist_studio": mal_ids, name = self.studio(data)
         else: mal_ids, _, name = self.relations(data)
         if status_message:
             logger.info(
                 f"Processing {pretty}: ({data}) {name} ({len(mal_ids)} Anime)"
             )
     else:
         raise Failed(f"AniList Error: Method {method} not supported")
     show_ids = []
     movie_ids = []
     for mal_id in mal_ids:
         try:
             ids = self.config.MyAnimeListIDList.find_mal_ids(mal_id)
             if "thetvdb_id" in ids and int(ids["thetvdb_id"]) > 0:
                 show_ids.append(int(ids["thetvdb_id"]))
             elif "themoviedb_id" in ids and int(ids["themoviedb_id"]) > 0:
                 movie_ids.append(int(ids["themoviedb_id"]))
             else:
                 raise Failed(
                     f"MyAnimeList Error: MyAnimeList ID: {mal_id} has no other IDs associated with it"
                 )
         except Failed as e:
             if status_message:
                 logger.error(e)
     if status_message:
         logger.debug(f"MyAnimeList IDs Found: {mal_ids}")
         logger.debug(f"Shows Found: {show_ids}")
         logger.debug(f"Movies Found: {movie_ids}")
     return movie_ids, show_ids
Example #27
0
 def validate_letterboxd_lists(self, letterboxd_lists, language):
     valid_lists = []
     for letterboxd_list in util.get_list(letterboxd_lists, split=False):
         list_url = letterboxd_list.strip()
         if not list_url.startswith(base_url):
             raise Failed(
                 f"Letterboxd Error: {list_url} must begin with: {base_url}"
             )
         elif len(self._parse_list(list_url, language)) > 0:
             valid_lists.append(list_url)
         else:
             raise Failed(f"Letterboxd Error: {list_url} failed to parse")
     return valid_lists
 def __init__(self, params):
     try:
         response = requests.get(
             "{}/api/v2?apikey={}&cmd=get_library_names".format(
                 params["url"], params["apikey"])).json()
     except Exception as e:
         util.print_stacktrace()
         raise Failed("Tautulli Error: Invalid url")
     if response["response"]["result"] != "success":
         raise Failed("Tautulli Error: {}".format(
             response["response"]["message"]))
     self.url = params["url"]
     self.apikey = params["apikey"]
Example #29
0
 def __init__(self, config, params):
     self.config = config
     self.apikey = params["apikey"]
     self.develop = params["develop"]
     self.test = params["test"]
     url, _ = self.get_url("user/validate/")
     response = self.config.get(url)
     response_json = response.json()
     if response.status_code >= 400 or ("result" in response_json and response_json["result"] == "error"):
         logger.debug(f"Response: {response_json}")
         raise Failed(f"({response.status_code} [{response.reason}]) {response_json}")
     if not params["test"] and not response_json["details"]["response"]:
         raise Failed("Notifiarr Error: Invalid apikey")
Example #30
0
 def validate_imdb_url(self, imdb_url, language):
     imdb_url = imdb_url.strip()
     if not imdb_url.startswith(
             self.urls["list"]) and not imdb_url.startswith(
                 self.urls["search"]) and not imdb_url.startswith(
                     self.urls["keyword"]):
         raise Failed(
             f"IMDb Error: {imdb_url} must begin with either:\n{self.urls['list']} (For Lists)\n{self.urls['search']} (For Searches)\n{self.urls['keyword']} (For Keyword Searches)"
         )
     total, _ = self.get_total(self.fix_url(imdb_url), language)
     if total > 0:
         return imdb_url
     raise Failed(f"IMDb Error: {imdb_url} failed to parse")