summaryrefslogtreecommitdiff
path: root/store.c
blob: 4bc2d8ea8cd3b893aa6afd2f676596fd288a6514 (plain)
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
142
143
144
145
146
147
148
/*
 * Created by yuuta on 4/1/22.
 */

#include "log.h"
#include "logic.h"
#include "db.h"
#include "botd.h"

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>

/* Temp object between message callback and link callback */
struct say {
    long long msg_id;
    long long chat_id;
    char *text;
    void (*cb)(bool);
};

static void cb_link(bool successful, struct TdObject *result, struct TdError *error, void *cb_arg) {
    struct say *s = cb_arg;
    if (!successful) {
        LOGEV("Cannot get link for %lld/%lld: %s (%d).",
              s->chat_id, s->msg_id,
              error ? error->message_ : "NULL",
              error ? error->code_ : 0);
        goto f;
    }
    LOGDV("%s", s->text);
    struct TdMessageLink *link = (struct TdMessageLink *) result;
    int r;
    sqlite3_stmt *stmt = NULL;
    if ((r = sqlite3_prepare_v2(db,
                                "INSERT INTO says(t, url, msg) VALUES(?, ?, ?)",
                                -1,
                                &stmt,
                                NULL))) {
        goto sql_err;
        sql_err:
        LOGEV("Cannot insert: %s.", sqlite3_errstr(r));
        if (stmt) sqlite3_finalize(stmt);
        goto f;
    }
    if ((r = sqlite3_bind_text(stmt, 1, s->text, (int) strlen(s->text), NULL))) {
        goto sql_err;
    }
    if ((r = sqlite3_bind_text(stmt, 2, link->link_, (int) strlen(link->link_), NULL))) {
        goto sql_err;
    }
    if ((r = sqlite3_bind_int64(stmt, 3, s->msg_id))) {
        goto sql_err;
    }
    r = sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    stmt = NULL;
    if (r != SQLITE_DONE && r != SQLITE_CONSTRAINT) {
        goto sql_err;
    } else if (r == SQLITE_CONSTRAINT) {
        goto f;
    } else {
        s->cb(true);
        goto cleanup;
    }
    assert(false);
    f:
    s->cb(false);
    goto cleanup;
    cleanup:
    free(s->text);
    free(s);
}

static bool filter(struct TdMessage *msg) {
    if (msg->chat_id_ != CHANNEL)
        return false;
    if (!msg->forward_info_ || !msg->forward_info_->origin_) {
        return false;
    }
    struct TdMessageForwardOrigin *origin = msg->forward_info_->origin_;
    switch (origin->ID) {
        case CODE_MessageForwardOriginChannel: {
            struct TdMessageForwardOriginChannel *chan =
                    (struct TdMessageForwardOriginChannel *) origin;
            if (chan->chat_id_ != -1001304761546 &&
                chan->chat_id_ != -1001565681839)
                return false;
            break;
        }
        case CODE_MessageForwardOriginHiddenUser: {
            struct TdMessageForwardOriginHiddenUser *hid_user =
                    (struct TdMessageForwardOriginHiddenUser *) origin;
            if (strcmp("ksyx", hid_user->sender_name_) != 0) return false;
            break;
        }
        case CODE_MessageForwardOriginUser: {
            struct TdMessageForwardOriginUser *usr =
                    (struct TdMessageForwardOriginUser *) origin;
            if (usr->sender_user_id_ != 1106621641) return false;
        }
        default: {
            return false;
        }
    }

    if (msg->content_->ID != CODE_MessageText) {
        return false;
    }
    return true;
}

void store(struct TdMessage *msg, void (*cb)(bool)) {
    if (!filter(msg)) {
        goto f;
        f:
        cb(false);
        return;
    }
    struct TdMessageText *text = (struct TdMessageText *) msg->content_;
    const char *t = text->text_->text_;
    struct say *s;
    if (!(s = malloc(sizeof(struct say)))) {
        LOGEV("Cannot allocate memory: %s.", strerror(errno));
        goto f;
    }
    memset(s, 0, sizeof(struct say));
    s->chat_id = msg->chat_id_;
    s->msg_id = msg->id_;
    s->cb = cb;
    /* I'm just too lazy to manually free in each callback, so just strdup. */
    if (!(s->text = strdup(t))) {
        LOGEV("Cannot allocate memory: %s.", strerror(errno));
        free(s);
        goto f;
    }
    td_send(TdCreateObjectGetMessageLink(msg->chat_id_,
                                         msg->id_,
                                         0,
                                         false,
                                         false),
            &cb_link,
            s);

}