Example #1
0
    return session.query(User).filter(User.name == username).first()


@app.before_request
def check_valid_login():
    # Allow access to root, login and swagger documentation without authentication
    if request.path == '/' or request.path.startswith('/auth/login') or \
            request.path.startswith('/auth/logout') or request.path.startswith('/swagger'):
        return

    if not current_user.is_authenticated:
        return current_app.login_manager.unauthorized()


# API Authentication and Authorization
auth_api = api.namespace('auth', description='Authentication')

login_api_schema = api.schema(
    'auth.login', {
        'type': 'object',
        'properties': {
            'username': {
                'type': 'string'
            },
            'password': {
                'type': 'string'
            }
        }
    })

login_parser = api.parser()
Example #2
0
from __future__ import unicode_literals, division, absolute_import

import datetime
from math import ceil

from flask import jsonify
from flask import request
from flask_restplus import inputs
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.plugins.filter import series

series_api = api.namespace('series', description='Flexget Series operations')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {
            'type': 'string'
        },
        'message': {
            'type': 'string'
        }
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)

empty_response = api.schema('empty', {'type': 'object'})
Example #3
0
from __future__ import unicode_literals, division, absolute_import

from flask import jsonify

from flexget.api import api, APIResource
from flexget.utils.imdb import ImdbSearch

imdb_api = api.namespace('imdb', description='IMDB lookup endpoint')


class ObjectsContainer(object):
    movie_object = {
        'type': 'object',
        'properties': {
            'imdb_id': {'type': 'string'},
            'match': {'type': 'number'},
            'name': {'type': 'string'},
            'url': {'type': 'string'},
            'year': {'type': 'string'},
            'thumbnail': {'type': 'string'}
        }
    }

    return_object = {'type': 'array', 'items': movie_object}


return_schema = api.schema('imdb_search_schema', ObjectsContainer.return_object)


@imdb_api.route('/search/<string:title>/')
@api.doc(params={'title': 'Movie name or IMDB ID'})
Example #4
0
from __future__ import unicode_literals, division, absolute_import

import copy
import logging
from math import ceil

from flask import jsonify, request
from sqlalchemy.orm.exc import NoResultFound

import flexget.plugins.list.entry_list as el
from flexget.api import api, APIResource

log = logging.getLogger('entry_list')

entry_list_api = api.namespace('entry_list',
                               description='Entry List operations')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {
            'type': 'string'
        },
        'message': {
            'type': 'string'
        }
    }
}
empty_response = api.schema('empty', {'type': 'object'})

default_error_schema = api.schema('default_error_schema', default_error_schema)
Example #5
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flask import jsonify
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.api.app import NotFoundError, BadRequest, etag
from flexget.components.tvmaze.api_tvmaze import APITVMaze

tvmaze_api = api.namespace('tvmaze', description='TVMaze Shows')


