3 # Purpose: XmlRpc interface client to paste.grml.org
4 # Author: Michael Gebetsroither <gebi@grml.org>
5 # License: This file is licensed under the GPL v2.
6 ################################################################################
9 from xmlrpc.client import ServerProxy
15 DEFAULT_SERVER = "http://paste.grml.org/server.pl"
18 class ActionFailedException(Exception):
19 """Thrown if server returned an error"""
21 def __init__(self, errormsg, ret):
22 Exception.__init__(self, errormsg, ret)
25 """Get errormessage"""
29 """Get more verbose errormessage"""
34 def __init__(self, args, opts):
38 def _createProxy(self):
39 return ServerProxy(self.opts_.server, verbose=False)
41 def _callProxy(self, functor, server=None):
42 """Wrapper for xml-rpc calls to server which throws an
43 ActionFailedException on error"""
45 server = self._createProxy()
48 raise ActionFailedException(ret["statusmessage"], ret)
51 def call(self, method_name):
52 """External Interface to call the appropriate action"""
53 return self.__getattribute__(method_name)()
55 def actionAddPaste(self):
56 """Add paste to the server: <1.line> <2.line> ...
58 default Read paste from stdin.
59 [text] Every argument on the commandline will be interpreted as
60 a seperate line of paste.
62 server = self._createProxy()
65 if len(self.args_) == 0:
66 code = [i.rstrip() for i in sys.stdin.readlines()]
67 code = "\n".join(code)
68 result = self._callProxy(lambda s: s.paste.addPaste(code, o.name, o.expire * 3600, o.lang, o.private),
70 return result["statusmessage"], result
72 def actionDelPaste(self):
73 """Delete paste from server: <digest>
75 <digest> Digest of paste you want to remove.
77 digest = self.args_.pop(0)
78 result = self._callProxy(lambda s: s.paste.deletePaste(digest))
79 return result["statusmessage"], result
81 def actionGetPaste(self):
82 """Get paste from server: <id>
84 <id> Id of paste you want to receive.
86 paste_id = self.args_.pop(0)
87 result = self._callProxy(lambda s: s.paste.getPaste(paste_id))
88 return result["code"], result
90 def actionGetLangs(self):
91 """Get supported language highlighting types from server"""
92 result = self._callProxy(lambda s: s.paste.getLanguages())
93 return "\n".join(result["langs"]), result
95 def actionAddShortUrl(self):
96 """Add short-URL: <url>
98 <url> Short-URL to add
100 url = self.args_.pop(0)
101 result = self._callProxy(lambda s: s.paste.addShortURL(url))
102 return result["url"], result
104 def actionGetShortUrl(self):
105 """Resolve short-URL: <url>
107 <url> Short-URL to get clicks of
109 url = self.args_.pop(0)
110 result = self._callProxy(lambda s: s.paste.resolveShortURL(url))
111 return (result["url"], result)
113 def actionGetShortUrlClicks(self):
114 """Get clicks of short-URL: <url>
116 <url> Short-URL to get clicks of
118 url = self.args_.pop(0)
119 result = self._callProxy(lambda s: s.paste.ShortURLClicks(url))
120 return result["count"], result
122 def actionHelp(self):
123 """Print more verbose help about specific action: <action>
125 <action> Topic on which you need more verbose help.
127 if len(self.args_) < 1:
130 alias = self.args_.pop(0)
134 print(inspect.getdoc(self.__getattribute__(fun)))
135 print("\naliase: " + " ".join([i for i in actions_r[fun] if i != alias]))
137 print("Error: No such command - %s" % (alias))
138 OPT_PARSER.print_usage()
142 # actionAddPaste -> [add, a]
145 # add -> actionAddPaste
146 # a -> actionAddPaste
156 if __name__ == "__main__":
157 action_spec = ["actionAddPaste add a",
158 "actionDelPaste del d rm",
159 "actionGetPaste get g",
160 "actionGetLangs getlangs gl langs l",
161 "actionAddShortUrl addurl",
162 "actionGetShortUrl geturl",
163 "actionGetShortUrlClicks getclicks",
165 for i in action_spec:
168 actions_r[cmd] = aliases
169 for (k, v) in actions_r.items():
173 usage = "usage: %prog [options] ACTION <args>\n\n" +\
175 "\n".join(["%12s\t%s" % (v[0], inspect.getdoc(getattr(Action, k)).split("\n")[0])
176 for (k, v) in actions_r.items()])
177 running_user = getpass.getuser()
178 parser = optparse.OptionParser(usage=usage)
179 parser.add_option("-n", "--name", default=running_user, help="Name of poster")
180 parser.add_option("-e", "--expire", type=int, default=72, metavar="HOURS",
181 help="Time at wich paste should expire")
182 parser.add_option("-l", "--lang", default="Plain", help="Type of language to highlight")
183 parser.add_option("-p", "--private", action="count", dest="private", default=0,
184 help="Create hidden paste"),
185 parser.add_option("-s", "--server", default=DEFAULT_SERVER,
187 parser.add_option("-v", "--verbose", action="count", default=0, help="More output")
188 (opts, args) = parser.parse_args()
192 parser.error("Please provide me with an action")
193 elif args[0] in actions:
195 action = Action(args, opts)
197 (msg, ret) = action.call(actions[cmd])
198 if opts.verbose == 0:
202 except ActionFailedException as e:
203 sys.stderr.write("Server Error: %s\n" % e.what())
208 parser.error("Unknown action: %s" % args[0])