summaryrefslogtreecommitdiffstats
path: root/src/core/ephraim_roster.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ephraim_roster.erl')
-rw-r--r--src/core/ephraim_roster.erl109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/core/ephraim_roster.erl b/src/core/ephraim_roster.erl
new file mode 100644
index 0000000..4f8dfef
--- /dev/null
+++ b/src/core/ephraim_roster.erl
@@ -0,0 +1,109 @@
+-module(ephraim_roster).
+-compile([debug_info, export_all]).
+-include_lib("exmpp/include/exmpp.hrl").
+
+-record(roster, {
+ entries :: dict()
+ }).
+
+-record(roster_entry, {
+ name :: binary() | undefined,
+ subscription :: atom() | undefined,
+ resources :: dict()
+ }).
+
+-record(resource_entry, {
+ priority :: integer(),
+ show :: atom(),
+ status :: string()
+ }).
+
+
+-spec init() -> ok.
+init() ->
+ loop(#roster{entries=dict:new()}).
+
+-spec updateResource(#roster{}, binary(), integer(), atom(), atom(), string()) -> #roster{}.
+updateResource(Roster, JID, Priority, Type, Show, Status) ->
+ {Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
+ BareJID = list_to_binary([Node, <<"@">>, Domain]),
+
+ RosterEntry = case dict:find(BareJID, Roster#roster.entries) of
+ {ok, Entry} ->
+ Entry;
+ error ->
+ #roster_entry{resources=dict:new()}
+ end,
+
+ Resources = case Type of
+ available ->
+ ResourceEntry = #resource_entry{priority=Priority,show=Show,status=Status},
+ dict:store(Resource, ResourceEntry, RosterEntry#roster_entry.resources);
+ _ ->
+ RosterEntry#roster_entry.resources
+ end,
+ Entries = dict:store(BareJID, RosterEntry#roster_entry{resources=Resources}, Roster#roster.entries),
+ if RosterEntry#roster_entry.subscription =:= undefined ->
+ ok;
+ true ->
+ ephraim ! {ui_update, {roster_update, JID, dict:to_list(Resources)}}
+ end,
+ Roster#roster{entries=Entries}.
+
+-spec updateRosterEntry(#roster{}, binary(), binary(), atom()) -> #roster{}.
+updateRosterEntry(Roster, JID, Name, Subscription) ->
+ Resources = case dict:find(JID, Roster#roster.entries) of
+ {ok, Entry} ->
+ Entry#roster_entry.resources;
+ error ->
+ dict:new()
+ end,
+ NewEntry = #roster_entry{subscription=Subscription,name=Name,resources=Resources},
+ Entries = dict:store(JID, NewEntry, Roster#roster.entries),
+ ephraim ! {ui_update, {roster_update, JID, dict:to_list(Resources)}},
+ Roster#roster{entries=Entries}.
+
+-spec handleRosterIQ(#roster{}, #xmlel{}) -> #roster{}.
+handleRosterIQ(Roster, Item) ->
+ JID = exmpp_xml:get_attribute(Item, jid, undefined),
+ Name = exmpp_xml:get_attribute(Item, name, undefined),
+ Subscription = binary_to_atom(exmpp_xml:get_attribute(Item, subscription, undefined), utf8),
+
+ updateRosterEntry(Roster, JID, Name, Subscription).
+
+-spec handleRosterIQs(#roster{}, [#xmlel{}]) -> #roster{}.
+handleRosterIQs(Roster, []) ->
+ Roster;
+
+handleRosterIQs(Roster, [Item = #xmlel{name=item}|Rest]) ->
+ Roster2 = handleRosterIQ(Roster, Item),
+ handleRosterIQs(Roster2, Rest);
+
+handleRosterIQs(Roster, [_|Rest]) ->
+ handleRosterIQs(Roster, Rest).
+
+-spec loop(#roster{}) -> ok.
+loop(Roster) ->
+ receive
+ stop ->
+ ok;
+
+ {presence, Packet} ->
+ From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
+
+ Priority = exmpp_presence:get_priority(Packet),
+ Type = exmpp_presence:get_type(Packet),
+ Show = exmpp_presence:get_show(Packet),
+ Status = exmpp_presence:get_status(Packet),
+
+ Roster2 = updateResource(Roster, From, Priority, Type, Show, Status),
+ loop(Roster2);
+
+ {roster_iq, Payload} ->
+ Roster2 = handleRosterIQs(Roster, Payload#xmlel.children),
+ loop(Roster2);
+
+ Msg ->
+ io:format("ephraim_roster: ~p~n", [Msg]),
+ loop(Roster)
+ end.