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
|
/*
* 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>
/* Temp object between message callback and link callback */
struct say {
long long msg_id;
long long chat_id;
char *text;
};
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 cleanup;
}
LOGDV("%s", s->text);
struct TdMessageLink *link = (struct TdMessageLink *) result;
int r;
sqlite3_stmt *stmt;
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));
goto cleanup;
}
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);
if (r != SQLITE_DONE && r != SQLITE_CONSTRAINT) {
goto sql_err;
}
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;
}
default: {
return false;
}
}
if (msg->content_->ID != CODE_MessageText) {
return false;
}
return true;
}
void store(struct TdMessage *msg) {
if (!filter(msg)) 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));
return;
}
memset(s, 0, sizeof(struct say));
s->chat_id = msg->chat_id_;
s->msg_id = msg->id_;
/* 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);
return;
}
td_send(TdCreateObjectGetMessageLink(msg->chat_id_,
msg->id_,
0,
false,
false),
&cb_link,
s);
}
|