Skip to content

Instantly share code, notes, and snippets.

@erszcz
Created June 24, 2015 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erszcz/ca31baea5071dbb80d56 to your computer and use it in GitHub Desktop.
Save erszcz/ca31baea5071dbb80d56 to your computer and use it in GitHub Desktop.
#!/usr/bin/env escript
%% -*- erlang -*-
%% vim: ft=erlang
%% Usage:
%%
%% echo "SELECT message FROM mam_message ORDER BY id DESC LIMIT 4" | \
%% psql -U user -t | ./decode_archived_message
%%
%% Basically any query which returns just mam_message.message column can
%% be fed to this script.
%%
%% Options:
%% -v print some debugging information
main(Args) ->
{V, _Rest} = get_verbosity(Args),
put(verbosity, V),
setup_code_paths(escript:script_name()),
loop(standard_io).
loop(Handle) ->
case file:read_line(Handle) of
{ok, Data} ->
process_line(Data),
loop(Handle);
eof -> ok;
{error, Reason} -> io:format(standard_error, "error: ~p", [Reason])
end.
process_line(Line) ->
case trim(Line) of
<<>> -> ok;
BMessage ->
print_message(decode_binary_message(BMessage))
end.
trim(Text) ->
print(get(verbosity), "trim: '~s'~n", [Text]),
{match, [Trimmed]} = re:run(Text, <<"\\s*(\\S*)\\s*">>,
[{capture, all_but_first, binary}]),
Trimmed.
setup_code_paths(ScriptName) ->
code:add_paths([base_dir(ScriptName)] ++
apps_dirs(ScriptName) ++
deps_dirs(ScriptName)).
get_verbosity(Args) ->
case lists:member("-v", Args) of
true -> {verbose, Args -- ["-v"]};
false -> {silent, Args}
end.
decode_binary_message(BMessage) ->
strip_whitespace_cdata
(binary_to_term(ejabberd_odbc:unescape_binary(hex, BMessage))).
%% Taken from github.com/lavrin/mlp
strip_whitespace_cdata({xmlcdata, CData} = El) ->
case is_whitespace_only(CData) of
true -> skip;
false -> El
end;
strip_whitespace_cdata({xmlel, Name, Args, Children}) ->
{xmlel, Name, Args, [ C || C0 <- Children,
C <- [strip_whitespace_cdata(C0)],
C /= skip ]}.
is_whitespace_only(Data) ->
re:run(Data, <<"\\S">>) == nomatch.
%% End of import from github.com/lavrin/mlp
print_message(Message) ->
print(verbose, "~s", [exml:to_pretty_iolist(Message)]).
base_dir(ScriptName) ->
filename:absname(filename:dirname(ScriptName)).
apps_dirs(ScriptName) ->
sub_dirs(ScriptName, "apps").
deps_dirs(ScriptName) ->
sub_dirs(ScriptName, "deps").
sub_dirs(ScriptName, SubDir) ->
Base = base_dir(ScriptName),
filelib:wildcard(filename:join([Base, "..", SubDir, "*", "ebin"])).
print(verbose, Fmt, Args) -> io:format(Fmt, Args);
print(silent, _Fmt, _Args) -> ok.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment