我正在尝试创建自定义mod_shared_roster,因此它会以JSON格式将所有需要的vcard数据发送到XS字段中的客户端。我从原始的mod_shared_roster.erl github mod_shared_roster.erl重写了方法get_user_roster:
get_user_roster(Items, US) ->
{U, S} = US,
DisplayedGroups = get_user_displayed_groups(US),
SRUsers = lists:foldl(fun (Group, Acc1) ->
GroupName = get_group_name(S, Group),
lists:foldl(fun (User, Acc2) ->
if User == US -> Acc2;
true ->
dict:append(User,
GroupName,
Acc2)
end
end,
Acc1, get_group_users(S, Group))
end,
dict:new(), DisplayedGroups),
{NewItems1, SRUsersRest} = lists:mapfoldl(fun (Item,
SRUsers1) ->
{_, _, {U1, S1, _}} =
Item#roster.usj,
US1 = {U1, S1},
case dict:find(US1,
SRUsers1)
of
{ok, _GroupNames} ->
{Item#roster{subscription
=
both,
ask =
none},
dict:erase(US1,
SRUsers1)};
error ->
{Item, SRUsers1}
end
end,
SRUsers, Items),
SRItems = [#roster{usj = {U, S, {U1, S1, <<"">>}},
us = US, jid = {U1, S1, <<"">>},
name = get_rosteritem_name(U1, S1),
subscription = both, ask = none, groups = GroupNames, xs = binary_to_list(get_rosteritem_data(U1, S1))}
|| {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)],
SRItems ++ NewItems1.
get_rosteritem_data(U, S) ->
case gen_mod:is_loaded(S, mod_vcard) of
true ->
SubEls = mod_vcard:get_vcard(U, S),
get_rosteritem_data_vcard(SubEls);
false ->
<<"">>
end.
get_rosteritem_data_vcard(Vcard) ->
Res = "{\"name\":\"",
Res2 = Res ++ binary_to_list(get_rosteritem_name_vcard(Vcard)),
Res3 = Res2 ++ "\",",
Res4 = Res3 ++ "\"nickname\":\"",
Res5 = Res4 ++ binary_to_list(get_rosteritem_nickname_vcard(Vcard)),
Res6 = Res5 ++ "\",",
Res7 = Res6 ++ "\"car_number\":\"",
Res8 = Res7 ++ binary_to_list(get_rosteritem_car_number_vcard(Vcard)),
Res9 = Res8 ++ "\",",
Res10 = Res9 ++ "\"lat\":\"",
Res11 = Res10 ++ binary_to_list(get_rosteritem_lat_vcard(Vcard)),
Res12 = Res11 ++ "\",",
Res13 = Res12 ++ "\"lon\":\"",
Res14 = Res13 ++ binary_to_list(get_rosteritem_lon_vcard(Vcard)),
Res15 = Res14 ++ "\"}",
JSON = list_to_binary(Res15),
?INFO_MSG("Roster json: ~p", [JSON]),
JSON.
get_rosteritem_name(U, S) ->
case gen_mod:is_loaded(S, mod_vcard) of
true ->
SubEls = mod_vcard:get_vcard(U, S),
get_rosteritem_name_vcard(SubEls);
false ->
<<"">>
end.
get_rosteritem_name_vcard([Vcard|_]) ->
case fxml:get_path_s(Vcard,
[{elem, <<"NAME">>}, cdata])
of
<<"">> -> <<"">>;
%Nick = fxml:get_path_s(Vcard, [{elem, <<"FN">>}, cdata]),
%?INFO_MSG("Roster nick: ~p", [Nick]),
% Nick;
Nickname -> Nickname,
?INFO_MSG("Roster NAME: ~p", [Nickname]),
Nickname
end;
get_rosteritem_name_vcard(_) ->
<<"">>.
get_rosteritem_nickname_vcard([Vcard|_]) ->
case fxml:get_path_s(Vcard,
[{elem, <<"NICKNAME">>}, cdata])
of
<<"">> -> <<"">>;
%Nick = fxml:get_path_s(Vcard, [{elem, <<"FN">>}, cdata]),
%?INFO_MSG("Roster nick: ~p", [Nick]),
%Nick;
Nickname -> Nickname,
?INFO_MSG("Roster Nickname: ~p", [Nickname]),
Nickname
end;
get_rosteritem_nickname_vcard(_) ->
<<"">>.
get_rosteritem_car_number_vcard([Vcard|_]) ->
case fxml:get_path_s(Vcard,
[{elem, <<"CAR_NUMBER">>}, cdata])
of
<<"">> -> <<"">>;
Nickname -> Nickname,
?INFO_MSG("Roster CAR_NUMBER: ~p", [Nickname]),
Nickname
end;
get_rosteritem_car_number_vcard(_) ->
<<"">>.
get_rosteritem_lat_vcard([Vcard|_]) ->
case fxml:get_path_s(Vcard,
[{elem, <<"LAT">>}, cdata])
of
<<"">> -> <<"">>;
Nickname -> Nickname,
?INFO_MSG("Roster LAT: ~p", [Nickname]),
Nickname
end;
get_rosteritem_lat_vcard(_) ->
<<"">>.
get_rosteritem_lon_vcard([Vcard|_]) ->
case fxml:get_path_s(Vcard,
[{elem, <<"LON">>}, cdata])
of
<<"">> -> <<"">>;
Nickname -> Nickname,
?INFO_MSG("Roster LON: ~p", [Nickname]),
Nickname
end;
get_rosteritem_lon_vcard(_) ->
<<"">>.
生成的JSON是正确的:
Roster json: <<"{\"name\":\"\",\"nickname\":\"\",\"car_number\":\"\",\"lat\":\"\....>>
但我总是在mod_roster.erl中的encode_item方法中遇到错误(顺序可能不同):
failed to process roster get for ubuntu1@95.46.99.57: {error,{{badrecord,roster},[{mod_roster,encode_item,1,[{file,"src/mod_roster.erl"},{line,345}]},{lists,map,2,[{file,"lists.erl"},{line,1238}]},{mod_roster,process_iq_get,1,[{file,"src/mod_roster.erl"},{line,292}]}
很难理解但是在localhost上一切正常,但是当我在真实服务器上加载beam文件时,我会收到错误。 有人能帮助我吗?