Example #1
0
    def update_show_indexer_metadata(self, show_obj):
        if self.show_metadata and show_obj and self._has_show_metadata(
                show_obj):
            logger.debug("Metadata provider " + self.name +
                         " updating show indexer info metadata file for " +
                         show_obj.name)

            nfo_file_path = self.get_show_file_path(show_obj)

            try:
                with open(nfo_file_path, 'rb') as xmlFileObj:
                    showXML = ElementTree.ElementTree(file=xmlFileObj)

                indexerid = showXML.find('id')

                root = showXML.getroot()
                if indexerid is not None:
                    if indexerid.text == str(show_obj.indexerid):
                        return True
                    indexerid.text = str(show_obj.indexerid)
                else:
                    ElementTree.SubElement(root,
                                           "id").text = str(show_obj.indexerid)

                # Make it purdy
                helpers.indentXML(root)

                showXML.write(nfo_file_path, encoding='UTF-8')
                helpers.chmodAsParent(nfo_file_path)

                return True
            except IOError as e:
                logger.error("Unable to write file to " + nfo_file_path +
                             " - are you sure the folder is writable? " +
                             str(e))
Example #2
0
    def update_episode_metadata(self, ep_obj):
        if self.episode_metadata and ep_obj and self._has_episode_metadata(
                ep_obj):
            logger.debug("Metadata provider " + self.name +
                         " updating episode indexer info metadata file for " +
                         ep_obj.pretty_name())
            nfo_file_path = self.get_episode_file_path(ep_obj)

            attribute_map = {
                'title': 'name',
                'aired': 'airdate',
                'season': 'season',
                'episode': 'episode',
                'showtitle': 'show.name',
                'runtime': 'show.runtime',
                'plot': 'description'
            }
            try:
                with open(nfo_file_path, 'rb') as xmlFileObj:
                    episodeXML = ElementTree.ElementTree(file=xmlFileObj)

                changed = False
                for attribute in attribute_map:
                    try:
                        if not hasattr(ep_obj, attribute_map[attribute]):
                            continue

                        node = episodeXML.find(attribute)
                        if node is None or node.text == str(
                                getattr(ep_obj, attribute_map[attribute])):
                            continue

                        node.text = str(
                            getattr(ep_obj, attribute_map[attribute]))
                        changed = True
                    except AttributeError:
                        pass

                if not changed:
                    return True

                root = episodeXML.getroot()

                # Make it purdy
                helpers.indentXML(root)

                episodeXML.write(nfo_file_path, encoding='UTF-8')
                helpers.chmodAsParent(nfo_file_path)

                return True
            except IOError as error:
                logger.warning(
                    "Unable to write file to {} - are you sure the folder is writable? {}"
                    .format(nfo_file_path, str(error)))
            except ElementTree.ParseError as error:
                logger.warning(
                    "Error parsing existing nfo file at {} - {}".format(
                        nfo_file_path, str(error)))
Example #3
0
    def dumpHTML(data):
        dumpName = os.path.join(settings.CACHE_DIR, 'custom_torrent.html')

        try:
            fileOut = open(dumpName, 'wb')
            fileOut.write(data)
            fileOut.close()
            helpers.chmodAsParent(dumpName)
        except IOError as error:
            logger.exception('Unable to save the file: {0}'.format(str(error)))
            return False

        logger.info('Saved custom_torrent html dump {0} '.format(dumpName))
        return True
Example #4
0
    def write_ep_file(self, ep_obj):
        """
        Generates and writes ep_obj's metadata under the given path with the
        given filename root. Uses the episode's name with the extension in
        _ep_nfo_extension.

        ep_obj: TVEpisode object for which to create the metadata

        file_name_path: The file name to use for this metadata. Note that the extension
                will be automatically added based on _ep_nfo_extension. This should
                include an absolute path.

        Note that this method expects that _ep_data will return an ElementTree
        object. If your _ep_data returns data in another format yo'll need to
        override this method.
        """

        data = self._ep_data(ep_obj)
        if not data:
            return False

        # def print_data(d):
        #     for child in d.getroot():
        #         print(str(child.tag), str(child.text))

        # print_data(data)

        nfo_file_path = self.get_episode_file_path(ep_obj)
        nfo_file_dir = os.path.dirname(nfo_file_path)

        try:
            if not os.path.isdir(nfo_file_dir):
                logger.debug("Metadata dir didn't exist, creating it at " +
                             nfo_file_dir)
                os.makedirs(nfo_file_dir)
                helpers.chmodAsParent(nfo_file_dir)

            logger.debug("Writing episode nfo file to " + nfo_file_path)
            nfo_file = open(nfo_file_path, 'wb')
            data.write(nfo_file, encoding='UTF-8')
            nfo_file.close()
            helpers.chmodAsParent(nfo_file_path)
        except IOError as e:
            logger.error("Unable to write file to " + nfo_file_path +
                         " - are you sure the folder is writable? " + str(e))
            return False

        return True
