aboutsummaryrefslogtreecommitdiff
path: root/libdino/src/service/roster_manager.vala
blob: 5181b90ed1038d4118139016c0fc87f5b5201465 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using Gee;

using Xmpp;
using Dino.Entities;

namespace Dino {

public class RosterManager : StreamInteractionModule, Object {
    public static ModuleIdentity<RosterManager> IDENTITY = new ModuleIdentity<RosterManager>("roster_manager");
    public string id { get { return IDENTITY.id; } }

    public signal void removed_roster_item(Account account, Jid jid, Roster.Item roster_item);
    public signal void updated_roster_item(Account account, Jid jid, Roster.Item roster_item);
    public signal void mutual_subscription(Account account, Jid jid);

    private StreamInteractor stream_interactor;
    private Database db;
    private Gee.Map<Account, RosterStoreImpl> roster_stores = new HashMap<Account, RosterStoreImpl>(Account.hash_func, Account.equals_func);

    public static void start(StreamInteractor stream_interactor, Database db) {
        RosterManager m = new RosterManager(stream_interactor, db);
        stream_interactor.add_module(m);
    }

    public RosterManager(StreamInteractor stream_interactor, Database db) {
        this.stream_interactor = stream_interactor;
        this.db = db;
        stream_interactor.account_added.connect(on_account_added);
        stream_interactor.module_manager.initialize_account_modules.connect((account, modules) => {
            if (!roster_stores.has_key(account)) roster_stores[account] = new RosterStoreImpl(account, db);
            modules.add(new Roster.VersioningModule(roster_stores[account]));
        });
    }

    public Collection<Roster.Item> get_roster(Account account) {
        return roster_stores[account].get_roster();
    }

    public Roster.Item? get_roster_item(Account account, Jid jid) {
        return roster_stores[account].get_item(jid);
    }

    public void remove_jid(Account account, Jid jid) {
        XmppStream? stream = stream_interactor.get_stream(account);
        if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).remove_jid(stream, jid.bare_jid);
    }

    public void add_jid(Account account, Jid jid, string? handle) {
        XmppStream? stream = stream_interactor.get_stream(account);
        if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).add_jid(stream, jid.bare_jid, handle);
    }

    public void set_jid_handle(Account account, Jid jid, string? handle) {
        XmppStream? stream = stream_interactor.get_stream(account);
        if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).set_jid_handle(stream, jid.bare_jid, handle);
    }

    private void on_account_added(Account account) {
        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).received_roster.connect_after( (stream, roster) => {
            foreach (Roster.Item roster_item in roster) {
                on_roster_item_updated(account, roster_item);
            }
        });
        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_removed.connect_after( (stream, roster_item) => {
            removed_roster_item(account, roster_item.jid, roster_item);
        });
        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_updated.connect_after( (stream, roster_item) => {
            on_roster_item_updated(account, roster_item);
        });

        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).mutual_subscription.connect_after( (stream, jid) => {
            mutual_subscription(account, jid);
        });
    }

    private void on_roster_item_updated(Account account, Roster.Item roster_item) {
        updated_roster_item(account, roster_item.jid, roster_item);
    }
}

public class RosterStoreImpl : Roster.Storage, Object {
    private Account account;
    private Database db;

    private HashMap<Jid, Roster.Item> items = new HashMap<Jid, Roster.Item>(Jid.hash_bare_func, Jid.equals_bare_func);

    public class RosterStoreImpl(Account account, Database db) {
        this.account = account;
        this.db = db;

        foreach (Qlite.Row row in db.roster.select().with(db.roster.account_id, "=", account.id)) {
            Roster.Item item = new Roster.Item();
            item.jid = Jid.parse(row[db.roster.jid]);
            item.name = row[db.roster.handle];
            item.subscription = row[db.roster.subscription];
            items[item.jid] = item;
        }
    }

    public string? get_roster_version() {
        return account.roster_version;
    }

    public Collection<Roster.Item> get_roster() {
        return items.values;
    }

    public Roster.Item? get_item(Jid jid) {
        return items.has_key(jid) ? items[jid] : null;
    }

    public void set_roster_version(string version) {
        account.roster_version = version;
    }

    public void set_roster(Collection<Roster.Item> items) {
        db.roster.delete().with(db.roster.account_id, "=", account.id).perform();
        foreach (Roster.Item item in items) {
            set_item(item);
        }
    }

    public void set_item(Roster.Item item) {
        items[item.jid] = item;
        db.roster.insert().or("REPLACE")
            .value(db.roster.account_id, account.id)
            .value(db.roster.jid, item.jid.to_string())
            .value(db.roster.handle, item.name)
            .value(db.roster.subscription, item.subscription)
            .perform();
    }

    public void remove_item(Roster.Item item) {
        items.unset(item.jid);
        db.roster.delete()
            .with(db.roster.account_id, "=", account.id)
            .with(db.roster.jid, "=", item.jid.to_string()).perform();
    }
}

}