mirror of
				https://github.com/KevinMidboe/delugeClient.git
				synced 2025-10-29 12:00:13 +00:00 
			
		
		
		
	Compare commits
	
		
			48 Commits
		
	
	
		
			snyk-fix-7
			...
			ci/build-a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e81f5f618e | |||
| 4b5500ec3b | |||
| 29c9feeaa1 | |||
| c36bacc264 | |||
| 48e5b3bf3e | |||
| 8853ae85d8 | |||
| 07c6e6fbe1 | |||
| 4d861e1739 | |||
| 5acf8e8848 | |||
| 103696e01a | |||
| b1018d7f9d | |||
| 7d4f4d0e9b | |||
| 2f716e65a3 | |||
| fa59acfd03 | |||
| 120d300b07 | |||
| 0faa42a048 | |||
| e2db73bf2a | |||
| 0841fdc03d | |||
| 76c99568a8 | |||
| 09e496a907 | |||
| 3989523632 | |||
| 30c3e117da | |||
| 3fa8c4b18f | |||
| 11e9677d1a | |||
| 519b51c47c | |||
| 6fd63ff348 | |||
| 74f6f2b06f | |||
| 7ef58745e1 | |||
| b076b1274b | |||
| 97d86253c8 | |||
| d546027df7 | |||
| 2420d9e8c4 | |||
| 2bbf175c2a | |||
| 8597615e68 | |||
| 9f959dd171 | |||
| 869fe579ad | |||
| 724af16f45 | |||
| 201f944fdc | |||
| 9273666fed | |||
| 0cc33c98c1 | |||
| 5ffb97824f | |||
| 365cfd0911 | |||
| 61d1734954 | |||
| c48b4aa68b | |||
| 32cb0e51a7 | |||
| e03247bcc6 | |||
| 1b2620b6f2 | |||
| b7eb06e266 | 
							
								
								
									
										66
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
---
 | 
			
		||||
kind: pipeline
 | 
			
		||||
type: docker
 | 
			
		||||
name: Build and test amd64
 | 
			
		||||
 | 
			
		||||
platform:
 | 
			
		||||
  os: linux
 | 
			
		||||
  arch: amd64
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
  - name: Build source
 | 
			
		||||
    image: python:3.10
 | 
			
		||||
    commands:
 | 
			
		||||
    - make build
 | 
			
		||||
 | 
			
		||||
  - name: Install
 | 
			
		||||
    image: python:3.10
 | 
			
		||||
    commands:
 | 
			
		||||
    - make dist
 | 
			
		||||
    - pip3 install -r requirements.txt
 | 
			
		||||
    - pip3 install dist/*.whl
 | 
			
		||||
#     - pipenv install pytest
 | 
			
		||||
 | 
			
		||||
#   - name: Run tests
 | 
			
		||||
#     image: python:3.10
 | 
			
		||||
#     commands:
 | 
			
		||||
#       pipenv run pytest
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
kind: pipeline
 | 
			
		||||
type: docker
 | 
			
		||||
name: Publish package to PyPi
 | 
			
		||||
 | 
			
		||||
platform:
 | 
			
		||||
  os: linux
 | 
			
		||||
  arch: amd64
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
  - name: Newer version to publish?
 | 
			
		||||
    image: python:3.10
 | 
			
		||||
    commands:
 | 
			
		||||
      - pip3 install delugeClient-kevin -q -q
 | 
			
		||||
      - bash publish_version?.sh
 | 
			
		||||
 | 
			
		||||
  - name: PyPi publish
 | 
			
		||||
    image: python:3.10
 | 
			
		||||
    commands: 
 | 
			
		||||
    - make dist
 | 
			
		||||
    - pip3 install twine
 | 
			
		||||
    - twine upload dist/*
 | 
			
		||||
 | 
			
		||||
depends_on:
 | 
			
		||||
  - Build and test amd64
 | 
			
		||||
 | 
			
		||||
trigger:
 | 
			
		||||
  branch:
 | 
			
		||||
    - master
 | 
			
		||||
  event:
 | 
			
		||||
    exclude:
 | 
			
		||||
      - pull_request
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
kind: signature
 | 
			
		||||
hmac: 08793426ddd2274e2de166144dc15cd63fe6a2c0fd47382d28f20ececee84898
 | 
			
		||||
 | 
			
		||||
...
 | 
			
		||||
							
								
								
									
										22
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
binaries=dist build
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
	python3 setup.py install
 | 
			
		||||
 | 
			
		||||
build:
 | 
			
		||||
	python3 setup.py build
 | 
			
		||||
 | 
			
		||||
tarball:
 | 
			
		||||
	python3 setup.py sdist
 | 
			
		||||
 | 
			
		||||
wheel:
 | 
			
		||||
	python3 setup.py bdist_wheel
 | 
			
		||||
 | 
			
		||||
dist: tarball wheel
 | 
			
		||||
 | 
			
		||||
upload: clean dist
 | 
			
		||||
	twine upload dist/*
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -rf $(binaries)
 | 
			
		||||
							
								
								
									
										115
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								README.md
									
									
									
									
									
								
							@@ -4,26 +4,20 @@
 | 
			
		||||
 | 
			
		||||
<h4 align="center"> A easy to use Deluge CLI that can connect to Deluge RPC (even over ssh) written entirely in python.</h4>
 | 
			
		||||
 | 
			
		||||
<p align="center">
 | 
			
		||||
  <a href="https://pypi.org/project/delugeClient-kevin/">
 | 
			
		||||
    <img src="https://img.shields.io/pypi/v/delugeClient-kevin" />
 | 
			
		||||
  </a>
 | 
			
		||||
  <a href="https://snyk.io/test/github/kevinmidboe/delugeclient?targetFile=requirements.txt">
 | 
			
		||||
  	<img src="https://snyk.io/test/github/kevinmidboe/delugeclient/badge.svg?targetFile=requirements.txt" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/kevinmidboe/delugeclient?targetFile=requirements.txt" style="max-width:100%;">
 | 
			
		||||
  </a>
 | 
			
		||||
| Tested version | PyPi package | License |
 | 
			
		||||
|:--------|:------|:------|
 | 
			
		||||
| [](https://www.python.org/downloads/release/python-3100/) | [](https://pypi.org/project/delugeClient_kevin/) |[](LICENSE)
 | 
			
		||||
 | 
			
		||||
  <a href="https://opensource.org/licenses/MIT">
 | 
			
		||||
    <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="">
 | 
			
		||||
  </a>
 | 
			
		||||
</p>
 | 
			
		||||
| Drone CI | Known vulnerabilities |
 | 
			
		||||
|:--------|:------|
 | 
			
		||||
| [](https://drone.schleppe.cloud/KevinMidboe/delugeClient) | [](https://snyk.io/test/github/kevinmidboe/delugeClient?targetFile=requirements.txt)
 | 
			
		||||
 | 
			
		||||
<p align="center">
 | 
			
		||||
  <a href="#abstract">Abstract</a> •
 | 
			
		||||
  <a href="#setup_virtualenv">Setup virtualenv</a> •
 | 
			
		||||
  <a href="#configure">Configure</a> •
 | 
			
		||||
  <a href="#installation">Install dependencies</a> •
 | 
			
		||||
  <a href="#install">Install</a> •
 | 
			
		||||
  <a href="#usage">Usage</a> •
 | 
			
		||||
  <a href="#running">Running</a> •
 | 
			
		||||
  <a href="#setup_virtualenv">Setup Virtual Environment</a> •
 | 
			
		||||
  <a href="#configure">Configure</a> •
 | 
			
		||||
  <a href="#contributing">Contributing</a>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
@@ -31,6 +25,44 @@
 | 
			
		||||
## <a name="abstract"></a> Abstract
 | 
			
		||||
Create a deluge python client for interfacing with deluge for common tasks like listing, adding, removing and setting download directory for torrents. 
 | 
			
		||||
 | 
			
		||||
## <a name="install"></a> Install
 | 
			
		||||
Install from source:
 | 
			
		||||
```bash
 | 
			
		||||
python3 setup.py install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Install from pip:
 | 
			
		||||
```bash
 | 
			
		||||
pip3 install delugeClient-kevin
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## <a name="usage"></a> Usage
 | 
			
		||||
View delugeClient cli options with `delugeClient --help`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 Usage: python -m delugeclient [OPTIONS] COMMAND [ARGS]...
 | 
			
		||||
 | 
			
		||||
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮
 | 
			
		||||
│ --debug                       Set log level to debug                                                            │
 | 
			
		||||
│ --info                        Set log level to info                                                             │
 | 
			
		||||
│ --warning                     Set log level to warning                                                          │
 | 
			
		||||
│ --error                       Set log level to error                                                            │
 | 
			
		||||
│ --install-completion          Install completion for the current shell.                                         │
 | 
			
		||||
│ --show-completion             Show completion for the current shell, to copy it or customize the installation.  │
 | 
			
		||||
│ --help                        Show this message and exit.                                                       │
 | 
			
		||||
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 | 
			
		||||
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────╮
 | 
			
		||||
│ add                Add magnet torrent                                                                           │
 | 
			
		||||
│ disk               Get free disk space                                                                          │
 | 
			
		||||
│ get                Get torrent by id or hash                                                                    │
 | 
			
		||||
│ ls                 List all torrents                                                                            │
 | 
			
		||||
│ remove             Remove torrent by id or hash                                                                 │
 | 
			
		||||
│ rm                 Remove torrent by name                                                                       │
 | 
			
		||||
│ search             Search for string segment in torrent name                                                    │
 | 
			
		||||
│ toggle             Toggle torrent download state                                                                │
 | 
			
		||||
│ version            Print package version                                                                        │
 | 
			
		||||
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## <a name="setup_virtualenv"></a> Setup Virtual Environment
 | 
			
		||||
Virtual environment allows us to create a local environment for the requirements needed. Because pip does not download packages already downloaded to your system, we can use virtualenv to save our packages in the project folder.
 | 
			
		||||
@@ -44,7 +76,7 @@ To install virtualenv, simply run:
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Usage
 | 
			
		||||
### Virtualenv setup
 | 
			
		||||
After you have downloaded this project go to it in your terminal by going to the folder you downloaded and typing the following:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -55,14 +87,12 @@ After you have downloaded this project go to it in your terminal by going to the
 | 
			
		||||
The to setup a virtual environment enter this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 $ virtualenv -p python3.6 env
 | 
			
		||||
 $ virtualenv -p python3.10 env
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 > If you get an error now it might be because you don't have python3.6, please make sure you have python version 3.6 if else you can download it from [here](https://www.python.org/downloads/)
 | 
			
		||||
 > If you get an error now it might be because you don't have python3.10, please make sure you have python version 3.10 if else you can download it from [here](https://www.python.org/downloads/)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
First we navigate to the folder we downloaded.
 | 
			
		||||
 | 
			
		||||
Then we use the ```virtualenv``` command to create a ```env``` subdirectory in our project. This is where pip will download everything to and where we can add other specific python versions. Then we need to *activate* our virtual environment by doing:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
@@ -99,51 +129,6 @@ Then you need to change the HOST and PORT to reflect the address for your deluge
 | 
			
		||||
 $ cat /home/USER/.config/deluge/auth
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## <a name="install"></a> Install Required Dependencies
 | 
			
		||||
Now that we have our virutalenv set up and activated we want to install all the necessary packages listed in `requirements.txt`. To install it's dependencies do the following:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 $ pip install -r requirements.txt
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Now we have our neccessary packages installed!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## <a name="usage"></a> Usage
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
Custom delugeRPC client
 | 
			
		||||
Usage:
 | 
			
		||||
   deluge_cli add MAGNET [DIR] [--debug | --warning | --error]
 | 
			
		||||
   deluge_cli get TORRENT
 | 
			
		||||
   deluge_cli ls [--downloading | --seeding | --paused]
 | 
			
		||||
   deluge_cli toggle TORRENT
 | 
			
		||||
   deluge_cli rm TORRENT [--debug | --warning | --error]
 | 
			
		||||
   deluge_cli (-h | --help)
 | 
			
		||||
   deluge_cli --version
 | 
			
		||||
 | 
			
		||||
Arguments:
 | 
			
		||||
   MAGNET        Magnet link to add
 | 
			
		||||
   DIR           Directory to save to
 | 
			
		||||
   TORRENT       A selected torrent
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
   -h --help     Show this screen
 | 
			
		||||
   --version     Show version
 | 
			
		||||
   --debug       Print all debug log
 | 
			
		||||
   --warning     Print only logged warnings
 | 
			
		||||
   --error       Print error messages (Error/Warning)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### <a name="running"></a> Running
 | 
			
		||||
To interface with deluged :
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 $ ./deluge_cli.py ls
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## <a name="contributing"></a> Contributing
 | 
			
		||||
- Fork it!
 | 
			
		||||
- Create your feature branch: git checkout -b my-new-feature
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,22 @@
 | 
			
		||||
import os
 | 
			
		||||
#!/usr/bin/env python3.10
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
from sys import path
 | 
			
		||||
from os.path import dirname, join
 | 
			
		||||
 | 
			
		||||
path.append(os.path.dirname(__file__))
 | 
			
		||||
 | 
			
		||||
__version__=0.1
 | 
			
		||||
path.append(dirname(__file__))
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
from delugeUtils import BASE_DIR
 | 
			
		||||
from utils import BASE_DIR
 | 
			
		||||
 | 
			
		||||
def addHandler(handler):
 | 
			
		||||
  handler.setFormatter(formatter)
 | 
			
		||||
  logger.addHandler(handler)
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('deluge_cli')
 | 
			
		||||
logger.setLevel(logging.DEBUG)
 | 
			
		||||
 | 
			
		||||
fh = logging.FileHandler(os.path.join(BASE_DIR, 'deluge_cli.log'))
 | 
			
		||||
fh.setLevel(logging.DEBUG)
 | 
			
		||||
ch = logging.StreamHandler()
 | 
			
		||||
ch.setLevel(logging.ERROR)
 | 
			
		||||
fh = logging.FileHandler(join(BASE_DIR, 'deluge_cli.log'))
 | 
			
		||||
formatter = logging.Formatter('%(asctime)s| %(levelname)s | %(message)s')
 | 
			
		||||
 | 
			
		||||
formatter = logging.Formatter('%(asctime)s %(levelname)8s %(name)s | %(message)s')
 | 
			
		||||
fh.setFormatter(formatter)
 | 
			
		||||
logger.addHandler(fh)
 | 
			
		||||
logger.addHandler(ch)
 | 
			
		||||
addHandler(fh)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,148 +1,177 @@
 | 
			
		||||
#!/usr/bin/env python3.6
 | 
			
		||||
#!/usr/bin/env python3.10
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""Custom delugeRPC client
 | 
			
		||||
Usage:
 | 
			
		||||
   deluge_cli add MAGNET [DIR] [--json | --debug | --warning | --error]
 | 
			
		||||
   deluge_cli search NAME [--json]
 | 
			
		||||
   deluge_cli get  TORRENT [--json | --debug | --warning | --error]
 | 
			
		||||
   deluge_cli ls [--downloading | --seeding | --paused | --json]
 | 
			
		||||
   deluge_cli toggle TORRENT
 | 
			
		||||
   deluge_cli progress [--json]
 | 
			
		||||
   deluge_cli rm NAME [--destroy] [--debug | --warning | --error]
 | 
			
		||||
   deluge_cli (-h | --help)
 | 
			
		||||
   deluge_cli --version
 | 
			
		||||
 | 
			
		||||
Arguments:
 | 
			
		||||
   MAGNET        Magnet link to add
 | 
			
		||||
   DIR           Directory to save to
 | 
			
		||||
   TORRENT       A selected torrent
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
from utils import ColorizeFilter, BASE_DIR
 | 
			
		||||
from __init__ import __version__
 | 
			
		||||
from utils import ColorizeFilter, BASE_DIR, validHash, convertFilesize
 | 
			
		||||
from __version__ import __version__
 | 
			
		||||
from __init__ import addHandler
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('deluge_cli')
 | 
			
		||||
logger.setLevel(logging.DEBUG)
 | 
			
		||||
 | 
			
		||||
fh = logging.FileHandler(os.path.join(BASE_DIR, 'deluge_cli.log'))
 | 
			
		||||
fh.setLevel(logging.DEBUG)
 | 
			
		||||
ch = logging.StreamHandler()
 | 
			
		||||
ch.setLevel(logging.ERROR)
 | 
			
		||||
ch.addFilter(ColorizeFilter())
 | 
			
		||||
addHandler(ch)
 | 
			
		||||
logger = logging.getLogger('deluge_cli')
 | 
			
		||||
 | 
			
		||||
formatter = logging.Formatter('%(asctime)s %(levelname)8s %(name)s | %(message)s')
 | 
			
		||||
fh.setFormatter(formatter)
 | 
			
		||||
logger.addHandler(fh)
 | 
			
		||||
logger.addHandler(ch)
 | 
			
		||||
 | 
			
		||||
logger.addFilter(ColorizeFilter())   
 | 
			
		||||
app = typer.Typer()
 | 
			
		||||
deluge = None
 | 
			
		||||
 | 
			
		||||
def signal_handler(signal, frame):
 | 
			
		||||
  """
 | 
			
		||||
  Handle exit by Keyboardinterrupt
 | 
			
		||||
  """
 | 
			
		||||
  logger.info('\nGood bye!')
 | 
			
		||||
  sys.exit(0)
 | 
			
		||||
  global deluge
 | 
			
		||||
  del deluge
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
  """
 | 
			
		||||
  Main function, parse the input
 | 
			
		||||
  """
 | 
			
		||||
  logger.info('\nGood bye!')
 | 
			
		||||
  sys.exit(1)
 | 
			
		||||
 | 
			
		||||
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['--warning']:
 | 
			
		||||
    ch.setLevel(logging.WARNING)
 | 
			
		||||
  elif arguments['--error']:
 | 
			
		||||
    ch.setLevel(logging.ERROR)
 | 
			
		||||
 | 
			
		||||
  logger.info('Deluge client')
 | 
			
		||||
  logger.debug(arguments)
 | 
			
		||||
 | 
			
		||||
  # Get config settings
 | 
			
		||||
  deluge = Deluge()
 | 
			
		||||
 | 
			
		||||
  _id = arguments['TORRENT']
 | 
			
		||||
  query = arguments['NAME']
 | 
			
		||||
  magnet = arguments['MAGNET']
 | 
			
		||||
  name = arguments['NAME']
 | 
			
		||||
  _filter = [ a[2:] for a in ['--downloading', '--seeding', '--paused'] if arguments[a] ]
 | 
			
		||||
 | 
			
		||||
  response = None
 | 
			
		||||
 | 
			
		||||
  if arguments['add']:
 | 
			
		||||
    logger.info('Add cmd selected with link {}'.format(magnet))
 | 
			
		||||
    response = deluge.add(magnet)
 | 
			
		||||
 | 
			
		||||
    if response is not None:
 | 
			
		||||
      logger.info('Successfully added torrent.\nResponse from deluge: {}'.format(response))
 | 
			
		||||
    else:
 | 
			
		||||
      logger.warning('Add response returned empty: {}'.format(response))
 | 
			
		||||
 | 
			
		||||
  elif arguments['search']:
 | 
			
		||||
    logger.info('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.info('Progress cmd selected.')
 | 
			
		||||
    response = deluge.progress()
 | 
			
		||||
 | 
			
		||||
  elif arguments['get']:
 | 
			
		||||
    logger.info('Get cmd selected for id: {}'.format(_id))
 | 
			
		||||
    response = deluge.get(_id)
 | 
			
		||||
 | 
			
		||||
  elif arguments['ls']:
 | 
			
		||||
    logger.info('List cmd selected')
 | 
			
		||||
    response = deluge.get_all(_filter=_filter)
 | 
			
		||||
 | 
			
		||||
  elif arguments['toggle']:
 | 
			
		||||
    logger.info('Toggling id: {}'.format(_id))
 | 
			
		||||
    deluge.togglePaused(_id)
 | 
			
		||||
 | 
			
		||||
  elif arguments['rm']:
 | 
			
		||||
    destroy = arguments['--destroy']
 | 
			
		||||
    logger.info('Remove by name: {}.'.format(name))
 | 
			
		||||
 | 
			
		||||
    if destroy:
 | 
			
		||||
      logger.info('Destroy set, removing files')
 | 
			
		||||
      deluge.remove(name, destroy)
 | 
			
		||||
 | 
			
		||||
def printResponse(response, json=False):
 | 
			
		||||
  try:
 | 
			
		||||
    if arguments['--json']:
 | 
			
		||||
      if len(response) > 1:
 | 
			
		||||
    if json:
 | 
			
		||||
      if isinstance(response, list):
 | 
			
		||||
        print('[{}]'.format(','.join([t.toJSON() for t in response])))
 | 
			
		||||
      else:
 | 
			
		||||
        print(response[0].toJSON())
 | 
			
		||||
        print(response.toJSON())
 | 
			
		||||
 | 
			
		||||
    elif isinstance(response, list):
 | 
			
		||||
      for el in response:
 | 
			
		||||
        print(el)
 | 
			
		||||
 | 
			
		||||
    elif response:
 | 
			
		||||
      print(response)
 | 
			
		||||
 | 
			
		||||
  except KeyError as error:
 | 
			
		||||
    logger.error('Unexpected error while trying to print')
 | 
			
		||||
    raise error
 | 
			
		||||
 | 
			
		||||
  return response
 | 
			
		||||
@app.command()
 | 
			
		||||
def add(magnet: str, json: bool = typer.Option(False, help="Print as json")):
 | 
			
		||||
  '''
 | 
			
		||||
  Add magnet torrent
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('Add command selected')
 | 
			
		||||
  logger.debug(magnet)
 | 
			
		||||
  response = deluge.add(magnet)
 | 
			
		||||
  if validHash(response):
 | 
			
		||||
    torrent = deluge.get(response)
 | 
			
		||||
    printResponse(torrent, json)
 | 
			
		||||
  else:
 | 
			
		||||
    logger.info('Unable to add torrent')
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def ls(json: bool = typer.Option(False, help="Print as json")):
 | 
			
		||||
  '''
 | 
			
		||||
  List all torrents
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('List command selected')
 | 
			
		||||
  response = deluge.get_all()
 | 
			
		||||
  if response is None:
 | 
			
		||||
    logger.info('No torrents found')
 | 
			
		||||
    return
 | 
			
		||||
 | 
			
		||||
  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.info('Get command selected for id: {}'.format(id))
 | 
			
		||||
  if not validHash(id):
 | 
			
		||||
    return logger.info("Id is not valid")
 | 
			
		||||
  response = deluge.get(id)
 | 
			
		||||
  printResponse(response, json)
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def toggle(id: str):
 | 
			
		||||
  '''
 | 
			
		||||
  Toggle torrent download state
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('Toggle command selected for id: {}'.format(id))
 | 
			
		||||
  if not validHash(id):
 | 
			
		||||
    return logger.info("Id is not valid")
 | 
			
		||||
  deluge.toggle(id)
 | 
			
		||||
  torrent = deluge.get(id)
 | 
			
		||||
  printResponse(torrent)
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def search(query: str, json: bool = typer.Option(False, help="Print as json")):
 | 
			
		||||
  '''
 | 
			
		||||
  Search for string segment in torrent name
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('Search command selected with query: {}'.format(query))
 | 
			
		||||
  response = deluge.search(query)
 | 
			
		||||
  printResponse(response, json)
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def rm(name: str, destroy: bool = typer.Option(False, help="Remove torrent by name")):
 | 
			
		||||
  '''
 | 
			
		||||
  Remove torrent by name
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('Removing torrent with name: {}, destroy flag: {}'.format(name, destroy))
 | 
			
		||||
  response = deluge.removeByName(name, destroy)
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def remove(id: str, destroy: bool = typer.Option(False, help="Remove torrent by id")):
 | 
			
		||||
  '''
 | 
			
		||||
  Remove torrent by id or hash
 | 
			
		||||
  '''
 | 
			
		||||
  logger.info('Removing torrent with id: {}, destroy flag: {}'.format(id, destroy))
 | 
			
		||||
  if not validHash(id):
 | 
			
		||||
    return logger.info("Id is not valid")
 | 
			
		||||
  response = deluge.remove(id, destroy)
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def disk():
 | 
			
		||||
  '''
 | 
			
		||||
  Get free disk space
 | 
			
		||||
  '''
 | 
			
		||||
  response = deluge.freeSpace()
 | 
			
		||||
  if response == None or not isinstance(response, int):
 | 
			
		||||
    logger.error("Unable to get available disk space")
 | 
			
		||||
    return
 | 
			
		||||
  print(convertFilesize(response))
 | 
			
		||||
 | 
			
		||||
@app.command()
 | 
			
		||||
def version():
 | 
			
		||||
  '''
 | 
			
		||||
  Print package version
 | 
			
		||||
  '''
 | 
			
		||||
  print(__version__)
 | 
			
		||||
 | 
			
		||||
# Runs before any command
 | 
			
		||||
@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.INFO)
 | 
			
		||||
 | 
			
		||||
  if '--json' in sys.argv:
 | 
			
		||||
    ch.setLevel(logging.CRITICAL)
 | 
			
		||||
  elif 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)
 | 
			
		||||
 | 
			
		||||
  # Initiate deluge
 | 
			
		||||
  global deluge
 | 
			
		||||
  deluge = Deluge()
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
  app()
 | 
			
		||||
  del deluge
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
  handleKeyboardInterrupt()
 | 
			
		||||
  main()
 | 
			
		||||
							
								
								
									
										4
									
								
								delugeClient/__version__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								delugeClient/__version__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
__version__ = '0.3.2'
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
  print(__version__)
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python3.6
 | 
			
		||||
#!/usr/bin/env python3.10
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
@@ -7,9 +7,9 @@ import logging
 | 
			
		||||
import requests
 | 
			
		||||
import logging.config
 | 
			
		||||
 | 
			
		||||
from deluge_client import DelugeRPCClient
 | 
			
		||||
from sshtunnel import SSHTunnelForwarder
 | 
			
		||||
from delugeUtils import getConfig, BASE_DIR
 | 
			
		||||
from deluge_client import DelugeRPCClient, FailedToReconnectException
 | 
			
		||||
from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError
 | 
			
		||||
from utils import getConfig, BASE_DIR
 | 
			
		||||
 | 
			
		||||
from torrent import Torrent
 | 
			
		||||
 | 
			
		||||
@@ -19,6 +19,14 @@ def split_words(string):
 | 
			
		||||
   logger.debug('Splitting input: {} (type: {}) with split_words'.format(string, type(string)))
 | 
			
		||||
   return re.findall(r"[\w\d']+", string.lower())
 | 
			
		||||
 | 
			
		||||
def responseToString(response=None):
 | 
			
		||||
   try:
 | 
			
		||||
      response = response.decode('utf-8')
 | 
			
		||||
   except (UnicodeDecodeError, AttributeError):
 | 
			
		||||
      pass
 | 
			
		||||
 | 
			
		||||
   return response
 | 
			
		||||
 | 
			
		||||
class Deluge(object):
 | 
			
		||||
   """docstring for ClassName"""
 | 
			
		||||
   def __init__(self):
 | 
			
		||||
@@ -33,7 +41,19 @@ class Deluge(object):
 | 
			
		||||
      self.ssh_pkey = config['ssh']['pkey']
 | 
			
		||||
      self.ssh_password = config['ssh']['password']
 | 
			
		||||
 | 
			
		||||
      try:
 | 
			
		||||
         self._connect()
 | 
			
		||||
      except FailedToReconnectException:
 | 
			
		||||
         logger.error("Unable to connect to deluge, make sure it's running")
 | 
			
		||||
         sys.exit(1)
 | 
			
		||||
      except ConnectionRefusedError:
 | 
			
		||||
         logger.error("Unable to connect to deluge, make sure it's running")
 | 
			
		||||
         sys.exit(1)
 | 
			
		||||
      except BaseException as error:
 | 
			
		||||
         logger.error("Unable to connect to deluge, make sure it's running")
 | 
			
		||||
         if 'nodename nor servname provided' in str(error):
 | 
			
		||||
            sys.exit(1)
 | 
			
		||||
         raise error
 | 
			
		||||
 | 
			
		||||
   def freeSpace(self):
 | 
			
		||||
      return self.client.call('core.get_free_space')
 | 
			
		||||
@@ -45,52 +65,74 @@ class Deluge(object):
 | 
			
		||||
         torrents.append(Torrent.fromDeluge(torrent))
 | 
			
		||||
      return torrents
 | 
			
		||||
 | 
			
		||||
   def _connect(self):
 | 
			
		||||
      logger.info('Checking if script on same server as deluge RPC')
 | 
			
		||||
      if self.host != 'localhost' and self.host is not None:
 | 
			
		||||
         try:
 | 
			
		||||
            if self.password:
 | 
			
		||||
   def establishSSHTunnel(self):
 | 
			
		||||
      logger.debug('Checking if script on same server as deluge RPC')
 | 
			
		||||
 | 
			
		||||
      if self.password is not None:
 | 
			
		||||
        self.tunnel = SSHTunnelForwarder(self.ssh_host, ssh_username=self.ssh_user, ssh_password=self.ssh_password, 
 | 
			
		||||
           local_bind_address=('localhost', self.port), remote_bind_address=('localhost', self.port))
 | 
			
		||||
      elif self.pkey is not None:
 | 
			
		||||
        self.tunnel = SSHTunnelForwarder(self.ssh_host, ssh_username=self.ssh_user, ssh_pkey=self.ssh_pkey, 
 | 
			
		||||
           local_bind_address=('localhost', self.port), remote_bind_address=('localhost', self.port))
 | 
			
		||||
         except ValueError as error:
 | 
			
		||||
      else:
 | 
			
		||||
         logger.error("Either password or private key path must be set in config.")
 | 
			
		||||
            raise error
 | 
			
		||||
         return
 | 
			
		||||
 | 
			
		||||
      try:
 | 
			
		||||
         self.tunnel.start()
 | 
			
		||||
      except BaseSSHTunnelForwarderError as sshError:
 | 
			
		||||
         logger.warning("SSH host {} online, check your connection".format(self.ssh_host))
 | 
			
		||||
         return
 | 
			
		||||
 | 
			
		||||
   def _call(self, command, *args):
 | 
			
		||||
      try:
 | 
			
		||||
         return self.client.call(command, *args)
 | 
			
		||||
      except ConnectionRefusedError as error:
 | 
			
		||||
         logger.error("Unable to run command, connection to deluge seems to be offline")
 | 
			
		||||
      except FailedToReconnectException as error:
 | 
			
		||||
         logger.error("Unable to run command, reconnection to deluge failed")
 | 
			
		||||
 | 
			
		||||
   def _connect(self):
 | 
			
		||||
      if self.host != 'localhost' and self.host is not None:
 | 
			
		||||
         self.establishSSHTunnel()
 | 
			
		||||
 | 
			
		||||
      self.client = DelugeRPCClient(self.host, self.port, self.user, self.password)
 | 
			
		||||
      self.client.connect()
 | 
			
		||||
 | 
			
		||||
   def add(self, url):
 | 
			
		||||
      logger.info('Adding magnet with url: {}.'.format(url))
 | 
			
		||||
      response = None
 | 
			
		||||
      if (url.startswith('magnet')):
 | 
			
		||||
         return self.client.call('core.add_torrent_magnet', url, {})
 | 
			
		||||
         response = self._call('core.add_torrent_magnet', url, {})
 | 
			
		||||
      elif url.startswith('http'):
 | 
			
		||||
         magnet = self.getMagnetFromFile(url)
 | 
			
		||||
         return self.client.call('core.add_torrent_magnet', magnet, {})
 | 
			
		||||
         response = self._call('core.add_torrent_magnet', magnet, {})
 | 
			
		||||
 | 
			
		||||
      return responseToString(response)
 | 
			
		||||
 | 
			
		||||
   def get_all(self, _filter=None):
 | 
			
		||||
      response = None
 | 
			
		||||
      if (type(_filter) is list and len(_filter)):
 | 
			
		||||
         if ('seeding' in _filter):
 | 
			
		||||
            response = self.client.call('core.get_torrents_status', {'state': 'Seeding'}, [])
 | 
			
		||||
            response = self._call('core.get_torrents_status', {'state': 'Seeding'}, [])
 | 
			
		||||
         elif ('downloading' in _filter):
 | 
			
		||||
            response = self.client.call('core.get_torrents_status', {'state': 'Downloading'}, [])
 | 
			
		||||
            response = self._call('core.get_torrents_status', {'state': 'Downloading'}, [])
 | 
			
		||||
         elif ('paused' in _filter):
 | 
			
		||||
            response = self.client.call('core.get_torrents_status', {'paused': 'true'}, [])
 | 
			
		||||
            response = self._call('core.get_torrents_status', {'paused': 'true'}, [])
 | 
			
		||||
      else:
 | 
			
		||||
         response = self.client.call('core.get_torrents_status', {}, [])
 | 
			
		||||
 | 
			
		||||
      if response == {}:
 | 
			
		||||
         return None
 | 
			
		||||
 | 
			
		||||
      return self.parseResponse(response)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   def search(self, query):
 | 
			
		||||
      allTorrents = self.get_all()
 | 
			
		||||
      torrentNamesMatchingQuery = []
 | 
			
		||||
      if len(allTorrents):
 | 
			
		||||
         for torrent in allTorrents:
 | 
			
		||||
            if query in torrent.name:
 | 
			
		||||
            if query in torrent.name.lower():
 | 
			
		||||
               torrentNamesMatchingQuery.append(torrent)
 | 
			
		||||
 | 
			
		||||
         allTorrents = torrentNamesMatchingQuery
 | 
			
		||||
@@ -101,34 +143,54 @@ class Deluge(object):
 | 
			
		||||
      return [ t for t in self.get_all() if (set(q_list) <= set(split_words(t.name))) ]
 | 
			
		||||
 | 
			
		||||
   def get(self, id):
 | 
			
		||||
      response = self.client.call('core.get_torrent_status', id, {})
 | 
			
		||||
      response = self._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 response
 | 
			
		||||
      if torrent is None:
 | 
			
		||||
         return
 | 
			
		||||
 | 
			
		||||
   def remove(self, name, destroy=False):
 | 
			
		||||
      if (torrent.paused):
 | 
			
		||||
         response = self._call('core.resume_torrent', [id])
 | 
			
		||||
      else:
 | 
			
		||||
         response = self._call('core.pause_torrent', [id])
 | 
			
		||||
 | 
			
		||||
      return responseToString(response)
 | 
			
		||||
 | 
			
		||||
   def removeByName(self, name, destroy=False):
 | 
			
		||||
      matches = list(filter(lambda t: t.name == name, self.get_all()))
 | 
			
		||||
      logger.info('Matches for {}: {}'.format(name, matches))
 | 
			
		||||
      
 | 
			
		||||
      if (len(matches) > 1):
 | 
			
		||||
      if len(matches) > 1:
 | 
			
		||||
         raise ValueError('Multiple files found matching key. Unable to remove.')
 | 
			
		||||
      elif (len(matches) == 1):
 | 
			
		||||
      elif len(matches) == 1:
 | 
			
		||||
         torrent = matches[0]
 | 
			
		||||
         response = self.client.call('core.remove_torrent', torrent.key, destroy)
 | 
			
		||||
         logger.info('Response: {}'.format(str(response)))
 | 
			
		||||
         response = self.remove(torrent.key, destroy)
 | 
			
		||||
         logger.debug('Response rm: {}'.format(str(response)))
 | 
			
		||||
 | 
			
		||||
         if (response == False):
 | 
			
		||||
         if response == False:
 | 
			
		||||
            raise AttributeError('Unable to remove torrent.')
 | 
			
		||||
         return response
 | 
			
		||||
         return responseToString(response)
 | 
			
		||||
      else:
 | 
			
		||||
         logger.error('ERROR. No torrent found with that name.')
 | 
			
		||||
 | 
			
		||||
   def remove(self, id, destroy=False):
 | 
			
		||||
      try:
 | 
			
		||||
         response = self.client.call('core.remove_torrent', id, destroy)
 | 
			
		||||
         logger.debug('Response from remove: {}'.format(str(response)))
 | 
			
		||||
         return responseToString(response)
 | 
			
		||||
      except BaseException as error:
 | 
			
		||||
         if 'torrent_id not in session' in str(error):
 | 
			
		||||
            logger.info('Unable to remove. No torrent with matching id')
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
         raise error
 | 
			
		||||
 | 
			
		||||
   def filterOnValue(self, torrents, value):
 | 
			
		||||
      filteredTorrents = []
 | 
			
		||||
      for t in torrents:
 | 
			
		||||
@@ -140,23 +202,14 @@ 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'):
 | 
			
		||||
         logger.info('Closing ssh tunnel')
 | 
			
		||||
         self.tunnel.stop()
 | 
			
		||||
      if hasattr(self, 'client') and self.client.connected:
 | 
			
		||||
         logger.debug('Disconnected deluge rpc')
 | 
			
		||||
         self.client.disconnect()
 | 
			
		||||
 | 
			
		||||
      if hasattr(self, 'tunnel') and self.tunnel.is_active:
 | 
			
		||||
         logger.debug('Closing ssh tunnel')
 | 
			
		||||
         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.key, self.name[:59].ljust(60), self.progress.rjust(5), self.eta.rjust(11), self.state.ljust(12), self.paused)
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#!/usr/bin/env python3.10
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# @Author: kevinmidboe
 | 
			
		||||
# @Date:   2018-04-17 19:55:38
 | 
			
		||||
@@ -50,7 +50,7 @@ def getConfig():
 | 
			
		||||
  for key, value in requiredParameters:
 | 
			
		||||
    if value == '':
 | 
			
		||||
      logger.error('Missing value for variable: "{}" in config: \
 | 
			
		||||
"$HOME/.config/delugeClient/config.ini".'.format(key))
 | 
			
		||||
"{}.'.format(key, user_config_dir))
 | 
			
		||||
      exit(1)
 | 
			
		||||
 | 
			
		||||
  return config
 | 
			
		||||
@@ -60,7 +60,7 @@ class ColorizeFilter(logging.Filter):
 | 
			
		||||
  Class for setting specific colors to levels of severity for log output
 | 
			
		||||
  """
 | 
			
		||||
  color_by_level = {
 | 
			
		||||
    10: 'chartreuse_3b',
 | 
			
		||||
    10: 'cyan',
 | 
			
		||||
    20: 'white',
 | 
			
		||||
    30: 'orange_1',
 | 
			
		||||
    40: 'red'
 | 
			
		||||
@@ -79,3 +79,20 @@ def convert(data):
 | 
			
		||||
  if isinstance(data, tuple):  return map(convert, data)
 | 
			
		||||
  json_data = json.dumps(data)
 | 
			
		||||
  return json_data
 | 
			
		||||
 | 
			
		||||
def validHash(hash: str):
 | 
			
		||||
  try:
 | 
			
		||||
    return hash and len(hash) == 40 and int(hash, 16)
 | 
			
		||||
  except ValueError:
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
import math
 | 
			
		||||
 | 
			
		||||
def convertFilesize(size_bytes):
 | 
			
		||||
 if size_bytes == None or size_bytes == 0:
 | 
			
		||||
    return "0B"
 | 
			
		||||
 size_name = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
 | 
			
		||||
 i = int(math.floor(math.log(size_bytes, 1024)))
 | 
			
		||||
 p = math.pow(1024, i)
 | 
			
		||||
 s = round(size_bytes / p, 2)
 | 
			
		||||
 return "%s %s" % (s, size_name[i])
 | 
			
		||||
							
								
								
									
										19
									
								
								publish_version?.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								publish_version?.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
#!/usr/bin/bash
 | 
			
		||||
 | 
			
		||||
PYPI_VERSION=$(pip3 show delugeClient-kevin | awk '$1 ~ /Version:/ { print $2 }')
 | 
			
		||||
SOURCE_VERSION=$(python3 delugeClient/__version__.py)
 | 
			
		||||
 | 
			
		||||
printf "Source version:\t\t %s\n" $SOURCE_VERSION
 | 
			
		||||
printf "Remote PyPi version:\t %s\n" $PYPI_VERSION
 | 
			
		||||
 | 
			
		||||
function version {
 | 
			
		||||
  echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if [ $(version $SOURCE_VERSION) -gt $(version $PYPI_VERSION) ]; then
 | 
			
		||||
  echo "Soure is newer than remote, publishing!"
 | 
			
		||||
  exit 0
 | 
			
		||||
else
 | 
			
		||||
  echo "Source is same or oldre than remote, nothing to do."
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
colored==1.4.2
 | 
			
		||||
colored==1.4.4
 | 
			
		||||
deluge-client==1.9.0
 | 
			
		||||
docopt==0.6.2
 | 
			
		||||
requests==2.25.1
 | 
			
		||||
requests==2.28.1
 | 
			
		||||
sshtunnel==0.4.0
 | 
			
		||||
websockets==9.1
 | 
			
		||||
typer==0.7.0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								setup.py
									
									
									
									
									
								
							@@ -1,39 +1,43 @@
 | 
			
		||||
#!/usr/bin/env python3.10
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
from setuptools import setup, find_packages
 | 
			
		||||
 | 
			
		||||
import delugeClient
 | 
			
		||||
from sys import path
 | 
			
		||||
from os.path import dirname
 | 
			
		||||
 | 
			
		||||
with open("README.md", "r", encoding="utf-8") as fh:
 | 
			
		||||
  long_description = fh.read()
 | 
			
		||||
 | 
			
		||||
exec(open('delugeClient/__version__.py').read())
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
  name="delugeClient-kevin",
 | 
			
		||||
  version=delugeClient.__version__,
 | 
			
		||||
  version=__version__,
 | 
			
		||||
  packages=find_packages(),
 | 
			
		||||
  package_data={
 | 
			
		||||
    'delugeClient': ['default_config.ini'],
 | 
			
		||||
  },
 | 
			
		||||
  python_requires=">=3.10",
 | 
			
		||||
  author="KevinMidboe",
 | 
			
		||||
  description="Deluge client with custom functions written in python",
 | 
			
		||||
  long_description=long_description,
 | 
			
		||||
  long_description_content_type="text/markdown",
 | 
			
		||||
  url="https://github.com/kevinmidboe/delugeClient",
 | 
			
		||||
  install_requires=[
 | 
			
		||||
    'colored==1.4.2',
 | 
			
		||||
    'deluge-client==1.9.0',
 | 
			
		||||
    'docopt==0.6.2',
 | 
			
		||||
    'requests==2.25.1',
 | 
			
		||||
    'sshtunnel==0.4.0',
 | 
			
		||||
    'websockets==9.1'
 | 
			
		||||
    'colored>=1.4.4',
 | 
			
		||||
    'deluge-client>=1.9.0',
 | 
			
		||||
    'requests>=2.28.1',
 | 
			
		||||
    'sshtunnel>=0.4.0',
 | 
			
		||||
    'typer[all]>=0.7.0'
 | 
			
		||||
  ],
 | 
			
		||||
  classifiers=[
 | 
			
		||||
    'Programming Language :: Python',
 | 
			
		||||
    'Operating System :: OS Independent',
 | 
			
		||||
    'Programming Language :: Python :: 3.6',
 | 
			
		||||
    'License :: OSI Approved :: MIT License',
 | 
			
		||||
    'Programming Language :: Python :: 3.10',
 | 
			
		||||
  ],
 | 
			
		||||
  entry_points={
 | 
			
		||||
    'console_scripts': [
 | 
			
		||||
      'delugeclient = delugeClient.__main__:main',
 | 
			
		||||
   ],
 | 
			
		||||
  },
 | 
			
		||||
  packages=find_packages(),
 | 
			
		||||
  package_data={
 | 
			
		||||
    'delugeClient': ['default_config.ini'],
 | 
			
		||||
  },
 | 
			
		||||
  python_requires=">=3.6",
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user