Ejemplo n.º 1
0
    async def _process_candidate(self, candidate, res):
        log.info(
            "Searching episode '%s' from series '%s'. Filename: %s",
            candidate.get("episode_title"),
            candidate.get("series_title"),
            candidate.get("scenename"),
        )

        candidate_files = self._search_candidate_files(candidate, res)
        if not candidate_files:
            return

        self._refresh_db_media(candidate, candidate_files[0])

        videos = self.filter_video_files(candidate_files, res)
        if not videos:
            return

        subtitles_info = await self.download_sub(videos, res)
        res.subtitles = subtitles_info
        if subtitles_info:
            res.successful("download successful")
            DopplerrDb().insert_event("subtitles",
                                      "subtitles fetched: {}".format(", ".join([
                                          "{} (lang: {}, source: {})".format(
                                              s.get("filename"),
                                              s.get("language"),
                                              s.get("provider"),
                                          ) for s in subtitles_info
                                      ])))
        else:
            DopplerrDb().insert_event("subtitles", "no subtitle found for: {}".format(
                ", ".join([Path(f).name for f in candidate_files])))
            res.failed("no subtitle found")
Ejemplo n.º 2
0
 async def _refresh_video(self, filepath):
     if DopplerrDb().media_exists(filepath):
         log.info("Already existing video file found: %s", filepath)
         return
     log.info("Unknown Video file found: %s", filepath)
     refined_lst = await RefineVideoFileTask().refine_file(filepath)
     if not refined_lst:
         log.error("Cannot refine file: %s", filepath)
         return
     if not isinstance(refined_lst, list):
         refined_lst = [refined_lst]
     for refined in refined_lst:
         if isinstance(refined, SeriesEpisodeInfo):
             DopplerrDb().update_series_media(
                 series_title=refined.series_title,
                 tv_db_id=refined.series_episode_uid.tv_db_id,
                 season_number=refined.series_episode_uid.season_number,
                 episode_number=refined.series_episode_uid.episode_number,
                 episode_title=refined.episode_title,
                 quality=refined.quality,
                 video_languages=refined.video_languages,
                 media_filename=refined.media_filename,
                 dirty=refined.dirty,
             )
             DopplerrDb().insert_event("media update",
                                       "Available TV episode: {} - {}x{} - {}.".format(
                                           refined.series_title,
                                           refined.series_episode_uid.season_number,
                                           refined.series_episode_uid.episode_number,
                                           refined.episode_title,
                                       ))
         else:
             log.error("Unsupported refined video type: %r", refined)
             return
Ejemplo n.º 3
0
    async def run(self, task) -> dict:
        content = task

        log.debug("Sonarr notification received: %r", content)
        res = await SonarrFilter().filter(content)
        if res.is_unhandled:
            # event has been filtered out
            return res.to_dict()

        if res.candidates:
            for candidate in res.candidates:
                DopplerrDb().insert_event(
                    "media update",
                    "Available TV episode: {} - {}x{} - {} [{}].".format(
                        candidate.get("series_title"),
                        candidate.get("season_number"),
                        candidate.get("episode_number"),
                        candidate.get("episode_title"),
                        candidate.get("quality"),
                    ))

        log.debug("Sonarr notification ok, posting background task")
        # processing ok, let's post our background task to the task queue
        self.post_task(self.task_sonarr_on_download_background(res))
        # asyncio.ensure_future(self.task_sonarr_on_download_background(res))
        res.successful("Request successfully posted")
        return res.to_dict()
Ejemplo n.º 4
0
 def _search_candidate_files(self, candidate, res):
     candidate_files = self.search_file(candidate['root_dir'], candidate['scenename'])
     log.debug("All found files: %r", candidate_files)
     if not candidate_files:
         res.failed("candidates defined in request but no video file found on disk")
         DopplerrDb().insert_event("subtitles", "No video file found on disk "
                                   "after sonarr notification")
         return []
     return candidate_files
Ejemplo n.º 5
0
 def _refresh_db_media(candidate, media_filename):
     DopplerrDb().update_series_media(
         series_title=candidate.get("series_title"),
         tv_db_id=candidate.get("tv_db_id"),
         season_number=candidate.get("season_number"),
         episode_number=candidate.get("episode_number"),
         episode_title=candidate.get("episode_title"),
         quality=candidate.get("quality"),
         video_languages=None,
         media_filename=media_filename,
         dirty=True)
Ejemplo n.º 6
0
    async def _run(self, task):
        log.debug("Starting Download subtitle for task")
        res = task
        if not res.candidates:
            DopplerrDb().insert_event("error", "event handled but no candidate found")
            log.debug("event handled but no candidate found")
            res.failed("event handled but no candidate found")
            return res

        for candidate in res.candidates:
            await self._process_candidate(candidate, res)
        return res
