aboutsummaryrefslogtreecommitdiff
path: root/libdino/src/service/search_processor.vala
blob: e56efa41b295ca6c8d2c98c7a823a0cefe10d274 (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
using Gee;

using Xmpp;
using Qlite;
using Dino.Entities;

namespace Dino {

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

    private StreamInteractor stream_interactor;
    private Database db;

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

    public SearchProcessor(StreamInteractor stream_interactor, Database db) {
        this.stream_interactor = stream_interactor;
        this.db = db;
    }

    private QueryBuilder prepare_search(string query, bool join_content) {
        string words = "";
        string? with = null;
        string? in_ = null;
        string? from = null;
        foreach(string word in query.split(" ")) {
            if (word.has_prefix("with:")) {
                if (with == null) {
                    with = word.substring(5) + "%";
                } else {
                    return db.message.select().where("0");
                }
            } else if (word.has_prefix("in:")) {
                if (in_ == null) {
                    in_ = word.substring(3) + "%";
                } else {
                    return db.message.select().where("0");
                }
            } else if (word.has_prefix("from:")) {
                if (from == null) {
                    from = word.substring(5) + "%";
                } else {
                    return db.message.select().where("0");
                }
            } else {
                words += word + "* ";
            }
        }
        if (in_ != null && with != null) {
            return db.message.select().where("0");
        }

        QueryBuilder rows = db.message
            .match(db.message.body, words)
            .order_by(db.message.id, "DESC")
            .join_with(db.jid, db.jid.id, db.message.counterpart_id)
            .join_with(db.account, db.account.id, db.message.account_id)
            .outer_join_with(db.real_jid, db.real_jid.message_id, db.message.id)
            .with(db.account.enabled, "=", true);
        if (join_content) {
            rows.join_on(db.content, "message.id=contentx.foreign_id AND contentx.content_type=1")
                .with(db.content.content_type, "=", 1);
        }
        if (with != null) {
            if (with.index_of("/") > 0) {
                rows.with(db.message.type_, "=", Message.Type.GROUPCHAT_PM)
                    .with(db.jid.bare_jid, "LIKE", with.substring(0, with.index_of("/")))
                    .with(db.message.counterpart_resource, "LIKE", with.substring(with.index_of("/") + 1));
            } else {
                rows.where(@"($(db.message.type_) = $((int)Message.Type.CHAT) AND $(db.jid.bare_jid) LIKE ?)"
                    + @" OR ($(db.message.type_) = $((int)Message.Type.GROUPCHAT_PM) AND $(db.real_jid.real_jid) LIKE ?)"
                    + @" OR ($(db.message.type_) = $((int)Message.Type.GROUPCHAT_PM) AND $(db.message.counterpart_resource) LIKE ?)", {with, with, with});
            }
        } else if (in_ != null) {
            rows.with(db.jid.bare_jid, "LIKE", in_)
                .with(db.message.type_, "=", Message.Type.GROUPCHAT);
        }
        if (from != null) {
            rows.where(@"($(db.message.direction) = 1 AND $(db.account.bare_jid) LIKE ?)"
                + @" OR ($(db.message.direction) = 1 AND $(db.message.type_) IN ($((int)Message.Type.GROUPCHAT), $((int)Message.Type.GROUPCHAT_PM)) AND $(db.message.our_resource) LIKE ?)"
                + @" OR ($(db.message.direction) = 0 AND $(db.message.type_) = $((int)Message.Type.CHAT) AND $(db.jid.bare_jid) LIKE ?)"
                + @" OR ($(db.message.direction) = 0 AND $(db.message.type_) IN ($((int)Message.Type.GROUPCHAT), $((int)Message.Type.GROUPCHAT_PM)) AND $(db.real_jid.real_jid) LIKE ?)"
                + @" OR ($(db.message.direction) = 0 AND $(db.message.type_) IN ($((int)Message.Type.GROUPCHAT), $((int)Message.Type.GROUPCHAT_PM)) AND $(db.message.counterpart_resource) LIKE ?)", {from, from, from, from, from});
        }
        return rows;
    }

    public Gee.List<MessageItem> match_messages(string query, int offset = -1) {
        Gee.List<MessageItem> ret = new ArrayList<MessageItem>();
        var rows = prepare_search(query, true).limit(10);
        if (offset > 0) {
            rows.offset(offset);
        }
        foreach (Row row in rows) {
            Message message = new Message.from_row(db, row);
            Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message);
            ret.add(new MessageItem(message, conversation, row[db.content.id]));
        }
        return ret;
    }

    public int count_match_messages(string query) {
        return (int)prepare_search(query, false).select({db.message.id}).count();
    }
}

}