X-Git-Url: http://git.grml.org/?a=blobdiff_plain;f=grml-paste;h=d8b02538e57a068628336df906e4c4666fa0f8f6;hb=0ac34191c2f3111a48fabc68c169cc51ca35f6bc;hp=d4b7fb6699f7b8509cfc144ae969b17b71fa55c7;hpb=453ebd84a6d80bdbfd34e0427b68b8e89a43500d;p=grml-paste.git diff --git a/grml-paste b/grml-paste index d4b7fb6..d8b0253 100755 --- a/grml-paste +++ b/grml-paste @@ -1,75 +1,208 @@ -#!/usr/bin/env ruby +#!/usr/bin/python3 # Filename: grml-paste -# Purpose: paste files to the online grml paste bot -# Authors: grml-team (grml.org), (c) 2007 Nico Golde -# Bug-Reports: see http://grml.org/bugs/ -# License: This file is licensed under the GPL v2 -########################################################################## - -require 'uri' -require 'net/http' - -url = URI.parse('http://paste.grml.org/paste') - -def usage - $stderr.puts "usage: #{$0} [-n nick] [-s summary] [-f source] [-h|--help]\n" - $stderr.puts "\t -n \tset your nickname (defaults to Anonymuos)" - $stderr.puts "\t -s \tspecify a summary of your paste (defaults to none)" - $stderr.puts "\t -f \tsets the file to read from, you don't need this for reading from stdin" - $stderr.puts "\t --help\t\tprint this help" - Kernel.exit(1) -end - -file = nil -summary = "none" -nick = "Anonymous" -channel = "#grml" -text = "" - -ARGV.each_index do |i| - if ARGV[i] == '-h' or ARGV[i] == '--help' then - usage - elsif ARGV[i] == '-n' and ARGV[i+1] != nil then - nick = ARGV[i+1] - elsif ARGV[i] == '-s' and ARGV[i+1] != nil then - summary = ARGV[i+1] - elsif ARGV[i] == '-f' and ARGV[i+1] != nil then - file = ARGV[i+1] - end -end - -if file == nil or file == "-" - f = STDIN -else - begin - f = File.open(file) - rescue - $stderr.puts "Error: couldn't open file: #{file}" - Kernel.exit(1) - end -end - -f.each_line do |line| - text << line -end - -begin - res = Net::HTTP.post_form(url,{'Paste it' => 'Paste it', 'paste' => text, 'channel' => channel, 'summary' => summary, 'nick' => nick}) -rescue - $stderr.puts "Unable to post HTTP request" - Kernel.exit(1) -end - -results = res.body.scan(/ 0 then - result = results[0].sub(/ +# 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 = 'http://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] + + +class Action(object): + def __init__(self, args, opts): + self.args_ = args + self.opts_ = opts + + def _createProxy(self): + return ServerProxy(self.opts_.server, verbose=False) + + def _callProxy(self, functor, server=None): + '''Wrapper for xml-rpc calls to server which throws an + ActionFailedException on error''' + if server is None: + server = self._createProxy() + ret = functor(server) + if ret['rc'] != 0: + raise ActionFailedException(ret['statusmessage'], ret) + return ret + + def call(self, method_name): + '''External Interface to call the appropriate action''' + return self.__getattribute__(method_name)() + + def actionAddPaste(self): + '''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. + ''' + server = self._createProxy() + o = self.opts_ + code = self.args_ + if len(self.args_) == 0: + code = [i.rstrip() for i in sys.stdin.readlines()] + code = '\n'.join(code) + result = self._callProxy(lambda s: s.paste.addPaste(code, o.name, o.expire * 3600, o.lang, o.private), + server) + return result['statusmessage'], result + + def actionDelPaste(self): + '''Delete paste from server: + + Digest of paste you want to remove. + ''' + digest = self.args_.pop(0) + result = self._callProxy(lambda s: s.paste.deletePaste(digest)) + return result['statusmessage'], result + + def actionGetPaste(self): + '''Get paste from server: + + Id of paste you want to receive. + ''' + paste_id = self.args_.pop(0) + result = self._callProxy(lambda s: s.paste.getPaste(paste_id)) + return result['code'], result + + def actionGetLangs(self): + '''Get supported language highlighting types from server''' + result = self._callProxy(lambda s: s.paste.getLanguages()) + return '\n'.join(result['langs']), result + + def actionAddShortUrl(self): + '''Add short-URL: + + Short-URL to add + ''' + url = self.args_.pop(0) + result = self._callProxy(lambda s: s.paste.addShortURL(url)) + return result['url'], result + + def actionGetShortUrl(self): + '''Resolve short-URL: + + Short-URL to get clicks of + ''' + url = self.args_.pop(0) + result = self._callProxy(lambda s: s.paste.resolveShortURL(url)) + return (result['url'], result) + + def actionGetShortUrlClicks(self): + '''Get clicks of short-URL: + + Short-URL to get clicks of + ''' + url = self.args_.pop(0) + result = self._callProxy(lambda s: s.paste.ShortURLClicks(url)) + return result['count'], result + + def actionHelp(self): + '''Print more verbose help about specific action: + + Topic on which you need more verbose help. + ''' + if len(self.args_) < 1: + alias = "help" + else: + alias = self.args_.pop(0) + + if alias in actions: + fun = actions[alias] + print(inspect.getdoc(self.__getattribute__(fun))) + print("\naliase: " + " ".join([i for i in actions_r[fun] if i != alias])) + else: + print("Error: No such command - %s" % (alias)) + OPT_PARSER.print_usage() + sys.exit(0) + + +# actionAddPaste -> [add, a] +actions_r = {} + +# add -> actionAddPaste +# a -> actionAddPaste +actions = {} + +# option parser +OPT_PARSER = None + + +## +# MAIN +## +if __name__ == "__main__": + action_spec = ['actionAddPaste add a', + 'actionDelPaste del d rm', + 'actionGetPaste get g', + 'actionGetLangs getlangs gl langs l', + 'actionAddShortUrl addurl', + 'actionGetShortUrl geturl', + 'actionGetShortUrlClicks getclicks', + 'actionHelp help'] + for i in action_spec: + aliases = i.split() + cmd = aliases.pop(0) + actions_r[cmd] = aliases + for (k, v) in actions_r.items(): + for i in v: + actions[i] = k + + usage = "usage: %prog [options] ACTION \n\n" +\ + "actions:\n" +\ + "\n".join(["%12s\t%s" % (v[0], inspect.getdoc(getattr(Action, k)).split('\n')[0]) + for (k, 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 = Action(args, opts) + try: + (msg, ret) = action.call(actions[cmd]) + if opts.verbose == 0: + print(msg) + else: + print(ret) + except ActionFailedException as e: + sys.stderr.write('Server Error: %s\n' % e.what()) + if opts.verbose > 0: + print(e.dwhat()) + sys.exit(1) + else: + parser.error('Unknown action: %s' % args[0])