From 5dea96ad915692e9abbc0620930756c51c256179 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 27 Feb 2025 23:23:57 +0000 Subject: restructure, refactor, a bit --- .luacheckrc | 2 ++ channel.lua | 15 +++++++++++++++ config.lua | 45 +++++++++++++++++++++++++++++++++++++++++++++ discord/pylon.lua | 37 +++++++++++-------------------------- irc/pylon.lua | 30 +++++------------------------- main.lua | 4 ++-- pylon.lua | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ queue.lua | 43 +++++++++++++++++++++++++++++++++++++++++++ util/channel.lua | 15 --------------- util/config.lua | 45 --------------------------------------------- util/queue.lua | 39 --------------------------------------- wilson.ini | 1 + xmpp/pylon.lua | 53 +++++++++++++++-------------------------------------- xmpp/xml.lua | 9 ++++----- 14 files changed, 198 insertions(+), 195 deletions(-) create mode 100644 .luacheckrc create mode 100644 channel.lua create mode 100644 config.lua create mode 100644 pylon.lua create mode 100644 queue.lua delete mode 100644 util/channel.lua delete mode 100644 util/config.lua delete mode 100644 util/queue.lua diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..8686178 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,2 @@ +codes = true +ignore = { "6..", "21.", "23.", "31.", "4.."} diff --git a/channel.lua b/channel.lua new file mode 100644 index 0000000..e908069 --- /dev/null +++ b/channel.lua @@ -0,0 +1,15 @@ +-- channel descriptor + +local Channel = {} +function Channel.make(pylon, descriptor) + return setmetatable({pylon=pylon, descriptor=descriptor}, Channel) +end +function Channel.__eq(self, other) + return self.pylon == other.pylon and self.descriptor == other.descriptor +end +function Channel.__call(_, ...) return Channel.make(...) end +function Channel.__tostring(self) + return self.pylon.name .. ':' .. self.descriptor +end +setmetatable(Channel, Channel) +return Channel diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..c19a087 --- /dev/null +++ b/config.lua @@ -0,0 +1,45 @@ +local function partial(f,x) return function(...) return f(x,...) end end + +local function kv_syntax(block,line) + local k,v = line:match"^([a-z0-9_-]+)%s*=%s*(.*)$" + assert(k,"syntax error in kv line: "..line) + k = k:gsub("-","_") + block[k]=v +end + +local function tuple_syntax(pattern) return function(block,line) + local matches = {line:match(pattern)} + assert(matches[1], "syntax error in tuple line: "..line) + table.insert(block, matches) +end end + +local schema = { + pylon = kv_syntax, + bus = tuple_syntax"^(%S+)%s+(%S+)$", +} + +local function parse_file(file) + local blocks = {} + for k in pairs(schema) do blocks[k] = {} end + local line_handler = function() error("line outside of block") end + + for line in file:lines() do + line = line:gsub(";.*$",""):gsub("^%s*",""):gsub("%s*$","") + if line == '' then goto next end + + local block_type, block_name = line:match"%[%s*(%S+)%s+(%S+)%s*%]" + if block_type then + local blocks_of_this_type = assert(blocks[block_type],"no such block type "..block_type) + local block = {} + blocks_of_this_type[block_name] = block + line_handler = partial(schema[block_type], block) + else + line_handler(line) + end + ::next:: + end + + return blocks +end + +return {parse=parse_file} diff --git a/discord/pylon.lua b/discord/pylon.lua index 1ecc042..f84db64 100644 --- a/discord/pylon.lua +++ b/discord/pylon.lua @@ -1,23 +1,15 @@ local consts = require'discord.consts' local websocket = require'http.websocket' local json = require 'dkjson' -local Queue = require 'util.queue' +local Queue = require 'queue' local exec_webhook = require'discord.the' local cqueues = require 'cqueues' +local pylon = require 'pylon' -local Discord = {} +local Discord = pylon.subclass "discord" -function Discord.make(wilson, conf) - local self = setmetatable(conf, {__index=Discord}) - - for k,v in pairs { - wilson = wilson, - inbox = Queue.make(), - } do self[k] = v end - - assert(self.token) - - return self +function Discord.init(self) + self:check_config "token" end local function identify_payload(token) @@ -44,14 +36,6 @@ function Discord._connect(self) -- end end -function Discord.run(self) - local cq = cqueues.new() - self:_connect() - cq:wrap(self.recving, self) - cq:wrap(self.sending, self) - print('discord', cq:loop()) -end - function Discord.recving(self) for event in self.ws:each() do print(event) @@ -59,11 +43,12 @@ function Discord.recving(self) end function Discord.sending(self) - local i = 1 - while true do - exec_webhook(self.temp_wh, { username = "god", content = "h"..("i"):rep(i) }) - i = i + 1 - cqueues.sleep(1) + for dest_channel, message in self.inbox:iter() do + print('DDD',message.sender,message.body) + exec_webhook(self.temp_wh, { + username = message.sender, + content = message.body, + }) end end diff --git a/irc/pylon.lua b/irc/pylon.lua index 0c898dd..8c43b13 100644 --- a/irc/pylon.lua +++ b/irc/pylon.lua @@ -2,10 +2,11 @@ local cqueues = require'cqueues' local socket = require'cqueues.socket' local pprint = require'pprint' local rirc = require'irc.rirc' -local Queue = require'util.queue' -local Channel = require'util.channel' +local Queue = require'queue' +local Channel = require'channel' +local pylon = require'pylon' -local Irc = {} +local Irc = pylon.subclass 'irc' function Irc._send(self, args) args.source = args.source or self.nodename @@ -13,21 +14,8 @@ function Irc._send(self, args) print('>', sent) end -function Irc.check_config(self, vars) - for x in vars:gmatch("%S+") do - assert(self[x], "missing conf field "..x) end end - -function Irc.make(wilson, conf) - local self = setmetatable(conf, {__index=Irc}) - - for k,v in pairs { - wilson = wilson, - inbox = Queue.make(), - } do self[k] = v end - +function Irc.init(self) self:check_config "host port password nodename" - - return self end function Irc._connect(self) @@ -36,14 +24,6 @@ function Irc._connect(self) self:_send{'SERVER', self.nodename, '1', 'i am wilson'} end -function Irc.run(self) - local cq = cqueues.new() - self:_connect() - cq:wrap(self.recving, self) - cq:wrap(self.sending, self) - print('irc', cq:loop()) -end - function Irc.recving(self) for line in self.sock:lines "*l" do print('<', line) diff --git a/main.lua b/main.lua index d7b6daf..fd0d146 100644 --- a/main.lua +++ b/main.lua @@ -1,6 +1,6 @@ local cqueues = require'cqueues' -local config = require'util.config' -local Channel = require'util.channel' +local config = require'config' +local Channel = require'channel' local pylon_classes = { irc = require'irc.pylon', diff --git a/pylon.lua b/pylon.lua new file mode 100644 index 0000000..12b3fdb --- /dev/null +++ b/pylon.lua @@ -0,0 +1,55 @@ +local cqueues = require 'cqueues' +local Queue = require 'queue' + +-- commonality between the different pylon classes +-- they can "inherit" from this + +local BasePylon = {} + +function BasePylon.check_config(self, vars) + for x in vars:gmatch"%S+" do + assert(self[x], "missing conf field "..x) + end +end + +function BasePylon.run(self) + local cq = cqueues.new() + self:_connect() + cq:wrap(self.recving, self) + cq:wrap(self.sending, self) + print(self.pylon_type, cq:loop()) +end + +function BasePylon.post(self, dest_channel, message) + self.inbox:enqueue(dest_channel, message) +end + +function BasePylon.log(self, ...) + if self.debug then + print(self.pylon_type, self.name, ...) + end +end + +local function subclass(pylon_type) + local Subclass = {} + setmetatable(Subclass, {__index=BasePylon}) + Subclass.pylon_type = pylon_type + + Subclass.make = function(wilson, conf) + local self = setmetatable(conf, {__index=Subclass}) + for k,v in pairs { + wilson = wilson, + inbox = Queue.make(), + } do self[k] = v end + + self:init(wilson, conf) + return self + end + + return Subclass +end + +return { + BasePylon = BasePylon, + subclass = subclass, +} diff --git a/queue.lua b/queue.lua new file mode 100644 index 0000000..5a30646 --- /dev/null +++ b/queue.lua @@ -0,0 +1,43 @@ +local cqueues = require'cqueues' +local condition = require'cqueues.condition' +local cqaux = require'cqueues.auxlib' + +local Queue = {} + +function Queue.make() + return setmetatable({ + items = {}, + cv = condition.new(), + }, {__index=Queue}) +end + +function Queue.enqueue(self, ...) + local item = table.pack(...) + print('q',...) + table.insert(self.items, item) + if #self.items > 128 then + print('warning: queue is quite big') + end + self.cv:signal() +end + +function Queue.iter(self) + return cqaux.wrap(function() + while true do + while #self.items > 0 do + local items = self.items + self.items = {} -- the old switcheroo + for _, item in ipairs(items) do + (function(...) + print('p',...) + coroutine.yield(...) + end)(table.unpack(item, 1, item.n)) + end + end + self.cv:wait() + end + end) +end + + +return Queue diff --git a/util/channel.lua b/util/channel.lua deleted file mode 100644 index e908069..0000000 --- a/util/channel.lua +++ /dev/null @@ -1,15 +0,0 @@ --- channel descriptor - -local Channel = {} -function Channel.make(pylon, descriptor) - return setmetatable({pylon=pylon, descriptor=descriptor}, Channel) -end -function Channel.__eq(self, other) - return self.pylon == other.pylon and self.descriptor == other.descriptor -end -function Channel.__call(_, ...) return Channel.make(...) end -function Channel.__tostring(self) - return self.pylon.name .. ':' .. self.descriptor -end -setmetatable(Channel, Channel) -return Channel diff --git a/util/config.lua b/util/config.lua deleted file mode 100644 index c19a087..0000000 --- a/util/config.lua +++ /dev/null @@ -1,45 +0,0 @@ -local function partial(f,x) return function(...) return f(x,...) end end - -local function kv_syntax(block,line) - local k,v = line:match"^([a-z0-9_-]+)%s*=%s*(.*)$" - assert(k,"syntax error in kv line: "..line) - k = k:gsub("-","_") - block[k]=v -end - -local function tuple_syntax(pattern) return function(block,line) - local matches = {line:match(pattern)} - assert(matches[1], "syntax error in tuple line: "..line) - table.insert(block, matches) -end end - -local schema = { - pylon = kv_syntax, - bus = tuple_syntax"^(%S+)%s+(%S+)$", -} - -local function parse_file(file) - local blocks = {} - for k in pairs(schema) do blocks[k] = {} end - local line_handler = function() error("line outside of block") end - - for line in file:lines() do - line = line:gsub(";.*$",""):gsub("^%s*",""):gsub("%s*$","") - if line == '' then goto next end - - local block_type, block_name = line:match"%[%s*(%S+)%s+(%S+)%s*%]" - if block_type then - local blocks_of_this_type = assert(blocks[block_type],"no such block type "..block_type) - local block = {} - blocks_of_this_type[block_name] = block - line_handler = partial(schema[block_type], block) - else - line_handler(line) - end - ::next:: - end - - return blocks -end - -return {parse=parse_file} diff --git a/util/queue.lua b/util/queue.lua deleted file mode 100644 index 8c9c373..0000000 --- a/util/queue.lua +++ /dev/null @@ -1,39 +0,0 @@ -local cqueues = require'cqueues' -local condition = require'cqueues.condition' -local cqaux = require'cqueues.auxlib' - -local Queue = {} - -function Queue.make() - return setmetatable({ - items = {}, - cv = condition.new(), - }, {__index=Queue}) -end - -function Queue.enqueue(self, ...) - local item = table.pack(...) - table.insert(self.items, item) - if #self.items > 128 then - print('warning: queue is quite big') - end - self.cv:signal() -end - -function Queue.iter(self) - return cqaux.wrap(function() - while true do - while #self.items > 0 do - local items = self.items - self.items = {} -- the old switcheroo - for _, item in ipairs(items) do - coroutine.yield(table.unpack(item, 1, item.n)) - end - end - self.cv:wait() - end - end) -end - - -return Queue diff --git a/wilson.ini b/wilson.ini index e3dba05..4ea80a4 100644 --- a/wilson.ini +++ b/wilson.ini @@ -19,3 +19,4 @@ temp_wh=https://discord.com/api/v8/webhooks/1277689699254800436/gzYU3voeunQsEdC7 [bus test] ubq-xmpp d@conference.ubq323.website local-irc #test +discord 868268751433375805 diff --git a/xmpp/pylon.lua b/xmpp/pylon.lua index ba9c252..2476fc9 100644 --- a/xmpp/pylon.lua +++ b/xmpp/pylon.lua @@ -1,42 +1,24 @@ -local cqueues = require'cqueues' -local cqaux = require'cqueues.auxlib' local socket = require'cqueues.socket' local xml = require'xmpp.xml' local X = xml.X local xmlify = xml.xmlify -local pprint=require'pprint' -local Queue = require'util.queue' local base64 = require'xmpp.base64' local sha1 = require'xmpp.sha1' -local Channel = require'util.channel' +local Channel = require'channel' +local pylon = require 'pylon' -local Xmpp = {} +local Xmpp = pylon.subclass "xmpp" local function make_auth(authz, authn, password) -- sasl plain (RFC4616) return base64.encode(authz..'\0'..authn..'\0'..password) end -function Xmpp.make(wilson, conf) - local self = { - name = conf.name, - wilson = wilson, - inbox = Queue.make(), - cq = wilson.cq, -- todo - nicks_inuse = {}, -- todo - } - local function conf_var(name) - assert(conf[name] ~= nil, 'missing conf field '..name) - self[name] = conf[name] - end - -- conf_var 'jid' - conf_var 'server' - -- conf_var 'resource' - conf_var 'component' - conf_var 'component_secret' - - setmetatable(self, {__index=Xmpp}) - return self +function Xmpp.init(self) + self:check_config "server component component_secret" + + self.cq = self.wilson.cq -- todo + self.nicks_inuse = {} -- todo end function Xmpp._connect_c2s(self) @@ -80,7 +62,7 @@ function Xmpp._connect_component(self) -- yes, our component name goes in the 'to' field. don't ask me why local start = ([[]]):format(self.component) - print(start) + -- print(start) -- state of the art xml parser local function check_and_send(test, text) @@ -91,7 +73,7 @@ function Xmpp._connect_component(self) sock:write(start) local streamhead = sock:read('-2048') - print('streamhead', streamhead) + -- print('streamhead', streamhead) assert(streamhead:find'accept') local streamid = streamhead:match"id='(.-)'" sock:write(xmlify(X.handshake{sha1.sha1(streamid..self.component_secret)})) @@ -99,26 +81,21 @@ function Xmpp._connect_component(self) return sock end +Xmpp._connect = Xmpp._connect_component local THE_MUC = 'd@conference.ubq323.website' -function Xmpp.run(self) - self:_connect_component() - self.cq:wrap(self.recving, self) - self.cq:wrap(self.sending, self) -end - function Xmpp.recving(self) local function getmore() local function t(...) - pprint(...) + -- pprint(...) return ... end return t(self.sock:read'-2048') end for x in xml.stanzae(getmore) do - pprint(x) - print(xmlify(x)) + -- pprint(x) + -- print(xmlify(x)) local body = x'body' and x'body'[1] if x.label == 'message' then local fr = x.xarg.from @@ -152,7 +129,7 @@ function Xmpp.sending(self) end ensure_joined(THE_MUC, 'wilson', 'wilson') for dest_channel, message in self.inbox:iter() do - pprint(dest_channel, message) + -- pprint(dest_channel, message) ensure_joined(THE_MUC, message.sender, message.sender) local user = message.sender:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") local jid = user..'@'..self.component diff --git a/xmpp/xml.lua b/xmpp/xml.lua index 68fa741..e54f27f 100644 --- a/xmpp/xml.lua +++ b/xmpp/xml.lua @@ -1,21 +1,20 @@ -- originally from http://lua-users.org/wiki/LuaXml -- modified by me a bit - -entity_escapes = { +local entity_escapes = { ["<"]="<", [">"]=">", ["&"]="&", ['"']=""", ["'"]="'" } -entity_unescapes = {} +local entity_unescapes = {} for k,v in pairs(entity_escapes) do entity_unescapes[v]=k end -function escape(s) +local function escape(s) return s:gsub("[<>&'\"]",entity_escapes) end -function unescape(s) +local function unescape(s) return s:gsub("&[a-z]+;",entity_unescapes) end -- cgit v1.2.3