#!/usr/bin/python3 # Filename: grml-paste # Purpose: XmlRpc interface client to paste.grml.org # Author: Michael Gebetsroither # License: This file is licensed under the GPL v2. ################################################################################ import sys from xmlrpc.client import ServerProxy import optparse import inspect import getpass # program defaults DEFAULT_SERVER = "https://paste.grml.org/server.pl" class ActionFailedException(Exception): """Thrown if server returned an error""" def __init__(self, errormsg, ret): Exception.__init__(self, errormsg, ret) def what(self): """Get errormessage""" return self.args[0] def dwhat(self): """Get more verbose errormessage""" return self.args[1] def _paste(opts): """Get paste proxy object""" return (ServerProxy(opts.server, verbose=False).paste) def _check_success(return_data): """Check if call was successful, raise AcitonFailedException otherwise""" if return_data["rc"] != 0: raise ActionFailedException(return_data["statusmessage"], return_data) return return_data def action_add_paste(opts, code): """Add paste to the server: <1.line> <2.line> ... default Read paste from stdin. [text] Every argument on the commandline will be interpreted as a seperate line of paste. """ if len(code) == 0: code = [line.rstrip() for line in sys.stdin.readlines()] code = "\n".join(code) result = _check_success(_paste(opts).addPaste(code, opts.name, opts.expire * 3600, opts.lang, opts.private)) return result["statusmessage"], result def action_del_paste(opts, args): """Delete paste from server: Digest of paste you want to remove. """ digest = args.pop(0) result = _check_success(_paste(opts).deletePaste(digest)) return result["statusmessage"], result def action_get_paste(opts, args): """Get paste from server: Id of paste you want to receive. """ paste_id = args.pop(0) result = _check_success(_paste(opts).getPaste(paste_id)) return result["code"], result def action_get_langs(opts, args): """Get supported language highlighting types from server""" result = _check_success(_paste(opts).getLanguages()) return "\n".join(result["langs"]), result def action_add_short_url(opts, args): """Add short-URL: Short-URL to add """ url = args.pop(0) result = _check_success(_paste(opts).addShortURL(url)) return result["url"], result def action_get_short_url(opts, args): """Resolve short-URL: Short-URL to get clicks of """ url = args.pop(0) result = _check_success(_paste(opts).resolveShortURL(url)) return result["url"], result def action_get_short_url_clicks(opts, args): """Get clicks of short-URL: Short-URL to get clicks of """ url = args.pop(0) result = _check_success(_paste(opts).ShortURLClicks(url)) return result["count"], result def action_help(opts, args): """Print more verbose help about specific action: Topic on which you need more verbose help. """ if len(args) < 1: alias = "help" else: alias = args.pop(0) if alias in actions: function_name = actions[alias] print(inspect.getdoc(globals()[function_name])) print("\naliases: " + " ".join([i for i in actions_r[function_name] if i != alias])) else: print("Error: No such command - %s" % (alias)) OPT_PARSER.print_usage() sys.exit(0) # action_add_paste -> [add, a] actions_r = {} # add -> action_add_paste # a -> action_add_paste actions = {} # option parser OPT_PARSER = None ## # MAIN ## if __name__ == "__main__": action_specs = [ "action_add_paste add a", "action_del_paste del d rm", "action_get_paste get g", "action_get_langs getlangs gl langs l", "action_add_short_url addurl", "action_get_short_url geturl", "action_get_short_url_clicks getclicks", "action_help help" ] for action_spec in action_specs: aliases = action_spec.split() cmd = aliases.pop(0) actions_r[cmd] = aliases for (action_name, v) in actions_r.items(): for i in v: actions[i] = action_name usage = "usage: %prog [options] ACTION \n\n" +\ "actions:\n" +\ "\n".join(["%12s\t%s" % (v[0], inspect.getdoc(globals()[action_name]).splitlines()[0]) for (action_name, v) in actions_r.items()]) running_user = getpass.getuser() parser = optparse.OptionParser(usage=usage) parser.add_option("-n", "--name", default=running_user, help="Name of poster") parser.add_option("-e", "--expire", type=int, default=72, metavar="HOURS", help="Time at wich paste should expire") parser.add_option("-l", "--lang", default="Plain", help="Type of language to highlight") parser.add_option("-p", "--private", action="count", dest="private", default=0, help="Create hidden paste"), parser.add_option("-s", "--server", default=DEFAULT_SERVER, help="Paste server") parser.add_option("-v", "--verbose", action="count", default=0, help="More output") (opts, args) = parser.parse_args() OPT_PARSER = parser if len(args) == 0: parser.error("Please provide me with an action") elif args[0] in actions: cmd = args.pop(0) action = actions[cmd] try: (msg, ret) = globals()[action](opts, args) if opts.verbose == 0: print(msg) else: print(ret) except ActionFailedException as except_inst: sys.stderr.write("Server Error: %s\n" % except_inst.what()) if opts.verbose > 0: print(except_inst.dwhat()) sys.exit(1) else: parser.error("Unknown action: %s" % args[0])