16#include <QNetworkAccessManager>
27#include <QNetworkReply>
28#include <QSharedPointer>
32#include <QJsonDocument>
49 if (
token.isEmpty()) {
55 QFuture<QByteArray> loginFuture =
sendRequest(QSharedPointer<TelegramGetMe>::create());
57 then(
this, [
this](
const QByteArray& data) {
58 ITelegramBot::handleLogin(data);
61 handleLoginErr(exeption.
code());
64 return loginFuture.isValid();
77 const QString &buttonText,
78 bool onetimeKeyboard) {
80 auto replyMarkup = QSharedPointer<QJsonObject>::create();
82 QJsonObject contactButton;
83 contactButton[
"text"] = buttonText;
84 contactButton[
"request_location"] =
true;
86 row.append(contactButton);
88 replyMarkup->insert(
"keyboard", keyboard);
89 replyMarkup->insert(
"resize_keyboard",
true);
90 replyMarkup->insert(
"one_time_keyboard", onetimeKeyboard);
96 bool onetimeKeyboard) {
97 auto replyMarkup = QSharedPointer<QJsonObject>::create();
99 QJsonObject contactButton;
100 contactButton[
"text"] = buttonText;
101 contactButton[
"request_contact"] =
true;
103 row.append(contactButton);
104 keyboard.append(row);
105 replyMarkup->insert(
"keyboard", keyboard);
106 replyMarkup->insert(
"resize_keyboard",
true);
107 replyMarkup->insert(
"one_time_keyboard", onetimeKeyboard);
118 if (args.
text.isEmpty()) {
122 auto msg = QSharedPointer<TelegramSendMsg>::create(args, extraObjects);
133 if (!chatId.isValid() || chatId.isNull())
136 if (!messageId.isValid() || messageId.isNull())
139 auto msg = QSharedPointer<TelegramDeleteMessage>::create(chatId,
147 const QList<QList<QString> > &keyboard,
149 bool autoResizeKeyboard) {
154 if (!messageId.isValid() || messageId.isNull())
157 auto msg = QSharedPointer<TelegramEditMessage>::create(messageId,
159 prepareKeyboard(autoResizeKeyboard,
170 auto&& keyboardJson = QSharedPointer<QJsonObject>::create();
171 QJsonArray keyboardArray;
173 for (
const auto& map : keyboard) {
174 QJsonArray keyboardLineArray;
175 for (
auto it = map.begin(); it != map.end(); it = std::next(it)) {
176 auto&& callBackKey = QString(
"callback_data_%0").arg(rand());
177 keyboardLineArray.push_back(QJsonObject{ {
"text", it.key()}, {
"callback_data", callBackKey } });
178 _handleButtons[callBackKey] = {it.value()};
180 keyboardArray.push_back(keyboardLineArray);
184 (*keyboardJson)[
"inline_keyboard"] = keyboardArray;
186 extraObjects[
"reply_markup"] = keyboardJson;
192qTbot::ITelegramBot::prepareKeyboard(
bool autoResizeKeyboard,
194 const QList<QList<QString>> &keyboard) {
196 auto&& keyboardJson = QSharedPointer<QJsonObject>::create();
197 QJsonArray keyboardArray;
199 for (
const auto &row :keyboard) {
200 QJsonArray keyboardLineArray;
202 for (
auto it = row.begin(); it != row.end(); it = std::next(it)) {
203 keyboardLineArray.push_back(QJsonObject{ {
"text", *it} });
205 keyboardArray.push_back(keyboardLineArray);
209 (*keyboardJson)[
"keyboard"] = keyboardArray;
211 (*keyboardJson)[
"resize_keyboard"] = autoResizeKeyboard;
212 (*keyboardJson)[
"one_time_keyboard"] = onTimeKeyboard;
214 extraObjects[
"reply_markup"] = keyboardJson;
227 if (!messageId.isValid() || messageId.isNull())
230 auto msg = QSharedPointer<TelegramEditMessage>::create(messageId,
232 prepareInlineKeyBoard(keyboard));
239 const QVariant &chatId,
241 const QString &callBackQueryId) {
242 if (!chatId.isValid() || chatId.isNull())
245 if (!messageId.isValid() || messageId.isNull())
248 auto msg = QSharedPointer<TelegramEditMessageReplyMarkup>::create(messageId,
249 TelegramArgs(chatId,
"", 0,
"html",
false, callBackQueryId),
250 prepareInlineKeyBoard(keyboard));
262 if (!messageId.isValid() || messageId.isNull())
265 if (args.
text.isEmpty())
268 auto msg = QSharedPointer<TelegramEditMessage>::create(messageId,
277 const QList<QList<QString> > &keyboard,
279 bool autoResizeKeyboard) {
284 if (args.
text.isEmpty()) {
288 return sendSpecificMessage(args, prepareKeyboard(autoResizeKeyboard, onTimeKeyboard, keyboard));
294 if (fileId.isEmpty()) {
298 auto localFilePath = findFileInlocatStorage(fileId);
300 if (!localFilePath.isEmpty()) {
301 QPromise<QByteArray> fileDataResult;
302 fileDataResult.start();
305 QFile localFile(localFilePath);
306 if (localFile.open(QIODevice::ReadOnly)) {
307 fileDataResult.addResult(localFile.readAll());
312 fileDataResult.addResult(localFilePath.toUtf8());
315 fileDataResult.setProgressRange(0,1);
316 fileDataResult.setProgressValue(1);
318 fileDataResult.finish();
320 return fileDataResult.future();
327 auto&& path = metaInfo->takePath();
329 auto&& msg = QSharedPointer<TelegrammDownloadFile>::create(path);
334 if (localFilePath.isEmpty())
337 QFuture<QByteArray> replay;
348 auto longWay = QSharedPointer<QPromise<QByteArray>>::create();
352 if (!future.isValid()) {
356 future.then([
this, fileId, fileType, longWay](
const QByteArray& header){
357 handleFileHeader(header);
359 auto&& future =
getFile(fileId, fileType);
361 if (!future.isValid()) {
362 longWay->setException(
InternalException(
"Failed to wrote file into internal cache!"));
366 future.then([longWay](
const QByteArray& data){
367 longWay->addResult(data);
369 }).onFailed([longWay](
const QException& exep){
370 longWay->setException(exep);
374 }).onFailed([longWay](
const QException& exep){
375 longWay->setException(exep);
378 return longWay->future();
382 auto msg = QSharedPointer<TelegramGetFile>::create(fileId);
384 if (future.isValid()) {
403 if (!file.isReadable()) {
408 QSharedPointer<TelegramSendPhoto>::create(args,
416 if (!fileName.size()) {
428 const QFileInfo &photo,
433 if (!photo.isReadable()) {
438 QSharedPointer<TelegramSendPhoto>::create(args,
440 prepareInlineKeyBoard(keyboard)), args.
msgIdCB);
444 const QByteArray &photo,
445 const QString &fileName,
452 if (!fileName.size()) {
461 QSharedPointer<TelegramSendPhoto>::create(args,
464 prepareInlineKeyBoard(keyboard)),
472 throw "the sendFileById is not implemented";
486 if (!(longitude && latitude)) {
493 prepareInlineKeyBoard(keyboard)));
497 const QString &phone,
498 const QString &firstName,
499 const QString &secondName) {
510 if (
auto && file = _filesMetaInfo.value(
id)) {
511 return file->fileSize();
518 return _filesMetaInfo.value(
id,
nullptr);
522 qWarning() << QString(
"code: %0 - %1").
523 arg(ansverWithError->errorCode()).
524 arg(ansverWithError->errorDescription());
533 if (
auto&& queryUpd = tupdate->callbackQueryUpdate()) {
534 auto &&handleButtonKey = queryUpd->callBackData();
536 if (
auto&& cb = _handleButtons.value(handleButtonKey)) {
537 cb(handleButtonKey, queryUpd->messageId());
544 const std::function<
void (
int)> &msgIdCB) {
546 if (future.isValid()) {
547 future.then(
this, [
this, msgIdCB](
const QByteArray& responseData){
549 QJsonDocument json = QJsonDocument::fromJson(responseData);
551 const QJsonObject&& obj = json.object();
552 if (obj.contains(
"result")) {
553 unsigned long long chatId = obj[
"result"][
"chat"][
"id"].toInteger();
554 int messageID = obj[
"result"][
"message_id"].toInt();
560 _lastMessageId[chatId] = messageID;
565 }).onFailed([msgIdCB](){
578void ITelegramBot::handleLogin(
const QByteArray&ansver) {
582 if (!ans->isValid()) {
583 qWarning() <<
"login error occured: ";
587 auto&& result = ans->result().toObject();
589 setId(result.value(
"id").toInteger());
590 setName( result.value(
"first_name").toString());
595void ITelegramBot::handleLoginErr(QNetworkReply::NetworkError err) {
597 qCritical() <<
"Network error occured. code: " << err;
601void ITelegramBot::handleFileHeader(
const QByteArray& header) {
604 if (!ansver->isValid()) {
611 _filesMetaInfo.insert(fileMetaInfo->fileId(), fileMetaInfo);
614QString ITelegramBot::findFileInlocatStorage(
const QString &fileId)
const {
617 auto &&localStorageList = defaultFileDir.entryInfoList(QDir::Filter::NoDotAndDotDot | QDir::Files);
618 for (
const auto& file: localStorageList) {
619 int size = file.size();
621 return file.absoluteFilePath();
629 _username = newUsername;
633 return request->baseAddress() +
"/bot" +
token() + request->makeUpload();
645 return _lastMessageId.value(chatId, 0);
The HttpException class is the base exception that is raised on all errors of the HTTP protocol.
QNetworkReply::NetworkError code() const
code Returns the network error code.
void setName(const QString &newName)
setName This method sets new value for the IBot::name field.
static QSharedPointer< MessageType > makeMesasge(const QByteArray &data, Args &&...args)
makeMesasge This is a factory method that can create a message type from raw byte data.
FileType
The FileType enum is a list of file types. It defines how a file should be downloaded - as a local ob...
@ Local
Local file type. The file will be saved in the internal file storage. This file type can use the file...
@ Ram
Ram virtual file type. All file data will be saved into a QFuture bytes array.
const QByteArray & token() const
token This is the token value for authentication on the remote server (bot).
virtual void handleIncomeNewUpdate(const QSharedPointer< iUpdate > &)
handleIncomeNewUpdate This method just emits the sigReceiveUpdate signal.
virtual QString defaultFileStorageLocation() const
defaultFileStorageLocation This method returns the default file storage location.
QFuture< QByteArray > sendRequest(const QSharedPointer< iRequest > &rquest)
sendRequest This method sends a custom request to the server.
void setToken(const QByteArray &newToken)
setToken This is the setter of the IBot::token value.
bool sendFile(const QFileInfo &file, const QVariant &chatId) override
sendFile This method sends the selected file to the chat.
~ITelegramBot()
~ITelegramBot destructor.
bool sendFileById(const QString &fileID, const QVariant &chatId)
sendFileById This is specific method of the telegram bot. sends a file by id.
int getFileSizeByUniqueId(const QString &id) const
getFileSizeByUniqueId This method return size of the file by id
bool editMessageKeyboard(const QVariant &messageId, const QVariant &chatId, const KeyboardOnMessage &keyboard={}, const QString &callBackQueryId="")
Edits a keyboard of message in a chat.
const QString & username() const
username This is the bot login
void setId(unsigned long long newId)
setId This method sets new value for the ITelegramBot::id property.
int gelLastMessageId(unsigned long long &chatId) const
gelLastMessageId this method returns last sent message id.
QFuture< QByteArray > getFile(const QString &fileId, FileType fileType=FileType::Ram) override
getFile This method sends a request to get a file by id. The files can be saved into local storage if...
QSharedPointer< TelegramFile > getFileInfoByUniqueId(const QString &id) const
getFileInfoByUniqueId return a local saved meta information about the file.
QFuture< QByteArray > getFileMeta(const QString &fileId)
getFileMeta This method receives the meta information of the file.
bool sendFileMessage(const TelegramArgs &args, const QFileInfo &file)
sendFileMessage This method sends a message with a file.
virtual void onRequestError(const QSharedPointer< TelegramUpdateAnswer > &ansverWithError) const
onRequestError This method invoked when the telegram server sends an error response....
bool editSpecificMessage(const QVariant &messageId, const TelegramArgs &args)
Edits a specific message in a chat.
bool sendSpecificMessageWithKeyboard(const TelegramArgs &args, const KeyboardOnMessage &keyboard)
Sends a specific message with a custom keyboard to a chat. This function sends a specific message to ...
void handleIncomeNewUpdate(const QSharedPointer< iUpdate > &) override
handleIncomeNewUpdate This method just emits the sigReceiveUpdate signal.
ITelegramBot()
ITelegramBot default constructor.
bool sendLocation(const TelegramArgs &args, float latitude, float longitude, const KeyboardOnMessage &keyboard={})
sendLocation This method sends a location to the user.
unsigned long long id() const
id This method returns the bot id number.
bool sendLocationRequest(const QVariant &chatId, const QString &text, const QString &buttonText, bool onetimeKeyboard)
sendLocationRequest This method sends into the chat a button that will automatically send the geo loc...
bool sendSelfContactRequest(const QVariant &chatId, const QString &text, const QString &buttonText, bool onetimeKeyboard)
sendSelfContactRequest This method sends into the chat a button that will automatically send the user...
bool sendMessage(const QVariant &chatId, const QString &text, iRequest::RequestPriority priority=iRequest::NormalPriority) override
sendMessage This method sends text to the selected chat.
virtual bool sendMessageRequest(const QSharedPointer< iRequest > &rquest, const std::function< void(int msgId)> &msgIdCB={})
sendMessageRequest This method invoke when bot will be sends any messages into the chat.
void setUsername(const QString &newUsername)
setUsername This method sets new value for the ITelegramBot::username property.
QString makeUrl(const QSharedPointer< iRequest > &request) const override
makeUrl This method prepares a prefix url for http requests.
bool sendContact(const TelegramArgs &args, const QString &phone, const QString &firstName, const QString &secondName="")
sendContact This method sends a contact data.
bool sendPhoto(const TelegramArgs &args, const QFileInfo &photo, const KeyboardOnMessage &keyboard={})
sendPhoto This method will send image into chat with chatId
bool login(const QByteArray &token) override
login This method gets basic information of the bot from the remote server.
bool sendSpecificMessage(const TelegramArgs &args, const qTbot::ExtraJsonObjects &extraObjects={})
Sends a specific message to a chat.
bool deleteMessage(const QVariant &chatId, const QVariant &messageId) override
deleteMessage This is the main method to delete messages.
bool editSpecificMessageWithKeyboard(const QVariant &messageId, const TelegramArgs &args, const QList< QList< QString > > &keyboard={}, bool onTimeKeyboard=false, bool autoResizeKeyboard=false)
Edits a specific message with a custom keyboard in a chat.
InternalException(const QByteArray &erroString={})
InternalException constructs the exception with an error description.
The TelegramUpdate class contains base information about updates from telegram.
RequestPriority
The RequestPriority enum This is the list of request execution priorities on the client side.
QHash< QString, QSharedPointer< QJsonObject > > ExtraJsonObjects
ExtraJsonObjects hash map of the extra objects of the message.
QList< QHash< QString, ButtonCB > > KeyboardOnMessage
KeyboardOnMessage type. A list of rows where each row is a map of button keys to the callback functio...
The TelegramArgs class is the base structure for all telegram message arguments.
iRequest::RequestPriority requestPriority
requestPriority This is the priority of the request.
TelegramArgs(const QVariant &id, const QString &text="", unsigned long long replyToMessageId=0, const QString &parseMode="html", bool disableWebPagePreview=false, const QString &callBackQueryId="", const std::function< void(int msgId)> &msgIdCB={}, iRequest::RequestPriority priority=iRequest::RequestPriority::NormalPriority)
TelegramArgs main constructor of the message arguments.
std::function< void(int msgId)> msgIdCB
msgIdCB This is the message id callback function. It will be invoked when the request finishes succes...
QVariant chatId
Chat ID where the message will be sent. Default: {}.
QString text
Text of the message. Default: "".