/* * Created by yuuta on 4/1/22. */ #include "log.h" #include "logic.h" #include "db.h" #include "botd.h" #include "utils.h" #include #include #include #include #include #include /* 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; uint32_t msg_index = tg_url_get_index(link->link_); sqlite3_stmt *stmt = NULL; if ((r = sqlite3_prepare_v2(db, "INSERT INTO says(t, msg_index, 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 (msg_index) { if ((r = sqlite3_bind_int64(stmt, 2, msg_index))) { goto sql_err; } } else { if ((r = sqlite3_bind_null(stmt, 2))) { 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) { if (!chan->author_signature_ || strcmp(chan->author_signature_, "ksyx") != 0) 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; } } return true; } void store(struct TdMessage *msg, void (*cb)(bool)) { if (!filter(msg)) { goto f; f: cb(false); return; } char *t; switch (msg->content_->ID) { case CODE_MessageText: { struct TdMessageText *text = (struct TdMessageText *) msg->content_; t = text->text_->text_; break; } case CODE_MessagePhoto: { struct TdMessagePhoto *photo = (struct TdMessagePhoto *) msg->content_; if (!photo->caption_ || !photo->caption_->text_) goto f; t = photo->caption_->text_; break; } default: { goto f; } } assert(t); 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); }