summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.lua1
-rw-r--r--quaddle/pylon.lua101
-rw-r--r--todo.txt3
-rw-r--r--wilson.ini.example8
4 files changed, 113 insertions, 0 deletions
diff --git a/main.lua b/main.lua
index aebc001..e928fdb 100644
--- a/main.lua
+++ b/main.lua
@@ -11,6 +11,7 @@ local pylon_classes = {
xmpp = require'xmpp.pylon',
discord = require'discord.pylon',
nanochat = require'nanochat.pylon',
+ quaddle = require'quaddle.pylon',
}
local Wilson = class()
diff --git a/quaddle/pylon.lua b/quaddle/pylon.lua
new file mode 100644
index 0000000..d176260
--- /dev/null
+++ b/quaddle/pylon.lua
@@ -0,0 +1,101 @@
+local websocket = require'http.websocket'
+local request = require'http.request'
+local json = require 'dkjson'
+local class = require 'r.class'
+
+local BasePylon = require 'pylon'
+local Channel = require 'channel'
+
+local Quaddle = class.extend(BasePylon)
+function Quaddle.init(self)
+ self:_check_fields "base_url bot_name bot_password"
+end
+
+-- https://codeberg.org/QWD/Quaddle/src/branch/main/doc/api.md
+
+function Quaddle._req(self, url, payload)
+ local req = request.new_from_uri(self.base_url..url)
+ req.headers:upsert(':method',payload and 'POST' or 'GET')
+ if self.token then req.headers:upsert('authorization',self.token) end
+ req.headers:upsert('user-agent','wilson (https://g.gh0.pw/wilson/, v0.0)')
+ if payload then
+ req.headers:upsert('content-type','application/json')
+ req:set_body(assert(json.encode(payload))) end
+
+ local head,body = assert(req:go())
+ local status = head:get':status'
+ local bod = body:get_body_as_string()
+
+ assert(status:match"^2", 'status was '..status..' body '..bod)
+
+ if #bod == 0 then return nil end
+ local val, _, err = json.decode(bod)
+ if err then error(err) else return val end
+end
+
+function Quaddle._connect(self)
+ local r = assert(self:_req("auth/login", { name=self.bot_name, password=self.bot_password }))
+ self.token = r.token
+
+ self.ws = websocket.new_from_uri(self.base_url:gsub("^http","ws").."app")
+ assert(self.ws:connect())
+ self.ws:send(json.encode{ op="identify", token=self.token }, 'text')
+
+ for busname, bus in pairs(self.wilson.busses) do
+ for _, channel in ipairs(bus) do
+ if channel.pylon == self then
+ self:add_channel(channel)
+ end
+ end
+ end
+end
+
+function Quaddle.add_channel(self, channel)
+ self.log("Subscribing to channel",channel.descriptor)
+ self.ws:send(json.encode{ op="subscribe", channel_id=channel.descriptor })
+end
+
+function Quaddle.recving(self)
+ for packet in self.ws:each() do
+ local event = json.decode(packet)
+ self.log:debug('event', event.event)
+ if event.event == "ready" then
+ -- self.session_id = event.session_id
+ self.bot_user = event.user
+ self.log("Logged in as id",self.bot_user.id,"name",self.bot_user.name)
+ elseif event.event == "error" then
+ self.log:error("Error from server:",event.reasons)
+ elseif event.event == "message_create" then
+ self:handle_message(event.message)
+ elseif event.event == "message_edit" then
+ -- TODO: wilson doesn't have edits yet
+ self:handle_message(event.message)
+ -- elseif event.event == "message_delete" then
+ -- TODO
+ else
+ self.log:debug("Unhandled Quaddle event:",json.encode(event))
+ end
+ end
+end
+
+function Quaddle.handle_message(self, msg)
+ self.log:proto('<',msg.channel_id,msg.author.username,msg.content)
+ if msg.author.id ~= self.bot_user.id then
+ self.wilson:deliver(Channel(self, msg.channel), {
+ body = msg.content,
+ sender = '[q]' .. msg.author.name,
+ })
+ end
+end
+
+function Quaddle.sending(self)
+ for dest_channel, message in self.inbox:iter() do
+ self.log:proto('>', dest_channel, message.sender, message.body)
+
+ self:_req('channels/'..dest_channel.descriptor..'/messages', {
+ content = message.sender..": "..message.body,
+ })
+ end
+end
+
+return Quaddle
diff --git a/todo.txt b/todo.txt
index 0ee8f75..d79aa3c 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,3 +2,6 @@
pylon.subclass should not have a pylon_type arg. is only used for logging. a pylon's _name_ should be used in log messages.
pylons harcode prepend names with [x] [d] [n] etc. this is not robust and is weird it should be in some way dynamic? maybe pylons can have configured short names? but then what in the case of two channels with different users of the same nick? they should not be conflated..
+
+discord and quaddle hard-depend on the configured url ending with a /
+note that http does not conflate // into / in the path.
diff --git a/wilson.ini.example b/wilson.ini.example
index 303d8a2..2eb7708 100644
--- a/wilson.ini.example
+++ b/wilson.ini.example
@@ -26,9 +26,17 @@ server=gloop.woop.example
port=44322
poll=5
+[pylon quaddle-boingy]
+type=quaddle
+base_url=https://boingy.example/
+bot_username=wilson
+bot_password=seeeeeecret_password_here
+
+
[bus test]
xmpp-barbaz test@conference.example.org
irc-boopbanana #test
discord-foobar channel_id_here
nanochat-gloop #test
+quaddle-boingy channel_id_here