From f702b50b6ac6cb2e1e0e848a629a623f323c9de2 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 24 Jun 2023 19:38:33 +0200 Subject: Merging upstream version 2.1.2~dev0+20230529. Signed-off-by: Daniel Baumann --- deluge/scripts/create_deluge_pngs | 71 +++++++ deluge/scripts/create_plugin.py | 415 ++++++++++++++++++++++++++++++++++++++ deluge/scripts/deluge_remote.py | 138 +++++++++++++ 3 files changed, 624 insertions(+) create mode 100755 deluge/scripts/create_deluge_pngs create mode 100644 deluge/scripts/create_plugin.py create mode 100644 deluge/scripts/deluge_remote.py (limited to 'deluge/scripts') diff --git a/deluge/scripts/create_deluge_pngs b/deluge/scripts/create_deluge_pngs new file mode 100755 index 0000000..6ed636d --- /dev/null +++ b/deluge/scripts/create_deluge_pngs @@ -0,0 +1,71 @@ +#!/bin/bash + +# A script to convert the Deluge svg icons to png. + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +data_dir="$DIR/../ui/data" +zopfli_iter="--iterations=100" +zopflipng_bin="zopflipng --filters=01234mepb --lossy_8bit --lossy_transparent -y" + +# Create deluge png icon pack for all sizes. +for size in 16 22 24 32 36 48 64 72 96 128 192 256 512; do + mkdir -p $data_dir/icons/hicolor/${size}x${size}/apps + in_svg=$data_dir/pixmaps/deluge.svg + out_png=$data_dir/icons/hicolor/${size}x${size}/apps/deluge.png + rsvg-convert -w ${size} -h ${size} -o $out_png $in_svg + if [ "$size" -gt 128 ]; then + zopfli_iter="" + fi + echo $zopflipng_bin $zopfli_iter + eval $zopflipng_bin $zopfli_iter $out_png $out_png +done + +# Create deluge-panel png for systray. +for size in 16 22 24; do + in_png=$data_dir/icons/hicolor/${size}x${size}/apps/deluge.png + out_png=$data_dir/icons/hicolor/${size}x${size}/apps/deluge-panel.png + cp $in_png $out_png +done + +# Create deluge.ico icon from pngs. +for size in 16 32 48 64 128 256; do + ico_infiles+="$data_dir/icons/hicolor/${size}x${size}/apps/deluge.png " +done +convert $ico_infiles $data_dir/pixmaps/deluge.ico + +# Copy of deluge.svg to icon theme pack. +mkdir -p $data_dir/icons/hicolor/scalable/apps/ +cp $data_dir/pixmaps/deluge.svg $data_dir/icons/hicolor/scalable/apps/deluge.svg + +# Create 48px deluge.png. +cp $data_dir/icons/hicolor/48x48/apps/deluge.png $data_dir/pixmaps/deluge.png + +# Create 16px png from deluge and status svgs. +for file in $data_dir/pixmaps/*.svg; do + out_png=${file%.*}16.png + rsvg-convert -w 16 -h 16 -o $out_png $file + eval $zopflipng_bin $out_png $out_png +done + +# Copy 16px deluge and status pngs to webui icons folder. +for icon in $data_dir/pixmaps/*16.png; do + iconname=$(basename $icon) + cp $icon $data_dir/../web/icons/${iconname::-6}.png +done +rm $data_dir/../web/icons/tracker*.png + +for size in 32 192 512; do + in_png=$data_dir/icons/hicolor/${size}x${size}/apps/deluge.png + out_png=$data_dir/../web/icons/deluge-${size}.png + cp $in_png $out_png + +# Create apple and android touch icons with background colour. +apple_icon=$data_dir/../web/icons/deluge-apple-180.png +rsvg-convert -w 180 -h 180 -b '#599EEE' -o $apple_icon $data_dir/pixmaps/deluge.svg +eval $zopflipng_bin $apple_icon $apple_icon + +# Create favicon.ico icon from pngs. +for size in 16 32 48; do + web_ico_infiles+="$data_dir/icons/hicolor/${size}x${size}/apps/deluge.png " +done +convert $web_ico_infiles $data_dir/../web/icons/favicon.ico diff --git a/deluge/scripts/create_plugin.py b/deluge/scripts/create_plugin.py new file mode 100644 index 0000000..7383661 --- /dev/null +++ b/deluge/scripts/create_plugin.py @@ -0,0 +1,415 @@ +""" +Creates an empty plugin and links it from ~/.config/deluge/plugins +This plugin includes the framework for using the preferences dialog + +example: +python create_plugin.py --name MyPlugin2 --basepath . --author-name "Your Name" --author-email "yourname@example.com" + +""" + +import os +import sys +from argparse import ArgumentParser +from datetime import datetime + +import deluge.common + +parser = ArgumentParser() +parser.add_argument( + '-n', '--name', metavar='', required=True, help='Plugin name' +) +parser.add_argument('-m', '--module-name', metavar='', help='Module name') +parser.add_argument( + '-p', '--basepath', metavar='', required=True, help='Base path' +) +parser.add_argument( + '-a', + '--author-name', + metavar='', + required=True, + help='Author name,for the GPL header', +) +parser.add_argument( + '-e', + '--author-email', + metavar='', + required=True, + help='Author email,for the GPL header', +) +parser.add_argument('-u', '--url', metavar='', help='Homepage URL') +parser.add_argument( + '-c', + '--config', + metavar='', + dest='configdir', + help='Location of deluge configuration', +) + +options = parser.parse_args() + + +def create_plugin(): + if not options.url: + options.url = '' + + if not os.path.exists(options.basepath): + print('basepath does not exist') + return + + if not options.configdir: + options.configdir = deluge.common.get_default_config_dir() + + options.configdir = os.path.realpath(options.configdir) + + real_name = options.name + name = real_name.replace(' ', '_') + safe_name = name.lower() + if options.module_name: + safe_name = options.module_name.lower() + plugin_base = os.path.realpath(os.path.join(options.basepath, name)) + src = os.path.join(plugin_base, 'deluge_' + safe_name) + data_dir = os.path.join(src, 'data') + python_path = sys.executable + + if os.path.exists(plugin_base): + print('the directory %s already exists, delete it first' % plugin_base) + return + + def write_file(path, filename, template, include_gpl=True): + plugin_args = { + 'author_name': options.author_name, + 'author_email': options.author_email, + 'name': name, + 'safe_name': safe_name, + 'filename': filename, + 'plugin_base': plugin_base, + 'python_path': python_path, + 'url': options.url, + 'configdir': options.configdir, + 'current_year': datetime.utcnow().year, + } + + filename = os.path.join(path, filename) + with open(filename, 'w') as _file: + if filename.endswith('.py') and include_gpl: + _file.write(GPL % plugin_args) + _file.write(template % plugin_args) + + print('creating folders..') + os.mkdir(plugin_base) + os.mkdir(src) + os.mkdir(data_dir) + + print('creating files..') + write_file(plugin_base, 'setup.py', SETUP) + write_file(src, '__init__.py', INIT) + write_file(src, 'gtk3ui.py', GTK3UI) + write_file(src, 'webui.py', WEBUI) + write_file(src, 'core.py', CORE) + write_file(src, 'common.py', COMMON) + write_file(data_dir, 'config.ui', GLADE) + write_file(data_dir, '%s.js' % safe_name, DEFAULT_JS) + + # add an input parameter for this? + print('building dev-link..') + if deluge.common.windows_check(): + write_file(plugin_base, 'create_dev_link.bat', CREATE_DEV_LINK_WIN) + dev_link_path = os.path.join(plugin_base, 'create_dev_link.bat') + else: + write_file(plugin_base, 'create_dev_link.sh', CREATE_DEV_LINK_NIX) + dev_link_path = os.path.join(plugin_base, 'create_dev_link.sh') + os.system('chmod +x %s' % dev_link_path) # lazy.. + os.system(dev_link_path) + + +CORE = """from __future__ import unicode_literals + +import logging + +import deluge.configmanager +from deluge.core.rpcserver import export +from deluge.plugins.pluginbase import CorePluginBase + +log = logging.getLogger(__name__) + +DEFAULT_PREFS = { + 'test': 'NiNiNi' +} + + +class Core(CorePluginBase): + def enable(self): + self.config = deluge.configmanager.ConfigManager( + '%(safe_name)s.conf', DEFAULT_PREFS) + + def disable(self): + pass + + def update(self): + pass + + @export + def set_config(self, config): + \"\"\"Sets the config dictionary\"\"\" + for key in config: + self.config[key] = config[key] + self.config.save() + + @export + def get_config(self): + \"\"\"Returns the config dictionary\"\"\" + return self.config.config +""" + +INIT = """from deluge.plugins.init import PluginInitBase + + +class CorePlugin(PluginInitBase): + def __init__(self, plugin_name): + from .core import Core as PluginClass + self._plugin_cls = PluginClass + super(CorePlugin, self).__init__(plugin_name) + + +class Gtk3UIPlugin(PluginInitBase): + def __init__(self, plugin_name): + from .gtk3ui import Gtk3UI as PluginClass + self._plugin_cls = PluginClass + super(Gtk3UIPlugin, self).__init__(plugin_name) + + +class WebUIPlugin(PluginInitBase): + def __init__(self, plugin_name): + from .webui import WebUI as PluginClass + self._plugin_cls = PluginClass + super(WebUIPlugin, self).__init__(plugin_name) +""" + + +SETUP = """from setuptools import find_packages, setup + +__plugin_name__ = '%(name)s' +__author__ = '%(author_name)s' +__author_email__ = '%(author_email)s' +__version__ = '0.1' +__url__ = '%(url)s' +__license__ = 'GPLv3' +__description__ = '' +__long_description__ = \"\"\"\"\"\" +__pkg_data__ = {'deluge_'+__plugin_name__.lower(): ['data/*']} + +setup( + name=__plugin_name__, + version=__version__, + description=__description__, + author=__author__, + author_email=__author_email__, + url=__url__, + license=__license__, + long_description=__long_description__, + + packages=find_packages(), + package_data=__pkg_data__, + + entry_points=\"\"\" + [deluge.plugin.core] + %%s = deluge_%%s:CorePlugin + [deluge.plugin.gtk3ui] + %%s = deluge_%%s:Gtk3UIPlugin + [deluge.plugin.web] + %%s = deluge_%%s:WebUIPlugin + \"\"\" %% ((__plugin_name__, __plugin_name__.lower()) * 3) +) +""" + +COMMON = """from __future__ import unicode_literals + +import os.path + +from pkg_resources import resource_filename + + +def get_resource(filename): + return resource_filename(__package__, os.path.join('data', filename)) +""" + +GTK3UI = """from __future__ import unicode_literals + +import logging + +from gi.repository import Gtk + +import deluge.component as component +from deluge.plugins.pluginbase import Gtk3PluginBase +from deluge.ui.client import client + +from .common import get_resource + +log = logging.getLogger(__name__) + + +class Gtk3UI(Gtk3PluginBase): + def enable(self): + self.builder = Gtk.Builder() + self.builder.add_from_file(get_resource('config.ui')) + + component.get('Preferences').add_page( + '%(name)s', self.builder.get_object('prefs_box')) + component.get('PluginManager').register_hook( + 'on_apply_prefs', self.on_apply_prefs) + component.get('PluginManager').register_hook( + 'on_show_prefs', self.on_show_prefs) + + def disable(self): + component.get('Preferences').remove_page('%(name)s') + component.get('PluginManager').deregister_hook( + 'on_apply_prefs', self.on_apply_prefs) + component.get('PluginManager').deregister_hook( + 'on_show_prefs', self.on_show_prefs) + + def on_apply_prefs(self): + log.debug('applying prefs for %(name)s') + config = { + 'test': self.builder.get_object('txt_test').get_text() + } + client.%(safe_name)s.set_config(config) + + def on_show_prefs(self): + client.%(safe_name)s.get_config().addCallback(self.cb_get_config) + + def cb_get_config(self, config): + \"\"\"callback for on show_prefs\"\"\" + self.builder.get_object('txt_test').set_text(config['test']) +""" + +GLADE = """ + + + + + + + True + + + True + Test config value: + + + + + True + True + + + 1 + + + + + + +""" + +WEBUI = """from __future__ import unicode_literals + +import logging + +from deluge.plugins.pluginbase import WebPluginBase + +from .common import get_resource + +log = logging.getLogger(__name__) + + +class WebUI(WebPluginBase): + + scripts = [get_resource('%(safe_name)s.js')] + + def enable(self): + pass + + def disable(self): + pass +""" + +DEFAULT_JS = """/** + * Script: %(filename)s + * The client-side javascript code for the %(name)s plugin. + * + * Copyright: + * (C) %(author_name)s %(current_year)s <%(author_email)s> + * + * This file is part of %(name)s and is licensed under GNU GPL 3.0, or + * later, with the additional special exception to link portions of this + * program with the OpenSSL library. See LICENSE for more details. + */ + +%(name)sPlugin = Ext.extend(Deluge.Plugin, { + constructor: function(config) { + config = Ext.apply({ + name: '%(name)s' + }, config); + %(name)sPlugin.superclass.constructor.call(this, config); + }, + + onDisable: function() { + deluge.preferences.removePage(this.prefsPage); + }, + + onEnable: function() { + this.prefsPage = deluge.preferences.addPage( + new Deluge.ux.preferences.%(name)sPage()); + } +}); +new %(name)sPlugin(); +""" + +GPL = """# -*- coding: utf-8 -*- +# Copyright (C) %(current_year)d %(author_name)s <%(author_email)s> +# +# Basic plugin template created by the Deluge Team. +# +# This file is part of %(name)s and is licensed under GNU GPL 3.0, or later, +# with the additional special exception to link portions of this program with +# the OpenSSL library. See LICENSE for more details. +""" + +CREATE_DEV_LINK_NIX = """#!/bin/bash +BASEDIR=$(cd `dirname $0` && pwd) +CONFIG_DIR=$( test -z $1 && echo "%(configdir)s" || echo "$1") +[ -d "$CONFIG_DIR/plugins" ] || echo "Config dir \"$CONFIG_DIR\" is either not a directory \ +or is not a proper deluge config directory. Exiting" +[ -d "$CONFIG_DIR/plugins" ] || exit 1 +cd $BASEDIR +test -d $BASEDIR/temp || mkdir $BASEDIR/temp +export PYTHONPATH=$BASEDIR/temp +%(python_path)s setup.py build develop --install-dir $BASEDIR/temp +cp $BASEDIR/temp/*.egg-link $CONFIG_DIR/plugins +rm -fr $BASEDIR/temp +""" + +CREATE_DEV_LINK_WIN = """@echo off +set BASEDIR=%%~dp0 +set BASEDIR=%%BASEDIR:~0,-1%% +if [%%1]==[] ( + set CONFIG_DIR=%(configdir)s +) else ( + set CONFIG_DIR=%%1 +) +if not exist %%CONFIG_DIR%%\\plugins ( + echo Config dir %%CONFIG_DIR%% is either not a directory \ +or is not a proper deluge config directory. Exiting + exit /b 1 +) +cd %%BASEDIR%% +if not exist %%BASEDIR%%\\temp ( + md %%BASEDIR%%\\temp +) +set PYTHONPATH=%%BASEDIR%%/temp +%(python_path)s setup.py build develop --install-dir %%BASEDIR%%\\temp +copy "%%BASEDIR%%\\temp\\*.egg-link" "%%CONFIG_DIR%%\\plugins" +rd /s /q %%BASEDIR%%\\temp +""" + +create_plugin() diff --git a/deluge/scripts/deluge_remote.py b/deluge/scripts/deluge_remote.py new file mode 100644 index 0000000..d983e53 --- /dev/null +++ b/deluge/scripts/deluge_remote.py @@ -0,0 +1,138 @@ +#!/usr/bin/python +# +# This software is in the public domain, furnished "as is", without technical +# support, and with no warranty, express or implied, as to its usefulness for +# any purpose. +# +# deluge_config.py +# This code (at least in theory) allows one to alter configuration settings +# on a deluge backend. At the moment, though, it only alters the parameters +# that I've found useful to change. +# +# Authour: Garett Harnish + +import logging +import sys +from optparse import OptionParser + + +def is_float_digit(string): + if string.isdigit(): + return True + else: + try: + float(string) + return True + except ValueError: + return False + + +# set up command-line options +parser = OptionParser() +parser.add_option( + '--port', + help='port for deluge backend host (default: 58846)', + default='58846', + dest='port', +) +parser.add_option( + '--host', + help='hostname of deluge backend to connect to (default: localhost)', + default='localhost', + dest='host', +) +parser.add_option( + '--max_active_limit', + dest='max_active_limit', + help='sets the absolute maximum number of active torrents on the deluge backend', +) +parser.add_option( + '--max_active_downloading', + dest='max_active_downloading', + help='sets the maximum number of active downloading torrents on the deluge backend', +) +parser.add_option( + '--max_active_seeding', + dest='max_active_seeding', + help='sets the maximum number of active seeding torrents on the deluge backend', +) +parser.add_option( + '--max_download_speed', + help='sets the maximum global download speed on the deluge backend', + dest='max_download_speed', +) +parser.add_option( + '--max_upload_speed', + help='sets the maximum global upload speed on the deluge backend', + dest='max_upload_speed', +) +parser.add_option( + '--debug', + help='outputs debug information to the console', + default=False, + action='store_true', + dest='debug', +) + +# grab command-line options +(options, args) = parser.parse_args() + +if not options.debug: + logging.disable(logging.ERROR) + +settings = {} + +# set values if set and valid +if options.max_active_limit: + if options.max_active_limit.isdigit() and int(options.max_active_limit) >= 0: + settings['max_active_limit'] = int(options.max_active_limit) + else: + sys.stderr.write('ERROR: Invalid max_active_limit parameter!\n') + sys.exit(-1) + +if options.max_active_downloading: + if ( + options.max_active_downloading.isdigit() + and int(options.max_active_downloading) >= 0 + ): + settings['max_active_downloading'] = int(options.max_active_downloading) + else: + sys.stderr.write('ERROR: Invalid max_active_downloading parameter!\n') + sys.exit(-1) + +if options.max_active_seeding: + if options.max_active_seeding.isdigit() and int(options.max_active_seeding) >= 0: + settings['max_active_seeding'] = int(options.max_active_seeding) + else: + sys.stderr.write('ERROR: Invalid max_active_seeding parameter!\n') + sys.exit(-1) + +if options.max_download_speed: + if is_float_digit(options.max_download_speed) and ( + float(options.max_download_speed) >= 0.0 + or float(options.max_download_speed) == -1.0 + ): + settings['max_download_speed'] = float(options.max_download_speed) + else: + sys.stderr.write('ERROR: Invalid max_download_speed parameter!\n') + sys.exit(-1) + +if options.max_upload_speed: + if is_float_digit(options.max_upload_speed) and ( + float(options.max_upload_speed) >= 0.0 + or float(options.max_upload_speed) == -1.0 + ): + settings['max_upload_speed'] = float(options.max_upload_speed) + else: + sys.stderr.write('ERROR: Invalid max_upload_speed parameter!\n') + sys.exit(-1) + +# If there is something to do ... +if settings: + # create connection to daemon + from deluge.ui.client import sclient as client + + client.set_core_uri('http://' + options.host + ':' + options.port) + + # commit configurations changes + client.set_config(settings) -- cgit v1.2.3