Example #5
0
    def write_show_file(self, show_obj):
        """
        Generates and writes show_obj's metadata under the given path to the
        filename given by get_show_file_path()

        show_obj: TVShow object for which to create the metadata

        path: An absolute or relative path where we should put the file. Note that
                the file name will be the default show_filename.

        Note that this method expects that _show_data will return an ElementTree
        object. If your _show_data returns data in another format yo'll need to
        override this method.
        """

        data = self._show_data(show_obj)

        if not data:
            return False

        nfo_file_path = self.get_show_file_path(show_obj)
        nfo_file_dir = os.path.dirname(nfo_file_path)

        try:
            if not os.path.isdir(nfo_file_dir):
                logger.debug("Metadata dir didn't exist, creating it at " +
                             nfo_file_dir)
                os.makedirs(nfo_file_dir)
                helpers.chmodAsParent(nfo_file_dir)

            logger.debug("Writing show nfo file to " + nfo_file_path)

            nfo_file = open(nfo_file_path, 'wb')

            data.write(nfo_file, encoding="utf-8", xml_declaration=True)
            nfo_file.close()
            helpers.chmodAsParent(nfo_file_path)
        except IOError as e:
            logger.error("Unable to write file to " + nfo_file_path +
                         " - are you sure the folder is writable? " + str(e))
            return False

        return True
Example #6
0
    def _write_image(image_data, image_path, overwrite=False):
        """
        Saves the data in image_data to the location image_path. Returns True/False
        to represent success or failure.

        image_data: binary image data to write to file
        image_path: file location to save the image to
        """

        # don't bother overwriting it
        if not overwrite and os.path.isfile(image_path):
            logger.debug("Image already exists, not downloading")
            return False

        image_dir = os.path.dirname(image_path)

        if not image_data:
            logger.debug(
                "Unable to retrieve image to save in {0}, skipping".format(
                    image_path))
            return False

        try:
            if not os.path.isdir(image_dir):
                logger.debug("Metadata dir didn't exist, creating it at " +
                             image_dir)
                os.makedirs(image_dir)
                helpers.chmodAsParent(image_dir)

            outFile = open(image_path, 'wb')
            outFile.write(image_data)
            outFile.close()
            helpers.chmodAsParent(image_path)
        except IOError as e:
            logger.error("Unable to write image to " + image_path +
                         " - are you sure the show folder is writable? " +
                         str(e))
            return False

        return True
Example #7
0
    def write_ep_file(self, ep_obj):
        """
        Generates and writes ep_obj's metadata under the given path with the
        given filename root. Uses the episode's name with the extension in
        _ep_nfo_extension.

        ep_obj: TVEpisode object for which to create the metadata

        filename_path: The file name to use for this metadata. Note that the extension
                will be automatically added based on _ep_nfo_extension. This should
                include an absolute path.
        """
        data = self._ep_data(ep_obj)

        if not data:
            return False

        nfo_file_path = self.get_episode_file_path(ep_obj)
        nfo_file_dir = os.path.dirname(nfo_file_path)

        try:
            if not os.path.isdir(nfo_file_dir):
                logger.debug("Metadata dir didn't exist, creating it at " +
                             nfo_file_dir)
                os.makedirs(nfo_file_dir)
                helpers.chmodAsParent(nfo_file_dir)

            logger.debug("Writing episode nfo file to " + nfo_file_path)

            data.write(nfo_file_path)
            helpers.chmodAsParent(nfo_file_path)

        except EnvironmentError as e:
            logger.error("Unable to write file to " + nfo_file_path +
                         " - are you sure the folder is writable? " + str(e))
            return False

        return True
