<commit_before>from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
from future.moves.urllib.parse import urlparse

import logging
import math

from requests import RequestException

from flexget import plugin
from flexget.event import event
from flexget.entry import Entry

log = logging.getLogger('next_sonarr_episodes')


class NextSonarrEpisodes(object):
    """
    This plugin return the 1st missing episode of every show configures in Sonarr.
    This can be used with the discover plugin or set_series_begin plugin to
    get the relevant data from Sonarr.

    Syntax:

    next_sonarr_episodes:
      base_url=<value> (Required)
      port=<value> (Default is 80)
      api_key=<value> (Required)
      include_ended=<yes|no> (Default is yes)
      only_monitored=<yes|no> (Default is yes)
      page_size=<value> (Default is 50)

    Page size determines the amount of results per each API call.
    Higher value means a bigger response. Lower value means more calls.
    Should be changed if there are performance issues.


    Usage: (Example with discover)

    discover_from_sonarr_task:
      discover:
        what:
          - next_sonarr_episodes:
              base_url: '{? credentials.sonarr.url ?}'
              port: 8989
              api_key: '{? credentials.sonarr.api_key ?}'
              include_ended: false
        from:
          - kat:
              verified: yes
      all_series: yes
      download: c:\bla\

    Usage: (Example with set_series_begin)

    set-series-begin-from-sonarr:
      next_sonarr_episodes:
        base_url: '{{ secrets.credentials.sonarr.url }}'
        port: 8989
        api_key: '{{ secrets.credentials.sonarr.api_key }}'
        include_ended: false
      accept_all: yes
      set_series_begin: yes
    """

    schema = {
        'type': 'object',
        'properties': {
            'base_url': {'type': 'string'},
            'port': {'type': 'number', 'default': 80},
            'api_key': {'type': 'string'},
            'include_ended': {'type': 'boolean', 'default': True},
            'only_monitored': {'type': 'boolean', 'default': True},
            'page_size': {'type': 'number', 'default': 50},
        },
        'required': ['api_key', 'base_url'],
        'additionalProperties': False,
    }

    # Function that gets a page number and page size and returns the responding result json
    def get_page(self, task, config, page_number):
        parsedurl = urlparse(config.get('base_url'))
        url = '{}://{}:{}{}/api/wanted/missing?page={}&pageSize={}&sortKey=series.title&sortdir=asc'.format(
            parsedurl.scheme,
            parsedurl.netloc,
            config.get('port'),
            parsedurl.path,
            page_number,
            config.get('page_size'),
        )
        headers = {'X-Api-Key': config['api_key']}
        try:
            json = task.requests.get(url, headers=headers).json()
        except RequestException as e:
            raise plugin.PluginError(
                'Unable to connect to Sonarr at {}://{}:{}{}. Error: {}'.format(
                    parsedurl.scheme, parsedurl.netloc, config.get('port'), parsedurl.path, e
                )
            )
        return json

    def on_task_input(self, task, config):
        json = self.get_page(task, config, 1)
        entries = []
        pages = int(
            math.ceil(json['totalRecords'] / config.get('page_size'))
        )  # Sets number of requested pages
        current_series_id = 0  # Initializes current series parameter
        for page in range(1, pages + 1):
            json = self.get_page(task, config, page)
            for record in json['records']:
                # Verifies that we only get the first missing episode from a series
                if current_series_id != record['seriesId']:
                    current_series_id = record['seriesId']
                    season = record['seasonNumber']
                    episode = record['episodeNumber']
                    entry = Entry(
                        url='',
                        series_name=record['series']['title'],
                        series_season=season,
                        series_episode=episode,
                        series_id='S%02dE%02d' % (season, episode),
                        tvdb_id=record['series'].get('tvdbId'),
                        tvrage_id=record['series'].get('tvRageId'),
                        tvmaze_id=record['series'].get('tvMazeId'),
                        title=record['series']['title'] + ' ' + 'S%02dE%02d' % (season, episode),
                    )
                    if entry.isvalid():
                        entries.append(entry)
                    else:
                        log.error('Invalid entry created? {}'.format(entry))
                    # Test mode logging
                    if entry and task.options.test:
                        log.verbose("Test mode. Entry includes:")
                        for key, value in list(entry.items()):
                            log.verbose('     {}: {}'.format(key.capitalize(), value))
        return entries


@event('plugin.register')
def register_plugin():
    plugin.register(NextSonarrEpisodes, 'next_sonarr_episodes', api_ver=2)
<commit_msg>Convert next_sonarr_episodes input to a generator<commit_after>from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin
from future.moves.urllib.parse import urlparse

import logging
import math

