We have a local etherpad running on the soupboat! We have access to the "APIKEY" (basically just a single password for all users to share that gives access to the API, or Application Programming Interface. This API is available "over HTTP" or as a "REST service" ... basically this means that the API is functions that you call via loading specific URLs)
Using the etherpad HTTP api:
https://etherpad.org/doc/v1.8.4/#index_http_api
The pad API is here:
Via this URL you can see what version of the API the pad supports...
https://hub.xpub.nl/soupboat/pad/api/
the version then goes into the URL:
https://hub.xpub.nl/soupboat/pad/api/1.2.15/listAllPads
aha, but you need to include the API KEY! (this is what prevents people from spamming your pad)
https://hub.xpub.nl/soupboat/pad/api/1.2.15/listAllPads?apikey=1234567
but that's not the good one, let's let python make a good URL:
with open("/opt/etherpad/APIKEY.txt") as f:
api_key = f.read()
print(api_key)
029ff291f1256972b277789579ce5e29e83b6bbd52e319fe49af198c35013e9b
It's important this APIKEY is never made public, if it's published then anyone has access to the API, and can (for instance) write a script to delete all pads, or (perhaps more likely) create random pads with links (how search engines are manipulated). For this reason, it's not advisable (though it's technically possible) to call the API directly from javascript) ... Need to think of a workaround.
api_url = "https://hub.xpub.nl/soupboat/pad/api/1.2.15/"
u = f"{api_url}listAllPads?apikey={api_key}"
print (u)
https://hub.xpub.nl/soupboat/pad/api/1.2.15/listAllPads?apikey=029ff291f1256972b277789579ce5e29e83b6bbd52e319fe49af198c35013e9b
A really useful API call is appendText, that let's you add text to the end of an (already existing) pad.
from urllib.request import urlopen
from urllib.parse import urlencode
import json
# the steps
data = {}
data['apikey'] = api_key
# turn dict into url-encoded string, e.g. {"text: "hey there"} becomes 'text=hey%20there'
data = urlencode(data)
# turn the str into bytes (urlopen requires this)
data = data.encode()
# use urlopen to contact the server, using data makes it a POST
resp = urlopen(f"{api_url}listAllPads" , data=data)
# json load can deal with any "file-like" object like the response from urlopen
data = json.load(resp)
print (data)
{'code': 0, 'message': 'ok', 'data': {'padIDs': ['yeeeees', 'yesssss']}}
# do all the steps above as a one-liner (no intermediate variables)
pads = json.load(urlopen(f"{api_url}listAllPads", data=urlencode({'apikey': api_key}).encode()))
print (pads)
{'code': 0, 'message': 'ok', 'data': {'padIDs': ['yeeeees', 'yesssss']}}
# wrap in a convenient function
def ep (fn, api_url, api_key, **data):
d = {}
d['apikey'] = api_key
for key in data:
d[key] = data[key]
return json.load(urlopen(f"{api_url}{fn}", data=urlencode(d).encode()))
ep("listAllPads", api_url, api_key)
{'code': 0, 'message': 'ok', 'data': {'padIDs': ['test', 'yeeeees', 'yesssss']}}
ep("appendText", api_url, api_key, padID="test", text="Hello from python\n")
{'code': 0, 'message': 'ok', 'data': None}
ep("createPad", api_url, api_key, padID="test")
{'code': 0, 'message': 'ok', 'data': None}
ep("getText", api_url, api_key, padID="test")
{'code': 0, 'message': 'ok', 'data': {'text': 'Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https://etherpad.org\nHello from pythonHello from pythonHello from pythonHello from python\n\n'}}
from time import sleep
for i in range(5):
sleep(5)
ep("appendText", api_url, api_key, padID="test", text="Hello from python\n")
ep("deletePad", api_url, api_key, padID="test")
{'code': 0, 'message': 'ok', 'data': None}