Ejemplo n.º 7
0
    async def task_sonarr_on_download_background(self, res):
        log.debug("Starting task_sonarr_on_download_background")
        downloader = DownloadSubtitleTask()
        res = await downloader.run_and_wait(res)
        if not res.is_successful:
            log.debug("not successful, leaving background task")
            return res

        for episode_info in res.sonarr_episode_infos:
            await emit_notifications(
                SubtitleFetchedNotification(series_episode_info=episode_info))
            DopplerrDb().update_fetched_series_subtitles(
                series_episode_uid=SeriesEpisodeUid(
                    episode_info['tv_db_id'],
                    episode_info['season_number'],
                    episode_info['episode_number'],
                ),
                subtitles_languages=episode_info['subtitles_languages'],
                dirty=False)
        log.debug("Background task finished with result: %s", res.to_json())
        return res
Ejemplo n.º 8
0
async def get_series(seriesid) -> Series:
    return DopplerrDb().get_series(seriesid)
Ejemplo n.º 9
0
async def list_series() -> SeriesList:
    return DopplerrDb().list_series()
Ejemplo n.º 10
0
async def medias_series() -> Medias:
    res = {"medias": DopplerrDb().get_medias_series()}
    return res
Ejemplo n.º 11
0
async def recent_fetched_series_num(num: int = 10) -> RecentSeries:
    num = int(num)
    if num > 100:
        num = 100
    res = {"events": DopplerrDb().get_last_fetched_series(num)}
    return res
Ejemplo n.º 12
0
async def recent_events_10() -> Events:
    res = {"events": DopplerrDb().get_recent_events(10)}
    return res
Ejemplo n.º 13
0
async def recent_events_num(num: int = 10) -> Events:
    num = int(num)
    if num > 100:
        num = 100
    res = {"events": DopplerrDb().get_recent_events(num)}
    return res
Ejemplo n.º 14
0
def main():
    outputtype = OutputType.PLAIN
    if "--debug-config" in sys.argv:
        default_level = logging.DEBUG
    else:
        default_level = logging.ERROR
    for i in range(len(sys.argv)):
        if sys.argv[i] == "--output-type":
            if i < len(sys.argv) and sys.argv[i + 1] == "dev":
                outputtype = OutputType.DEV
                break

    debug = default_level is logging.DEBUG
    setup_logging(debug=debug, outputtype=outputtype)
    log.debug("Initializing Dopplerr version %s...", DOPPLERR_VERSION)

    DopplerrConfig().find_configuration_values()
    log.debug("Current configuration: %s", DopplerrConfig().json(safe=True))

    debug = DopplerrConfig().get_cfg_value("general.verbose")
    output_type = DopplerrConfig().get_cfg_value("general.output_type")
    if output_type == 'dev':
        outputtype = OutputType.DEV
    elif output_type == 'plain':
        outputtype = OutputType.PLAIN
    else:
        raise NotImplementedError(
            "Invalid output type: {!r}".format(output_type))

    log.debug("Applying configuration")
    custom_log_levels = [
        ("peewee", logging.DEBUG if debug else logging.ERROR),
        ("sanic", logging.INFO),
        ("cfgtree", logging.DEBUG if debug else logging.ERROR),
        ("apscheduler", logging.INFO),
        # Subliminal loggers
        ("chardet", logging.ERROR),
        ("dogpile", logging.ERROR),
        ("enzyme", logging.ERROR),
        ("rebulk.processors", logging.INFO),
        ("rebulk", logging.ERROR),
        ("subliminal.providers", logging.ERROR),
        ("subliminal.score", logging.ERROR),
        ("subliminal.subtitle", logging.ERROR),
        ("subliminal", logging.INFO),
        ("urllib3", logging.ERROR),
    ]
    setup_logging(outputtype=outputtype,
                  debug=debug,
                  logfile=DopplerrConfig().get_cfg_value("general.logfile"),
                  custom_log_levels=custom_log_levels)
    log.info(
        "Logging is set to %s", "verbose" if
        DopplerrConfig().get_cfg_value("general.verbose") else "not verbose")
    DopplerrStatus().refresh_from_cfg()
    # Backup configuration, now refresh_from_cfg has updated the version
    DopplerrConfig().save_configuration()

    log.info("Initializing Subtitle DopplerrDownloader Service")

    SubliminalSubDownloader.initialize_db()
    DopplerrStatus().sqlite_db_path = (
        Path(DopplerrConfig().get_cfg_value("general.configdir")) /
        "sqlite.db")
    reset_db = False
    if DopplerrStatus().has_minor_version_changed:
        log.warning("Major version change, dropping all databases")
        reset_db = True
    else:
        log.info("Previous version was %s, now: %s",
                 DopplerrStatus().previous_version,
                 DopplerrConfig().get_cfg_value("general.version"))
    log.debug("SQLite DB: %s", DopplerrStatus().sqlite_db_path.as_posix())
    DopplerrDb().init(DopplerrStatus().sqlite_db_path, reset_db=reset_db)
    DopplerrDb().create_tables()
    if reset_db:
        DopplerrDb().insert_event(
            "db reset",
            "Doppler major or minor version upgrade caused a DB reset ")

    # change current work dir for subliminal work files
    os.chdir(DopplerrConfig().get_cfg_value("general.configdir"))

    DopplerrDb().insert_event("start", "dopplerr started")

    # main event loop (Asyncio behind)
    listen()

    logging.info("Clean stopping")
    DopplerrDb().insert_event("stop", "dopplerr stopped")

    return 0