diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/pad/py_etherpad | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/pad/py_etherpad')
| -rw-r--r-- | addons/pad/py_etherpad/__init__.py | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/addons/pad/py_etherpad/__init__.py b/addons/pad/py_etherpad/__init__.py new file mode 100644 index 00000000..2d4872f3 --- /dev/null +++ b/addons/pad/py_etherpad/__init__.py @@ -0,0 +1,251 @@ +"""Module to talk to EtherpadLite API.""" +import requests +import logging + +from odoo.tools import html2plaintext + +_logger = logging.getLogger(__name__) + + +class EtherpadLiteClient: + """Client to talk to EtherpadLite API.""" + API_VERSION = 1 # TODO probably 1.1 sometime soon + + CODE_OK = 0 + CODE_INVALID_PARAMETERS = 1 + CODE_INTERNAL_ERROR = 2 + CODE_INVALID_FUNCTION = 3 + CODE_INVALID_API_KEY = 4 + TIMEOUT = 20 + + apiKey = "" + baseUrl = "http://localhost:9001/api" + + def __init__(self, apiKey=None, baseUrl=None): + if apiKey: + self.apiKey = apiKey + + if baseUrl: + self.baseUrl = baseUrl + + def call(self, function, arguments=None): + """Create a dictionary of all parameters""" + url = '%s/%d/%s' % (self.baseUrl, self.API_VERSION, function) + + params = arguments or {} + params['apikey'] = self.apiKey + + r = requests.post(url, data=params, timeout=self.TIMEOUT) + r.raise_for_status() + return self.handleResult(r.json()) + + def handleResult(self, result): + """Handle API call result""" + if 'code' not in result: + raise Exception("API response has no code") + if 'message' not in result: + raise Exception("API response has no message") + + if 'data' not in result: + result['data'] = None + + if result['code'] == self.CODE_OK: + return result['data'] + elif result['code'] == self.CODE_INVALID_PARAMETERS or result['code'] == self.CODE_INVALID_API_KEY: + raise ValueError(result['message']) + elif result['code'] == self.CODE_INTERNAL_ERROR: + raise Exception(result['message']) + elif result['code'] == self.CODE_INVALID_FUNCTION: + raise Exception(result['message']) + else: + raise Exception("An unexpected error occurred whilst handling the response") + + # GROUPS + # Pads can belong to a group. There will always be public pads that do not belong to a group (or we give this group the id 0) + + def createGroup(self): + """creates a new group""" + return self.call("createGroup") + + def createGroupIfNotExistsFor(self, groupMapper): + """this functions helps you to map your application group ids to etherpad lite group ids""" + return self.call("createGroupIfNotExistsFor", { + "groupMapper": groupMapper + }) + + def deleteGroup(self, groupID): + """deletes a group""" + return self.call("deleteGroup", { + "groupID": groupID + }) + + def listPads(self, groupID): + """returns all pads of this group""" + return self.call("listPads", { + "groupID": groupID + }) + + def createGroupPad(self, groupID, padName, text=''): + """creates a new pad in this group""" + params = { + "groupID": groupID, + "padName": padName, + } + if text: + params['text'] = text + return self.call("createGroupPad", params) + + # AUTHORS + # Theses authors are bind to the attributes the users choose (color and name). + + def createAuthor(self, name=''): + """creates a new author""" + params = {} + if name: + params['name'] = name + return self.call("createAuthor", params) + + def createAuthorIfNotExistsFor(self, authorMapper, name=''): + """this functions helps you to map your application author ids to etherpad lite author ids""" + params = { + 'authorMapper': authorMapper + } + if name: + params['name'] = name + return self.call("createAuthorIfNotExistsFor", params) + + # SESSIONS + # Sessions can be created between a group and a author. This allows + # an author to access more than one group. The sessionID will be set as + # a cookie to the client and is valid until a certain date. + + def createSession(self, groupID, authorID, validUntil): + """creates a new session""" + return self.call("createSession", { + "groupID": groupID, + "authorID": authorID, + "validUntil": validUntil + }) + + def deleteSession(self, sessionID): + """deletes a session""" + return self.call("deleteSession", { + "sessionID": sessionID + }) + + def getSessionInfo(self, sessionID): + """returns informations about a session""" + return self.call("getSessionInfo", { + "sessionID": sessionID + }) + + def listSessionsOfGroup(self, groupID): + """returns all sessions of a group""" + return self.call("listSessionsOfGroup", { + "groupID": groupID + }) + + def listSessionsOfAuthor(self, authorID): + """returns all sessions of an author""" + return self.call("listSessionsOfAuthor", { + "authorID": authorID + }) + + # PAD CONTENT + # Pad content can be updated and retrieved through the API + + def getText(self, padID, rev=None): + """returns the text of a pad""" + params = {"padID": padID} + if rev is not None: + params['rev'] = rev + return self.call("getText", params) + + # introduced with pull request merge + def getHtml(self, padID, rev=None): + """returns the html of a pad""" + params = {"padID": padID} + if rev is not None: + params['rev'] = rev + return self.call("getHTML", params) + + def setText(self, padID, text): + """sets the text of a pad""" + return self.call("setText", { + "padID": padID, + "text": text + }) + + def setHtmlFallbackText(self, padID, html): + try: + # Prevents malformed HTML errors + html_wellformed = '<html><body>' + html + '</body></html>' + return self.setHtml(padID, html_wellformed) + except Exception: + _logger.exception('Falling back to setText. SetHtml failed with message:') + return self.setText(padID, html2plaintext(html).encode('UTF-8')) + + def setHtml(self, padID, html): + """sets the text of a pad from html""" + return self.call("setHTML", { + "padID": padID, + "html": html + }) + + # PAD + # Group pads are normal pads, but with the name schema + # GROUPID$PADNAME. A security manager controls access of them and its + # forbidden for normal pads to include a in the name. + + def createPad(self, padID, text=''): + """creates a new pad""" + params = { + "padID": padID, + } + if text: + params['text'] = text + return self.call("createPad", params) + + def getRevisionsCount(self, padID): + """returns the number of revisions of this pad""" + return self.call("getRevisionsCount", { + "padID": padID + }) + + def deletePad(self, padID): + """deletes a pad""" + return self.call("deletePad", { + "padID": padID + }) + + def getReadOnlyID(self, padID): + """returns the read only link of a pad""" + return self.call("getReadOnlyID", { + "padID": padID + }) + + def setPublicStatus(self, padID, publicStatus): + """sets a boolean for the public status of a pad""" + return self.call("setPublicStatus", { + "padID": padID, + "publicStatus": publicStatus + }) + + def getPublicStatus(self, padID): + """return true of false""" + return self.call("getPublicStatus", { + "padID": padID + }) + + def setPassword(self, padID, password): + """returns ok or a error message""" + return self.call("setPassword", { + "padID": padID, + "password": password + }) + + def isPasswordProtected(self, padID): + """returns true or false""" + return self.call("isPasswordProtected", { + "padID": padID + }) |
