mirror of
https://github.com/KevinMidboe/delugeClient.git
synced 2025-10-29 12:00:13 +00:00
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:
@@ -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()
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = '0.2.2'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user