from requests import RequestException

from flexget import plugin
from flexget.event import event
from flexget.entry import Entry

log = logging.getLogger('next_sonarr_episodes')


class NextSonarrEpisodes(object):
    """
    This plugin return the 1st missing episode of every show configures in Sonarr.
    This can be used with the discover plugin or set_series_begin plugin to
    get the relevant data from Sonarr.

    Syntax:

    next_sonarr_episodes:
      base_url=<value> (Required)
      port=<value> (Default is 80)
      api_key=<value> (Required)
      include_ended=<yes|no> (Default is yes)
      only_monitored=<yes|no> (Default is yes)
      page_size=<value> (Default is 50)

    Page size determines the amount of results per each API call.
    Higher value means a bigger response. Lower value means more calls.
    Should be changed if there are performance issues.


    Usage: (Example with discover)

    discover_from_sonarr_task:
      discover:
        what:
          - next_sonarr_episodes:
              base_url: '{? credentials.sonarr.url ?}'
              port: 8989
              api_key: '{? credentials.sonarr.api_key ?}'
              include_ended: false
        from:
          - kat:
              verified: yes
      all_series: yes
      download: c:\bla\

    Usage: (Example with set_series_begin)

    set-series-begin-from-sonarr:
      next_sonarr_episodes:
        base_url: '{{ secrets.credentials.sonarr.url }}'
        port: 8989
        api_key: '{{ secrets.credentials.sonarr.api_key }}'
        include_ended: false
      accept_all: yes
      set_series_begin: yes
    """

    schema = {
        'type': 'object',
        'properties': {
            'base_url': {'type': 'string'},
            'port': {'type': 'number', 'default': 80},
            'api_key': {'type': 'string'},
            'include_ended': {'type': 'boolean', 'default': True},
            'only_monitored': {'type': 'boolean', 'default': True},
            'page_size': {'type': 'number', 'default': 50},
        },
        'required': ['api_key', 'base_url'],
        'additionalProperties': False,
    }

    # Function that gets a page number and page size and returns the responding result json
    def get_page(self, task, config, page_number):
        parsedurl = urlparse(config.get('base_url'))
        url = '{}://{}:{}{}/api/wanted/missing?page={}&pageSize={}&sortKey=series.title&sortdir=asc'.format(
            parsedurl.scheme,
            parsedurl.netloc,
            config.get('port'),
            parsedurl.path,
            page_number,
            config.get('page_size'),
        )
        headers = {'X-Api-Key': config['api_key']}
        try:
            json = task.requests.get(url, headers=headers).json()
        except RequestException as e:
            raise plugin.PluginError(
                'Unable to connect to Sonarr at {}://{}:{}{}. Error: {}'.format(
                    parsedurl.scheme, parsedurl.netloc, config.get('port'), parsedurl.path, e
                )
            )
        return json

    def on_task_input(self, task, config):
        json = self.get_page(task, config, 1)
        pages = int(
            math.ceil(json['totalRecords'] / config.get('page_size'))
        )  # Sets number of requested pages
        current_series_id = 0  # Initializes current series parameter
        for page in range(1, pages + 1):
            json = self.get_page(task, config, page)
            for record in json['records']:
                # Verifies that we only get the first missing episode from a series
                if current_series_id != record['seriesId']:
                    current_series_id = record['seriesId']
                    season = record['seasonNumber']
                    episode = record['episodeNumber']
                    entry = Entry(
                        url='',
                        series_name=record['series']['title'],
                        series_season=season,
                        series_episode=episode,
                        series_id='S%02dE%02d' % (season, episode),
                        tvdb_id=record['series'].get('tvdbId'),
                        tvrage_id=record['series'].get('tvRageId'),
                        tvmaze_id=record['series'].get('tvMazeId'),
                        title=record['series']['title'] + ' ' + 'S%02dE%02d' % (season, episode),
                    )
                    # Test mode logging
                    if entry and task.options.test:
                        log.verbose("Test mode. Entry includes:")
                        for key, value in list(entry.items()):
                            log.verbose('     {}: {}'.format(key.capitalize(), value))
                    if entry.isvalid():
                        yield entry
                    else:
                        log.error('Invalid entry created? {}'.format(entry))


@event('plugin.register')
def register_plugin():
    plugin.register(NextSonarrEpisodes, 'next_sonarr_episodes', api_ver=2)

{'fraction_non_alphanumeric': 0.11413553594893937, 'fraction_numerical': 0.005631687629059508, 'mean_word_length': 1.983758050966116, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3391474', 'n_tokens_mistral': 3010, 'n_tokens_neox': 2873, 'n_words': 741}