xmpp ejabberd-用户状态查询

xmpp ejabberd-用户状态查询,xmpp,ejabberd,Xmpp,Ejabberd,如果用户的订阅类型为“两者”,是否有一种方法可以查询XMPP中的用户存在 由于我是为移动平台构建的,所以我使用隐私列表阻止了所有传入的状态节。在我的用例中,一个用户将至少订阅500个用户,处理这些多个状态节将给移动设备带来很大的压力 因此,我不想处理所有的用户节,我只想在查询时获得用户的状态。ejabberd内部目前没有此类功能,但这绝对是可以作为插件开发的。您可以编写一个插件,该插件将使用http Web服务器处理http请求,并在回答用户状态之前进行任何处理和安全检查。为了将来的参考,我已经

如果用户的订阅类型为“两者”,是否有一种方法可以查询XMPP中的用户存在

由于我是为移动平台构建的,所以我使用隐私列表阻止了所有传入的状态节。在我的用例中,一个用户将至少订阅500个用户,处理这些多个状态节将给移动设备带来很大的压力


因此,我不想处理所有的用户节,我只想在查询时获得用户的状态。

ejabberd内部目前没有此类功能,但这绝对是可以作为插件开发的。您可以编写一个插件,该插件将使用http Web服务器处理http请求,并在回答用户状态之前进行任何处理和安全检查。

为了将来的参考,我已经设法收集了一些代码(感谢mod_last.erl)并构建了一个模块,允许您查询用户状态。如有建议和反馈,将不胜感激

-module(mod_query_presence).
-behaviour(gen_mod).

-export([start/2, stop/1,
    process_sm_iq/3
]).

-include("ejabberd.hrl").
-include("jlib.hrl").
-include("logger.hrl").

-include("mod_privacy.hrl").

-define(NS_QUERY_PRESENCE, <<"jabber:iq:qpresence">>).

start(Host, Opts) ->
    IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
                             one_queue),
    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, 
                                  ?NS_QUERY_PRESENCE, ?MODULE, process_sm_iq, IQDisc),
    ?INFO_MSG("Loading module 'mod_iqtest' v.01", []).

stop(Host) ->
    gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_QUERY_PRESENCE),
    ?INFO_MSG("Stoping module 'mod_iqtest' ", []).

process_sm_iq(From, To,
              #iq{type = Type, sub_el = SubEl} = IQ) ->
    case Type of
      set ->
          IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
      get ->
          User = To#jid.luser,
          Server = To#jid.lserver,
          Resource = xml:get_tag_attr_s(list_to_binary("resource"), SubEl), 
          {Subscription, _Groups} =
              ejabberd_hooks:run_fold(roster_get_jid_info, Server,
                                      {none, []}, [User, Server, From]),
          if (Subscription == both) or (Subscription == from) or
               (From#jid.luser == To#jid.luser) and
                 (From#jid.lserver == To#jid.lserver) ->
                 UserListRecord =
                     ejabberd_hooks:run_fold(privacy_get_user_list, Server,
                                             #userlist{}, [User, Server]),
                 case ejabberd_hooks:run_fold(privacy_check_packet,
                                              Server, allow,
                                              [User, Server, UserListRecord,
                                               {To, From,
                                                #xmlel{name = <<"presence">>,
                                                       attrs = [],
                                                       children = []}},
                                               out])
                     of
                   allow -> get_presence(IQ, SubEl, User, Server, Resource);
                   deny ->
                       IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
                 end;
             true ->
                 IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
          end
    end.

get_presence(IQ, SubEl, LUser, LServer, LResource) ->
  case ejabberd_sm:get_session_pid(LUser, LServer, LResource) of
        none ->
            IQ#iq{type = error,
                      sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
        Pid ->
            {_U, _Resource, Status, StatusText} = ejabberd_c2s:get_presence(Pid),
            IQ#iq{type = result,
                    sub_el =
                          [#xmlel{name = <<"query">>,
                              attrs =
                                  [{<<"xmlns">>, ?NS_QUERY_PRESENCE},
                                   {<<"status">>, Status},
                                   {<<"StatusText">>, StatusText}],
                                   children = []}]}
    end.
-模块(模块查询状态)。
-行为(gen_mod)。
-导出([开始/2,停止/1,
过程管理智商/3
]).
-包括(“ejabberd.hrl”)。
-包括(“jlib.hrl”)。
-包括(“logger.hrl”)。
-包括(“mod_privacy.hrl”)。
-定义(NS\u查询\u状态,)。
开始(主机,选项)->
IQDisc=gen_mod:get_opt(IQDisc,Opts,fun gen_iq_处理程序:检查类型/1,
一队),,
gen_iq_处理程序:添加iq_处理程序(ejabberd_sm,主机,
?NS_查询_存在、模块、过程_sm_iq、IQDisc),
?信息信息(“加载模块‘mod_iqtest’v.01’,[])。
停止(主机)->
gen_iq_处理程序:删除_iq_处理程序(ejabberd_sm、主机、NS_查询存在),
?信息消息(“停止模块'mod_iqtest'”,[])。
过程管理智商(从,到,
#智商{type=type,sub_el=SubEl}=iq)->
案例类型
设置->
IQ#IQ{type=error,sub_el=[SubEl,?ERR_NOT_ALLOWED]};
获取->
User=To#jid.luser,
服务器=到#jid.lserver,
Resource=xml:get_tag_attr_s(list_to_binary(“资源”),SubEl),
{订阅,_组}=
ejabberd_hooks:run_fold(名册、信息、服务器、,
{none,[]}[用户,服务器,发件人],
如果(订阅==两者)或(订阅==从)或
(从#jid.luser==到#jid.luser)和
(从#jid.lserver==到#jid.lserver)->
用户列表记录=
ejabberd挂钩:运行折叠(隐私、获取、用户列表、服务器、,
#用户列表{},[用户,服务器],
案例ejabberd_挂钩:运行折叠(隐私检查包),
服务器,允许,
[用户,服务器,用户列表记录,
{到,从,
#xmlel{name=,
属性=[],
children=[]},
外])
属于
允许->获取状态(IQ、SubEl、用户、服务器、资源);
拒绝->
智商#智商{type=error,sub#el=[SubEl,?ERR#u probled]}
结束;
正确->
智商#智商{type=error,sub#el=[SubEl,?ERR#u probled]}
结束
结束。
获取信息(IQ、SubEl、LUser、LServer、LResource)->
案例ejabberd_sm:获取
无->
IQ#IQ{type=错误,
sub_el=[SubEl,?ERR_SERVICE_UNAVAILABLE]};
Pid->
{{U,{U资源,状态,状态文本}=ejabberd_c2s:get_presence(Pid),
IQ#IQ{类型=结果,
sub_el=
[#xmlel{name=,
属性=
[{,NS\u查询\u存在},
{,状态},
{,StatusText}],
子项=[]}]}
结束。
IQ请求格式

<iq id='id' to='56876c654366178e0e75a8cd@192.168.1.150' type='get'>
    <query xmlns='jabber:iq:qpresence' resource='Smack'/>
</iq>

如果用户在线,IQ回复格式

<iq from='56876c654366178e0e75a8cd@192.168.1.150' to='56876c654366178e0e75a8cd@192.168.1.150/Smack' id='last1' type='result'>
    <query xmlns='jabber:iq:qpresence' status='dnd' StatusText='YO'/>
</iq>

如果用户未联机,则会出现“服务不可用”错误