Replaced docopt with typer. Bumps version to 0.3.0

Switched out the cli package to typer.
Removed progress command since it did mostly what ls did.
Priting Torrents pads output to be a bit more readable.
Make sure to disconnect from deluge & ssh before script exits
This commit is contained in:
2022-09-28 21:11:08 +02:00
parent 9f959dd171
commit 8597615e68
5 changed files with 115 additions and 131 deletions

View File

@@ -1,40 +1,11 @@
#!/usr/bin/env python3.6
"""Custom delugeRPC client
Usage:
deluge_cli add MAGNET [DIR] [--json | --debug | --info | --warning | --error]
deluge_cli search QUERY [--json]
deluge_cli get ID [--json | --debug | --warning | --error]
deluge_cli ls [--downloading | --seeding | --paused | --json]
deluge_cli toggle TORRENT
deluge_cli progress [--json]
deluge_cli rm ID [--destroy] [--debug | --warning | --error]
deluge_cli (-h | --help)
deluge_cli --version
Arguments:
MAGNET Magnet link to add
DIR Directory to save to
ID A torrent hash
QUERY Query search string
Options:
-h --help Show this screen
--version Show version
--print Print response from commands
--json Print response as JSON
--debug Print all debug log
--warning Print only logged warnings
--error Print error messages (Error/Warning)
"""
import os
import sys
import signal
import logging
from docopt import docopt
import typer
from pprint import pprint
from deluge import Deluge
@@ -46,94 +17,35 @@ ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
logger.addHandler(ch)
logger.addFilter(ColorizeFilter())
logger.addFilter(ColorizeFilter())
app = typer.Typer()
deluge = Deluge()
def signal_handler(signal, frame):
"""
Handle exit by Keyboardinterrupt
"""
del deluge
logger.info('\nGood bye!')
sys.exit(0)
def main():
"""
Main function, parse the input
"""
def handleKeyboardInterrupt():
signal.signal(signal.SIGINT, signal_handler)
arguments = docopt(__doc__, version=__version__)
# Set logging level for streamHandler
if arguments['--debug']:
ch.setLevel(logging.DEBUG)
elif arguments['--info']:
ch.setLevel(logging.INFO)
elif arguments['--warning']:
ch.setLevel(logging.WARNING)
elif arguments['--error']:
ch.setLevel(logging.ERROR)
logger.debug(arguments)
# Get config settings
deluge = Deluge()
_id = arguments['ID']
magnet = arguments['MAGNET']
query = arguments['QUERY']
_filter = [ a[2:] for a in ['--downloading', '--seeding', '--paused'] if arguments[a] ]
response = None
if arguments['add']:
response = deluge.add(magnet)
if response is not None:
msg = 'Successfully added torrent with id: {}'.format(response)
logger.info(msg)
else:
logger.warning('Add response returned empty: {}'.format(response))
elif arguments['search']:
logger.debug('Search cmd selected for query: {}'.format(query))
response = deluge.search(query)
if response is not None or response != '[]':
logger.info('Search found {} torrents'.format(len(response)))
else:
logger.info('Empty response for search query.')
elif arguments['progress']:
logger.debug('Progress cmd selected.')
response = deluge.progress()
elif arguments['get']:
logger.debug('Get cmd selected for id: {}'.format(_id))
response = deluge.get(_id)
elif arguments['ls']:
logger.debug('List cmd selected')
response = deluge.get_all(_filter=_filter)
elif arguments['toggle']:
logger.debug('Toggling id: {}'.format(_id))
deluge.togglePaused(_id)
elif arguments['rm']:
destroy = arguments['--destroy']
logger.debug('Remove by id: {}.'.format(_id))
if destroy:
logger.info('Destroy set, removing files')
if not _id:
logger.error("Unable to remove. No id supplied.")
return
deluge.remove(_id, destroy)
def printResponse(response, json=False):
try:
if arguments['--json']:
print('[{}]'.format(','.join([t.toJSON() for t in response])))
if json:
if isinstance(response, list):
print('[{}]'.format(','.join([t.toJSON() for t in response])))
else:
print(response.toJSON())
elif isinstance(response, list):
for el in response:
print(el)
elif response:
print(response)
@@ -141,7 +53,85 @@ def main():
logger.error('Unexpected error while trying to print')
raise error
sys.exit(0)
@app.command()
def add(magnet: str):
'''
Add magnet torrent
'''
logger.debug('Add command selected')
logger.debug(magnet)
response = deluge.add(magnet)
printResponse(response)
@app.command()
def ls(json: bool = typer.Option(False, help="Print as json")):
'''
List all torrents
'''
logger.debug('List command selected')
response = deluge.get_all()
printResponse(response, json)
@app.command()
def get(id: str, json: bool = typer.Option(False, help="Print as json")):
'''
Get torrent by id or hash
'''
logger.debug('Get command selected for id {}'.format(id))
response = deluge.get(id)
printResponse(response, json)
@app.command()
def toggle(id: str):
'''
Toggle torrent download state
'''
logger.debug('Toggle command selected for id {}'.format(id))
response = deluge.toggle(id)
printResponse(response)
@app.command()
def search(query: str, json: bool = typer.Option(False, help="Print as json")):
'''
Search for string segment in torrent name
'''
logger.debug('Search command selected with query: {}'.format(query))
response = deluge.search(query)
printResponse(response, json)
@app.command()
def remove(id: str, destroy: bool = typer.Option(False, help="Remove torrent data")):
'''
Remove torrent by id or hash
'''
logger.debug('Remove command selected for id: {} with destroy: {}'.format(id, destroy))
response = deluge.remove(id, destroy)
printResponse(response)
@app.command()
def version():
'''
Print package version
'''
print(__version__)
@app.callback()
def defaultOptions(debug: bool = typer.Option(False, '--debug', help='Set log level to debug'), info: bool = typer.Option(False, '--info', help='Set log level to info'), warning: bool = typer.Option(False, '--warning', help='Set log level to warning'), error: bool = typer.Option(False, '--error', help='Set log level to error')):
ch.setLevel(logging.WARNING)
if error == True:
ch.setLevel(logging.ERROR)
elif warning == True:
ch.setLevel(logging.WARNING)
elif info == True:
ch.setLevel(logging.INFO)
elif debug == True:
ch.setLevel(logging.DEBUG)
def main():
app()
del deluge
if __name__ == '__main__':
main()
handleKeyboardInterrupt()
main()

