add basic URL validation for all modes

This commit is contained in:
Slavasil 2024-10-15 14:37:49 +00:00
parent 910a2e6bd9
commit da01612315
4 changed files with 64 additions and 41 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(shortener_bot LANGUAGES C CXX) project(shortener_bot LANGUAGES C CXX)
add_executable(bot main.cpp telegram_client.cpp commands.cpp) add_executable(bot main.cpp telegram_client.cpp commands.cpp util.cpp)
set_property(TARGET bot PROPERTY CXX_STANDARD 20) set_property(TARGET bot PROPERTY CXX_STANDARD 20)
set_property(TARGET bot PROPERTY CXX_STANDARD_REQUIRED ON) set_property(TARGET bot PROPERTY CXX_STANDARD_REQUIRED ON)

View File

@ -4,6 +4,7 @@
#include "curl/easy.h" #include "curl/easy.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/tl/TlObject.h" #include "td/tl/TlObject.h"
#include "util.h"
#include <cstring> #include <cstring>
#include <functional> #include <functional>
#include <random> #include <random>
@ -14,6 +15,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
void send_help_msg(context *ctx, td_api::message &msg);
void cmd::handle_regular_message(context *ctx, td_api::message &msg) { void cmd::handle_regular_message(context *ctx, td_api::message &msg) {
if (msg.content_->get_id() == td_api::messageText::ID) { if (msg.content_->get_id() == td_api::messageText::ID) {
std::string text = static_cast<td_api::messageText&>(*msg.content_).text_->text_; std::string text = static_cast<td_api::messageText&>(*msg.content_).text_->text_;
@ -24,7 +27,11 @@ void cmd::handle_regular_message(context *ctx, td_api::message &msg) {
param.remove_suffix(param.size() - nextSpace); param.remove_suffix(param.size() - nextSpace);
spdlog::info("Command /shorten received with parameter '{}'", param); spdlog::info("Command /shorten received with parameter '{}'", param);
// TODO check URL validity std::string paramStr(param);
if (!url::is_url_valid(paramStr)) {
send_help_msg(ctx, msg);
return;
}
bool result = shorten_link(std::string(param), ctx, [tg = ctx->tg, chat_id = msg.chat_id_, thread_id = msg.message_thread_id_](std::string url){ bool result = shorten_link(std::string(param), ctx, [tg = ctx->tg, chat_id = msg.chat_id_, thread_id = msg.message_thread_id_](std::string url){
tg->send_query(td_api::make_object<td_api::sendMessage>( tg->send_query(td_api::make_object<td_api::sendMessage>(
@ -49,53 +56,49 @@ void cmd::handle_regular_message(context *ctx, td_api::message &msg) {
), {}); ), {});
} }
} else if (std::strncmp(text.c_str(), "/shorten", 8) == 0) { } else if (std::strncmp(text.c_str(), "/shorten", 8) == 0) {
std::string textRaw("usage: /shorten <url>"); send_help_msg(ctx, msg);
std::vector<td_api::object_ptr<td_api::textEntity>> empty;
auto text = static_cast<td_api::object_ptr<td_api::InputMessageContent>>(td_api::make_object<td_api::inputMessageText>(td_api::make_object<td_api::formattedText>(textRaw, std::move(empty)), nullptr, false));
ctx->tg->send_query(td_api::make_object<td_api::sendMessage>(msg.chat_id_, msg.message_thread_id_, nullptr, nullptr, nullptr, std::move(text)), {});
} }
} }
} }
void cmd::handle_inline_query(context *ctx, td_api::updateNewInlineQuery &query) { void cmd::handle_inline_query(context *ctx, td_api::updateNewInlineQuery &query) {
// TODO check URL validity
uint64_t pendingQueryId = new_pending_query_id();
ctx->inlineQueries.insert(std::pair<uint64_t, pending_inline_query>(pendingQueryId, {query.query_, std::chrono::steady_clock::now() + std::chrono::hours(5)}));
std::vector<td_api::object_ptr<td_api::InputInlineQueryResult>> results; std::vector<td_api::object_ptr<td_api::InputInlineQueryResult>> results;
results.reserve(1); if (url::is_url_valid(query.query_)) {
auto messageButton = td_api::make_object<td_api::inlineKeyboardButton>( uint64_t pendingQueryId = new_pending_query_id();
"press to shorten", ctx->inlineQueries.insert(std::pair<uint64_t, pending_inline_query>(pendingQueryId, {query.query_, std::chrono::steady_clock::now() + std::chrono::hours(5)}));
static_cast<td_api::object_ptr<td_api::InlineKeyboardButtonType>>(td_api::make_object<td_api::inlineKeyboardButtonTypeCallback>(std::to_string(pendingQueryId)))
);
std::vector<decltype(messageButton)> messageButtonRow; auto messageButton = td_api::make_object<td_api::inlineKeyboardButton>(
messageButtonRow.push_back(std::move(messageButton)); "press to shorten",
static_cast<td_api::object_ptr<td_api::InlineKeyboardButtonType>>(td_api::make_object<td_api::inlineKeyboardButtonTypeCallback>(std::to_string(pendingQueryId)))
);
std::vector<decltype(messageButtonRow)> messageButtonRows; std::vector<decltype(messageButton)> messageButtonRow;
messageButtonRows.push_back(std::move(messageButtonRow)); messageButtonRow.push_back(std::move(messageButton));
results.push_back(static_cast<td_api::object_ptr<td_api::InputInlineQueryResult>>(td_api::make_object<td_api::inputInlineQueryResultArticle>( std::vector<decltype(messageButtonRow)> messageButtonRows;
"shorten", messageButtonRows.push_back(std::move(messageButtonRow));
"",
true, // hide_url results.push_back(static_cast<td_api::object_ptr<td_api::InputInlineQueryResult>>(td_api::make_object<td_api::inputInlineQueryResultArticle>(
"Shorten!", "shorten",
"...", "",
"https://slavasil.ru/favicon.ico", true, // hide_url
48, 48, "Shorten!",
static_cast<td_api::object_ptr<td_api::ReplyMarkup>>(td_api::make_object<td_api::replyMarkupInlineKeyboard>( "...",
std::move(messageButtonRows) "https://slavasil.ru/favicon.ico",
)), 48, 48,
static_cast<td_api::object_ptr<td_api::InputMessageContent>>(td_api::make_object<td_api::inputMessageText>( static_cast<td_api::object_ptr<td_api::ReplyMarkup>>(td_api::make_object<td_api::replyMarkupInlineKeyboard>(
td_api::make_object<td_api::formattedText>( std::move(messageButtonRows)
query.query_, )),
std::move(std::vector<td_api::object_ptr<td_api::textEntity>>()) static_cast<td_api::object_ptr<td_api::InputMessageContent>>(td_api::make_object<td_api::inputMessageText>(
), td_api::make_object<td_api::formattedText>(
td_api::make_object<td_api::linkPreviewOptions>(true, "", false, false, false), query.query_,
false // clear_draft std::move(std::vector<td_api::object_ptr<td_api::textEntity>>())
)) ),
))); td_api::make_object<td_api::linkPreviewOptions>(true, "", false, false, false),
false // clear_draft
))
)));
}
ctx->tg->send_query(td_api::make_object<td_api::answerInlineQuery>( ctx->tg->send_query(td_api::make_object<td_api::answerInlineQuery>(
query.id_, query.id_,
false, // is_personal false, // is_personal
@ -185,8 +188,15 @@ bool cmd::shorten_link(std::string link, context *ctx, std::function<void(std::s
return r == CURLM_OK; return r == CURLM_OK;
} }
void send_help_msg(context *ctx, td_api::message &msg) {
std::string textRaw("usage: /shorten <url>");
std::vector<td_api::object_ptr<td_api::textEntity>> empty;
auto text = static_cast<td_api::object_ptr<td_api::InputMessageContent>>(td_api::make_object<td_api::inputMessageText>(td_api::make_object<td_api::formattedText>(textRaw, std::move(empty)), nullptr, false));
ctx->tg->send_query(td_api::make_object<td_api::sendMessage>(msg.chat_id_, msg.message_thread_id_, nullptr, nullptr, nullptr, std::move(text)), {});
}
uint64_t cmd::new_pending_query_id() { uint64_t cmd::new_pending_query_id() {
static std::mt19937 rng; static std::mt19937 rng;
static std::uniform_int_distribution<uint64_t> dist(0, 0xFFFFFFFFFFFFFFFFULL); static std::uniform_int_distribution<uint64_t> dist(0, 0xFFFFFFFFFFFFFFFFULL);
return dist(rng); return dist(rng);
} }

7
util.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "util.h"
#include <regex>
bool url::is_url_valid(std::string &url) { static std::regex r("https?:\\/\\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)");
std::cmatch m;
return std::regex_match(url.c_str(), m, r);
}

6
util.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <string>
namespace url {
bool is_url_valid(std::string &url);
}