繁体   English   中英

未调用 Ejabberd 中的自定义模块

[英]Custom module in Ejabberd is not called

原来的

几天来,我一直在尝试将适用于以前版本的开源 Ejabberd 模块 (mod_offline_http_post) 适应当前版本 (20.04)。 例如,某些部分现在对于导出很重要,例如 mod_options 和 mod_depends。 它们不是模块源代码的一部分。 我添加了它们。 我仍然有一个错误。

.ejabberd-modules/sources/mod_offline_http_post/src/mod_offline_http_post.erl

 %% name of module must match file name %% Update: info@ph-f.nl -module(mod_offline_http_post). -author("dev@codepond.org"). -behaviour(gen_mod). -export([start/2, stop/1, depends/2, mod_options/1, create_message/1, create_message/3]). %% Required by?INFO_MSG macros -include("logger.hrl"). -include("scram.hrl"). -include("xmpp.hrl"). start(_Host, _Opt) ->?INFO_MSG("mod_offline_http_post loading", []), inets:start(), ?INFO_MSG("HTTP client started", []), ejabberd_hooks:add(offline_message_hook, _Host, ?MODULE, create_message, 1). stop (_Host) ->?INFO_MSG("stopping mod_offline_http_post", []), ejabberd_hooks:delete(offline_message_hook, _Host, ?MODULE, create_message, 1). depends(_Host, _Opts) -> []. mod_options(_Host) -> []. create_message({Action, Packet} = Acc) when (Packet#message.type == chat) and (Packet#message.body /= []) -> [{text, _, Body}] = Packet#message.body, post_offline_message(Packet#message.from, Packet#message.to, Body, Packet#message.id), Acc; create_message(Acc) -> Acc. create_message(_From, _To, Packet) when (Packet#message.type == chat) and (Packet#message.body /= []) -> Body = fxml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]), MessageId = fxml:get_tag_attr_s(list_to_binary("id"), Packet), post_offline_message(_From, _To, Body, MessageId), ok. post_offline_message(From, To, Body, MessageId) ->?INFO_MSG("Posting From ~p To ~p Body ~p ID ~p~n",[From, To, Body, MessageId]), Token = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), PostUrl = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), ToUser = To#jid.luser, FromUser = From#jid.luser, Vhost = To#jid.lserver, case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, confidential, false) of true -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&messageId=", binary_to_list(MessageId)], ""); false -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&body=", binary_to_list(Body), "&messageId=", binary_to_list(MessageId)], "") end, Request = {binary_to_list(PostUrl), [{"Authorization", binary_to_list(Token)}], "application/x-www-form-urlencoded", Data}, httpc:request(post, Request,[],[]), ?INFO_MSG("post request sent", []).

.ejabberd-modules/sources/mod_offline_http_post/conf/mod_offline_http_post.yml

 modules: mod_offline_http_post: auth_token: "secret" post_url: "http://SERVER_IP_ADDRESS/end_of_url" confidential: false ### Local Variables: ### mode: yaml ### End: ### vim: set filetype=yaml tabstop=8

如果需要,我可以提供更多详细信息。

在此先感谢您的帮助。

编辑 1

现在看来它正在工作......当向离线用户发送消息并且现在可以识别选项时,会有一个日志。 一旦没有更多问题,我将发布我为使其工作所做的工作,作为答案。 这,对于其他人。

剩下的问题是我怀疑该模块是否被调用。 我谈到的日志不是来自模块,而可能来自 Ejabberd 路由器。 我谈论它是因为过去没有这样的事情。 那么,有一些积极的事情正在发生。 为了使事情更加确定,当我卸载模块时它显示“Bad module”。

这是新的erl代码:

 %% name of module must match file name %% Update: info@ph-f.nl -module(mod_offline_http_post). -author("dev@codepond.org"). -behaviour(gen_mod). -export([start/2, stop/1, depends/2, mod_options/1, mod_opt_type/1, create_message/1, create_message/3]). %% Required by?INFO_MSG macros -include("logger.hrl"). -include("scram.hrl"). -include("xmpp.hrl"). start(_Host, _Opt) ->?INFO_MSG("mod_offline_http_post loading", []), inets:start(), ?INFO_MSG("HTTP client started", []), ejabberd_hooks:add(offline_message_hook, _Host, ?MODULE, create_message, 1). stop (_Host) ->?INFO_MSG("stopping mod_offline_http_post", []), ejabberd_hooks:delete(offline_message_hook, _Host, ?MODULE, create_message, 1). depends(_Host, _Opts) -> []. mod_options(_Host) -> [{auth_token, <<"secret">>}, {post_url, <<"http://example.com/test">>}, {confidential, false}]. mod_opt_type(auth_token) -> fun iolist_to_binary/1; mod_opt_type(post_url) -> fun iolist_to_binary/1; mod_opt_type(confidential) -> fun (B) when is_boolean(B) -> B end. create_message({Action, Packet} = Acc) when (Packet#message.type == chat) and (Packet#message.body /= []) -> [{text, _, Body}] = Packet#message.body, post_offline_message(Packet#message.from, Packet#message.to, Body, Packet#message.id), Acc; create_message(Acc) -> Acc. create_message(_From, _To, Packet) when (Packet#message.type == chat) and (Packet#message.body /= []) -> Body = fxml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]), MessageId = fxml:get_tag_attr_s(list_to_binary("id"), Packet), post_offline_message(_From, _To, Body, MessageId), ok. post_offline_message(From, To, Body, MessageId) ->?DEBUG("Posting From ~p To ~p Body ~p ID ~p~n",[From, To, Body, MessageId]), Token = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), PostUrl = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), ToUser = To#jid.luser, FromUser = From#jid.luser, Vhost = To#jid.lserver, case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, confidential, false) of true -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&messageId=", binary_to_list(MessageId)], ""); false -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&body=", binary_to_list(Body), "&messageId=", binary_to_list(MessageId)], "") end, Request = {binary_to_list(PostUrl), [{"Authorization", binary_to_list(Token)}], "application/x-www-form-urlencoded", Data}, httpc:request(post, Request,[],[]), ?DEBUG("post request sent", []).

编辑 2

这是一个非常有前途的案例。 该模块被调用。 只是它崩溃了,这是另一个非常有趣的案例。 这是错误日志:

 2020-05-21 11:53:35.897 [error] <0.508.0>@ejabberd_hooks:safe_apply:240 Hook offline_message_hook crashed when running mod_offline_http_post:create_message/1: ** exception error: undefined function gen_mod:get_module_opt/5 in function mod_offline_http_post:post_offline_message/4 (/opt/ejabberd/.ejabberd-modules/sources/mod_offline_http_post/src/mod_offline_http_post.erl, line 63) in call from mod_offline_http_post:create_message/1 (/opt/ejabberd/.ejabberd-modules/sources/mod_offline_http_post/src/mod_offline_http_post.erl, line 49) in call from ejabberd_hooks:safe_apply/4 (src/ejabberd_hooks.erl, line 236) in call from ejabberd_hooks:run_fold1/4 (src/ejabberd_hooks.erl, line 217) in call from ejabberd_sm:route/1 (src/ejabberd_sm.erl, line 146) in call from ejabberd_router:do_route/1 (src/ejabberd_router.erl, line 399) in call from ejabberd_router:route/1 (src/ejabberd_router.erl, line 92)

有用 !!

惊人。 它现在正在工作。 通知会发送给离线用户。 好吧,我的意思是,给离线用户的消息被转发到后端,后端又向用户发送 FCM 通知。

由于我在这上面花了 3 天时间并且几乎没有关于当前版本 20.04 的有关此问题的信息,我将 go 详细介绍遇到该问题的人的解决方案。

首先,除了 start/2 和 stop/1,如果您的自定义模块支持选项,则导出这 3 个函数:depends/2(可能是指示依赖关系的 function,即,如果我没记错的话,您在那里列出所需的模块), mod_opt_type/1(应验证每个选项)和 mod_options/2(列出选项及其默认值的位置)。

其次,互联网上的许多自定义模块是为不需要这些的以前版本制作的。 然后,如果他们使用 gen_mod:get_module_opt,他们会添加验证和默认值。 你最终会得到 gen_mod:get_module_opt/4 或 gen_mod:get_module_opt/5。 现在,由于您已经获得了 mod_options/2 和 mod_opt_type/1 中每个选项的验证和默认值,所以 mod:get_module_opt 变为 mod:get_module_opt/3。 您应该只保留前 3 个参数。

如果您像我的情况一样通过 RPM package 安装 Ejabberd,您可能会在未启用 LAGER 的情况下编译服务器。 好吧,或者像这样的解释,至少对于自定义模块。 我的意思是,您会看到 package 中嵌入的模块的日志,但您的自定义模块中看不到您的日志。 要启用 LAGER 或您的信息(如果我没有使用正确的术语,请更正这些陈述),请在导出后立即执行此操作:

 -ifndef(LAGER). -define(LAGER, 1). -endif.

尽管这段代码似乎只与调试过程有关,但当我在代码中没有自定义模块时,根本没有调用它。 有趣的奇怪。

我看到有些人对该模块“mod_offline_http_post”有问题,出现错误,例如找不到 ebin 目录。 问题是,一旦您在 .ejabberd-modules/sources 目录中创建了 git 克隆,该模块将在那里,但 Ejabberd 可能缺乏对此的权限。 之后执行此操作: chown -R ejabberd:ejabberd your_path_to_.ejabberd-modules/sources 之后,点击 ejabberdctl install mod_offline_http_post。 如果您看到类似 ArgumentX 未使用的警告,请忽略它。 这只是它所说的意思。 为防止显示此内容,只需在 erl 文件中未使用的 arg 前加一个下划线,即 _ArgumentX。

其他一些人甚至没有 .ejabberd-modules 目录。 只需安装一个像 mod_cron 这样的随机贡献模块,就会创建这个目录。 Go where ejabberdctl is, mine is in /opt/ejabberd-20.04/bin and hit: ejabberdctl module_install mod_cron Once done, don't remove it but go to /opt/ejabberd/.ejabberd-modules/sources and git clone the custom module那里。 之后,通过执行 ejabberdctl module_uninstall mod_cron 卸载 mod_cron。

您的 directory.ejabberd-modules 可能在其他地方。 在这些命令之后,您不需要重新启动 Ejabberd。 事实上,module_install 编译、安装和启动模块。

好吧,由于您需要将模块放在 ejabberd.yml 中,因此您必须重新启动 ejabberd 但是一旦完成,如果某些事情不起作用并且您最终卸载了自定义模块,一旦重新安装,您就不需要重新启动 Ejabberd .

我将发布适用于 Ejabberd 19.02 的原始代码和适用于 20.04 的编辑代码

对于 19.02

 %% name of module must match file name %% Update: info@ph-f.nl -module(mod_offline_http_post). -author("dev@codepond.org"). -behaviour(gen_mod). -export([start/2, stop/1, create_message/1, create_message/3]). -include("scram.hrl"). -include("xmpp.hrl"). -include("logger.hrl"). start(_Host, _Opt) ->?INFO_MSG("mod_offline_http_post loading", []), inets:start(), ?INFO_MSG("HTTP client started", []), ejabberd_hooks:add(offline_message_hook, _Host, ?MODULE, create_message, 1). stop (_Host) ->?INFO_MSG("stopping mod_offline_http_post", []), ejabberd_hooks:delete(offline_message_hook, _Host, ?MODULE, create_message, 1). create_message({Action, Packet} = Acc) when (Packet#message.type == chat) and (Packet#message.body /= []) -> [{text, _, Body}] = Packet#message.body, post_offline_message(Packet#message.from, Packet#message.to, Body, Packet#message.id), Acc; create_message(Acc) -> Acc. create_message(_From, _To, Packet) when (Packet#message.type == chat) and (Packet#message.body /= []) -> Body = fxml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]), MessageId = fxml:get_tag_attr_s(list_to_binary("id"), Packet), post_offline_message(_From, _To, Body, MessageId), ok. post_offline_message(From, To, Body, MessageId) ->?INFO_MSG("Posting From ~p To ~p Body ~p ID ~p~n",[From, To, Body, MessageId]), Token = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), PostUrl = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), ToUser = To#jid.luser, FromUser = From#jid.luser, Vhost = To#jid.lserver, case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, confidential, false) of true -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&messageId=", binary_to_list(MessageId)], ""); false -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&body=", binary_to_list(Body), "&messageId=", binary_to_list(MessageId)], "") end, Request = {binary_to_list(PostUrl), [{"Authorization", binary_to_list(Token)}], "application/x-www-form-urlencoded", Data}, httpc:request(post, Request,[],[]), ?INFO_MSG("post request sent", []).

对于 20.04

 %% name of module must match file name %% Update: pape.diack@live.fr -module(mod_offline_http_post). -author("dev@codepond.org"). -behaviour(gen_mod). -export([start/2, stop/1, depends/2, mod_options/1, mod_opt_type/1, create_message/1, create_message/3]). -ifndef(LAGER). -define(LAGER, 1). -endif. -include("logger.hrl"). -include("xmpp.hrl"). start(_Host, _Opt) ->?INFO_MSG("mod_offline_http_post loading", []), inets:start(), ?INFO_MSG("HTTP client started", []), ejabberd_hooks:add(offline_message_hook, _Host, ?MODULE, create_message, 50). stop (_Host) ->?INFO_MSG("stopping mod_offline_http_post", []), ejabberd_hooks:delete(offline_message_hook, _Host, ?MODULE, create_message, 50). depends(_Host, _Opts) -> []. mod_options(_Host) -> [{auth_token, <<"secret">>}, {post_url, <<"http://example.com/test">>}, {confidential, false}]. mod_opt_type(auth_token) -> fun iolist_to_binary/1; mod_opt_type(post_url) -> fun iolist_to_binary/1; mod_opt_type(confidential) -> fun (B) when is_boolean(B) -> B end. create_message({Action, Packet} = Acc) when (Packet#message.type == chat) and (Packet#message.body /= []) -> [{text, _, Body}] = Packet#message.body, post_offline_message(Packet#message.from, Packet#message.to, Body, Packet#message.id), Acc; create_message(Acc) -> Acc. create_message(_From, _To, Packet) when (Packet#message.type == chat) and (Packet#message.body /= []) -> Body = fxml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]), MessageId = fxml:get_tag_attr_s(list_to_binary("id"), Packet), post_offline_message(_From, _To, Body, MessageId), ok. post_offline_message(From, To, Body, MessageId) ->?INFO_MSG("Posting From ~p To ~p Body ~p ID ~p~n",[From, To, Body, MessageId]), Token = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, auth_token), PostUrl = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, post_url), ToUser = To#jid.luser, FromUser = From#jid.luser, Vhost = To#jid.lserver, case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, confidential) of true -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&messageId=", binary_to_list(MessageId)], ""); false -> Data = string:join(["to=", binary_to_list(ToUser), "&from=", binary_to_list(FromUser), "&vhost=", binary_to_list(Vhost), "&body=", binary_to_list(Body), "&messageId=", binary_to_list(MessageId)], "") end, Request = {binary_to_list(PostUrl), [{"Authorization", binary_to_list(Token)}, {"Logged-Out", "logged-out"}], "application/x-www-form-urlencoded", Data}, httpc:request(post, Request,[],[]), ?INFO_MSG("post request sent", []).

过上更轻松的生活。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM