xmpp ejabberd - 查询用户存在

Posted

技术标签:

【中文标题】xmpp ejabberd - 查询用户存在【英文标题】:xmpp ejabberd - query for user presence 【发布时间】:2016-01-29 04:13:46 【问题描述】:

如果用户的订阅类型是“两者”,有没有办法在 XMPP 中查询用户存在?

自从我为移动平台构建以来,我已经使用隐私列表阻止了所有传入的存在节。在我的用例中,一个用户至少会订阅 500 个用户,处理这么多的出席信息节会给移动设备带来很大的压力。

因此,我不想处理所有用户节,而是希望仅在查询用户时才获得用户的存在。

【问题讨论】:

【参考方案1】:

目前 ejabberd 内部没有这样的功能,但这绝对是您可以开发为插件的东西。您可以编写一个插件,该插件将使用 HTTP 网络服务器处理 http 请求,并在响应用户存在之前执行您想要的任何处理和安全检查。

【讨论】:

【参考方案2】:

为了将来的参考,我已经设法收集了一些代码(感谢 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,
              #iqtype = Type, sub_el = SubEl = IQ) ->
    case Type of
      set ->
          IQ#iqtype = 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,
                                                #xmlelname = <<"presence">>,
                                                       attrs = [],
                                                       children = [],
                                               out])
                     of
                   allow -> get_presence(IQ, SubEl, User, Server, Resource);
                   deny ->
                       IQ#iqtype = error, sub_el = [SubEl, ?ERR_FORBIDDEN]
                 end;
             true ->
                 IQ#iqtype = 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#iqtype = error,
                      sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE];
        Pid ->
            _U, _Resource, Status, StatusText = ejabberd_c2s:get_presence(Pid),
            IQ#iqtype = result,
                    sub_el =
                          [#xmlelname = <<"query">>,
                              attrs =
                                  [<<"xmlns">>, ?NS_QUERY_PRESENCE,
                                   <<"status">>, Status,
                                   <<"StatusText">>, StatusText],
                                   children = []]
    end.

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>

如果用户不在线,你会得到一个服务不可用的错误。

【讨论】:

以上是关于xmpp ejabberd - 查询用户存在的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中配置 Xmpp 库?

Ejabberd,Python:检查用户,如果没有创建

如何使用 XMPPHP 客户端创建 XMPP(ejabberd) 用户

如何在 ejabberd/XMPP 中获取所有在线用户的列表?

无法将用户从 iOS 客户端注册到 Ejabberd 服务器 - XMPP

操作无法完成。 (kCFStreamErrorDomainSSL 错误 -9847。)使用 xmpp 聊天在 ejabberd 中注册新用户时