class ObjectsContainer(object):
    actor_object = {
        'type': 'object',
        'properties': {
            "last_update": {
                'type': 'string',
                'format': 'date-time'
            },
            "medium_image": {
                'type': 'string'
            },
            "name": {
                'type': 'string'
            },
            "original_image": {
                'type': 'string'
            },
            "tvmaze_id": {
Example #6
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

from flask import jsonify
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.plugins.internal.api_tvmaze import APITVMaze as tvm

tvmaze_api = api.namespace('tvmaze', description='TVMaze Shows')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {'type': 'string'},
        'message': {'type': 'string'}
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)

actor_object = {
    'type': 'object',
    'properties': {
        "last_update": {'type': 'string', 'format': 'date-time'},
        "medium_image": {'type': 'string'},
        "name": {'type': 'string'},
        "original_image": {'type': 'string'},
        "tvmaze_id": {'type': 'integer'},
        "url": {'type': 'string'},
    }
Example #7
0
from flask import jsonify, Response
from flask import request

from flexget.api import api, APIResource, ApiError, NotFoundError
from flexget.config_schema import process_config
from flexget.entry import Entry
from flexget.event import event
from flexget.options import get_parser
from flexget.task import task_phases
from flexget.utils import json
from flexget.utils import requests
from flexget.utils.lazy_dict import LazyLookup

# Tasks API
tasks_api = api.namespace('tasks', description='Manage Tasks')

tasks_list_api_schema = api.schema('tasks.list', {
    "type": "object",
    "properties": {
        "tasks": {
            "type": "array",
            "items": {'$ref': '#/definitions/tasks.task'}
        }
    },
    'additionalProperties': False
})

task_schema_validate = {
    'type': 'object',
    'properties': {
Example #8
0
from __future__ import unicode_literals, division, absolute_import

import logging

from flask import request, jsonify

from flexget.api import api, APIResource
from flexget.api.app import empty_response, etag
from flexget.components.variables.variables import variables_from_db, variables_to_db

log = logging.getLogger('variables')

variables_api = api.namespace('variables', description='View and edit config variables')


@variables_api.route('/')
class VariablesAPI(APIResource):
    @etag
    @api.response(200, model=empty_response)
    def get(self, session=None):
        """ Get variables data from DB """
        return jsonify(variables_from_db())

    @api.response(201, 'Successfully updated variables file')
    @api.validate(empty_response)
    @api.doc(
        description='Note that editing variables may not be persistent, depending on user config'
    )
    def put(self, session=None):
        """ Store variables data to DB """
        data = request.json
Example #9
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *

from flask import jsonify, request
from jsonschema import RefResolutionError

from flexget.api import api, APIResource
from flexget.config_schema import schema_paths, resolve_ref

schema_api = api.namespace('schema', description='Config and plugin schemas')
_plugins_cache = None

schema_api_list = api.schema('schema.list', {
    'type': 'object',
    'properties': {
        'schemas': {
            'type': 'array',
            'items': {'type': 'object'}
        }
    }
})


@schema_api.route('/')
class SchemaAllAPI(APIResource):
    @api.response(200, model=schema_api_list)
    def get(self, session=None):
        """ List all schema definitions """
        schemas = {}
        for path in schema_paths:
            schemas[path] = resolve_ref(path)
Example #10
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import datetime
from math import ceil

from flask import jsonify, request
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.plugins.api.series import NoResultFound
from flexget.plugins.filter import movie_queue as mq
from flexget.utils import qualities

movie_queue_api = api.namespace(
    'movie_queue', description='Movie Queue operations (DEPRECATED)')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {
            'type': 'string'
        },
        'message': {
            'type': 'string'
        }
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)
Example #11
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

from flask.helpers import send_file
from flask_restplus import inputs
from flexget.api import api, APIResource
from flexget.api.app import APIError, BadRequest
from flexget.utils.cache import cached_resource
from requests import RequestException

cached_api = api.namespace('cached', description='Cache remote resources')

cached_parser = api.parser()
cached_parser.add_argument('url', required=True, help='URL to cache')
cached_parser.add_argument('force',
                           type=inputs.boolean,
                           default=False,
                           help='Force fetching remote resource')


@cached_api.route('/')
@api.doc(
    description=
    'Returns a cached copy of the requested resource, matching its mime type')
class CachedResource(APIResource):
    @api.response(200, description='Cached resource')
    @api.response(BadRequest)
    @api.response(APIError)
    @api.doc(parser=cached_parser)
    def get(self, session=None):
        """ Cache remote resources """
Example #12
0
from datetime import datetime
from Queue import Queue, Empty

from flask import request, jsonify, Response

from flexget.options import get_parser
from flexget.api import api, APIResource
from flexget.utils import json
from json import JSONEncoder
from flexget.event import event
from flexget.utils.lazy_dict import LazyLookup

execution_api = api.namespace('execution', description='Execute tasks')


def _task_info_dict(task):
    return {
        'id': int(task.id),
        'name': task.name,
        'current_phase': task.current_phase,
        'current_plugin': task.current_plugin,
    }


task_info_schema = {
    'type': 'object',
    'properties': {
        'id': {'type': 'integer'},
        'name': {'type': 'string'},
        'current_phase': {'type': 'string'},
        'current_plugin': {'type': 'string'},
Example #13
0
from flask import jsonify

from flexget.api import api, APIResource
from flexget.config_schema import schema_paths, resolve_ref


schema_api = api.namespace('schema', description='Flexget JSON schema')


@schema_api.route('/')
class SchemaAllAPI(APIResource):
    def get(self, session=None):
        schemas = {}
        for path in schema_paths:
            schemas[path] = resolve_ref(path)

        return jsonify({'schemas': schemas})


@schema_api.route('/<path:path>')
@api.doc(params={'path': 'Path of schema'})
@api.response(404, 'invalid schema path')
class SchemaAPI(APIResource):

    def get(self, path, session=None):
        path = '/schema/%s' % path
        if path in schema_paths:
            return resolve_ref(path)
        return {'error': 'invalid schema path'}, 404
Example #14
0
from math import ceil

from flask import jsonify, request
from flask_restplus import inputs
from loguru import logger

from flexget.api import APIResource, api
from flexget.api.app import BadRequest, NotFoundError, etag, pagination_headers
from flexget.plugin import DependencyError, get_plugin_by_name, get_plugins

logger = logger.bind(name='plugins')

plugins_api = api.namespace('plugins', description='Get Flexget plugins')


class ObjectsContainer:
    phase_object = {
        'type': 'object',
        'properties': {
            'phase': {
                'type': 'string'
            },
            'priority': {
                'type': 'integer'
            }
        },
    }

    plugin_object = {
        'type': 'object',
        'properties': {
Example #15
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flask import jsonify
from flask_restplus import inputs
from flexget.api import api, APIResource
from flexget.api.app import BadRequest, NotFoundError, success_response, base_message_schema, empty_response

irc_api = api.namespace('irc', description='View and manage IRC connections')

irc_parser = api.parser()
irc_parser.add_argument('name', help='Name of connection. Leave empty to apply to all connections.')


class ObjectsContainer(object):
    connection_object = {
        'type': 'object',
        'properties': {
            'alive': {'type': 'boolean'},
            'channels': {
                'type': 'array', 'items': {
                    'type': 'object',
                    'patternProperties': {
                        '\w': {'type': 'integer'}
                    }
                }
            },
            'connected_channels': {'type': 'array', 'items': {'type': 'string'}},
            'port': {'type': 'integer'},
            'server': {'type': 'string'}
        }
Example #16
0
from __future__ import unicode_literals, division, absolute_import

from math import ceil
from operator import itemgetter

from flask import jsonify, request

from flexget.api import api, APIResource
from flexget.plugins.filter import movie_queue as mq
from flexget.utils import qualities

movie_queue_api = api.namespace('movie_queue', description='Movie Queue operations')

movie_object = {
    'type': 'object',
    'properties': {
        'added': {'type': 'string'},
        'downloaded': {'type': 'string'},
        'entry_original_url': {'type': 'string'},
        'entry_title': {'type': 'string'},
        'entry_url': {'type': 'string'},
        'id': {'type': 'integer'},
        'imdb_id': {'type': 'string'},
        'quality': {'type': 'string'},
        'title': {'type': 'string'},
        'tmdb_id': {'type': 'string'},
    }
}

movie_queue_schema = {
    'type': 'object',
Example #17
0
        # Update our cache to mark the items that have expired
        for chunk in chunked(expired_series):
            num = session.query(TVDBSeries).filter(TVDBSeries.id.in_(chunk)).update({'expired': True}, 'fetch')
            log.debug('%s series marked as expired', num)
        for chunk in chunked(expired_episodes):
            num = session.query(TVDBEpisode).filter(TVDBEpisode.id.in_(chunk)).update({'expired': True}, 'fetch')
            log.debug('%s episodes marked as expired', num)

        # Save the time of this update
        session.commit()
        persist['last_local'] = datetime.now()
        persist['last_server'] = new_server


tvdb_api = api.namespace('tvdb', description='TheTVDB Shows')

tvdb_api_parser = api.parser()
tvdb_api_parser.add_argument('search', type=str, required=True, help='TV Show name or tvdbid')


@tvdb_api.route('/search/')
class TVDBSearchApi(APIResource):

    @api.doc(parser=tvdb_api_parser)
    @api.response(400, 'missing search parameter')
    def get(self, session=None):
        args = tvdb_api_parser.parse_args()
        search = args['search']

        if not search:
Example #18
0
    base_message_schema,
    etag,
    success_response,
)
from flexget.config_schema import process_config
from flexget.entry import Entry
from flexget.event import event
from flexget.log import capture_logs
from flexget.options import get_parser
from flexget.task import task_phases
from flexget.terminal import capture_console
from flexget.utils import json, requests
from flexget.utils.lazy_dict import LazyLookup

# Tasks API
tasks_api = api.namespace('tasks', description='Manage Tasks')


class ObjectsContainer:
    tasks_list_object = {
        'oneOf': [
            {
                'type': 'array',
                'items': {
                    '$ref': '#/definitions/tasks.task'
                }
            },
            {
                'type': 'array',
                'items': {
                    'type': 'string'
Example #19
0
import traceback
from time import sleep

import cherrypy
from flask import Response
from flask_restplus import inputs
from pyparsing import Word, Keyword, Group, Forward, Suppress, OneOrMore, oneOf, White, restOfLine, ParseException, \
    Combine
from pyparsing import nums, alphanums, printables

from flexget._version import __version__
from flexget.api import api, APIResource, ApiError, __version__ as __api_version__

log = logging.getLogger('api.server')

server_api = api.namespace('server', description='Manage Daemon')


@server_api.route('/reload/')
class ServerReloadAPI(APIResource):
    @api.response(ApiError, description='Error loading the config')
    @api.response(200, description='Newly reloaded config')
    def get(self, session=None):
        """ Reload Flexget config """
        log.info('Reloading config from disk.')
        try:
            self.manager.load_config()
        except ValueError as e:
            raise ApiError('Error loading config: %s' % e.args[0])

        log.info('Config successfully reloaded from disk.')
Example #20
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flask import request, jsonify
from flask_login import current_user

from flexget.api import api, APIResource
from flexget.api.app import BadRequest, base_message_schema, success_response
from flexget.webserver import change_password, generate_token, WeakPassword

user_api = api.namespace('user', description='Manage user login credentials')


class ObjectsContainer(object):
    user_password_input = {
        'type': 'object',
        'properties': {
            'password': {'type': 'string'}
        },
        'required': ['password'],
        'additionalProperties': False
    }

    user_token_response = {
        'type': 'object',
        'properties': {
            'token': {'type': 'string'}
        }
    }

Example #21
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import logging

from flask import jsonify, request
from math import ceil
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.api.app import base_message_schema, success_response, etag, NotFoundError, pagination_headers
from flexget.plugins.filter.remember_rejected import RememberEntry, get_rejected

log = logging.getLogger('rejected')

rejected_api = api.namespace(
    'rejected', description='View and manage remembered rejected entries')


def rejected_entry_to_dict(entry):
    return {
        'id': entry.id,
        'added': entry.added,
        'expires': entry.expires,
        'title': entry.title,
        'url': entry.url,
        'rejected_by': entry.rejected_by,
        'reason': entry.reason
    }


class ObjectsContainer(object):
Example #22
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import logging
from math import ceil

from flask import jsonify, request
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.api.app import base_message_schema, success_response, NotFoundError, etag, pagination_headers
from flexget.plugins.filter.retry_failed import FailedEntry, get_failures

log = logging.getLogger('failed_api')

retry_failed_api = api.namespace('failed', description='View and manage failed entries')


class ObjectsContainer(object):
    retry_failed_entry_object = {
        'type': 'object',
        'properties': {
            'id': {'type': 'integer'},
            'title': {'type': 'string'},
            'url': {'type': 'string'},
            'added_at': {'type': 'string', 'format': 'date-time'},
            'reason': {'type': 'string'},
            'count': {'type': 'integer'},
            'retry_time': {'type': ['string', 'null'], 'format': 'date-time'}
        },
        'required': ['id', 'title', 'url', 'added_at', 'reason', 'count', 'retry_time'],
Example #23
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

from flask import request
from flask_login import current_user

from flexget.api import api, APIResource
from flexget.webserver import change_password, generate_token, WeakPassword

user_api = api.namespace('user', description='Manage user login credentials')

user_password_input = {
    'type': 'object',
    'properties': {
        'password': {'type': 'string'}
    }
}
user_password_input_schema = api.schema('user_password_input', user_password_input)

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {'type': 'string'},
        'message': {'type': 'string'}
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)

empty_response = api.schema('empty', {'type': 'object'})
Example #24
0
def load_user(username, session=None):
    return session.query(User).filter(User.name == username).first()


@app.before_request
def check_valid_login():
    # Allow access to root, login and swagger documentation without authentication
    if request.path == '/' or request.path.startswith('/login') or \
            request.path.startswith('/logout') or request.path.startswith('/swagger'):
        return

    if not current_user.is_authenticated:
        return current_app.login_manager.unauthorized()

# API Authentication and Authorization
login_api = api.namespace('login', description='API Authentication')

login_api_schema = api.schema('login', {
    'type': 'object',
    'properties': {
        'username': {'type': 'string'},
        'password': {'type': 'string'}
    }
})

login_parser = api.parser()
login_parser.add_argument('remember', type=bool, required=False, default=False, help='Remember for next time')


@login_api.route('/')
@api.doc(description='Login to API with username and password')
Example #25
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import copy

from flask import request, jsonify

from flexget.manager import manager
from flexget.plugins.daemon.scheduler import schedule_schema, scheduler, scheduler_job_map
from flexget.api import api, APIResource

schedule_api = api.namespace('schedules', description='Task Scheduler')

# SwaggerUI does not yet support anyOf or oneOf
schedule_schema = copy.deepcopy(schedule_schema)
schedule_schema['properties']['id'] = {'type': 'integer'}
api_schedule_schema = api.schema('schedules.schedule', schedule_schema)
api_schedules_list_schema = api.schema('schedules.list', {
    'type': 'object',
    'properties': {
        'schedules': {
            'type': 'array',
            'items': schedule_schema
        }
    }
})


def _schedule_by_id(schedule_id):
    for schedule in manager.config.get('schedules', []):
        if id(schedule) == schedule_id:
Example #26
0
from __future__ import unicode_literals, division, absolute_import

import copy

from flask import jsonify
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.plugins.internal.api_trakt import ApiTrakt as at, list_actors, get_translations_dict

trakt_api = api.namespace('trakt', description='Trakt lookup endpoint')


class objects_container(object):
    internal_image_object = {
        "type": "object",
        "properties": {
            "full": {"type": ["string", "null"]},
            "medium": {"type": ["string", "null"]},
            "thumb": {"type": ["string", "null"]}
        },
        'additionalProperties': False
    }

    images_object = {
        "type": "object",
        "properties": {
            "banner": internal_image_object,
            "clearart": internal_image_object,
            "fanart": internal_image_object,
            "logo": internal_image_object,
Example #27
0
from flask import jsonify, request
from flask_restplus import inputs
from future.moves.urllib.parse import unquote
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.api.app import (
    NotFoundError,
    base_message_schema,
    success_response,
    etag,
    pagination_headers,
)
from . import db

seen_api = api.namespace('seen',
                         description='Managed Flexget seen entries and fields')


class ObjectsContainer(object):
    seen_field_object = {
        'type': 'object',
        'properties': {
            'id': {
                'type': 'integer'
            },
            'field': {
                'type': 'string'
            },
            'value': {
                'type': 'string'
            },
Example #28
0
import copy
import datetime
from math import ceil

from flask import jsonify
from flask import request
from flask_restplus import inputs
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource, ApiClient
from flexget.event import fire_event
from flexget.plugin import PluginError
from flexget.plugins.filter import series

series_api = api.namespace('series', description='Flexget Series operations')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {'type': 'string'},
        'message': {'type': 'string'}
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)

empty_response = api.schema('empty', {'type': 'object'})

begin_object = {
    'type': 'object',
Example #29
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import logging
from math import ceil

from flask import jsonify, request
from flask_restplus import inputs

from flexget.plugin import get_plugins, get_plugin_by_name, DependencyError
from flexget.api import api, APIResource
from flexget.api.app import BadRequest, NotFoundError, etag, pagination_headers

log = logging.getLogger('plugins')

plugins_api = api.namespace('plugins', description='Get Flexget plugins')


class ObjectsContainer(object):
    phase_object = {
        'type': 'object',
        'properties': {
            'phase': {'type': 'string'},
            'priority': {'type': 'integer'}
        }
    }

    plugin_object = {
        'type': 'object',
        'properties': {
            'name': {'type': 'string'},
Example #30
0
import copy

from flask import request

from flexget.config_schema import process_config
from flexget.api import api, APIResource, ApiError, NotFoundError


# Tasks API
tasks_api = api.namespace('tasks', description='Manage Tasks')

task_api_schema = {
    'type': 'object',
    'properties': {
        'name': {'type': 'string'},
        'config': {'$ref': '/schema/plugins'}
    },
    'additionalProperties': False
}

tasks_api_schema = {
    "type": "object",
    "properties": {
        "tasks": {
            "type": "array",
            "items": task_api_schema
        }
    },
    'additionalProperties': False
}
Example #31
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *

import logging
from math import ceil

from flask import jsonify
from sqlalchemy import desc

from flexget.api import api, APIResource
from flexget.plugins.output.history import History

log = logging.getLogger('history')

history_api = api.namespace('history', description='Entry History')

history_api_schema = {
    'type': 'object',
    'properties': {
        'entries': {
            'type': 'array',
            'items': {
                'type': 'object',
                'properties': {
                    'details': {'type': 'string'},
                    'filename': {'type': 'string'},
                    'id': {'type': 'integer'},
                    'task': {'type': 'string'},
                    'time': {'type': 'string'},
                    'title': {'type': 'string'},
                    'url': {'type': 'string'}
Example #32
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin
from future.moves.urllib.parse import unquote

import copy
from math import ceil

from flask import jsonify, request
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.plugins.filter import seen

seen_api = api.namespace('seen', description='Managed Flexget seen entries and fields')

PLUGIN_TASK_NAME = 'seen_plugin_API'  # Name of task to use when adding entries via API

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {'type': 'string'},
        'message': {'type': 'string'}
    }
}

empty_response = api.schema('empty', {'type': 'object'})

default_error_schema = api.schema('default_error_schema', default_error_schema)

seen_field_object = {
    'type': 'object',
Example #33
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import logging

from flask import request

from flexget.api import api, APIResource, NotFoundError
from flexget.plugins.modify.config_secrets import secrets_from_db, secrets_to_db

log = logging.getLogger('secrets')

secrets_api = api.namespace('secrets', description='View and edit secrets')
empty_object = api.schema('empty_object', {'type': 'object'})


@secrets_api.route('/')
class SecretsAPI(APIResource):
    @api.response(200)
    @api.response(NotFoundError)
    def get(self, session=None):
        return secrets_from_db()

    @api.response(201, 'Successfully updated secrets file')
    @api.response(NotFoundError)
    @api.validate(empty_object)
    @api.doc(
        description=
        'Note that editing secrets may not be persistent, depending on user config'
    )
    def put(self, session=None):
Example #34
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import logging

from flask import request

from flexget.api import api, APIResource, NotFoundError
from flexget.plugins.modify.config_secrets import secrets_from_db, secrets_to_db

log = logging.getLogger('secrets')

secrets_api = api.namespace('secrets', description='View and edit secrets')
empty_object = api.schema('empty_object', {'type': 'object'})


@secrets_api.route('/')
class SecretsAPI(APIResource):

    @api.response(200)
    @api.response(NotFoundError)
    def get(self, session=None):
        return secrets_from_db()

    @api.response(201, 'Successfully updated secrets file')
    @api.response(NotFoundError)
    @api.validate(empty_object)
    @api.doc(description='Note that editing secrets may not be persistent, depending on user config')
    def put(self, session=None):
        data = request.json
        secrets_to_db(data)
Example #35
0
File: api.py Project: x572b/Flexget
from flask import jsonify
from flask_restx import inputs

from flexget.api import APIResource, api
from flexget.api.app import (
    BadRequest,
    NotFoundError,
    base_message_schema,
    empty_response,
    success_response,
)

irc_api = api.namespace('irc', description='View and manage IRC connections')

irc_parser = api.parser()
irc_parser.add_argument(
    'name',
    help='Name of connection. Leave empty to apply to all connections.')


class ObjectsContainer:
    connection_object = {
        'type': 'object',
        'properties': {
            'alive': {
                'type': 'boolean'
            },
            'channels': {
                'type': 'array',
                'items': {
                    'type': 'object',
Example #36
0
    return session.query(User).filter(User.name == username).first()


@app.before_request
def check_valid_login():
    # Allow access to root, login and swagger documentation without authentication
    if request.path == '/' or request.path.startswith('/auth/login') or \
            request.path.startswith('/auth/logout') or request.path.startswith('/swagger'):
        return

    if not current_user.is_authenticated:
        return current_app.login_manager.unauthorized()


# API Authentication and Authorization
auth_api = api.namespace('auth', description='Authentication')

login_api_schema = api.schema('auth.login', {
    'type': 'object',
    'properties': {
        'username': {'type': 'string'},
        'password': {'type': 'string'}
    }
})

login_parser = api.parser()
login_parser.add_argument('remember', type=inputs.boolean, required=False, default=False,
                          help='Remember login (sets persistent session cookies)'
                          )

Example #37
0
import logging
from math import ceil

from flask import jsonify
from flask import request
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.api.app import Conflict, NotFoundError, base_message_schema, success_response, BadRequest, etag, \
    pagination_headers
from flexget.plugins.list import movie_list as ml
from flexget.plugins.list.movie_list import MovieListBase

log = logging.getLogger('movie_list')

movie_list_api = api.namespace('movie_list', description='Movie List operations')


class ObjectsContainer(object):
    input_movie_list_id_object = {
        'type': 'array',
        'items': {
            'type': 'object',
            'minProperties': 1,
            'additionalProperties': True
        }
    }

    input_movie_entry = {
        'type': 'object',
        'properties': {
Example #38
0
    return session.query(User).filter(User.name == username).first()


@app.before_request
def check_valid_login():
    # Allow access to root, login and swagger documentation without authentication
    if request.path == '/' or request.path.startswith('/login') or \
            request.path.startswith('/logout') or request.path.startswith('/swagger'):
        return

    if not current_user.is_authenticated:
        return current_app.login_manager.unauthorized()


# API Authentication and Authorization
login_api = api.namespace('login', description='API Authentication')

login_api_schema = api.schema(
    'login', {
        'type': 'object',
        'properties': {
            'username': {
                'type': 'string'
            },
            'password': {
                'type': 'string'
            }
        }
    })

login_parser = api.parser()
Example #39
0
from flexget.api import api, APIResource
from flexget.api.app import (
    Conflict,
    NotFoundError,
    base_message_schema,
    success_response,
    BadRequest,
    etag,
    pagination_headers,
)
from flexget.plugins.list import movie_list as ml
from flexget.plugins.list.movie_list import MovieListBase

log = logging.getLogger("movie_list")

movie_list_api = api.namespace("movie_list", description="Movie List operations")


class ObjectsContainer(object):
    input_movie_list_id_object = {
        "type": "array",
        "items": {"type": "object", "minProperties": 1, "additionalProperties": True},
    }

    input_movie_entry = {
        "type": "object",
        "properties": {
            "movie_name": {"type": "string"},
            "movie_year": {"type": "integer"},
            "movie_identifiers": input_movie_list_id_object,
        },
Example #40
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flexget.api import api, APIResource
from flexget.api.app import base_message_schema, success_response

schema_api = api.namespace(
    'format_check',
    description='Test Flexget custom schema format validations')


class ObjectContainer(object):
    format_checker_input = {
        'type': 'object',
        'properties': {
            'quality': {
                'type': 'string',
                'format': 'quality'
            },
            'quality_requirements': {
                'type': 'string',
                'format': 'quality_requirements'
            },
            'time': {
                'type': 'string',
                'format': 'time'
            },
            'interval': {
                'type': 'string',
                'format': 'interval'
            },
Example #41
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flexget.api import api, APIResource
from flexget.api.app import base_message_schema, success_response

schema_api = api.namespace(
    'format_check', description='Test Flexget custom schema format validations'
)


class ObjectContainer(object):
    format_checker_input = {
        'type': 'object',
        'properties': {
            'quality': {'type': 'string', 'format': 'quality'},
            'quality_requirements': {'type': 'string', 'format': 'quality_requirements'},
            'time': {'type': 'string', 'format': 'time'},
            'interval': {'type': 'string', 'format': 'interval'},
            'size': {'type': 'string', 'format': 'size'},
            'percent': {'type': 'string', 'format': 'percent'},
            'regex': {'type': 'string', 'format': 'regex'},
            'file': {'type': 'string', 'format': 'file'},
            'path': {'type': 'string', 'format': 'path'},
            'url': {'type': 'string', 'format': 'url'},
            'episode_identifier': {'type': 'string', 'format': 'episode_identifier'},
            'episode_or_season_id': {'type': 'string', 'format': 'episode_or_season_id'},
        },
    }

Example #42
0
from __future__ import unicode_literals, division, absolute_import

import copy
import logging
from math import ceil

from flask import jsonify, request
from sqlalchemy.orm.exc import NoResultFound

import flexget.plugins.list.entry_list as el
from flexget.api import api, APIResource

log = logging.getLogger('entry_list')

entry_list_api = api.namespace('entry_list', description='Entry List operations')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {'type': 'string'},
        'message': {'type': 'string'}
    }
}
empty_response = api.schema('empty', {'type': 'object'})

default_error_schema = api.schema('default_error_schema', default_error_schema)
entry_list_base_object = {
    'type': 'object',
    'properties': {
        'id': {'type': 'integer'},
        'name': {'type': 'string'},
Example #43
0
from flask import jsonify, request
from sqlalchemy.orm.exc import NoResultFound

from flexget.plugins.list.pending_list import (
    get_pending_lists, get_list_by_exact_name, PendingListList, get_list_by_id,
    delete_list_by_id, get_entries_by_list_id, get_entry_by_title,
    PendingListEntry, get_entry_by_id)
from flexget.api import api, APIResource
from flexget.api.app import (NotFoundError, base_message_schema,
                             success_response, etag, pagination_headers,
                             Conflict, BadRequest)

log = logging.getLogger('pending_list')

pending_list_api = api.namespace('pending_list',
                                 description='Pending List operations')


class ObjectsContainer(object):
    pending_list_base_object = {
        'type': 'object',
        'properties': {
            'id': {
                'type': 'integer'
            },
            'name': {
                'type': 'string'
            },
            'added_on': {
                'type': 'string'
            }
Example #44
0
from __future__ import unicode_literals, division, absolute_import

import datetime
from math import ceil

from flask import jsonify, request
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.plugins.api.series import NoResultFound
from flexget.plugins.filter import movie_queue as mq
from flexget.utils import qualities

movie_queue_api = api.namespace('movie_queue',
                                description='Movie Queue operations')

default_error_schema = {
    'type': 'object',
    'properties': {
        'status': {
            'type': 'string'
        },
        'message': {
            'type': 'string'
        }
    }
}

default_error_schema = api.schema('default_error_schema', default_error_schema)

empty_response = api.schema('empty', {'type': 'object'})
Example #45
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import logging

from flask import jsonify
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.plugins.filter.retry_failed import FailedEntry

log = logging.getLogger('failed_api')

retry_failed_api = api.namespace('failed',
                                 description='View and manage failed entries')

empty_response = api.schema('empty', {'type': 'object'})

retry_failed_entry_object = {
    'type': 'object',
    'properties': {
        'id': {
            'type': 'integer'
        },
        'title': {
            'type': 'string'
        },
        'url': {
            'type': 'string'
        },
        'added_at': {
Example #46
0
from __future__ import unicode_literals, division, absolute_import

from builtins import *  # pylint: disable=unused-import, redefined-builtin
from flask import jsonify
from flask_restplus import inputs

from flexget.api import api, APIResource
from flexget.api.app import NotFoundError, BadRequest, etag
from flexget.plugins.internal.api_tvdb import lookup_series, lookup_episode, search_for_series

tvdb_api = api.namespace('tvdb', description='TheTVDB Shows')


class ObjectsContainer(object):
    tvdb_series_object = {
        'type': 'object',
        'properties': {
            'tvdb_id': {'type': 'integer'},
            'last_updated': {'type': 'string', 'format': 'date-time'},
            'expired': {'type': 'boolean'},
            'series_name': {'type': 'string'},
            'rating': {'type': 'number'},
            'status': {'type': 'string'},
            'runtime': {'type': 'integer'},
            'airs_time': {'type': 'string'},
            'airs_dayofweek': {'type': 'string'},
            'content_rating': {'type': 'string'},
            'network': {'type': 'string'},
            'overview': {'type': 'string'},
            'imdb_id': {'type': 'string'},
            'zap2it_id': {'type': 'string'},
Example #47
0
        scheduler.shutdown(wait=True)


@event("manager.shutdown")
def stop_scheduler(manager):
    if scheduler and scheduler.running:
        scheduler.shutdown(wait=False)


@event("config.register")
def register_config():
    register_config_key("schedules", main_schema)
    register_schema("/schema/config/schedule", schedule_schema)


schedule_api = api.namespace("schedules", description="Task Scheduler")

api_schedule_schema = api.schema("schedule", schedule_schema)
api_schedules_list_schema = api.schema("schedule", main_schema)


def _schedule_by_id(schedule_id):
    for schedule in manager.config.get("schedules", []):
        if id(schedule) == schedule_id:
            schedule = schedule.copy()
            schedule["id"] = schedule_id
            return schedule


@schedule_api.route("/")
class SchedulesAPI(APIResource):
Example #48
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flask.helpers import send_file
from flask_restplus import inputs
from flexget.api import api, APIResource
from flexget.api.app import APIError, BadRequest
from flexget.utils.cache import cached_resource
from requests import RequestException

cached_api = api.namespace('cached', description='Cache remote resources')

cached_parser = api.parser()
cached_parser.add_argument('url', required=True, help='URL to cache')
cached_parser.add_argument(
    'force', type=inputs.boolean, default=False, help='Force fetching remote resource'
)


@cached_api.route('/')
@api.doc(description='Returns a cached copy of the requested resource, matching its mime type')
class CachedResource(APIResource):
    @api.response(200, description='Cached resource')
    @api.response(BadRequest)
    @api.response(APIError)
    @api.doc(parser=cached_parser)
    def get(self, session=None):
        """ Cache remote resources """
        args = cached_parser.parse_args()
        url = args.get('url')
        force = args.get('force')
Example #49
0
from flask import jsonify, request
from flask_restplus import inputs
from flexget.api import api, APIResource
from flexget.api.app import (
    base_message_schema,
    success_response,
    NotFoundError,
    etag,
    pagination_headers,
    BadRequest,
)
from sqlalchemy.orm.exc import NoResultFound

from . import db

pending_api = api.namespace('pending', description='View and manage pending entries')


class ObjectsContainer(object):
    pending_entry_object = {
        'type': 'object',
        'properties': {
            'id': {'type': 'integer'},
            'task_name': {'type': 'string'},
            'title': {'type': 'string'},
            'url': {'type': 'string'},
            'approved': {'type': 'boolean'},
            'added': {'type': 'string', 'format': 'date-time'},
        },
    }
Example #50
0
import cherrypy
import yaml
from flask import Response, jsonify, request
from flask_restplus import inputs
from pyparsing import Word, Keyword, Group, Forward, Suppress, OneOrMore, oneOf, White, restOfLine, ParseException, \
    Combine
from pyparsing import nums, alphanums, printables
from yaml.error import YAMLError

from flexget._version import __version__
from flexget.api import api, APIResource, ApiError, __version__ as __api_version__

log = logging.getLogger('api.server')

server_api = api.namespace('server', description='Manage Daemon')

yaml_error_response = {
    'type': 'object',
    'properties': {
        'code': {
            'type': 'integer'
        },
        'column': {
            'type': 'integer'
        },
        'line': {
            'type': 'integer'
        },
        'message': {
            'type': 'string'
Example #51
0
import logging
from math import ceil

from flask import jsonify
from flask import request
from sqlalchemy.orm.exc import NoResultFound

from flexget.api import api, APIResource
from flexget.api.app import Conflict, NotFoundError, base_message_schema, success_response, BadRequest, etag, \
    pagination_headers
from flexget.plugins.list import movie_list as ml
from flexget.plugins.list.movie_list import MovieListBase

log = logging.getLogger('movie_list')

movie_list_api = api.namespace('movie_list',
                               description='Movie List operations')


class ObjectsContainer(object):
    input_movie_list_id_object = {
        'type': 'array',
        'items': {
            'type': 'object',
            'minProperties': 1,
            'additionalProperties': True
        }
    }

    input_movie_entry = {
        'type': 'object',
        'properties': {
Example #52
0
from flask import jsonify
from flexget.api import api, APIResource
from flexget.config_schema import schema_paths, resolve_ref

schema_api = api.namespace('schema', description='Config and plugin schemas')
_plugins_cache = None

schema_api_list = api.schema(
    'schema.list', {
        'type': 'object',
        'properties': {
            'schemas': {
                'type': 'array',
                'items': {
                    'type': 'object'
                }
            }
        }
    })


@schema_api.route('/')
class SchemaAllAPI(APIResource):
    @api.response(200, model=schema_api_list)
    def get(self, session=None):
        """ List all schema definitions """
        schemas = {}
        for path in schema_paths:
            schemas[path] = resolve_ref(path)

        return jsonify({'schemas': schemas})
Example #53
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import copy

from flask import request, jsonify

from flexget.plugins.daemon.scheduler import schedule_schema, scheduler, scheduler_job_map, DEFAULT_SCHEDULES
from flexget.api import api, APIResource
from flexget.api.app import NotFoundError, APIError, base_message_schema, success_response, etag, Conflict

schedule_api = api.namespace('schedules', description='Task Scheduler')


class ObjectsContainer(object):
    # SwaggerUI does not yet support anyOf or oneOf
    schedule_object = copy.deepcopy(schedule_schema)
    schedule_object['properties']['id'] = {'type': 'integer'}
    schedule_object['maxProperties'] += 1

    schedules_list = {'type': 'array', 'items': schedule_object}


base_schedule_schema = api.schema('schedules.base', schedule_schema)
api_schedule_schema = api.schema('schedules.schedule', ObjectsContainer.schedule_object)
api_schedules_list_schema = api.schema('schedules.list', ObjectsContainer.schedules_list)


def _schedule_by_id(schedule_id, schedules):
    for idx, schedule in enumerate(schedules):
        if schedule and id(schedule) == schedule_id:
Example #54
0
from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flask import jsonify, request

from flexget.db_schema import reset_schema, plugin_schemas
from flexget.api import api, APIResource
from flexget.api.app import base_message_schema, success_response, BadRequest

db_api = api.namespace('database', description='Manage Flexget DB')


class ObjectsContainer(object):
    plugin_list = {'type': 'array', 'items': {'type': 'string'}}

    database_input_object = {
        'type': 'object',
        'properties': {
            'operation': {'type': 'string', 'enum': ['cleanup', 'vacuum', 'plugin_reset']},
            'plugin_name': {'type': 'string'},
        },
        'required': ['operation'],
        'additionalProperties': False,
    }


plugins_schema = api.schema_model('plugins_list', ObjectsContainer.plugin_list)
input_schema = api.schema_model('db_schema', ObjectsContainer.database_input_object)


@db_api.route('/')
Example #55
0
from datetime import datetime
from Queue import Queue, Empty

from flask import request, jsonify, Response

from flexget.options import get_parser
from flexget.api import api, APIResource
from flexget.utils import json
from json import JSONEncoder
from flexget.event import event
from flexget.utils.lazy_dict import LazyLookup

execution_api = api.namespace('execution', description='Execute tasks')


def _task_info_dict(task):
    return {
        'id': int(task.id),
        'name': task.name,
        'current_phase': task.current_phase,
        'current_plugin': task.current_plugin,
    }


task_info_schema = {
    'type': 'object',
    'properties': {
        'id': {
            'type': 'integer'
        },
        'name': {