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({ source_channel = Channel(self, msg.channel), body = msg.content, sender = 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.source_channel.pylon.shortname.."] "..message.sender..": "..message.body, }) end end return Quaddle