如何在 Ejabberd 的自定义模块中加载模块?

How to load a module inside a custom module in Ejabberd?

我正在创建一个自定义模块,它使用 mod_shared_roster 模块中的一些导出函数。这是代码。


-module(mod_shared_roster_extra).
-author('https://github.com/eric-mendoza').

-behaviour(gen_mod).

-include("logger.hrl").
-include("translate.hrl").

-export([start/2, stop/1, reload/3, mod_options/1,
  get_commands_spec/0, depends/2, mod_doc/0]).



% Commands API
-export([
  % Shared roster
  srg_display_group_add/4, srg_display_group_del/4, srg_set_opts/4
]).


-include("ejabberd_commands.hrl").
-include("mod_roster.hrl").
-include("mod_privacy.hrl").
-include("ejabberd_sm.hrl").
-include_lib("xmpp/include/xmpp.hrl").
-include("mod_shared_roster.hrl").


%%%
%%% gen_mod
%%%

start(_Host, _Opts) ->
  ejabberd_commands:register_commands(get_commands_spec()).

stop(Host) ->
  case gen_mod:is_loaded_elsewhere(Host, ?MODULE) of
    false ->
      ejabberd_commands:unregister_commands(get_commands_spec());
    true ->
      ok
  end.

reload(_Host, _NewOpts, _OldOpts) ->
  ok.

depends(_Host, _Opts) ->
  [{mod_shared_roster, hard}].


%%%
%%% Register commands
%%%

get_commands_spec() ->
  [
    #ejabberd_commands{name = srg_display_group_add, tags = [shared_roster_group],
      desc = "Add group id to the Shared Roster Group display list",
      module = ?MODULE, function = srg_display_group_add,
      args = [{displaygroup, binary}, {displaygrouphost, binary}, {group, binary}, {grouphost, binary}],
      args_example = [<<"group1">>, <<"myserver.com">>, <<"group3">>, <<"myserver.com">>],
      args_desc = ["Group to be added in display list", "Group server name", "Group to modify display list identifier", "Group server name"],
      result = {res, rescode}},
    #ejabberd_commands{name = srg_display_group_del, tags = [shared_roster_group],
      desc = "Delete group id from the Shared Roster Group",
      module = ?MODULE, function = srg_display_group_del,
      args = [{displaygroup, binary}, {displaygrouphost, binary}, {group, binary}, {grouphost, binary}],
      args_example = [<<"group1">>, <<"myserver.com">>, <<"group3">>, <<"myserver.com">>],
      args_desc = ["Group to be removed from display list", "Group server name", "Group to modify display list identifier", "Group server name"],
      result = {res, rescode}},
    #ejabberd_commands{name = srg_set_opts, tags = [shared_roster_group],
      desc = "Update Shared Roster Group options (name and description)",
      module = ?MODULE, function = srg_set_opts,
      args = [{name, binary}, {description, binary}, {group, binary}, {grouphost, binary}],
      args_example = [<<"Group Test Name">>, <<"Group used for testing.">>, <<"group3">>, <<"myserver.com">>],
      args_desc = ["Shared roster group name", "Shared Roster Group description", "Group identifier", "Group server name"],
      result = {res, rescode}}
  ].

%%%
%%% Shared Roster Groups
%%%

to_list([]) -> [];
to_list([H|T]) -> [to_list(H)|to_list(T)];
to_list(E) when is_atom(E) -> atom_to_list(E);
to_list(E) -> binary_to_list(E).

srg_display_group_add(NewGroup, NewGroupHost, Group, GroupHost) ->
  ?DEBUG("Adding group to display list.", []),

  Opts = mod_shared_roster:get_group_opts(Group, GroupHost),
  mod_shared_roster:set_group_opts(GroupHost, Group, Opts),
  ok.

srg_display_group_del(DeleteGroup, DeleteGroupHost, Group, GroupHost) ->
  ?DEBUG("Removing group from display list.", []),
  Opts = mod_shared_roster:get_group_opts(Group, GroupHost),
%%  mod_shared_roster:set_group_opts(GroupHost, Group, Opts),
  ok.

srg_set_opts(Label1, Description1, Group, GroupHost) ->
  ?DEBUG("Setting group options -> Label: ~p, Description: ~p~n", [Label1, Description1]),
  Opts = mod_shared_roster:get_group_opts(Group, GroupHost),
  Label = if Label1 == <<"">> -> [];
              true -> [{label, Label1}]
          end,
  Description = if Description1 == <<"">> -> [];
                  true -> [{description, Description1}]
                end,
  Displayed1 = get_opt(Opts, displayed_groups, []),
  Displayed = if Displayed1 == [] -> [];
                  true -> [{displayed_groups, Displayed1}]
              end,
  ?DEBUG("Options: ~p~n", [Label ++ Description ++ Displayed]),
  mod_shared_roster:set_group_opts(GroupHost, Group, Label ++ Description ++ Displayed),
  ok.

mod_options(_) -> [].

get_opt(Opts, Opt, Default) ->
  case lists:keysearch(Opt, 1, Opts) of
    {value, {_, Val}} -> Val;
    false -> Default
  end.

mod_doc() ->
  #{desc =>
  ?T("This module provides additional administrative commands for shared rosters.")}.

模块安装正确,但是当我调用使用 mod_shared_roster:get_group_opts 的方法 srg_set_opts 时,出现以下错误:

error: {module_not_loaded, mod_shared_roster, <<"srg_group10">>}

我看过其他模块作为指南,我注意到的唯一区别是那些模块依赖项包含在同一目录中。但是,我怎么能用自定义模块实现呢?我对 Erlang 没有经验,所以它可能只是一个简单的导入。


我正在使用通过 docker-ejabberd, and used Ejabberd module docs for Docker 安装的 ejabberd 20.04 来安装模块。

Opts = mod_shared_roster:get_group_opts(Group, GroupHost),

我认为该函数的参数是 Host,然后是 Group,但您以相反的顺序提供它们。