View File

@@ -1 +1 @@
__version__ = '0.2.2'
__version__ = '0.3.0'

View File

@@ -81,7 +81,7 @@ class Deluge(object):
magnet = self.getMagnetFromFile(url)
response = self.client.call('core.add_torrent_magnet', magnet, {})
return responseToString(response.decode('utf-8'))
return responseToString(response)
def get_all(self, _filter=None):
if (type(_filter) is list and len(_filter)):
@@ -101,7 +101,7 @@ class Deluge(object):
torrentNamesMatchingQuery = []
if len(allTorrents):
for torrent in allTorrents:
if query in torrent.name:
if query in torrent.name.lower():
torrentNamesMatchingQuery.append(torrent)
allTorrents = torrentNamesMatchingQuery
@@ -113,14 +113,19 @@ class Deluge(object):
def get(self, id):
response = self.client.call('core.get_torrent_status', id, {})
if response == {}:
logger.warning('No torrent with id: {}'.format(id))
return None
return Torrent.fromDeluge(response)
def togglePaused(self, id):
def toggle(self, id):
torrent = self.get(id)
if (torrent.paused):
response = self.client.call('core.resume_torrent', [id])
else:
response = self.client.call('core.pause_torrent', [id])
return responseToString(response)
def removeByName(self, name, destroy=False):
@@ -160,23 +165,12 @@ class Deluge(object):
filteredTorrents.append(value_template)
return filteredTorrents
def progress(self):
attributes = ['progress', 'eta', 'state', 'finished']
all_torrents = self.get_all()
torrents = []
for i, attribute in enumerate(attributes):
if i < 1:
torrents = self.filterOnValue(all_torrents, attribute)
continue
torrents = [dict(e, **v) for e,v in zip(torrents, self.filterOnValue(all_torrents, attribute))]
return torrents
def __del__(self):
if hasattr(self, 'tunnel'):
self.client.disconnect()
if hasattr(self, 'tunnel') and self.tunnel.is_active:
logger.debug('Closing ssh tunnel')
self.tunnel.stop()
self.tunnel.stop(True)
def getMagnetFromFile(self, url):
logger.info('File url found, fetching magnet.')

View File

@@ -44,5 +44,5 @@ class Torrent(object):
return json.dumps(torrentDict)
def __str__(self):
return "Name: {}, Progress: {}%, ETA: {}, State: {}, Paused: {}".format(
self.name, self.progress, self.eta, self.state, self.paused)
return "{} Progress: {}% ETA: {} State: {} Paused: {}".format(
self.name[:59].ljust(60), self.progress.rjust(5), self.eta.rjust(11), self.state.ljust(12), self.paused)

View File

@@ -25,9 +25,9 @@ setup(
install_requires=[
'colored',
'deluge-client',
'docopt',
'requests',
'sshtunnel',
'typer',
'websockets'
],
classifiers=[