Example #8
0
    def addNewShow(
        self,
        whichSeries=None,
        indexerLang=None,
        rootDir=None,
        defaultStatus=None,
        quality_preset=None,
        anyQualities=None,
        bestQualities=None,
        season_folders=None,
        subtitles=None,
        subtitles_sr_metadata=None,
        fullShowPath=None,
        other_shows=None,
        skipShow=None,
        providedIndexer=None,
        anime=None,
        scene=None,
        blacklist=None,
        whitelist=None,
        defaultStatusAfter=None,
    ):
        """
        Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are
        provided then it forwards back to newShow, if not it goes to /home.
        """

        if not indexerLang:
            indexerLang = settings.INDEXER_DEFAULT_LANGUAGE

        # grab our list of other dirs if given
        if not other_shows:
            other_shows = []
        elif not isinstance(other_shows, list):
            other_shows = [other_shows]

        def finishAddShow():
            # if there are no extra shows then go home
            if not other_shows:
                return self.redirect("/home/")

            # peel off the next one
            next_show_dir = other_shows[0]
            rest_of_show_dirs = other_shows[1:]

            # go to add the next show
            return self.newShow(next_show_dir, rest_of_show_dirs)

        # if we're skipping then behave accordingly
        if skipShow:
            return finishAddShow()

        # sanity check on our inputs
        if (not rootDir and not fullShowPath) or not whichSeries:
            return _(
                "Missing params, no Indexer ID or folder: {show_to_add} and {root_dir}/{show_path}"
            ).format(show_to_add=whichSeries,
                     root_dir=rootDir,
                     show_path=fullShowPath)

        # figure out what show we're adding and where
        series_pieces = whichSeries.split("|")
        if (whichSeries and rootDir) or (whichSeries and fullShowPath
                                         and len(series_pieces) > 1):
            if len(series_pieces) < 6:
                logger.error(
                    "Unable to add show due to show selection. Not enough arguments: {0}"
                    .format((repr(series_pieces))))
                ui.notifications.error(
                    _("Unknown error. Unable to add show due to problem with show selection."
                      ))
                return self.redirect("/addShows/existingShows/")

            indexer = int(series_pieces[1])
            indexer_id = int(series_pieces[3])
            # Show name was sent in UTF-8 in the form
            show_name = xhtml_unescape(series_pieces[4])
        else:
            # if no indexer was provided use the default indexer set in General settings
            if not providedIndexer:
                providedIndexer = settings.INDEXER_DEFAULT

            indexer = int(providedIndexer)
            indexer_id = int(whichSeries)
            show_name = os.path.basename(
                os.path.normpath(xhtml_unescape(fullShowPath)))

        # use the whole path if it's given, or else append the show name to the root dir to get the full show path
        if fullShowPath:
            show_dir = os.path.normpath(xhtml_unescape(fullShowPath))
            extra_check_dir = show_dir
        else:
            folder_name = show_name
            s = sickchill.indexer.series_by_id(indexerid=indexer_id,
                                               indexer=indexer,
                                               language=indexerLang)
            if settings.ADD_SHOWS_WITH_YEAR and s.firstAired:
                try:
                    year = "({0})".format(
                        dateutil.parser.parse(s.firstAired).year)
                    if year not in folder_name:
                        folder_name = "{0} {1}".format(s.seriesName, year)
                except (TypeError, ValueError):
                    logger.info(
                        _("Could not append the show year folder for the show: {0}"
                          ).format(folder_name))

            show_dir = os.path.join(
                rootDir, sanitize_filename(xhtml_unescape(folder_name)))
            extra_check_dir = os.path.join(
                rootDir, sanitize_filename(xhtml_unescape(show_name)))

        # blanket policy - if the dir exists you should have used "add existing show" numbnuts
        if (os.path.isdir(show_dir)
                or os.path.isdir(extra_check_dir)) and not fullShowPath:
            ui.notifications.error(
                _("Unable to add show"),
                _("Folder {show_dir} exists already").format(
                    show_dir=show_dir))
            return self.redirect("/addShows/existingShows/")

        # don't create show dir if config says not to
        if settings.ADD_SHOWS_WO_DIR:
            logger.info("Skipping initial creation of " + show_dir +
                        " due to config.ini setting")
        else:
            dir_exists = helpers.makeDir(show_dir)
            if not dir_exists:
                logger.exception("Unable to create the folder " + show_dir +
                                 ", can't add the show")
                ui.notifications.error(
                    _("Unable to add show"),
                    _("Unable to create the folder {show_dir}, can't add the show"
                      ).format(show_dir=show_dir))
                # Don't redirect to default page because user wants to see the new show
                return self.redirect("/home/")
            else:
                helpers.chmodAsParent(show_dir)

        # prepare the inputs for passing along
        scene = config.checkbox_to_value(scene)
        anime = config.checkbox_to_value(anime)
        season_folders = config.checkbox_to_value(season_folders)
        subtitles = config.checkbox_to_value(subtitles)
        subtitles_sr_metadata = config.checkbox_to_value(subtitles_sr_metadata)

        if whitelist:
            whitelist = short_group_names(whitelist)
        if blacklist:
            blacklist = short_group_names(blacklist)

        if not anyQualities:
            anyQualities = []
        if not bestQualities or try_int(quality_preset, None):
            bestQualities = []
        if not isinstance(anyQualities, list):
            anyQualities = [anyQualities]
        if not isinstance(bestQualities, list):
            bestQualities = [bestQualities]
        newQuality = Quality.combineQualities([int(q) for q in anyQualities],
                                              [int(q) for q in bestQualities])

        # add the show
        settings.showQueueScheduler.action.add_show(
            indexer,
            indexer_id,
            showDir=show_dir,
            default_status=int(defaultStatus),
            quality=newQuality,
            season_folders=season_folders,
            lang=indexerLang,
            subtitles=subtitles,
            subtitles_sr_metadata=subtitles_sr_metadata,
            anime=anime,
            scene=scene,
            paused=None,
            blacklist=blacklist,
            whitelist=whitelist,
            default_status_after=int(defaultStatusAfter),
            root_dir=rootDir,
        )
        ui.notifications.message(
            _("Show added"),
            _("Adding the specified show into {show_dir}").format(
                show_dir=show_dir))

        return finishAddShow()