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
parents 1ffbd73c54ba
children 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