from __future__ import unicode_literals, division, absolute_import from flask import render_template, Blueprint from flexget.ui.webui import register_plugin home = Blueprint('home', __name__) @home.route('/') def index(): return render_template('home/home.html') register_plugin(home, menu='Home', order=0, home=True)
@schedule.route('/delete/<task>') def delete_schedule(task): db_session.query(Schedule).filter(Schedule.task == task).delete() db_session.commit() stop_empty_timers() return redirect(url_for('.index')) @schedule.route('/add/<task>') def add_schedule(task): schedule = db_session.query(Schedule).filter(Schedule.task == task).first() if not schedule: schedule = Schedule(task, DEFAULT_INTERVAL) db_session.add(schedule) db_session.commit() start_timer(DEFAULT_INTERVAL) return redirect(url_for('.index')) def get_all_tasks(): return [task for task in manager.config.get('tasks', {}).keys() if not task.startswith('_')] def get_scheduled_tasks(): return [item.task for item in db_session.query(Schedule).all()] register_plugin(schedule, menu='Schedule')
item = func(item) if set is not None: obj[item] = set return obj[item] except (TypeError, LookupError, ValueError): pass raise LookupError('%s not in config' % item) @config.route('/<path:path>', methods=['GET', 'POST']) def with_path(path): path = path.split('/') result = manager.config try: for elem in path[:-1]: result = getset_item(result, elem) elem = path[-1] if request.method == 'POST': getset_item(result, elem, set=json.loads(request.data)) result = jsonify(getset_item(result, elem)) except LookupError as e: return unicode(e), 404 # TODO: This should not be hard coded if len(path) == 2 and path[0] in ['tasks', 'presets']: result.headers[ b'Content-Type'] += '; profile=/schema/plugins?context=task' return result register_plugin(config)
db_session.commit() return redirect('/series') @outputs_module.route('/forget/<int:rel_id>', methods=['POST', 'GET']) def forget_episode(rel_id): """ Executes a --series-forget statement for an episode. Redirects back to the series index. """ release = db_session.query(Release).get(rel_id) context = {'release': release, 'command': 'series forget "%s" %s' % ( release.episode.series.name, release.episode.identifier)} if request.method == 'POST': if request.form.get('really', False): try: forget_series_episode(release.episode.series.name, release.episode.identifier) flash('Forgot %s %s.' % ( release.episode.series.name, release.episode.identifier), 'delete') except ValueError as e: flash(e.message, 'error') return redirect(url_for('.index')) return render_template('series/forget.html', **context) register_plugin(outputs_module, menu='Outputs')
import logging from sqlalchemy import desc from flexget.ui.webui import register_plugin, db_session from flask import render_template, Module from flexget.plugin import DependencyError try: from flexget.plugins.output.history import History except ImportError: raise DependencyError(issued_by='ui.history', missing='history') log = logging.getLogger('ui.history') history = Module(__name__) @history.route('/') def index(): context = { 'items': db_session.query(History).order_by(desc(History.time)).limit(50).all() } return render_template('history/history.html', **context) register_plugin(history, menu='History')
global timers if timers.get(interval): timers[interval].cancel() del timers[interval] def stop_empty_timers(): """Stops timers that don't have any more feeds using them.""" current_intervals = set([i.interval for i in db_session.query(Schedule).all()]) for interval in timers.keys(): if interval not in current_intervals: stop_timer(interval) @event("webui.start") def on_webui_start(): # Start timers for all schedules for interval in set([item.interval for item in db_session.query(Schedule).all()]): start_timer(interval) @event("webui.stop") def on_webui_stop(): log.info("Terminating") # Stop all running timers for interval in timers.keys(): stop_timer(interval) register_plugin(schedule, menu="Schedule")
return render_template('inject/inject.html') @inject.route('/do', methods=['POST', 'GET']) def do_inject(): fields = {} # Requests is a special dict, and cannot be passed as keyword arguments, make it into a normal dict. for key, value in request.values.iteritems(): # Translate on and off to True and False if value == 'on': fields[key] = True elif value == 'off': fields[key] = False else: fields[key] = value # If we only got a url, make a title from the url filename fields['title'] = fields.get('title') or posixpath.basename(urlparse.urlsplit(fields.get('url', '')).path) if fields.get('title') and fields.get('url'): # Create the entry for injection entry = Entry(**fields) executor.execute(options={'dump_entries': True}, entries=[entry]) flash('Scheduled execution for entry `%s`' % entry['title'], 'success') else: flash('Title and URL required for inject.', 'error') return redirect(url_for('index')) register_plugin(inject)
query = query.filter(LogEntry.execution == execution) count = query.count() # Use a trick to do ceiling division total_pages = 0 - ((0 - count) / limit) if page > total_pages: page = total_pages start = limit * page - limit json = {'total': total_pages, 'page': page, 'records': count, 'rows': []} result = query.order_by(sord(sidx))[start:start + limit] for entry in result: json['rows'].append({ 'id': entry.id, 'created': entry.created.strftime('%Y-%m-%d %H:%M'), 'levelno': logging.getLevelName(entry.levelno), 'logger': entry.logger, 'task': entry.task, 'message': entry.message }) return jsonify(json) @event('webui.start') def initialize(): # Register db handler with base logger logger = logging.getLogger() handler = DBLogHandler() logger.addHandler(handler) register_plugin(log_viewer, menu='Log', order=256)
elif len(text) < 5: flash('Search text is too short, use at least 5 characters', 'error') else: results = search(db_session, text) if not results: flash('No results', 'info') else: # not sure if this len check is a good idea, I think it forces to load all items from db ? if len(results) > 500: flash('Too many results, displaying first 500', 'error') results = results[0:500] context['results'] = results return render_template('archive/archive.html', **context) @archive.route('/count') def count(): log.debug('getting count for archive') return str(db_session.query(ArchiveEntry).count()) @archive.route('/inject/<id>') def inject(id): options = {'archive_inject_id': id, 'archive_inject_immortal': True} executor.execute(options=options) flash('Queued execution, see log for results', 'info') return render_template('archive/archive.html') register_plugin(archive, menu='Archive')
query = query.filter(LogEntry.execution == execution) count = query.count() # Use a trick to do ceiling division total_pages = 0 - ((0 - count) / limit) if page > total_pages: page = total_pages start = limit * page - limit json = {'total': total_pages, 'page': page, 'records': count, 'rows': []} result = query.order_by(sord(sidx))[start:start + limit] for entry in result: json['rows'].append({ 'id': entry.id, 'created': entry.created.strftime('%Y-%m-%d %H:%M'), 'levelno': logging.getLevelName(entry.levelno), 'logger': entry.logger, 'task': entry.task, 'message': entry.message }) return jsonify(json) @event('webui.start') def initialize(): # Register db handler with base logger logger = logging.getLogger() handler = DBLogHandler() logger.addHandler(handler) register_plugin(log_viewer, url_prefix='/log', menu='Log', order=256)
try: item = func(item) if set is not None: obj[item] = set return obj[item] except (TypeError, LookupError, ValueError): pass raise LookupError("%s not in config" % item) @config.route("/<path:path>", methods=["GET", "POST"]) def with_path(path): path = path.split("/") result = manager.config try: for elem in path[:-1]: result = getset_item(result, elem) elem = path[-1] if request.method == "POST": getset_item(result, elem, set=json.loads(request.data)) result = jsonify(getset_item(result, elem)) except LookupError as e: return unicode(e), 404 # TODO: This should not be hard coded if len(path) == 2 and path[0] in ["tasks", "presets"]: result.headers[b"Content-Type"] += "; profile=/schema/plugins?context=task" return result register_plugin(config)
query = query.filter(LogEntry.execution == execution) count = query.count() # Use a trick to do ceiling division total_pages = 0 - ((0 - count) / limit) if page > total_pages: page = total_pages start = limit * page - limit json = {'total': total_pages, 'page': page, 'records': count, 'rows': []} result = query.order_by(sord(sidx))[start:start + limit] for entry in result: json['rows'].append({'id': entry.id, 'created': entry.created.strftime('%Y-%m-%d %H:%M'), 'levelno': logging.getLevelName(entry.levelno), 'logger': entry.logger, 'task': entry.task, 'message': entry.message}) return jsonify(json) @event('webui.start') def initialize(): # Register db handler with base logger logger = logging.getLogger() handler = DBLogHandler() logger.addHandler(handler) register_plugin(log_viewer, menu='Log', order=256)
from flexget.ui.webui import register_plugin, manager from flexget.plugin import plugins from flask import render_template, Module plugins_module = Module(__name__, url_prefix='/plugins') @plugins_module.route('/') def index(): context = {'plugins': plugins} return render_template('plugins/plugins.html', **context) if manager.options.debug: register_plugin(plugins_module, menu='Plugins (DEV)')
from __future__ import unicode_literals, division, absolute_import from flask import render_template, Blueprint from flexget.ui.webui import register_plugin home = Blueprint("home", __name__) @home.route("/") def index(): return render_template("home/home.html") register_plugin(home, menu="Home", order=0, home=True)
def edit(root, name): context = {'name': name} context['config'] = manager.config[root][name] return render_template('configure/edit.html', **context) @app.template_filter('other_type') def other_type(root): if root == 'tasks': return 'presets' return 'tasks' def get_related(root, name): """Returns a list of related tasks/presets for a given preset/task""" if root == 'tasks': presets = manager.config[root][name].get('preset', []) if isinstance(presets, basestring): presets = [presets] return presets elif root == 'presets': tasks = [] for task, config in manager.config['tasks'].iteritems(): if config.get('preset'): if name == config['preset'] or name in config['preset']: tasks.append(task) return tasks register_plugin(configure, menu='Configure', order=10)
@event('webui.start') def enable_authentication(): if manager.options.webui.no_auth: return global credentials credentials = db_session.query(AuthCredentials).first() if not credentials: credentials = AuthCredentials('flexget', 'flexget') db_session.add(credentials) if manager.options.webui.username: credentials.username = manager.options.username if manager.options.webui.password: credentials.password = manager.options.webui.password db_session.commit() app.before_request(check_authenticated) def check_authenticated(): # TODO: Is this a big security hole? Maybe figure out a better way to authenticate for local IPC if manager.options.webui.no_local_auth and request.remote_addr == '127.0.0.1': return auth = request.authorization if not auth or not check_auth(auth.username, auth.password): return authenticate() register_plugin(auth)
Redirects back to the series index. """ release = db_session.query(Release).get(rel_id) context = { 'release': release, 'command': 'series forget "%s" %s' % (release.episode.series.name, release.episode.identifier) } if request.method == 'POST': if request.form.get('really', False): try: forget_series_episode(release.episode.series.name, release.episode.identifier) flash( 'Forgot %s %s.' % (release.episode.series.name, release.episode.identifier), 'delete') except ValueError as e: flash(e.message, 'error') return redirect(url_for('.index')) return render_template('series/forget.html', **context) register_plugin(outputs_module, menu='Outputs')
query = query.filter(LogEntry.execution == execution) count = query.count() # Use a trick to do ceiling division total_pages = 0 - ((0 - count) / limit) if page > total_pages: page = total_pages start = limit * page - limit json = {'total': total_pages, 'page': page, 'records': count, 'rows': []} result = query.order_by(sord(sidx))[start:start + limit] for entry in result: json['rows'].append({'id': entry.id, 'created': entry.created.strftime('%Y-%m-%d %H:%M'), 'levelno': logging.getLevelName(entry.levelno), 'logger': entry.logger, 'task': entry.task, 'message': entry.message}) return jsonify(json) @event('webui.start') def initialize(): # Register db handler with base logger logger = logging.getLogger() handler = DBLogHandler() logger.addHandler(handler) register_plugin(log_viewer, url_prefix='/log', menu='Log', order=256)
db_session.commit() return redirect('/series') @series_module.route('/forget/<int:rel_id>', methods=['POST', 'GET']) def forget_episode(rel_id): ''' Executes a --series-forget statement for an episode. Redirects back to the series index. ''' release = db_session.query(Release).get(rel_id) context = {'release': release, 'command': '--series-forget "%s" %s' % ( release.episode.series.name, release.episode.identifier)} if request.method == 'POST': if request.form.get('really', False): try: forget_series_episode(release.episode.series.name, release.episode.identifier) flash('Forgot %s %s.' % ( release.episode.series.name, release.episode.identifier), 'delete') except ValueError, e: flash(e.message, 'error') return redirect(url_for('index')) return render_template('series/forget.html', **context) register_plugin(series_module, menu='Series')
from __future__ import unicode_literals, division, absolute_import from flask import Module, jsonify, request from jsonschema import RefResolutionError from flexget.config_schema import resolve_ref from flexget.ui.webui import register_plugin schema = Module(__name__) @schema.route('/', defaults={'path': ''}) @schema.route('/<path:path>') def get_schema(path): refpath = '/schema/' + path if request.query_string: refpath += '?' + request.query_string try: return jsonify(resolve_ref(refpath)) except RefResolutionError: return 'Schema not found', 404 register_plugin(schema)
'You have to login with proper credentials', 401, {'WWW-Authenticate': 'Basic realm="Login Required"'}) @event('webui.start') def enable_authentication(): if manager.options.no_auth: return global credentials credentials = db_session.query(AuthCredentials).first() if not credentials: credentials = AuthCredentials('flexget', 'flexget') db_session.add(credentials) if manager.options.username: credentials.username = manager.options.username if manager.options.password: credentials.password = manager.options.password db_session.commit() app.before_request(check_authenticated) def check_authenticated(): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): return authenticate() register_plugin(auth)
from __future__ import unicode_literals, division, absolute_import import logging from sqlalchemy import desc from flexget.ui.webui import register_plugin, db_session from flask import render_template, Module from flexget.plugin import DependencyError try: from flexget.plugins.output.history import History except ImportError: raise DependencyError(issued_by='ui.history', missing='history') log = logging.getLogger('ui.history') history = Module(__name__) @history.route('/') def index(): context = {'items': db_session.query(History).order_by(desc(History.time)).limit(50).all()} return render_template('history/history.html', **context) register_plugin(history, menu='History')
@plugins_module.route('/context/<context>') def plugins_by_context(context): return jsonify(plugins=plugin_infos(get_plugins(context=context))) @plugins_module.route('/categories') def categories(): # TODO: Should this only return the list of categories that actually have plugins? return jsonify(categories=task_phases) @plugins_module.route('/category/<category>') def plugins_by_category(category): return jsonify(plugins=plugin_infos(get_plugins(category=category))) @plugins_module.route('/schema/<name>') def plugin_schema(name): try: plugin = get_plugin_by_name(name).instance except DependencyError: return 'Plugin %s does not exist' % name, 404 try: validator = plugin.validator() except AttributeError: return 'Plugin %s does not have a schema' % name, 404 return jsonify(validator.schema()) register_plugin(plugins_module)
from __future__ import unicode_literals, division, absolute_import from flexget.ui.webui import register_plugin, stop_server from flask import render_template, Module import logging shutdown = Module(__name__, url_prefix='/shutdown') log = logging.getLogger('shutdown') @shutdown.route('/') def index(): return render_template('shutdown/shutdown.html') @shutdown.route('/now') def now(): stop_server() return 'Shutdown Complete' register_plugin(shutdown, menu='Shutdown', order=512)
# Use a trick to do ceiling division total_pages = 0 - ((0 - count) / limit) if page > total_pages: page = total_pages start = limit * page - limit json = {"total": total_pages, "page": page, "records": count, "rows": []} result = query.order_by(sord(sidx))[start : start + limit] for entry in result: json["rows"].append( { "id": entry.id, "created": entry.created.strftime("%Y-%m-%d %H:%M"), "levelno": logging.getLevelName(entry.levelno), "logger": entry.logger, "feed": entry.feed, "message": entry.message, } ) return jsonify(json) @event("webui.start") def initialize(): # Register db handler with base logger logger = logging.getLogger() handler = DBLogHandler() logger.addHandler(handler) register_plugin(log_viewer, url_prefix="/log", menu="Log", order=256)
def cover(imdb_id): import os # TODO: return '' should be replaced with something sane, http error 404 ? tmdb_lookup = get_plugin_by_name('api_tmdb').instance.lookup try: movie = tmdb_lookup(imdb_id=imdb_id) except LookupError: log.error('No cached data for %s' % imdb_id) return '' filepath = None for poster in movie.posters: if poster.size == 'thumb': filepath = os.path.join(manager.config_base, 'userstatic', *poster.get_file()) break if filepath is None: log.error('No cover for %s' % imdb_id) return '' elif not os.path.exists(filepath): log.error('File %s does not exist' % filepath) return '' log.debug('sending thumb file %s' % filepath) return send_file(filepath, mimetype='image/png') register_plugin(movies_module, menu='Movies')
from __future__ import unicode_literals, division, absolute_import from flask import render_template, Module from flexget.ui.webui import register_plugin home = Module(__name__, url_prefix='/home') @home.route('/') def index(): return render_template('home/home.html') register_plugin(home, menu='Home', order=0, home=True)
context['options'] = request.form['options'] else: manager.execute(options=options.execute, output=bufferqueue) context['execute_progress'] = True context['progress'] = progress(as_list=True) return render_template('execute/execute.html', **context) @execute.route('/progress.json') def progress(as_list=False): """ Gets messages from the queue and exports them to JSON. """ result = {'items': []} try: while True: item = bufferqueue.get_nowait() result['items'].append(item) bufferqueue.task_done() except Empty: pass if as_list: return result['items'] return jsonify(result) register_plugin(execute, menu='Execute')
global timers if timers.get(interval): timers[interval].cancel() del timers[interval] def stop_empty_timers(): """Stops timers that don't have any more tasks using them.""" current_intervals = set([i.interval for i in db_session.query(Schedule).all()]) for interval in timers.keys(): if interval not in current_intervals: stop_timer(interval) @event('webui.start') def on_webui_start(): # Start timers for all schedules for interval in set([item.interval for item in db_session.query(Schedule).all()]): start_timer(interval) @event('webui.stop') def on_webui_stop(): log.info('Terminating') # Stop all running timers for interval in timers.keys(): stop_timer(interval) register_plugin(schedule, menu='Schedule')
@configure.route('/jsonary') def jsonary(): return render_template('configure/edit_jsonary.html') @app.template_filter('other_type') def other_type(root): if root == 'tasks': return 'presets' return 'tasks' def get_related(root, name): """Returns a list of related tasks/presets for a given preset/task""" if root == 'tasks': presets = manager.config[root][name].get('preset', []) if isinstance(presets, basestring): presets = [presets] return presets elif root == 'presets': tasks = [] for task, config in manager.config['tasks'].iteritems(): if config.get('preset'): if name == config['preset'] or name in config['preset']: tasks.append(task) return tasks register_plugin(configure, menu='Configure', order=10)
Redirects back to the series index. ''' release = db_session.query(Release).get(rel_id) context = { 'release': release, 'command': '--series-forget "%s" %s' % (release.episode.series.name, release.episode.identifier) } if request.method == 'POST': if request.form.get('really', False): try: forget_series_episode(release.episode.series.name, release.episode.identifier) flash( 'Forgot %s %s.' % (release.episode.series.name, release.episode.identifier), 'delete') except ValueError as e: flash(e.message, 'error') return redirect(url_for('index')) return render_template('series/forget.html', **context) register_plugin(series_module, menu='Series')
else: manager.scheduler.execute(options=options.execute, output=bufferqueue) context['execute_progress'] = True context['progress'] = progress(as_list=True) return render_template('execute/execute.html', **context) @execute.route('/progress.json') def progress(as_list=False): """ Gets messages from the queue and exports them to JSON. """ result = {'items': []} try: while True: item = bufferqueue.get_nowait() result['items'].append(item) bufferqueue.task_done() except Empty: pass if as_list: return result['items'] return jsonify(result) register_plugin(execute, menu='Execute')
return redirect("/series") @series_module.route("/forget/<int:rel_id>", methods=["POST", "GET"]) def forget_episode(rel_id): """ Executes a --series-forget statement for an episode. Redirects back to the series index. """ release = db_session.query(Release).get(rel_id) context = { "release": release, "command": '--series-forget "%s" %s' % (release.episode.series.name, release.episode.identifier), } if request.method == "POST": if request.form.get("really", False): try: forget_series_episode(release.episode.series.name, release.episode.identifier) flash("Forgot %s %s." % (release.episode.series.name, release.episode.identifier), "delete") except ValueError as e: flash(e.message, "error") return redirect(url_for("index")) return render_template("series/forget.html", **context) register_plugin(series_module, menu="Series")