aboutsummaryrefslogtreecommitdiff
path: root/libdino/src/service/presence_manager.vala
diff options
context:
space:
mode:
Diffstat (limited to 'libdino/src/service/presence_manager.vala')
-rw-r--r--libdino/src/service/presence_manager.vala150
1 files changed, 150 insertions, 0 deletions
diff --git a/libdino/src/service/presence_manager.vala b/libdino/src/service/presence_manager.vala
new file mode 100644
index 00000000..b89c6570
--- /dev/null
+++ b/libdino/src/service/presence_manager.vala
@@ -0,0 +1,150 @@
+using Gee;
+
+using Xmpp;
+using Dino.Entities;
+
+namespace Dino {
+public class PresenceManager : StreamInteractionModule, Object {
+ public const string id = "presence_manager";
+
+ public signal void show_received(Show show, Jid jid, Account account);
+ public signal void received_subscription_request(Jid jid, Account account);
+
+ private StreamInteractor stream_interactor;
+ private HashMap<Jid, HashMap<Jid, ArrayList<Show>>> shows = new HashMap<Jid, HashMap<Jid, ArrayList<Show>>>(Jid.hash_bare_func, Jid.equals_bare_func);
+ private HashMap<Jid, ArrayList<Jid>> resources = new HashMap<Jid, ArrayList<Jid>>(Jid.hash_bare_func, Jid.equals_bare_func);
+
+ public static void start(StreamInteractor stream_interactor) {
+ PresenceManager m = new PresenceManager(stream_interactor);
+ stream_interactor.add_module(m);
+ }
+
+ private PresenceManager(StreamInteractor stream_interactor) {
+ this.stream_interactor = stream_interactor;
+ stream_interactor.account_added.connect(on_account_added);
+ }
+
+ public Show get_last_show(Jid jid, Account account) {
+ Core.XmppStream? stream = stream_interactor.get_stream(account);
+ if (stream != null) {
+ Xmpp.Presence.Stanza? presence = Xmpp.Presence.Flag.get_flag(stream).get_presence(jid.to_string());
+ if (presence != null) {
+ return new Show(jid, presence.show, new DateTime.now_local());
+ }
+ }
+ return new Show(jid, Show.OFFLINE, new DateTime.now_local());
+ }
+
+ public HashMap<Jid, ArrayList<Show>>? get_shows(Jid jid, Account account) {
+ return shows[jid];
+ }
+
+ public ArrayList<Jid>? get_full_jids(Jid jid, Account account) {
+ Core.XmppStream? stream = stream_interactor.get_stream(account);
+ if (stream != null) {
+ Gee.List<string> resources = Xmpp.Presence.Flag.get_flag(stream).get_resources(jid.bare_jid.to_string());
+ if (resources == null) {
+ return null;
+ }
+ ArrayList<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
+ foreach (string resource in resources) {
+ ret.add(new Jid(resource));
+ }
+ return ret;
+ }
+ return null;
+ }
+
+ public void request_subscription(Account account, Jid jid) {
+ Core.XmppStream stream = stream_interactor.get_stream(account);
+ if (stream != null) Xmpp.Presence.Module.get_module(stream).request_subscription(stream, jid.bare_jid.to_string());
+ }
+
+ public void approve_subscription(Account account, Jid jid) {
+ Core.XmppStream stream = stream_interactor.get_stream(account);
+ if (stream != null) Xmpp.Presence.Module.get_module(stream).approve_subscription(stream, jid.bare_jid.to_string());
+ }
+
+ public void deny_subscription(Account account, Jid jid) {
+ Core.XmppStream stream = stream_interactor.get_stream(account);
+ if (stream != null) Xmpp.Presence.Module.get_module(stream).deny_subscription(stream, jid.bare_jid.to_string());
+ }
+
+ public static PresenceManager? get_instance(StreamInteractor stream_interactor) {
+ return (PresenceManager) stream_interactor.get_module(id);
+ }
+
+ internal string get_id() {
+ return id;
+ }
+
+ private void on_account_added(Account account) {
+ stream_interactor.module_manager.presence_modules[account].received_available_show.connect((stream, jid, show) =>
+ on_received_available_show(account, new Jid(jid), show)
+ );
+ stream_interactor.module_manager.presence_modules[account].received_unavailable.connect((stream, jid) =>
+ on_received_unavailable(account, new Jid(jid))
+ );
+ stream_interactor.module_manager.presence_modules[account].received_subscription_request.connect((stream, jid) =>
+ received_subscription_request(new Jid(jid), account)
+ );
+ }
+
+ private void on_received_available_show(Account account, Jid jid, string show) {
+ lock (resources) {
+ if (!resources.has_key(jid)){
+ resources[jid] = new ArrayList<Jid>(Jid.equals_func);
+ }
+ if (!resources[jid].contains(jid)) {
+ resources[jid].add(jid);
+ }
+ }
+ add_show(account, jid, show);
+ }
+
+ private void on_received_unavailable(Account account, Jid jid) {
+ lock (resources) {
+ if (resources.has_key(jid)) {
+ resources[jid].remove(jid);
+ if (resources[jid].size == 0 || jid.is_bare()) {
+ resources.unset(jid);
+ }
+ }
+ }
+ add_show(account, jid, Show.OFFLINE);
+ }
+
+ private void add_show(Account account, Jid jid, string s) {
+ Show show = new Show(jid, s, new DateTime.now_local());
+ lock (shows) {
+ if (!shows.has_key(jid)) {
+ shows[jid] = new HashMap<Jid, ArrayList<Show>>();
+ }
+ if (!shows[jid].has_key(jid)) {
+ shows[jid][jid] = new ArrayList<Show>();
+ }
+ shows[jid][jid].add(show);
+ }
+ show_received(show, jid, account);
+ }
+}
+
+public class Show : Object {
+ public const string ONLINE = Xmpp.Presence.Stanza.SHOW_ONLINE;
+ public const string AWAY = Xmpp.Presence.Stanza.SHOW_AWAY;
+ public const string CHAT = Xmpp.Presence.Stanza.SHOW_CHAT;
+ public const string DND = Xmpp.Presence.Stanza.SHOW_DND;
+ public const string XA = Xmpp.Presence.Stanza.SHOW_XA;
+ public const string OFFLINE = "offline";
+
+ public Jid jid;
+ public string as;
+ public DateTime datetime;
+
+ public Show(Jid jid, string show, DateTime datetime) {
+ this.jid = jid;
+ this.as = show;
+ this.datetime = datetime;
+ }
+}
+} \ No newline at end of file