Tue, 27 Oct 2015 23:08:48 +0000
parser, objects.client: Experimental support for more liberal object names
local async = require "scansion.async"; local verse = require "verse".init("client"); local parse_xml = require "scansion.xml".parse; local stanza_timeout = 5; local stanzacmp = require "scansion.stanzacmp"; local function fill_vars(script, stanza) for k, v in pairs(stanza.attr) do local expr = v:match("^%$%{(.+)%}$"); if expr then local name, value_name = expr:match("^(.+)'s (.+)$"); assert(name, "Unable to parse expression: "..expr); local key = value_name:lower():gsub(" ", "_"); assert(script.objects[name], "Unknown object called "..name); local value = script.objects[name][key]; assert(value ~= nil, "Unknown attribute (of "..name.."): "..value_name); stanza.attr[k] = value; end end for _, child in ipairs(stanza.tags) do fill_vars(script, child); end return stanza; end return { _validate = function (client) assert(client.jid, "No JID specified"); client.stream = verse.new(verse.new_logger(client.name)); function client.log(fmt, ...) return client.stream:info(fmt, ...); end -- This one prints all received data client.stream:hook("incoming-raw", function (s) client.log("Data in: %s", s); end, 1000); client.stream:hook("outgoing-raw", function (s) client.log("Data out: %s", s); end, 1000); -- And incoming, parsed, stanzas client.stream:hook("stanza", function (s) client.log("Stanza: %s", s) end); end; connects = function (client) local wait, done = async.waiter(); client.stream:hook("ready", function () client.log"ready" done() client.log("ready done") end); client.stream:connect_client(client.jid, client.password); wait(); client.full_jid = client.stream.jid; end; sends = function (client, data) local stanza = fill_vars(client.script, assert(parse_xml((table.concat(data):gsub("\t", " "))))); client.stream:send(stanza); end; receives = function (client, data) local wait, done = async.waiter(); local expected_stanza = fill_vars(client.script, assert(parse_xml((table.concat(data):gsub("\t", " "))))); local function stanza_handler(received_stanza) if not stanzacmp.stanzas_match(expected_stanza, received_stanza) then client.log("NOT IT!") client.log("Expected: %s", expected_stanza); client.log("Received: %s", received_stanza); error("Received unexpected stanza"); else client.log("YES! %s", expected_stanza) end expected_stanza = nil; client.stream:unhook("stanza", stanza_handler); done(); end client.stream:hook("stanza", stanza_handler, 100); verse.add_task(stanza_timeout, function () if not expected_stanza then return; end -- Stanza already received client.log("TIMEOUT waiting for %s", expected_stanza) error("Timed out waiting for stanza"); done(); end); wait(); end; disconnects = function (client) client.stream:close(); end; }