Software /
code /
prosody-modules
Comparison
mod_storage_xmlarchive/mod_storage_xmlarchive.lua @ 2815:d48d4d9ccae7
mod_storage_xmlarchive: Add a prosodyctl command for migrating to/from the internal storage format
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 09 Nov 2017 13:42:35 +0100 |
parent | 2814:1ffbd73c54ba |
child | 2917:cd5e6534b813 |
comparison
equal
deleted
inserted
replaced
2814:1ffbd73c54ba | 2815:d48d4d9ccae7 |
---|---|
299 end | 299 end |
300 end | 300 end |
301 end | 301 end |
302 | 302 |
303 module:provides("storage", provider); | 303 module:provides("storage", provider); |
304 | |
305 | |
306 function module.command(arg) | |
307 local jid = require "util.jid"; | |
308 if arg[1] == "convert" and (arg[2] == "to" or arg[2] == "from") and arg[4] then | |
309 local convert; | |
310 if arg[2] == "to" then | |
311 local xml = require "util.xml"; | |
312 function convert(user, host, store) | |
313 local dates, err = archive.dates({ host = host, store = store }, user); | |
314 if not dates then assert(not err, err); return end | |
315 assert(dm.list_store(user, host, store, nil)); | |
316 for _, date in ipairs(dates) do | |
317 print(date); | |
318 local items = assert(dm.list_load(user .. "@" .. date, host, store)); | |
319 local xmlfile = assert(io.open(dm.getpath(user .. "@" .. date, host, store, "xml"))); | |
320 for _, item in ipairs(items) do | |
321 assert(xmlfile:seek("set", item.offset)); | |
322 local data = assert(xmlfile:read(item.length)); | |
323 assert(#data == item.length, "short read"); | |
324 data = assert(xml.parse(data)); | |
325 data = st.preserialize(data); | |
326 data.key = item.id; | |
327 data.with = item.with; | |
328 data.when = tonumber(item.when) or dt.parse(item.when); | |
329 data.attr.stamp = item.when; | |
330 data.attr.stamp_legacy = dt.legacy(data.when); | |
331 assert(dm.list_append(user, host, store, data)); | |
332 end | |
333 end | |
334 end | |
335 else -- convert from internal | |
336 function convert(user, host, store) | |
337 local items, err = dm.list_load(user, host, store); | |
338 if not items then assert(not err, err); return end | |
339 local dates = {}; | |
340 local dayitems, date, xmlfile; | |
341 for _, item in ipairs(items) do | |
342 local meta = { | |
343 id = item.key; | |
344 with = item.with; | |
345 when = item.when or dt.parse(item.attr.stamp); | |
346 }; | |
347 local current_date = dt.date(meta.when); | |
348 if current_date ~= date then | |
349 if xmlfile then | |
350 assert(xmlfile:close()); | |
351 end | |
352 if dayitems then | |
353 assert(dm.list_store(user .. "@" .. date, host, store, dayitems)); | |
354 end | |
355 print(current_date); | |
356 dayitems = {}; | |
357 date = current_date; | |
358 table.insert(dates, date); | |
359 xmlfile = assert(io.open(dm.getpath(user .. "@" .. date, host, store, "xml"), "w")); | |
360 end | |
361 item.attr.stamp, item.attr.stamp_legacy = nil, nil; | |
362 local stanza = tostring(st.deserialize(item)) .. "\n"; | |
363 meta.offset, meta.length = xmlfile:seek(), #stanza; | |
364 assert(xmlfile:write(stanza)); | |
365 table.insert(dayitems, meta); | |
366 end | |
367 assert(xmlfile:close()); | |
368 assert(dm.list_store(user .. "@" .. date, host, store, dayitems)); | |
369 assert(dm.list_store(user, host, store, dates)); | |
370 end | |
371 end | |
372 | |
373 local store = arg[4]; | |
374 if arg[3] == "internal" then | |
375 for i = 5, #arg do | |
376 local user, host = jid.prepped_split(arg[i]); | |
377 if not user then | |
378 print(string.format("Argument #%d (%q) is an invalid JID, aborting", i, arg[i])); | |
379 os.exit(1); | |
380 end | |
381 convert(user, host, store); | |
382 end | |
383 print("Done"); | |
384 return 0; | |
385 else | |
386 print("Currently only conversion to/from mod_storage_internal is supported"); | |
387 print("Check out https://modules.prosody.im/mod_migrate"); | |
388 end | |
389 end | |
390 print("prosodyctl mod_storage_xmlarchive convert (from|to) internal (archive|archive2|muc_log) user@host"); | |
391 end | |
392 |