diff options
Diffstat (limited to 'src/mod_muc_sql.erl')
-rw-r--r-- | src/mod_muc_sql.erl | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl new file mode 100644 index 000000000..55628d43e --- /dev/null +++ b/src/mod_muc_sql.erl @@ -0,0 +1,202 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net> +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> +%%%------------------------------------------------------------------- +-module(mod_muc_sql). + +-behaviour(mod_muc). + +%% API +-export([init/2, store_room/4, restore_room/3, forget_room/3, + can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4, + import/1, import/2, export/1]). + +-include("jlib.hrl"). +-include("mod_muc.hrl"). +-include("logger.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== +init(_Host, _Opts) -> + ok. + +store_room(LServer, Host, Name, Opts) -> + SName = ejabberd_sql:escape(Name), + SHost = ejabberd_sql:escape(Host), + SOpts = ejabberd_sql:encode_term(Opts), + F = fun () -> + sql_queries:update_t(<<"muc_room">>, + [<<"name">>, <<"host">>, <<"opts">>], + [SName, SHost, SOpts], + [<<"name='">>, SName, <<"' and host='">>, + SHost, <<"'">>]) + end, + ejabberd_sql:sql_transaction(LServer, F). + +restore_room(LServer, Host, Name) -> + SName = ejabberd_sql:escape(Name), + SHost = ejabberd_sql:escape(Host), + case catch ejabberd_sql:sql_query(LServer, + [<<"select opts from muc_room where name='">>, + SName, <<"' and host='">>, SHost, + <<"';">>]) of + {selected, [<<"opts">>], [[Opts]]} -> + mod_muc:opts_to_binary(ejabberd_sql:decode_term(Opts)); + _ -> + error + end. + +forget_room(LServer, Host, Name) -> + SName = ejabberd_sql:escape(Name), + SHost = ejabberd_sql:escape(Host), + F = fun () -> + ejabberd_sql:sql_query_t([<<"delete from muc_room where name='">>, + SName, <<"' and host='">>, SHost, + <<"';">>]) + end, + ejabberd_sql:sql_transaction(LServer, F). + +can_use_nick(LServer, Host, JID, Nick) -> + SJID = jid:to_string(jid:tolower(jid:remove_resource(JID))), + SNick = ejabberd_sql:escape(Nick), + SHost = ejabberd_sql:escape(Host), + case catch ejabberd_sql:sql_query(LServer, + [<<"select jid from muc_registered ">>, + <<"where nick='">>, SNick, + <<"' and host='">>, SHost, <<"';">>]) of + {selected, [<<"jid">>], [[SJID1]]} -> SJID == SJID1; + _ -> true + end. + +get_rooms(LServer, Host) -> + SHost = ejabberd_sql:escape(Host), + case catch ejabberd_sql:sql_query(LServer, + [<<"select name, opts from muc_room ">>, + <<"where host='">>, SHost, <<"';">>]) of + {selected, [<<"name">>, <<"opts">>], RoomOpts} -> + lists:map( + fun([Room, Opts]) -> + #muc_room{name_host = {Room, Host}, + opts = mod_muc:opts_to_binary( + ejabberd_sql:decode_term(Opts))} + end, RoomOpts); + Err -> + ?ERROR_MSG("failed to get rooms: ~p", [Err]), + [] + end. + +get_nick(LServer, Host, From) -> + SJID = ejabberd_sql:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))), + SHost = ejabberd_sql:escape(Host), + case catch ejabberd_sql:sql_query(LServer, + [<<"select nick from muc_registered where " + "jid='">>, + SJID, <<"' and host='">>, SHost, + <<"';">>]) of + {selected, [<<"nick">>], [[Nick]]} -> Nick; + _ -> error + end. + +set_nick(LServer, Host, From, Nick) -> + JID = jid:to_string(jid:tolower(jid:remove_resource(From))), + SJID = ejabberd_sql:escape(JID), + SNick = ejabberd_sql:escape(Nick), + SHost = ejabberd_sql:escape(Host), + F = fun () -> + case Nick of + <<"">> -> + ejabberd_sql:sql_query_t( + [<<"delete from muc_registered where ">>, + <<"jid='">>, SJID, + <<"' and host='">>, Host, + <<"';">>]), + ok; + _ -> + Allow = case ejabberd_sql:sql_query_t( + [<<"select jid from muc_registered ">>, + <<"where nick='">>, + SNick, + <<"' and host='">>, + SHost, <<"';">>]) of + {selected, [<<"jid">>], [[J]]} -> J == JID; + _ -> true + end, + if Allow -> + sql_queries:update_t(<<"muc_registered">>, + [<<"jid">>, <<"host">>, + <<"nick">>], + [SJID, SHost, SNick], + [<<"jid='">>, SJID, + <<"' and host='">>, SHost, + <<"'">>]), + ok; + true -> + false + end + end + end, + ejabberd_sql:sql_transaction(LServer, F). + +export(_Server) -> + [{muc_room, + fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) -> + case str:suffix(Host, RoomHost) of + true -> + SName = ejabberd_sql:escape(Name), + SRoomHost = ejabberd_sql:escape(RoomHost), + SOpts = ejabberd_sql:encode_term(Opts), + [[<<"delete from muc_room where name='">>, SName, + <<"' and host='">>, SRoomHost, <<"';">>], + [<<"insert into muc_room(name, host, opts) ", + "values (">>, + <<"'">>, SName, <<"', '">>, SRoomHost, + <<"', '">>, SOpts, <<"');">>]]; + false -> + [] + end + end}, + {muc_registered, + fun(Host, #muc_registered{us_host = {{U, S}, RoomHost}, + nick = Nick}) -> + case str:suffix(Host, RoomHost) of + true -> + SJID = ejabberd_sql:escape( + jid:to_string( + jid:make(U, S, <<"">>))), + SNick = ejabberd_sql:escape(Nick), + SRoomHost = ejabberd_sql:escape(RoomHost), + [[<<"delete from muc_registered where jid='">>, + SJID, <<"' and host='">>, SRoomHost, <<"';">>], + [<<"insert into muc_registered(jid, host, " + "nick) values ('">>, + SJID, <<"', '">>, SRoomHost, <<"', '">>, SNick, + <<"');">>]]; + false -> + [] + end + end}]. + +import(_LServer) -> + [{<<"select name, host, opts from muc_room;">>, + fun([Name, RoomHost, SOpts]) -> + Opts = mod_muc:opts_to_binary(ejabberd_sql:decode_term(SOpts)), + #muc_room{name_host = {Name, RoomHost}, opts = Opts} + end}, + {<<"select jid, host, nick from muc_registered;">>, + fun([J, RoomHost, Nick]) -> + #jid{user = U, server = S} = jid:from_string(J), + #muc_registered{us_host = {{U, S}, RoomHost}, + nick = Nick} + end}]. + +import(_, _) -> + pass. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== |