Compare commits

...

4 Commits

Author SHA1 Message Date
R4SAS ac0a145865
just print json, do not encode string 4 months ago
R4SAS c22c0f06ae
remove unused argparse json options, use configuration instead of args for json output 4 months ago
R4SAS 88ea07dba2
json output for send command (closes #39) 4 months ago
Benjamin Renard 063ec9d881 Remove dependency on deprecated distutils.util.strtobool helper 4 months ago
  1. 1
      README.md
  2. 3
      README.rst
  3. 73
      pbincli/actions.py
  4. 14
      pbincli/api.py
  5. 25
      pbincli/cli.py
  6. 1
      requirements.txt

1
README.md

@ -62,6 +62,7 @@ proxy=http://127.0.0.1:3128
| auth_user | None | Basic authorization username | | auth_user | None | Basic authorization username |
| auth_pass | None | Basic authorization password | | auth_pass | None | Basic authorization password |
| auth_custom | None | Custom authorization headers in JSON format, like `{'Authorization': 'Bearer token'}` | | auth_custom | None | Custom authorization headers in JSON format, like `{'Authorization': 'Bearer token'}` |
| json | False | Print sending result in JSON format |
# Usage # Usage

3
README.rst

@ -128,6 +128,9 @@ List of OPTIONS available
* - auth_custom * - auth_custom
- None - None
- Custom authorization headers in JSON format, like ``{'Authorization': 'Bearer token'}`` - Custom authorization headers in JSON format, like ``{'Authorization': 'Bearer token'}``
* - json
- False
- Print sending result in JSON format
Usage Usage

73
pbincli/actions.py

@ -1,4 +1,4 @@
import signal, sys import json, signal, sys
from urllib.parse import parse_qsl from urllib.parse import parse_qsl
from pbincli.api import Shortener from pbincli.api import Shortener
@ -21,20 +21,20 @@ def send(args, api_client, settings=None):
if args.text: if args.text:
text = args.text text = args.text
elif args.stdin: elif args.stdin:
print("Reading text from stdin…") if not settings['json']: print("Reading text from stdin…")
text = args.stdin.read() text = args.stdin.read()
elif not args.file: elif not args.file:
PBinCLIError("Nothing to send!") PBinCLIError("Nothing to send!")
else: else:
text = "" text = ""
print("Preparing paste…") if not settings['json']: print("Preparing paste…")
paste = Paste(args.debug) paste = Paste(args.debug)
if args.verbose: print("Used server: {}".format(api_client.getServer())) if args.verbose: print("Used server: {}".format(api_client.getServer()))
# get from server supported paste format version and update object # get from server supported paste format version and update object
if args.verbose: print("Getting supported paste format version from server…") if args.debug: print("Getting supported paste format version from server…")
version = api_client.getVersion() version = api_client.getVersion()
paste.setVersion(version) paste.setVersion(version)
@ -61,15 +61,17 @@ def send(args, api_client, settings=None):
discussion = settings['discus'], discussion = settings['discus'],
expiration = settings['expire']) expiration = settings['expire'])
if args.verbose: print("Sending request to server…") if args.verbose: print("Preparing request to server…")
request = paste.getJSON() request = paste.getJSON()
if args.debug: print("Passphrase:\t{}\nRequest:\t{}".format(paste.getHash(), request)) if args.debug: print("Passphrase:\t{}\nRequest:\t{}".format(paste.getHash(), request))
# If we use dry option, exit now # If we use dry option, exit now
if args.dry: sys.exit(0) if args.dry:
if not settings['json']: print("Dry mode: paste will not be uploaded. Exiting…")
sys.exit(0)
print("Uploading paste…") if not settings['json']: print("Uploading paste…")
result = api_client.post(request) result = api_client.post(request)
if args.debug: print("Response:\t{}\n".format(result)) if args.debug: print("Response:\t{}\n".format(result))
@ -78,6 +80,47 @@ def send(args, api_client, settings=None):
if not result['status']: # return code is zero if not result['status']: # return code is zero
passphrase = paste.getHash() passphrase = paste.getHash()
if settings['json']: # JSON output
response = {
'status': result['status'],
'result': {
'id': result['id'],
'password': passphrase,
'deletetoken': result['deletetoken'],
'link': "{}?{}#{}".format(
settings['server'],
result['id'],
passphrase),
'deletelink': "{}?pasteid={}&deletetoken={}".format(
settings['server'],
result['id'],
result['deletetoken']),
}
}
if settings['mirrors']:
urls = settings['mirrors'].split(',')
mirrors = []
for x in urls:
mirrors.append("{}?{}#{}".format(
validate_url_ending(x),
result['id'],
passphrase)
)
response['result']['mirrors'] = mirrors
if settings['short']:
try:
response['result']['short'] = shortener.getlink("{}?{}#{}".format(
settings['server'],
result['id'],
passphrase))
except Exception as ex:
response['result']['short_error'] = ex
print(json.dumps(response))
sys.exit(0)
else:
# Paste information # Paste information
print("Paste uploaded!\nPasteID:\t{}\nPassword:\t{}\nDelete token:\t{}".format( print("Paste uploaded!\nPasteID:\t{}\nPassword:\t{}\nDelete token:\t{}".format(
result['id'], result['id'],
@ -106,18 +149,22 @@ def send(args, api_client, settings=None):
result['id'], result['id'],
passphrase)) passphrase))
elif result['status']: # return code is other then zero
PBinCLIError("Something went wrong…\nError:\t\t{}".format(result['message']))
else: # or here no status field in response or it is empty
PBinCLIError("Something went wrong…\nError: Empty response.")
if settings['short']: if settings['short']:
print("\nQuerying URL shortening service…") print("\nQuerying URL shortening service…")
shortener.getlink("{}?{}#{}".format( try:
link = shortener.getlink("{}?{}#{}".format(
settings['server'], settings['server'],
result['id'], result['id'],
passphrase)) passphrase))
print("Short Link:\t{}".format(link))
except Exception as ex:
PBinCLIError("Something went wrong…\nError:\t\t{}".format(ex))
sys.exit(0)
elif result['status']: # return code is other then zero
PBinCLIError("Something went wrong…\nError:\t\t{}".format(result['message']))
else: # or here no status field in response or it is empty
PBinCLIError("Something went wrong…\nError: Empty response.")
def get(args, api_client, settings=None): def get(args, api_client, settings=None):
parseduri, isuri = uri_validator(args.pasteinfo) parseduri, isuri = uri_validator(args.pasteinfo)

