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) {
601void ITelegramBot::handleFileHeader(
const QByteArray& header) {
614QString ITelegramBot::findFileInlocatStorage(
const QString &fileId)
const {
621 return file.absoluteFilePath();
633 return request->baseAddress() +
"/bot" +
token() + request->makeUpload();
645 return _lastMessageId.value(chatId, 0);
The HttpException class is base exaption that will raise on all errors of the HTTP protocol,...
QNetworkReply::NetworkError code() const
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 factory method tha can create a messages types.
FileType
The FileType enum is is file types, deffine how we should download a file - as a local object in file...
@ Ram
The Ram is a Virtual type of download files will save all file data into QFuture bytes array.
const QByteArray & token() const
token This is token value for authication on the remote server (bot)
virtual void handleIncomeNewUpdate(const QSharedPointer< iUpdate > &)
handleIncomeNewUpdate This method just emit the sigReceiveUpdate signal.
virtual QString defaultFileStorageLocation() const
defaultFileStorageLocation This method return default file storage location.
QFuture< QByteArray > sendRequest(const QSharedPointer< iRequest > &rquest)
sendRequest This method sent custom requests to the server.
void setToken(const QByteArray &newToken)
setToken This is setter of the IBot::token value.
bool sendFile(const QFileInfo &file, const QVariant &chatId) override
send file .
bool sendFileById(const QString &fileID, const QVariant &chatId)
sendFileById This is specific method of the telegram bot. sents 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 bots 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 sendet message id.
QFuture< QByteArray > getFile(const QString &fileId, FileType fileType=FileType::Ram) override
getFile This method sent request to get a file by id. The files can be saved into local storage if th...
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 receive meta information of the file.
bool sendFileMessage(const TelegramArgs &args, const QFileInfo &file)
sendFileMessage This method sents a message with file.
virtual void onRequestError(const QSharedPointer< TelegramUpdateAnswer > &ansverWithError) const
onRequestError This method invokent when telegram server sent error responce. Default implementation ...
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 emit the sigReceiveUpdate signal.
bool sendLocation(const TelegramArgs &args, float latitude, float longitude, const KeyboardOnMessage &keyboard={})
sendLocation This method sents locatin to user.
unsigned long long id() const
id This method return bots id number.
bool sendLocationRequest(const QVariant &chatId, const QString &text, const QString &buttonText, bool onetimeKeyboard)
sendLocationRequest This method setn into chat button that will automaticaly sent geo location to bot...
bool sendSelfContactRequest(const QVariant &chatId, const QString &text, const QString &buttonText, bool onetimeKeyboard)
sendSelfContactRequest This method sent into chat button that will automaticaly sent self contact inf...
bool sendMessage(const QVariant &chatId, const QString &text, iRequest::RequestPriority priority=iRequest::NormalPriority) override
sendMessage This method sents 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 sent eny messages into 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 prepare a prefix url for http requests.
bool sendContact(const TelegramArgs &args, const QString &phone, const QString &firstName, const QString &secondName="")
sendContact This method sents 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 get bae information of the bot from 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 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.
The InternalException class contais string value to describe what happened.
The TelegramUpdate class contains base information about updates from telegram.
RequestPriority
The RequestPriority enum.
QHash< QString, QSharedPointer< QJsonObject > > ExtraJsonObjects
ExtraJsonObjects hash map of the extra objects of the message.
QList< QHash< QString, ButtonCB > > KeyboardOnMessage
The TelegramArgs class is base structure for the all tellegram message arguments.
iRequest::RequestPriority requestPriority
std::function< void(int msgId)> msgIdCB
msgIdCB This is id message call bak function. Will be inwoked when request finished successful.
QVariant chatId
Chat ID where the message will be sent. Default: {}.
QString text
Text of the message. Default: "".