#!/usr/bin/env escript %%! -sname import@localhost % NOTE: If the node name of your server is *not* 'ejabberd@localhost' (see the % "ejabberdctl status" output), you must change the @localhost part of the node % names above and below. -define(NODE, 'ejabberd@localhost'). % Copyright (c) 2016 Holger Weiss . % % This program is free software; you can redistribute it and/or modify it under % the terms of the GNU General Public License as published by the Free Software % Foundation; either version 2 of the License, or (at your option) any later % version. % % This program is distributed in the hope that it will be useful, but WITHOUT % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS % FOR A PARTICULAR PURPOSE. See the GNU General Public License for more % details. % % You should have received a copy of the GNU General Public License along with % this program; if not, write to the Free Software Foundation, Inc., 51 Franklin % Street, Fifth Floor, Boston, MA 02110-1301 USA. -record(archive_msg, {us, id, timestamp, peer, bare_peer, packet, nick, type}). -record(mam_msg, {key, time, route, from, to, stanza}). usage(IoDevice, ExitStatus) -> ok = io:put_chars(IoDevice, "Usage: import-mam-archives [days]"), ok = io:nl(IoDevice), halt(ExitStatus). get_timestamp() -> calendar:datetime_to_gregorian_seconds(calendar:universal_time()). import(MinTS) -> TabDef = [{disc_only_copies, [?NODE]}, {type, bag}, {attributes, record_info(fields, archive_msg)}], rpc:call(?NODE, mnesia, create_table, [archive_msg, TabDef]), ImportMsg = fun(#mam_msg{key = {{U, S}, ID}, time = TS, route = Direction, from = {FromU, FromS, FromR}, to = {ToU, ToS, ToR}, stanza = Msg}, {ok, N}) when MinTS =:= undefined; TS > MinTS -> {PeerU, PeerS, PeerR} = case Direction of incoming -> {FromU, FromS, FromR}; outgoing -> {ToU, ToS, ToR} end, Record = #archive_msg{us = {U, S}, id = integer_to_binary(ID), timestamp = TS, peer = {PeerU, PeerS, PeerR}, bare_peer = {PeerU, PeerS, <<>>}, type = chat, nick = <<>>, packet = Msg}, case N rem 100 of 0 -> io:put_chars("."); _ -> ok end, {mnesia:write(Record), N + 1}; (#mam_msg{}, {ok, N}) -> {ok, N} end, ImportTab = fun() -> mnesia:foldl(ImportMsg, {ok, 0}, mam_msg) end, Start = get_timestamp(), io:put_chars("Please wait "), {ok, N} = rpc:call(?NODE, mnesia, activity, [sync_dirty, ImportTab, [], mnesia_frag]), {atomic, ok} = rpc:call(?NODE, mnesia, delete_table, [mam_msg]), {atomic, ok} = rpc:call(?NODE, mnesia, delete_table, [mam_meta]), End = get_timestamp(), io:fwrite("~nImported ~B messages in ~.1f minutes.~n", [N, (End - Start) / 60]). main(["-h"]) -> usage(standard_io, 0); main([]) -> import(undefined); main([Days]) -> Secs = try D = list_to_integer(Days), true = D > 0, true = D < 10000, D * 86400 catch _:_ -> usage(standard_error, 2) end, {MS, S, US} = os:timestamp(), CurS = MS * 1000000 + S, MinS = CurS - Secs, import({MinS div 1000000, MinS rem 1000000, US}); main(_Junk) -> usage(standard_error, 2).