14
pbincli/api.py

@ -167,7 +167,7 @@ class Shortener:
'custom': self._custom 'custom': self._custom
} }
# run function selected by choosen API # run function selected by choosen API
servicesList[self.api](url) return servicesList[self.api](url)
def _yourls(self,url): def _yourls(self,url):
@ -196,7 +196,7 @@ class Shortener:
if not 'shorturl' in response: if not 'shorturl' in response:
PBinCLIError("YOURLS: Unknown error: {}".format(response['message'])) PBinCLIError("YOURLS: Unknown error: {}".format(response['message']))
else: else:
print("Short Link:\t{}".format(response['shorturl'])) return response['shorturl']
else: else:
PBinCLIError("YOURLS: No status, statusCode or message fields in response! Received:\n{}".format(response)) PBinCLIError("YOURLS: No status, statusCode or message fields in response! Received:\n{}".format(response))
@ -208,7 +208,7 @@ class Shortener:
result = self.session.post( result = self.session.post(
url = "https://clck.ru/--", url = "https://clck.ru/--",
data = request) data = request)
print("Short Link:\t{}".format(result.text)) return result.text
except Exception as ex: except Exception as ex:
PBinCLIError("clck.ru: unexcepted behavior: {}".format(ex)) PBinCLIError("clck.ru: unexcepted behavior: {}".format(ex))
@ -220,7 +220,7 @@ class Shortener:
result = self.session.post( result = self.session.post(
url = "https://tinyurl.com/api-create.php", url = "https://tinyurl.com/api-create.php",
data = request) data = request)
print("Short Link:\t{}".format(result.text)) return result.text
except Exception as ex: except Exception as ex:
PBinCLIError("TinyURL: unexcepted behavior: {}".format(ex)) PBinCLIError("TinyURL: unexcepted behavior: {}".format(ex))
@ -242,7 +242,7 @@ class Shortener:
response = result.json() response = result.json()
if 'shorturl' in response: if 'shorturl' in response:
print("Short Link:\t{}".format(response['shorturl'])) return response['shorturl']
else: else:
PBinCLIError("{}: got error {} from API: {}".format( PBinCLIError("{}: got error {} from API: {}".format(
"is.gd" if self.api == 'isgd' else 'v.gd', "is.gd" if self.api == 'isgd' else 'v.gd',
@ -265,7 +265,7 @@ class Shortener:
result = self.session.post( result = self.session.post(
url = "https://cutt.ly/scripts/shortenUrl.php", url = "https://cutt.ly/scripts/shortenUrl.php",
data = request) data = request)
print("Short Link:\t{}".format(result.text)) return result.text
except Exception as ex: except Exception as ex:
PBinCLIError("cutt.ly: unexcepted behavior: {}".format(ex)) PBinCLIError("cutt.ly: unexcepted behavior: {}".format(ex))
@ -281,6 +281,6 @@ class Shortener:
try: try:
result = self.session.get( result = self.session.get(
url = rUrl) url = rUrl)
print("Short Link:\t{}".format(result.text)) return result.text
except Exception as ex: except Exception as ex:
PBinCLIError("Shorter: unexcepted behavior: {}".format(ex)) PBinCLIError("Shorter: unexcepted behavior: {}".format(ex))

25
pbincli/cli.py

@ -1,7 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# PYTHON_ARGCOMPLETE_OK # PYTHON_ARGCOMPLETE_OK
import os, sys, argparse import os, sys, argparse
from distutils.util import strtobool
import argcomplete import argcomplete
@ -20,6 +19,16 @@ elif sys.platform == "darwin":
CONFIG_PATHS.append(os.path.join(os.getenv("HOME") or "~", "Library", "Application Support", "pbincli", "pbincli.conf")) CONFIG_PATHS.append(os.path.join(os.getenv("HOME") or "~", "Library", "Application Support", "pbincli", "pbincli.conf"))
def strtobool(value):
try:
return {
'y': True, 'yes': True, 't': True, 'true': True, 'on': True, '1': True,
'n': False, 'no': False, 'f': False, 'false': False, 'off': False, '0': False,
}[str(value).lower()]
except KeyError:
raise ValueError('"{}" is not a valid bool value'.format(value))
def read_config(filename): def read_config(filename):
"""Read config variables from a file""" """Read config variables from a file"""
settings = {} settings = {}
@ -81,7 +90,8 @@ def main():
## ##
send_parser.add_argument("-L", "--mirrors", default=argparse.SUPPRESS, help="Comma-separated list of mirrors of service with scheme (default: None)") send_parser.add_argument("-L", "--mirrors", default=argparse.SUPPRESS, help="Comma-separated list of mirrors of service with scheme (default: None)")
send_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output") send_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
send_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output") send_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output. Includes verbose output")
send_parser.add_argument("--json", default=argparse.SUPPRESS, action="store_true", help="Print result in JSON format")
send_parser.add_argument("--dry", default=False, action="store_true", help="Invoke dry run") send_parser.add_argument("--dry", default=False, action="store_true", help="Invoke dry run")
send_parser.add_argument("stdin", help="Input paste text from stdin", nargs="?", type=argparse.FileType("r"), default=sys.stdin) send_parser.add_argument("stdin", help="Input paste text from stdin", nargs="?", type=argparse.FileType("r"), default=sys.stdin)
send_parser.set_defaults(func=pbincli.actions.send) send_parser.set_defaults(func=pbincli.actions.send)
@ -105,7 +115,7 @@ def main():
get_parser.add_argument("--auth-custom", default=argparse.SUPPRESS, help="Custom authorization header in JSON format") get_parser.add_argument("--auth-custom", default=argparse.SUPPRESS, help="Custom authorization header in JSON format")
## ##
get_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output") get_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
get_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output") get_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output. Includes verbose output")
get_parser.set_defaults(func=pbincli.actions.get) get_parser.set_defaults(func=pbincli.actions.get)
# a delete command # a delete command
@ -124,7 +134,7 @@ def main():
delete_parser.add_argument("--auth-custom", default=argparse.SUPPRESS, help="Custom authorization header in JSON format") delete_parser.add_argument("--auth-custom", default=argparse.SUPPRESS, help="Custom authorization header in JSON format")
## ##
delete_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output") delete_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
delete_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output") delete_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output. Includes verbose output")
delete_parser.set_defaults(func=pbincli.actions.delete) delete_parser.set_defaults(func=pbincli.actions.delete)
# Add argcomplete trigger # Add argcomplete trigger
@ -155,7 +165,8 @@ def main():
'auth': None, 'auth': None,
'auth_user': None, 'auth_user': None,
'auth_pass': None, 'auth_pass': None,
'auth_custom': None 'auth_custom': None,
'json': False
} }
# Configuration preference order: # Configuration preference order:
@ -182,7 +193,9 @@ def main():
# Re-validate PrivateBin instance URL # Re-validate PrivateBin instance URL
CONFIG['server'] = validate_url_ending(CONFIG['server']) CONFIG['server'] = validate_url_ending(CONFIG['server'])
if args.debug: print("Whole configuration:\n{}\n".format(CONFIG)) if args.debug:
print("Whole configuration:\n{}\n".format(CONFIG))
args.verbose = True
api_client = PrivateBin(CONFIG) api_client = PrivateBin(CONFIG)
if hasattr(args, "func"): if hasattr(args, "func"):

1
requirements.txt

@ -3,3 +3,4 @@ sjcl
base58 base58
requests requests
argcomplete argcomplete
pysocks
Loading…
Cancel
Save