mirror of
https://github.com/moritzsternemann/QtTelegramBot.git
synced 2025-07-29 19:07:14 +02:00
Initial commit
This commit is contained in:
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
### Qt ###
|
||||||
|
# C++ objects and libs
|
||||||
|
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lai
|
||||||
|
*.so
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Qt-es
|
||||||
|
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
*.qbs.user
|
||||||
|
*.qbs.user.*
|
||||||
|
*.moc
|
||||||
|
moc_*.cpp
|
||||||
|
qrc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
Makefile*
|
||||||
|
*-build-*
|
||||||
|
|
||||||
|
# QtCreator
|
||||||
|
|
||||||
|
*.autosave
|
||||||
|
|
||||||
|
#QtCtreator Qml
|
||||||
|
*.qmlproject.user
|
||||||
|
*.qmlproject.user.*
|
||||||
|
**/bin
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Moritz Sternemann
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
43
QtTelegramBot.pri
Normal file
43
QtTelegramBot.pri
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
|
QT += core network
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/qttelegrambot.cpp \
|
||||||
|
$$PWD/networking.cpp \
|
||||||
|
$$PWD/types/message.cpp \
|
||||||
|
$$PWD/types/update.cpp \
|
||||||
|
$$PWD/types/chat.cpp \
|
||||||
|
$$PWD/types/user.cpp \
|
||||||
|
$$PWD/types/document.cpp \
|
||||||
|
$$PWD/types/photosize.cpp \
|
||||||
|
$$PWD/types/audio.cpp \
|
||||||
|
$$PWD/types/sticker.cpp \
|
||||||
|
$$PWD/types/video.cpp \
|
||||||
|
$$PWD/types/voice.cpp \
|
||||||
|
$$PWD/types/contact.cpp \
|
||||||
|
$$PWD/types/location.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/qttelegrambot.h \
|
||||||
|
$$PWD/networking.h \
|
||||||
|
$$PWD/types/message.h \
|
||||||
|
$$PWD/types/update.h \
|
||||||
|
$$PWD/types/chat.h \
|
||||||
|
$$PWD/types/user.h \
|
||||||
|
$$PWD/types/file.h \
|
||||||
|
$$PWD/types/document.h \
|
||||||
|
$$PWD/types/photosize.h \
|
||||||
|
$$PWD/types/audio.h \
|
||||||
|
$$PWD/types/sticker.h \
|
||||||
|
$$PWD/types/video.h \
|
||||||
|
$$PWD/types/voice.h \
|
||||||
|
$$PWD/types/contact.h \
|
||||||
|
$$PWD/types/location.h \
|
||||||
|
$$PWD/types/reply/genericreply.h \
|
||||||
|
$$PWD/types/reply/replykeyboardmarkup.h \
|
||||||
|
$$PWD/types/reply/replykeyboardhide.h \
|
||||||
|
$$PWD/types/reply/forcereply.h
|
||||||
|
|
||||||
|
OTHER_FILES += \
|
||||||
|
$$PWD/README.md
|
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
## Introduction
|
||||||
|
Qt5 library for the Telegram Bot API ([https://core.telegram.org/bots/api]()).
|
||||||
|
It can be used to interact with the API directly and/or configured to automatically notify you on updates using Qt’s signals and slots.
|
||||||
|
You need a bot token to make API calls. Text the [@botfather](https://telegram.me/BotFather) to create a new bot and obtain a token.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Create a lib directory in your project directory and cd into it:
|
||||||
|
mkdir lib && cd lib
|
||||||
|
|
||||||
|
Clone the repo to your projects source directory:
|
||||||
|
git clone https://github.com/iMoritz/QtTelegramBot.git
|
||||||
|
|
||||||
|
Alternatively you can add QtTelegramBot as a git submodule to always stay up-to-date:
|
||||||
|
git submodule add https://github.com/iMoritz/QtTelegramBot.git
|
||||||
|
|
||||||
|
In your project file (*project*.pro) add this include:
|
||||||
|
include($$PWD/lib/QtTelegramBot/QtTelegramBot.pri)
|
||||||
|
|
||||||
|
Now you can use the Bot classes using:
|
||||||
|
#include "qttelegrambot.h"
|
||||||
|
|
||||||
|
|
||||||
|
Everything in *QtTelegramBot* is in the `Telegram` namespace.
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
Examples can be found in the `examples` directory. You can build them in QtCreator or using the command line.
|
73
examples/echo/.gitignore
vendored
Normal file
73
examples/echo/.gitignore
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
|
12
examples/echo/echo.pro
Normal file
12
examples/echo/echo.pro
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
QT += core
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
TARGET = echo
|
||||||
|
CONFIG += console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
SOURCES += main.cpp
|
||||||
|
|
||||||
|
include(../../QtTelegramBot.pri)
|
27
examples/echo/main.cpp
Normal file
27
examples/echo/main.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "qttelegrambot.h"
|
||||||
|
|
||||||
|
#define TOKEN "YOUR BOT TOKEN"
|
||||||
|
|
||||||
|
Telegram::Bot *bot;
|
||||||
|
|
||||||
|
void newMessage(Telegram::Message message)
|
||||||
|
{
|
||||||
|
qDebug() << "new message:" << message;
|
||||||
|
|
||||||
|
if (bot && message.type == Telegram::Message::TextType) {
|
||||||
|
bot->sendMessage(message.from.id, message.string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
bot = new Telegram::Bot(TOKEN, false, 500, 4);
|
||||||
|
QObject::connect(bot, &Telegram::Bot::message, &newMessage);
|
||||||
|
qDebug() << "Started Telegram Bot";
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
3
examples/examples.pro
Normal file
3
examples/examples.pro
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TEMPLATE = subdirs
|
||||||
|
SUBDIRS += \
|
||||||
|
echo
|
157
networking.cpp
Normal file
157
networking.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#include "networking.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Networking::Networking(QString token, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_nam(new QNetworkAccessManager(this)),
|
||||||
|
m_token(token)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Networking::~Networking()
|
||||||
|
{
|
||||||
|
delete m_nam;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Networking::request(QString endpoint, ParameterList params, Networking::Method method)
|
||||||
|
{
|
||||||
|
if (endpoint.isEmpty()) {
|
||||||
|
qWarning("Cannot do request without endpoint");
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
if (m_token.isEmpty()) {
|
||||||
|
qWarning("Cannot do request without a Telegram Bot Token");
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest req;
|
||||||
|
QUrl url = buildUrl(endpoint);
|
||||||
|
req.setUrl(url);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
qDebug("HTTP request: %s", qUtf8Printable(req.url().toString()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QEventLoop loop;
|
||||||
|
|
||||||
|
QNetworkReply *reply;
|
||||||
|
|
||||||
|
if (method == GET) {
|
||||||
|
url.setQuery(parameterListToString(params));
|
||||||
|
req.setUrl(url);
|
||||||
|
reply = m_nam->get(req);
|
||||||
|
} else if (method == POST) {
|
||||||
|
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
reply = m_nam->post(req, parameterListToString(params));
|
||||||
|
} else if (method == UPLOAD) {
|
||||||
|
QByteArray boundary = generateMultipartBoundary(params);
|
||||||
|
req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary);
|
||||||
|
QByteArray requestData = generateMultipartFormData(params, boundary);
|
||||||
|
req.setHeader(QNetworkRequest::ContentLengthHeader, requestData.length());
|
||||||
|
reply = m_nam->post(req, requestData);
|
||||||
|
} else {
|
||||||
|
qCritical("No valid method!");
|
||||||
|
reply = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply == NULL) {
|
||||||
|
qWarning("Reply is NULL");
|
||||||
|
delete reply;
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qCritical("%s", qPrintable(QString("[%1] %2").arg(reply->error()).arg(reply->errorString())));
|
||||||
|
delete reply;
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ret = reply->readAll();
|
||||||
|
delete reply;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl Networking::buildUrl(QString endpoint)
|
||||||
|
{
|
||||||
|
QUrl url = QUrl();
|
||||||
|
url.setScheme("https");
|
||||||
|
url.setHost(API_HOST);
|
||||||
|
url.setPath("/bot" + m_token + endpoint);
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Networking::parameterListToString(ParameterList list)
|
||||||
|
{
|
||||||
|
QByteArray ret;
|
||||||
|
|
||||||
|
ParameterList::iterator i = list.begin();
|
||||||
|
while (i != list.end()) {
|
||||||
|
ret.append(i.key() + "=" + i.value().value + "&");
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
ret = ret.left(ret.length() - 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Networking::generateMultipartBoundary(ParameterList list)
|
||||||
|
{
|
||||||
|
// Generates a boundary that is not existent in the data
|
||||||
|
QByteArray result;
|
||||||
|
|
||||||
|
srand((unsigned int) time(NULL));
|
||||||
|
ParameterList::iterator i = list.begin();
|
||||||
|
while (i != list.end()) {
|
||||||
|
if (i.value().isFile) {
|
||||||
|
while (result.isEmpty() || i.value().value.contains(result)) {
|
||||||
|
result.append(generateRandomString(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Networking::generateMultipartFormData(ParameterList list, QByteArray boundary)
|
||||||
|
{
|
||||||
|
QByteArray result;
|
||||||
|
|
||||||
|
ParameterList::iterator i = list.begin();
|
||||||
|
while (i != list.end()) {
|
||||||
|
HttpParameter param = i.value();
|
||||||
|
result.append("--" + boundary + "\r\n");
|
||||||
|
result.append("Content-Disposition: form-data; name=\"" + i.key());
|
||||||
|
if (param.isFile) {
|
||||||
|
result.append("\"; filename=\"" + param.filename);
|
||||||
|
}
|
||||||
|
result.append("\"\r\n");
|
||||||
|
if (param.isFile) {
|
||||||
|
result.append("Content-Type: " + param.mimeType + "\r\n");
|
||||||
|
}
|
||||||
|
result.append("\r\n");
|
||||||
|
result.append(param.value);
|
||||||
|
result.append("\r\n");
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
result.append("--" + boundary + "--");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Networking::generateRandomString(int length)
|
||||||
|
{
|
||||||
|
static const std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890-=[]\\;',./!@#$%^&*()_+{}|:\"<>?`~");
|
||||||
|
static const size_t charsLen = chars.length();
|
||||||
|
QString result;
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
result += QChar(chars[rand() % charsLen]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
69
networking.h
Normal file
69
networking.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef NETWORKING_H
|
||||||
|
#define NETWORKING_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QEventLoop>
|
||||||
|
|
||||||
|
#define API_HOST "api.telegram.org"
|
||||||
|
|
||||||
|
#define ENDPOINT_GET_ME "/getMe"
|
||||||
|
#define ENDPOINT_SEND_MESSAGE "/sendMessage"
|
||||||
|
#define ENDPOINT_FORWARD_MESSAGE "/forwardMessage"
|
||||||
|
#define ENDPOINT_SEND_PHOTO "/sendPhoto"
|
||||||
|
#define ENDPOINT_SEND_AUDIO "/sendAudio"
|
||||||
|
#define ENDPOINT_SEND_DOCUMENT "/sendDocument"
|
||||||
|
#define ENDPOINT_SEND_STICKER "/sendSticker"
|
||||||
|
#define ENDPOINT_SEND_VIDEO "/sendVideo"
|
||||||
|
#define ENDPOINT_SEND_VOICE "/sendVoice"
|
||||||
|
#define ENDPOINT_SEND_LOCATION "/sendLocation"
|
||||||
|
#define ENDPOINT_SEND_CHAT_ACTION "/sendChatAction"
|
||||||
|
#define ENDPOINT_GET_USER_PROFILE_PHOTOS "/getUserProfilePhotos"
|
||||||
|
#define ENDPOINT_GET_UPDATES "/getUpdates"
|
||||||
|
#define ENDPOINT_SET_WEBHOOK "/setWebhook"
|
||||||
|
#define ENDPOINT_GET_FILE "/getFile"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class HttpParameter {
|
||||||
|
public:
|
||||||
|
HttpParameter() {}
|
||||||
|
HttpParameter(QVariant value, bool isFile = false, QString mimeType = "text/plain", QString filename = "") :
|
||||||
|
value(value.toByteArray()), isFile(isFile), mimeType(mimeType), filename(filename) {}
|
||||||
|
|
||||||
|
QByteArray value;
|
||||||
|
bool isFile;
|
||||||
|
QString mimeType;
|
||||||
|
QString filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QMap<QString, HttpParameter> ParameterList;
|
||||||
|
|
||||||
|
class Networking : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Networking(QString token, QObject *parent = 0);
|
||||||
|
~Networking();
|
||||||
|
|
||||||
|
enum Method { GET, POST, UPLOAD };
|
||||||
|
|
||||||
|
QByteArray request(QString endpoint, ParameterList params, Method method);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager *m_nam;
|
||||||
|
QString m_token;
|
||||||
|
|
||||||
|
QUrl buildUrl(QString endpoint);
|
||||||
|
QByteArray parameterListToString(ParameterList list);
|
||||||
|
|
||||||
|
QByteArray generateMultipartBoundary(ParameterList list);
|
||||||
|
QByteArray generateMultipartFormData(ParameterList list, QByteArray boundary);
|
||||||
|
QString generateRandomString(int length);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NETWORKING_H
|
402
qttelegrambot.cpp
Normal file
402
qttelegrambot.cpp
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
#include "qttelegrambot.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Bot::Bot(QString token, bool updates, quint32 updateInterval, quint32 pollingTimeout, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_net(new Networking(token)),
|
||||||
|
m_internalUpdateTimer(new QTimer(this)),
|
||||||
|
m_updateInterval(updateInterval),
|
||||||
|
m_pollingTimeout(pollingTimeout)
|
||||||
|
{
|
||||||
|
QLoggingCategory::setFilterRules("qt.network.ssl.warning=false");
|
||||||
|
|
||||||
|
if (updates) {
|
||||||
|
m_internalUpdateTimer->setSingleShot(true);
|
||||||
|
connect(m_internalUpdateTimer, &QTimer::timeout, this, &Bot::internalGetUpdates);
|
||||||
|
internalGetUpdates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bot::~Bot()
|
||||||
|
{
|
||||||
|
delete m_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
User Bot::getMe()
|
||||||
|
{
|
||||||
|
QJsonObject json = this->jsonObjectFromByteArray(
|
||||||
|
m_net->request(ENDPOINT_GET_ME, ParameterList(), Networking::GET));
|
||||||
|
|
||||||
|
User ret;
|
||||||
|
ret.id = json.value("id").toInt();
|
||||||
|
ret.firstname = json.value("first_name").toString();
|
||||||
|
ret.lastname = json.value("last_name").toString();
|
||||||
|
ret.username = json.value("username").toString();
|
||||||
|
|
||||||
|
if (ret.id == 0 || ret.firstname.isEmpty()) {
|
||||||
|
qCritical("%s", qPrintable("Got invalid user in " + QString(ENDPOINT_GET_ME)));
|
||||||
|
return User();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendMessage(QVariant chatId, QString text, bool markdown, bool disableWebPagePreview, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
if (markdown) params.insert("parse_mode", HttpParameter("Markdown"));
|
||||||
|
if (disableWebPagePreview) params.insert("disable_web_page_preview", HttpParameter(disableWebPagePreview));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, text, ParameterList(), replyToMessageId, replyMarkup, "text", ENDPOINT_SEND_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::forwardMessage(QVariant chatId, quint32 fromChatId, quint32 messageId)
|
||||||
|
{
|
||||||
|
if (chatId.type() != QVariant::String && chatId.type() != QVariant::Int) {
|
||||||
|
qCritical("Please provide a QString or int as chatId");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("chat_id", HttpParameter(chatId));
|
||||||
|
params.insert("from_chat_id", HttpParameter(fromChatId));
|
||||||
|
params.insert("message_id", HttpParameter(messageId));
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(ENDPOINT_FORWARD_MESSAGE, params, Networking::POST));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendPhoto(QVariant chatId, QFile *file, QString caption, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
if (!caption.isEmpty()) params.insert("caption", HttpParameter(caption));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, file, params, replyToMessageId, replyMarkup, "photo", ENDPOINT_SEND_PHOTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendPhoto(QVariant chatId, QString fileId, QString caption, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
if (!caption.isEmpty()) params.insert("caption", HttpParameter(caption));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, fileId, params, replyToMessageId, replyMarkup, "photo", ENDPOINT_SEND_PHOTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendAudio(QVariant chatId, QFile *file, qint64 duration, QString performer, QString title, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
if (duration >= 0) params.insert("duration", HttpParameter(duration));
|
||||||
|
if (!performer.isEmpty()) params.insert("performer", HttpParameter(performer));
|
||||||
|
if (!title.isEmpty()) params.insert("title", HttpParameter(title));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, file, params, replyToMessageId, replyMarkup, "audio", ENDPOINT_SEND_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendAudio(QVariant chatId, QString fileId, qint64 duration, QString performer, QString title, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
if (duration >= 0) params.insert("duration", HttpParameter(duration));
|
||||||
|
if (!performer.isEmpty()) params.insert("performer", HttpParameter(performer));
|
||||||
|
if (!title.isEmpty()) params.insert("title", HttpParameter(title));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, fileId, params, replyToMessageId, replyMarkup, "audio", ENDPOINT_SEND_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendDocument(QVariant chatId, QFile *file, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
return this->_sendPayload(chatId, file, ParameterList(), replyToMessageId, replyMarkup, "document", ENDPOINT_SEND_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendDocument(QVariant chatId, QString fileId, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
return this->_sendPayload(chatId, fileId, ParameterList(), replyToMessageId, replyMarkup, "document", ENDPOINT_SEND_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendSticker(QVariant chatId, QFile *file, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
return this->_sendPayload(chatId, file, ParameterList(), replyToMessageId, replyMarkup, "sticker", ENDPOINT_SEND_STICKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendSticker(QVariant chatId, QString fileId, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
return this->_sendPayload(chatId, fileId, ParameterList(), replyToMessageId, replyMarkup, "sticker", ENDPOINT_SEND_STICKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendVideo(QVariant chatId, QFile *file, qint64 duration, QString caption, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("duration", HttpParameter(duration));
|
||||||
|
params.insert("caption", HttpParameter(caption));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, file, params, replyToMessageId, replyMarkup, "video", ENDPOINT_SEND_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendVideo(QVariant chatId, QString fileId, qint64 duration, QString caption, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("duration", HttpParameter(duration));
|
||||||
|
params.insert("caption", HttpParameter(caption));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, fileId, params, replyToMessageId, replyMarkup, "video", ENDPOINT_SEND_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendVoice(QVariant chatId, QFile *file, qint64 duration, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("duration", HttpParameter(duration));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, file, params, replyToMessageId, replyMarkup, "voice", ENDPOINT_SEND_VOICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendVoice(QVariant chatId, QString fileId, qint64 duration, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("duration", HttpParameter(duration));
|
||||||
|
|
||||||
|
return this->_sendPayload(chatId, fileId, params, replyToMessageId, replyMarkup, "voice", ENDPOINT_SEND_VOICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendLocation(QVariant chatId, float latitude, float longitude, qint32 replyToMessageId, const GenericReply &replyMarkup)
|
||||||
|
{
|
||||||
|
Q_UNUSED(replyMarkup); // TODO
|
||||||
|
if (chatId.type() != QVariant::String && chatId.type() != QVariant::Int) {
|
||||||
|
qCritical("Please provide a QString or int as chatId");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("chat_id", HttpParameter(chatId));
|
||||||
|
params.insert("latitude", HttpParameter(latitude));
|
||||||
|
params.insert("longitude", HttpParameter(longitude));
|
||||||
|
if (replyToMessageId >= 0) params.insert("reply_to_message_id", HttpParameter(replyToMessageId));
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(ENDPOINT_SEND_LOCATION, params, Networking::POST));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::sendChatAction(QVariant chatId, Bot::ChatAction action)
|
||||||
|
{
|
||||||
|
if (chatId.type() != QVariant::String && chatId.type() != QVariant::Int) {
|
||||||
|
qCritical("Please provide a QString or int as chatId");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("chat_id", HttpParameter(chatId));
|
||||||
|
switch (action) {
|
||||||
|
case Typing:
|
||||||
|
params.insert("action", HttpParameter("typing"));
|
||||||
|
break;
|
||||||
|
case UploadingPhoto:
|
||||||
|
params.insert("action", HttpParameter("upload_photo"));
|
||||||
|
break;
|
||||||
|
case RecordingVideo:
|
||||||
|
params.insert("action", HttpParameter("record_video"));
|
||||||
|
break;
|
||||||
|
case UploadingVideo:
|
||||||
|
params.insert("action", HttpParameter("upload_video"));
|
||||||
|
break;
|
||||||
|
case RecordingAudio:
|
||||||
|
params.insert("action", HttpParameter("record_audio"));
|
||||||
|
break;
|
||||||
|
case UploadingAudio:
|
||||||
|
params.insert("action", HttpParameter("upload_audio"));
|
||||||
|
break;
|
||||||
|
case UploadingDocument:
|
||||||
|
params.insert("action", HttpParameter("upload_document"));
|
||||||
|
break;
|
||||||
|
case FindingLocation:
|
||||||
|
params.insert("action", HttpParameter("find_location"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(ENDPOINT_SEND_CHAT_ACTION, params, Networking::POST));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfilePhotos Bot::getUserProfilePhotos(quint32 userId, qint16 offset, qint8 limit)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("user_id", HttpParameter(userId));
|
||||||
|
if (offset > -1) params.insert("offset", HttpParameter(offset));
|
||||||
|
if (limit > -1) params.insert("limit", HttpParameter(limit));
|
||||||
|
|
||||||
|
QJsonObject json = this->jsonObjectFromByteArray(m_net->request(ENDPOINT_GET_USER_PROFILE_PHOTOS, params, Networking::GET));
|
||||||
|
|
||||||
|
UserProfilePhotos ret;
|
||||||
|
|
||||||
|
QList<PhotoSize> photo;
|
||||||
|
foreach (QJsonValue val, json.value("photos").toArray()) {
|
||||||
|
photo = QList<PhotoSize>();
|
||||||
|
|
||||||
|
foreach (QJsonValue p, val.toArray()) {
|
||||||
|
PhotoSize ps;
|
||||||
|
ps.fileId = p.toObject().value("file_id").toString();
|
||||||
|
ps.width = p.toObject().value("width").toInt();
|
||||||
|
ps.height = p.toObject().value("height").toInt();
|
||||||
|
if (p.toObject().contains("file_size")) ps.fileSize = p.toObject().value("file_size").toInt();
|
||||||
|
photo.append(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.append(photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Update> Bot::getUpdates(quint32 timeout, quint32 limit, quint32 offset)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("offset", HttpParameter(offset));
|
||||||
|
params.insert("limit", HttpParameter(limit));
|
||||||
|
params.insert("timeout", HttpParameter(timeout));
|
||||||
|
QJsonArray json = this->jsonArrayFromByteArray(m_net->request(ENDPOINT_GET_UPDATES, params, Networking::GET));
|
||||||
|
|
||||||
|
QList<Update> ret = QList<Update>();
|
||||||
|
foreach (QJsonValue value, json) {
|
||||||
|
ret.append(Update(value.toObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::setWebhook(QString url, QFile *certificate)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("url", HttpParameter(url));
|
||||||
|
|
||||||
|
QMimeDatabase db;
|
||||||
|
bool openedFile = false;
|
||||||
|
if (!certificate->isOpen()) {
|
||||||
|
if (!certificate->open(QFile::ReadOnly)) {
|
||||||
|
qCritical("Could not open file %s [%s]", qPrintable(certificate->fileName()), qPrintable(certificate->errorString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
openedFile = true;
|
||||||
|
}
|
||||||
|
QByteArray data = certificate->readAll();
|
||||||
|
if (openedFile) certificate->close();
|
||||||
|
params.insert("certificate", HttpParameter(data, true, db.mimeTypeForData(data).name(), certificate->fileName()));
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(ENDPOINT_SET_WEBHOOK, params, Networking::UPLOAD));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
File Bot::getFile(QString fileId)
|
||||||
|
{
|
||||||
|
ParameterList params;
|
||||||
|
params.insert("file_id", HttpParameter(fileId));
|
||||||
|
|
||||||
|
QJsonObject json = this->jsonObjectFromByteArray(m_net->request(ENDPOINT_GET_FILE, params, Networking::GET));
|
||||||
|
|
||||||
|
return File(json.value("file_id").toString(), json.value("file_size").toInt(-1), json.value("file_path").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::_sendPayload(QVariant chatId, QFile *filePayload, ParameterList params, qint32 replyToMessageId, const GenericReply &replyMarkup, QString payloadField, QString endpoint)
|
||||||
|
{
|
||||||
|
if (chatId.type() != QVariant::String && chatId.type() != QVariant::Int) {
|
||||||
|
qCritical("Please provide a QString or int as chatId");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.insert("chat_id", HttpParameter(chatId));
|
||||||
|
|
||||||
|
QMimeDatabase db;
|
||||||
|
bool openedFile = false;
|
||||||
|
if (!filePayload->isOpen()) {
|
||||||
|
if (!filePayload->open(QFile::ReadOnly)) {
|
||||||
|
qCritical("Could not open file %s [%s]", qPrintable(filePayload->fileName()), qPrintable(filePayload->errorString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
openedFile = true;
|
||||||
|
}
|
||||||
|
QByteArray data = filePayload->readAll();
|
||||||
|
if (openedFile) filePayload->close();
|
||||||
|
params.insert(payloadField, HttpParameter(data, true, db.mimeTypeForData(data).name(), filePayload->fileName()));
|
||||||
|
|
||||||
|
if (replyToMessageId >= 0) params.insert("reply_to_message_id", HttpParameter(replyToMessageId));
|
||||||
|
if (replyMarkup.isValid()) params.insert("reply_markup", HttpParameter(replyMarkup.serialize()));
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(endpoint, params, Networking::UPLOAD));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::_sendPayload(QVariant chatId, QString textPayload, ParameterList params, qint32 replyToMessageId, const GenericReply &replyMarkup, QString payloadField, QString endpoint)
|
||||||
|
{
|
||||||
|
if (chatId.type() != QVariant::String && chatId.type() != QVariant::Int) {
|
||||||
|
qCritical("Please provide a QString or int as chatId");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
params.insert("chat_id", HttpParameter(chatId));
|
||||||
|
params.insert(payloadField, HttpParameter(textPayload));
|
||||||
|
if (replyToMessageId >= 0) params.insert("reply_to_message_id", HttpParameter(replyToMessageId));
|
||||||
|
if (replyMarkup.isValid()) params.insert("reply_markup", HttpParameter(replyMarkup.serialize()));
|
||||||
|
|
||||||
|
bool success = this->responseOk(m_net->request(endpoint, params, Networking::POST));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Bot::jsonObjectFromByteArray(QByteArray json)
|
||||||
|
{
|
||||||
|
QJsonDocument d = QJsonDocument::fromJson(json);
|
||||||
|
QJsonObject obj = d.object();
|
||||||
|
|
||||||
|
if (obj.isEmpty()) {
|
||||||
|
qCritical("Got an empty response object");
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.value("ok").toBool() != true) {
|
||||||
|
qWarning("Result is not Ok");
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj.value("result").toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray Bot::jsonArrayFromByteArray(QByteArray json)
|
||||||
|
{
|
||||||
|
QJsonDocument d = QJsonDocument::fromJson(json);
|
||||||
|
QJsonObject obj = d.object();
|
||||||
|
|
||||||
|
if (obj.isEmpty()) {
|
||||||
|
qCritical("Got an empty response object");
|
||||||
|
return QJsonArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.value("ok").toBool() != true) {
|
||||||
|
qWarning("Result is not Ok");
|
||||||
|
return QJsonArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj.value("result").toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::responseOk(QByteArray json)
|
||||||
|
{
|
||||||
|
QJsonDocument d = QJsonDocument::fromJson(json);
|
||||||
|
QJsonObject obj = d.object();
|
||||||
|
|
||||||
|
return (!obj.isEmpty() && obj.value("ok").toBool() == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bot::internalGetUpdates()
|
||||||
|
{
|
||||||
|
QList<Update> updates = getUpdates(m_pollingTimeout, 50, m_updateOffset);
|
||||||
|
|
||||||
|
foreach (Update u, updates) {
|
||||||
|
// change updateOffset to u.id to avoid duplicate updates
|
||||||
|
m_updateOffset = (u.id >= m_updateOffset ? u.id + 1 : m_updateOffset);
|
||||||
|
|
||||||
|
emit message(u.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_internalUpdateTimer->start(m_updateInterval);
|
||||||
|
}
|
309
qttelegrambot.h
Normal file
309
qttelegrambot.h
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
#ifndef QTTELEGRAMBOT_H
|
||||||
|
#define QTTELEGRAMBOT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QHttpPart>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "networking.h"
|
||||||
|
#include "types/chat.h"
|
||||||
|
#include "types/update.h"
|
||||||
|
#include "types/user.h"
|
||||||
|
#include "types/file.h"
|
||||||
|
#include "types/message.h"
|
||||||
|
#include "types/reply/genericreply.h"
|
||||||
|
#include "types/reply/replykeyboardmarkup.h"
|
||||||
|
#include "types/reply/replykeyboardhide.h"
|
||||||
|
#include "types/reply/forcereply.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
typedef QList<QList<PhotoSize> > UserProfilePhotos;
|
||||||
|
|
||||||
|
class Bot : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Bot constructor
|
||||||
|
* @param token
|
||||||
|
* @param updates - enable automatic update polling
|
||||||
|
* @param updateInterval - interval between update polls in msec
|
||||||
|
* @param pollingTimeout - timeout in sec
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
explicit Bot(QString token, bool updates = false, quint32 updateInterval = 1000, quint32 pollingTimeout = 0, QObject *parent = 0);
|
||||||
|
~Bot();
|
||||||
|
|
||||||
|
enum ChatAction { Typing, UploadingPhoto, RecordingVideo, UploadingVideo, RecordingAudio, UploadingAudio, UploadingDocument, FindingLocation };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns basic information about the bot in form of a `User` object.
|
||||||
|
* @return User Object
|
||||||
|
* @see https://core.telegram.org/bots/api#getme
|
||||||
|
*/
|
||||||
|
User getMe();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send text message.
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param text - Text of the message to be sent
|
||||||
|
* @param markdown - Use markdown in message display (only Telegram for Android supports this)
|
||||||
|
* @param disableWebPagePreview - Disables link previews for links in this message
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendmessage
|
||||||
|
*/
|
||||||
|
bool sendMessage(QVariant chatId, QString text, bool markdown = false, bool disableWebPagePreview = false, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward messages of any kind.
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fromChatId - Unique identifier for the chat where the original message was sent
|
||||||
|
* @param messageId - Unique message identifier
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#forwardmessage
|
||||||
|
*/
|
||||||
|
bool forwardMessage(QVariant chatId, quint32 fromChatId, quint32 messageId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a photo
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param file - A file to send
|
||||||
|
* @param caption - Photo caption
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendphoto
|
||||||
|
*/
|
||||||
|
bool sendPhoto(QVariant chatId, QFile *file, QString caption = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a photo
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param caption - Photo caption
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendphoto
|
||||||
|
*/
|
||||||
|
bool sendPhoto(QVariant chatId, QString fileId, QString caption = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send audio
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param file - A file to send
|
||||||
|
* @param duration - Duration of the audio in seconds
|
||||||
|
* @param performer - Performer of the audio
|
||||||
|
* @param title - Track name of the audio
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendaudio
|
||||||
|
*/
|
||||||
|
bool sendAudio(QVariant chatId, QFile *file, qint64 duration = -1, QString performer = QString(), QString title = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send audio
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent audio
|
||||||
|
* @param duration - Duration of the audio in seconds
|
||||||
|
* @param performer - Performer of the audio
|
||||||
|
* @param title - Track name of the audio
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendaudio
|
||||||
|
*/
|
||||||
|
bool sendAudio(QVariant chatId, QString fileId, qint64 duration = -1, QString performer = QString(), QString title = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a document
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param file - A file to send
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#senddocument
|
||||||
|
*/
|
||||||
|
bool sendDocument(QVariant chatId, QFile *file, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a document
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#senddocument
|
||||||
|
*/
|
||||||
|
bool sendDocument(QVariant chatId, QString fileId, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a sticker
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param file - A file to send
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendsticker
|
||||||
|
*/
|
||||||
|
bool sendSticker(QVariant chatId, QFile *file, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a sticker
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendsticker
|
||||||
|
*/
|
||||||
|
bool sendSticker(QVariant chatId, QString fileId, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a video
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param duration - Duration of sent video in seconds
|
||||||
|
* @param caption - Video caption
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendvideo
|
||||||
|
*/
|
||||||
|
bool sendVideo(QVariant chatId, QFile *file, qint64 duration = -1, QString caption = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a video
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param duration - Duration of sent video in seconds
|
||||||
|
* @param caption - Video caption
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendvideo
|
||||||
|
*/
|
||||||
|
bool sendVideo(QVariant chatId, QString fileId, qint64 duration = -1, QString caption = QString(), qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a voice
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param duration - Duration of sent audio in seconds
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendvoice
|
||||||
|
*/
|
||||||
|
bool sendVoice(QVariant chatId, QFile *file, qint64 duration = -1, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a voice
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param fileId - Telegram file_id of already sent photo
|
||||||
|
* @param duration - Duration of sent audio in seconds
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendvoice
|
||||||
|
*/
|
||||||
|
bool sendVoice(QVariant chatId, QString fileId, qint64 duration = -1, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a location
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param latitude - latitude of the location
|
||||||
|
* @param longitude - longitude of the location
|
||||||
|
* @param replyToMessageId - If the message is a reply, ID of the original message
|
||||||
|
* @param replyMarkup - Additional interface options
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendlocation
|
||||||
|
*/
|
||||||
|
bool sendLocation(QVariant chatId, float latitude, float longitude, qint32 replyToMessageId = -1, const GenericReply &replyMarkup = GenericReply());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method when you need to tell the user that something is happening on the bot's side.
|
||||||
|
* @param chatId - Unique identifier for the message recipient or @channelname
|
||||||
|
* @param action - Type of action to broadcast
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#sendchataction
|
||||||
|
*/
|
||||||
|
bool sendChatAction(QVariant chatId, ChatAction action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to get a list of profile pictures for a user.
|
||||||
|
* @param userId - Unique identifier of the target user
|
||||||
|
* @param offset - Sequential number of the first photo to be returned.
|
||||||
|
* @param limit - Limits the number of photos to be retrieved. Values between 1—100 are accepted. Defaults to 100.
|
||||||
|
* @return UserProfilePhotos list
|
||||||
|
* @see Use this method to get a list of profile pictures for a user.
|
||||||
|
*/
|
||||||
|
UserProfilePhotos getUserProfilePhotos(quint32 userId, qint16 offset = -1, qint8 limit = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to receive incoming updates using long polling
|
||||||
|
* @param timeout - Timeout in seconds for long polling.
|
||||||
|
* @param limit - Limits the number of updates to be retrieved.
|
||||||
|
* @param offset - Identifier of the first update to be returned.
|
||||||
|
* @return List of Update objects
|
||||||
|
* @see https://core.telegram.org/bots/api#getupdates
|
||||||
|
*/
|
||||||
|
QList<Update> getUpdates(quint32 timeout, quint32 limit, quint32 offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to specify a url and receive incoming updates via an outgoing webhook.
|
||||||
|
* @param url - HTTPS url to send updates to. Use an empty string to remove webhook integration
|
||||||
|
* @param certificate - Upload your public key certificate so that the root certificate in use can be checked.
|
||||||
|
* @return success
|
||||||
|
* @see https://core.telegram.org/bots/api#setwebhook
|
||||||
|
*/
|
||||||
|
bool setWebhook(QString url, QFile *certificate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to get basic info about a file and prepare it for downloading.
|
||||||
|
* @param fileId - File identifier to get info about
|
||||||
|
* @return File object
|
||||||
|
* @see https://core.telegram.org/bots/api#getfile
|
||||||
|
*/
|
||||||
|
File getFile(QString fileId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Networking *m_net;
|
||||||
|
|
||||||
|
bool _sendPayload(QVariant chatId, QFile *filePayload, ParameterList params, qint32 replyToMessageId, const GenericReply &replyMarkup, QString payloadField, QString endpoint);
|
||||||
|
bool _sendPayload(QVariant chatId, QString textPayload, ParameterList params, qint32 replyToMessageId, const GenericReply &replyMarkup, QString payloadField, QString endpoint);
|
||||||
|
|
||||||
|
QJsonObject jsonObjectFromByteArray(QByteArray json);
|
||||||
|
QJsonArray jsonArrayFromByteArray(QByteArray json);
|
||||||
|
bool responseOk(QByteArray json);
|
||||||
|
|
||||||
|
void internalGetUpdates();
|
||||||
|
QTimer *m_internalUpdateTimer;
|
||||||
|
quint32 m_updateInterval;
|
||||||
|
quint32 m_updateOffset;
|
||||||
|
quint32 m_pollingTimeout;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void message(Message message);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QTTELEGRAMBOT_H
|
13
types/audio.cpp
Normal file
13
types/audio.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Audio::Audio(QJsonObject audio)
|
||||||
|
{
|
||||||
|
fileId = audio.value("file_id").toString();
|
||||||
|
duration = audio.value("duration").toInt();
|
||||||
|
performer = audio.value("performer").toString();
|
||||||
|
title = audio.value("title").toString();
|
||||||
|
mimeType = audio.value("mime_type").toString();
|
||||||
|
fileSize = audio.value("file_size").toInt();
|
||||||
|
}
|
39
types/audio.h
Normal file
39
types/audio.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef AUDIO_H
|
||||||
|
#define AUDIO_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Audio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Audio() {}
|
||||||
|
Audio(QJsonObject audio);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
quint64 duration;
|
||||||
|
QString performer;
|
||||||
|
QString title;
|
||||||
|
QString mimeType;
|
||||||
|
quint64 fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Audio &audio)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Audio(fileId=%1; duration=%2; performer=%3; title=%4; mimeType=%5; fileSize=%6)")
|
||||||
|
.arg(audio.fileId)
|
||||||
|
.arg(audio.duration)
|
||||||
|
.arg(audio.performer)
|
||||||
|
.arg(audio.title)
|
||||||
|
.arg(audio.mimeType)
|
||||||
|
.arg(audio.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // AUDIO_H
|
15
types/chat.cpp
Normal file
15
types/chat.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "chat.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Chat::Chat(QJsonObject chat)
|
||||||
|
{
|
||||||
|
id = chat.value("id").toInt();
|
||||||
|
QString chatType = chat.value("type").toString();
|
||||||
|
if (chatType == "private") type = Private;
|
||||||
|
else if (chatType == "group") type = Group;
|
||||||
|
else if (chatType == "channel") type = Channel;
|
||||||
|
username = chat.value("username").toString();
|
||||||
|
firstname = chat.value("first_name").toString();
|
||||||
|
lastname = chat.value("last_name").toString();
|
||||||
|
}
|
43
types/chat.h
Normal file
43
types/chat.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef CHAT_H
|
||||||
|
#define CHAT_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Chat
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Chat() {}
|
||||||
|
Chat(QJsonObject chat);
|
||||||
|
|
||||||
|
enum ChatType {
|
||||||
|
Private, Group, Channel
|
||||||
|
};
|
||||||
|
|
||||||
|
quint32 id;
|
||||||
|
ChatType type;
|
||||||
|
QString title;
|
||||||
|
QString username;
|
||||||
|
QString firstname;
|
||||||
|
QString lastname;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Chat &chat)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Chat(id=%1; type=%2; title=%3; username=%4; firstname=%5; lastname=%6)")
|
||||||
|
.arg(chat.id)
|
||||||
|
.arg(chat.type)
|
||||||
|
.arg(chat.title)
|
||||||
|
.arg(chat.username)
|
||||||
|
.arg(chat.firstname)
|
||||||
|
.arg(chat.lastname));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CHAT_H
|
11
types/contact.cpp
Normal file
11
types/contact.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "contact.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Contact::Contact(QJsonObject contact)
|
||||||
|
{
|
||||||
|
phoneNumber = contact.value("phone_number").toString();
|
||||||
|
firstname = contact.value("first_name").toString();
|
||||||
|
lastname = contact.value("last_name").toString();
|
||||||
|
userId = contact.value("user_id").toInt();
|
||||||
|
}
|
35
types/contact.h
Normal file
35
types/contact.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef CONTACT_H
|
||||||
|
#define CONTACT_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Contact
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Contact() {}
|
||||||
|
Contact(QJsonObject contact);
|
||||||
|
|
||||||
|
QString phoneNumber;
|
||||||
|
QString firstname;
|
||||||
|
QString lastname;
|
||||||
|
quint32 userId;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Contact &contact)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Contact(phoneNumber=%1; firstname=%2; lastname=%3; userId=%4)")
|
||||||
|
.arg(contact.phoneNumber)
|
||||||
|
.arg(contact.firstname)
|
||||||
|
.arg(contact.lastname)
|
||||||
|
.arg(contact.userId));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONTACT_H
|
12
types/document.cpp
Normal file
12
types/document.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "document.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Document::Document(QJsonObject document)
|
||||||
|
{
|
||||||
|
fileId = document.value("file_id").toString();
|
||||||
|
thumb = PhotoSize(document.value("thumb").toObject());
|
||||||
|
fileName = document.value("file_name").toString();
|
||||||
|
mimeType = document.value("mime_type").toString();
|
||||||
|
fileSize = document.value("file_size").toInt();
|
||||||
|
}
|
38
types/document.h
Normal file
38
types/document.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef DOCUMENT_H
|
||||||
|
#define DOCUMENT_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "photosize.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Document
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Document() {}
|
||||||
|
Document(QJsonObject document);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
PhotoSize thumb;
|
||||||
|
QString fileName;
|
||||||
|
QString mimeType;
|
||||||
|
quint64 fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Document &document)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Document(fileId=%1; thumb=%2; fileName=%3; mimeType=%4; fileSize=%5)")
|
||||||
|
.arg(document.fileId)
|
||||||
|
.arg("PhotoSize(" + document.thumb.fileId + ")")
|
||||||
|
.arg(document.fileName)
|
||||||
|
.arg(document.mimeType)
|
||||||
|
.arg(document.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOCUMENT_H
|
32
types/file.h
Normal file
32
types/file.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef FILE_H
|
||||||
|
#define FILE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
File(QString fileId, qint64 fileSize = -1, QString filePath = QString()) :
|
||||||
|
fileId(fileId), fileSize(fileSize), filePath(filePath) {}
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
qint64 fileSize;
|
||||||
|
QString filePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const File &file)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::File(fileId=%1; fileSize=%2; filePath=%3)")
|
||||||
|
.arg(file.fileId)
|
||||||
|
.arg(file.fileSize)
|
||||||
|
.arg(file.filePath));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FILE_H
|
9
types/location.cpp
Normal file
9
types/location.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "location.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Location::Location(QJsonObject location)
|
||||||
|
{
|
||||||
|
longitude = location.value("longitude").toDouble();
|
||||||
|
latitude = location.value("latitude").toDouble();
|
||||||
|
}
|
31
types/location.h
Normal file
31
types/location.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef LOCATION_H
|
||||||
|
#define LOCATION_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Location
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Location() {}
|
||||||
|
Location(QJsonObject location);
|
||||||
|
|
||||||
|
float longitude;
|
||||||
|
float latitude;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Location &location)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Location(longitude=%1; latitude=%2)")
|
||||||
|
.arg(location.longitude)
|
||||||
|
.arg(location.latitude));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LOCATION_H
|
116
types/message.cpp
Normal file
116
types/message.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include "message.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Message::Message(QJsonObject message)
|
||||||
|
{
|
||||||
|
id = message.value("message_id").toInt();
|
||||||
|
date = QDateTime::fromMSecsSinceEpoch(message.value("date").toInt());
|
||||||
|
chat = Chat(message.value("chat").toObject());
|
||||||
|
|
||||||
|
/**
|
||||||
|
x audio Audio Optional. Message is an audio file, information about the file
|
||||||
|
document Document Optional. Message is a general file, information about the file
|
||||||
|
photo Array of PhotoSize Optional. Message is a photo, available sizes of the photo
|
||||||
|
sticker Sticker Optional. Message is a sticker, information about the sticker
|
||||||
|
video Video Optional. Message is a video, information about the video
|
||||||
|
voice Voice Optional. Message is a voice message, information about the file
|
||||||
|
caption String Optional. Caption for the photo or video
|
||||||
|
contact Contact Optional. Message is a shared contact, information about the contact
|
||||||
|
location Location Optional. Message is a shared location, information about the location
|
||||||
|
new_chat_participant User Optional. A new member was added to the group, information about them (this member may be bot itself)
|
||||||
|
left_chat_participant User Optional. A member was removed from the group, information about them (this member may be bot itself)
|
||||||
|
new_chat_photo Array of PhotoSize Optional. A chat photo was change to this value
|
||||||
|
delete_chat_photo True Optional. Informs that the chat photo was deleted
|
||||||
|
group_chat_created True Optional. Informs that the group has been created
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (message.contains("from")) {
|
||||||
|
from = User(message.value("from").toObject());
|
||||||
|
}
|
||||||
|
if (message.contains("forward_from")) {
|
||||||
|
forwardFrom = User(message.value("forward_from").toObject());
|
||||||
|
}
|
||||||
|
if (message.contains("forward_date")) {
|
||||||
|
forwardDate = QDateTime::fromMSecsSinceEpoch(message.value("forward_date").toInt());
|
||||||
|
}
|
||||||
|
if (message.contains("reply_to_message")) {
|
||||||
|
replyToMessage = new Message(message.value("reply_to_message").toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse payload
|
||||||
|
QJsonObject obj;
|
||||||
|
if (message.contains("text")) {
|
||||||
|
string = message.value("text").toString();
|
||||||
|
type = Message::TextType;
|
||||||
|
}
|
||||||
|
if (message.contains("audio")) {
|
||||||
|
obj = message.value("audio").toObject();
|
||||||
|
audio = Audio(obj);
|
||||||
|
type = Message::AudioType;
|
||||||
|
}
|
||||||
|
if (message.contains("document")) {
|
||||||
|
obj = message.value("document").toObject();
|
||||||
|
document = Document(obj);
|
||||||
|
type = Message::DocumentType;
|
||||||
|
}
|
||||||
|
if (message.contains("photo")) {
|
||||||
|
foreach (QJsonValue val, message.value("photo").toArray()) {
|
||||||
|
photo.append(PhotoSize(val.toObject()));
|
||||||
|
}
|
||||||
|
type = Message::PhotoType;
|
||||||
|
}
|
||||||
|
if (message.contains("sticker")) {
|
||||||
|
obj = message.value("sticker").toObject();
|
||||||
|
sticker = Sticker(obj);
|
||||||
|
type = Message::StickerType;
|
||||||
|
}
|
||||||
|
if (message.contains("video")) {
|
||||||
|
obj = message.value("video").toObject();
|
||||||
|
video = Video(obj);
|
||||||
|
type = Message::VideoType;
|
||||||
|
}
|
||||||
|
if (message.contains("voice")) {
|
||||||
|
obj = message.value("voice").toObject();
|
||||||
|
voice = Voice(obj);
|
||||||
|
type = Message::VoiceType;
|
||||||
|
}
|
||||||
|
if (message.contains("contact")) {
|
||||||
|
obj = message.value("contact").toObject();
|
||||||
|
contact = Contact(obj);
|
||||||
|
type = Message::ContactType;
|
||||||
|
}
|
||||||
|
if (message.contains("location")) {
|
||||||
|
obj = message.value("location").toObject();
|
||||||
|
location = Location(obj);
|
||||||
|
type = Message::LocationType;
|
||||||
|
}
|
||||||
|
if (message.contains("new_chat_participant")) {
|
||||||
|
obj = message.value("new_chat_participant").toObject();
|
||||||
|
user = User(obj);
|
||||||
|
type = Message::NewChatParticipantType;
|
||||||
|
}
|
||||||
|
if (message.contains("left_chat_participant")) {
|
||||||
|
obj = message.value("left_chat_participant").toObject();
|
||||||
|
user = User(obj);
|
||||||
|
type = Message::LeftChatParticipantType;
|
||||||
|
}
|
||||||
|
if (message.contains("new_chat_title")) {
|
||||||
|
string = message.value("new_chat_title").toString();
|
||||||
|
type = Message::NewChatTitleType;
|
||||||
|
}
|
||||||
|
if (message.contains("new_chat_photo")) {
|
||||||
|
foreach (QJsonValue val, message.value("new_chat_photo").toArray()) {
|
||||||
|
photo.append(PhotoSize(val.toObject()));
|
||||||
|
}
|
||||||
|
type = Message::NewChatPhotoType;
|
||||||
|
}
|
||||||
|
if (message.contains("delete_chat_photo")) {
|
||||||
|
boolean = true;
|
||||||
|
type = Message::DeleteChatPhotoType;
|
||||||
|
}
|
||||||
|
if (message.contains("group_chat_created")) {
|
||||||
|
boolean = true;
|
||||||
|
type = Message::GroupChatCreatedType;
|
||||||
|
}
|
||||||
|
}
|
79
types/message.h
Normal file
79
types/message.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef MESSAGE_H
|
||||||
|
#define MESSAGE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
#include "document.h"
|
||||||
|
#include "photosize.h"
|
||||||
|
#include "sticker.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "voice.h"
|
||||||
|
#include "contact.h"
|
||||||
|
#include "location.h"
|
||||||
|
#include "chat.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Message
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Message() {}
|
||||||
|
Message(QJsonObject message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Telegram message events
|
||||||
|
*/
|
||||||
|
enum MessageType {
|
||||||
|
TextType, AudioType, DocumentType, PhotoType, StickerType, VideoType, VoiceType, ContactType,
|
||||||
|
LocationType, NewChatParticipantType, LeftChatParticipantType, NewChatTitleType,
|
||||||
|
NewChatPhotoType, DeleteChatPhotoType, GroupChatCreatedType
|
||||||
|
};
|
||||||
|
|
||||||
|
// required
|
||||||
|
quint32 id;
|
||||||
|
QDateTime date;
|
||||||
|
Chat chat;
|
||||||
|
|
||||||
|
// optional
|
||||||
|
User from;
|
||||||
|
User forwardFrom;
|
||||||
|
QDateTime forwardDate;
|
||||||
|
Message *replyToMessage;
|
||||||
|
|
||||||
|
MessageType type;
|
||||||
|
|
||||||
|
// payload
|
||||||
|
QString string;
|
||||||
|
User user;
|
||||||
|
Audio audio;
|
||||||
|
Document document;
|
||||||
|
QList<PhotoSize> photo;
|
||||||
|
Sticker sticker;
|
||||||
|
Video video;
|
||||||
|
Voice voice;
|
||||||
|
Contact contact;
|
||||||
|
Location location;
|
||||||
|
bool boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Message &message)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Message(id=%1; date=%2; chat=%3; type=%4)")
|
||||||
|
.arg(message.id)
|
||||||
|
.arg(message.date.toString("dd.MM.yyyy hh:mm:ss"))
|
||||||
|
.arg("Chat(" + QString::number(message.chat.id) + ")")
|
||||||
|
.arg(message.type));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MESSAGE_H
|
11
types/photosize.cpp
Normal file
11
types/photosize.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "photosize.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
PhotoSize::PhotoSize(QJsonObject photoSize)
|
||||||
|
{
|
||||||
|
fileId = photoSize.value("file_id").toString();
|
||||||
|
width = photoSize.value("width").toInt();
|
||||||
|
height = photoSize.value("height").toInt();
|
||||||
|
fileSize = photoSize.value("file_size").toInt();
|
||||||
|
}
|
35
types/photosize.h
Normal file
35
types/photosize.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef PHOTOSIZE_H
|
||||||
|
#define PHOTOSIZE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class PhotoSize
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhotoSize() {}
|
||||||
|
PhotoSize(QJsonObject photoSize);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
quint16 width;
|
||||||
|
quint16 height;
|
||||||
|
quint64 fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const PhotoSize &photoSize)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::PhotoSize(fileId=%1; width=%2; height=%3; fileSize=%4)")
|
||||||
|
.arg(photoSize.fileId)
|
||||||
|
.arg(photoSize.width)
|
||||||
|
.arg(photoSize.height)
|
||||||
|
.arg(photoSize.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PHOTOSIZE_H
|
31
types/reply/forcereply.h
Normal file
31
types/reply/forcereply.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef FORCEREPLY
|
||||||
|
#define FORCEREPLY
|
||||||
|
|
||||||
|
#include "genericreply.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class ForceReply : public GenericReply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ForceReply(bool selective = false)
|
||||||
|
: GenericReply(selective),
|
||||||
|
forceReply(true) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows reply interface to the user, as if they manually selected the bot‘s message and tapped ’Reply'
|
||||||
|
*/
|
||||||
|
const bool forceReply;
|
||||||
|
|
||||||
|
virtual QString serialize() const {
|
||||||
|
QJsonObject o = QJsonObject();
|
||||||
|
o.insert("force_reply", forceReply);
|
||||||
|
o.insert("selective", selective);
|
||||||
|
return serializeJson(o);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FORCEREPLY
|
||||||
|
|
44
types/reply/genericreply.h
Normal file
44
types/reply/genericreply.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef GENERICREPLY_H
|
||||||
|
#define GENERICREPLY_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class GenericReply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GenericReply() : valid(false) {}
|
||||||
|
GenericReply(bool selective) : selective(selective), valid(true) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Use this parameter if you want to show the keyboard to specific users only.
|
||||||
|
* Targets: 1) users that are @mentioned in the text of the Message object;
|
||||||
|
* 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message.
|
||||||
|
*/
|
||||||
|
bool selective;
|
||||||
|
|
||||||
|
virtual QString serialize() const {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() const {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool valid;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QByteArray serializeJson(QJsonObject o) const {
|
||||||
|
QJsonDocument d = QJsonDocument(o);
|
||||||
|
return d.toJson(QJsonDocument::Compact);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GENERICREPLY_H
|
30
types/reply/replykeyboardhide.h
Normal file
30
types/reply/replykeyboardhide.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef REPLYKEYBOARDHIDE
|
||||||
|
#define REPLYKEYBOARDHIDE
|
||||||
|
|
||||||
|
#include "genericreply.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class ReplyKeyboardHide : public GenericReply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReplyKeyboardHide(bool selective = false)
|
||||||
|
: GenericReply(selective),
|
||||||
|
hideKeyboard(true) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests clients to hide the custom keyboard
|
||||||
|
*/
|
||||||
|
const bool hideKeyboard;
|
||||||
|
|
||||||
|
virtual QString serialize() const {
|
||||||
|
QJsonObject o = QJsonObject();
|
||||||
|
o.insert("hide_keyboard", hideKeyboard);
|
||||||
|
o.insert("selective", selective);
|
||||||
|
return serializeJson(o);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // REPLYKEYBOARDHIDE
|
54
types/reply/replykeyboardmarkup.h
Normal file
54
types/reply/replykeyboardmarkup.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef REPLYKEYBOARDMARKUP_H
|
||||||
|
#define REPLYKEYBOARDMARKUP_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "genericreply.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
typedef QList<QStringList> KeyboardMarkup;
|
||||||
|
|
||||||
|
class ReplyKeyboardMarkup : public GenericReply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReplyKeyboardMarkup(KeyboardMarkup keyboard, bool resizeKeyboard = false, bool oneTimeKeyboard = false, bool selective = false)
|
||||||
|
: GenericReply(selective),
|
||||||
|
keyboard(keyboard),
|
||||||
|
resizeKeyboard(resizeKeyboard),
|
||||||
|
oneTimeKeyboard(oneTimeKeyboard) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of button rows, each represented by an Array of Strings
|
||||||
|
*/
|
||||||
|
KeyboardMarkup keyboard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Requests clients to resize the keyboard vertically for optimal fit (e.g., make the keyboard smaller if there are just two rows of buttons).
|
||||||
|
* Defaults to false, in which case the custom keyboard is always of the same height as the app's standard keyboard.
|
||||||
|
*/
|
||||||
|
bool resizeKeyboard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Requests clients to hide the keyboard as soon as it's been used.
|
||||||
|
* Defaults to false.
|
||||||
|
*/
|
||||||
|
bool oneTimeKeyboard;
|
||||||
|
|
||||||
|
virtual QString serialize() const {
|
||||||
|
QJsonObject o = QJsonObject();
|
||||||
|
QJsonArray keyboardMarkup = QJsonArray();
|
||||||
|
foreach (QStringList list, keyboard) {
|
||||||
|
keyboardMarkup.append(QJsonArray::fromStringList(list));
|
||||||
|
}
|
||||||
|
o.insert("keyboard", keyboardMarkup);
|
||||||
|
o.insert("resize_keyboard", resizeKeyboard);
|
||||||
|
o.insert("one_time_keyboard", oneTimeKeyboard);
|
||||||
|
o.insert("selective", selective);
|
||||||
|
return serializeJson(o);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // REPLYKEYBOARDMARKUP_H
|
12
types/sticker.cpp
Normal file
12
types/sticker.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "sticker.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Sticker::Sticker(QJsonObject sticker)
|
||||||
|
{
|
||||||
|
fileId = sticker.value("file_id").toString();
|
||||||
|
width = sticker.value("width").toInt();
|
||||||
|
height = sticker.value("height").toInt();
|
||||||
|
thumb = PhotoSize(sticker.value("thumb").toObject());
|
||||||
|
fileSize = sticker.value("file_size").toInt();
|
||||||
|
}
|
38
types/sticker.h
Normal file
38
types/sticker.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef STICKER_H
|
||||||
|
#define STICKER_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "photosize.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Sticker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sticker() {}
|
||||||
|
Sticker(QJsonObject sticker);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
quint16 width;
|
||||||
|
quint16 height;
|
||||||
|
PhotoSize thumb;
|
||||||
|
quint64 fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Sticker &sticker)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Sticker(fileId=%1; width=%2; height=%3; thumb=%4; fileSize=%5)")
|
||||||
|
.arg(sticker.fileId)
|
||||||
|
.arg(sticker.width)
|
||||||
|
.arg(sticker.height)
|
||||||
|
.arg("PhotoSize(" + sticker.thumb.fileId + ")")
|
||||||
|
.arg(sticker.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STICKER_H
|
9
types/update.cpp
Normal file
9
types/update.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "update.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Update::Update(QJsonObject update)
|
||||||
|
{
|
||||||
|
id = update.value("update_id").toInt();
|
||||||
|
message = Message(update.value("message").toObject());
|
||||||
|
}
|
31
types/update.h
Normal file
31
types/update.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef UPDATE_H
|
||||||
|
#define UPDATE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "message.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Update
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Update() {}
|
||||||
|
Update(QJsonObject update);
|
||||||
|
|
||||||
|
quint32 id;
|
||||||
|
Message message;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Update &update)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Update(id=%1; message=%2)")
|
||||||
|
.arg(update.id)
|
||||||
|
.arg("Message(" + QString::number(update.message.id) + ")"));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UPDATE_H
|
11
types/user.cpp
Normal file
11
types/user.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "user.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Telegram::User::User(QJsonObject user)
|
||||||
|
{
|
||||||
|
id = user.value("id").toInt();
|
||||||
|
firstname = user.value("first_name").toString();
|
||||||
|
lastname = user.value("last_name").toString();
|
||||||
|
username = user.value("username").toString();
|
||||||
|
}
|
35
types/user.h
Normal file
35
types/user.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef USER_H
|
||||||
|
#define USER_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class User
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
User() : id(0), firstname(QString()), lastname(QString()), username(QString()) {}
|
||||||
|
User(QJsonObject user);
|
||||||
|
|
||||||
|
quint32 id;
|
||||||
|
QString firstname;
|
||||||
|
QString lastname;
|
||||||
|
QString username;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const User &user)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::User(id=%1; firstname=%2; lastname=%3; username=%4)")
|
||||||
|
.arg(user.id)
|
||||||
|
.arg(user.firstname)
|
||||||
|
.arg(user.lastname)
|
||||||
|
.arg(user.username));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USER_H
|
14
types/video.cpp
Normal file
14
types/video.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Video::Video(QJsonObject video)
|
||||||
|
{
|
||||||
|
fileId = video.value("file_id").toString();
|
||||||
|
width = video.value("width").toInt();
|
||||||
|
height = video.value("height").toInt();
|
||||||
|
duration = video.value("duration").toInt();
|
||||||
|
thumb = PhotoSize(video.value("thumb").toObject());
|
||||||
|
mimeType = video.value("mime_type").toString();
|
||||||
|
fileSize = video.value("file_size").toInt();
|
||||||
|
}
|
41
types/video.h
Normal file
41
types/video.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef VIDEO_H
|
||||||
|
#define VIDEO_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "photosize.h"
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Video
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Video() {}
|
||||||
|
Video(QJsonObject video);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
quint16 width;
|
||||||
|
quint16 height;
|
||||||
|
quint64 duration;
|
||||||
|
PhotoSize thumb;
|
||||||
|
QString mimeType;
|
||||||
|
QString fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Video &video)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Video(fileId=%1; width=%2; height=%3; duration=%4; thumb=%5; mimeType=%6; fileSize=%7)")
|
||||||
|
.arg(video.fileId)
|
||||||
|
.arg(video.width)
|
||||||
|
.arg(video.height)
|
||||||
|
.arg(video.duration)
|
||||||
|
.arg("PhotoSize(" + video.thumb.fileId + ")")
|
||||||
|
.arg(video.mimeType)
|
||||||
|
.arg(video.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VIDEO_H
|
11
types/voice.cpp
Normal file
11
types/voice.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "voice.h"
|
||||||
|
|
||||||
|
using namespace Telegram;
|
||||||
|
|
||||||
|
Voice::Voice(QJsonObject voice)
|
||||||
|
{
|
||||||
|
fileId = voice.value("file_id").toString();
|
||||||
|
duration = voice.value("duration").toInt();
|
||||||
|
mimeType = voice.value("mime_type").toString();
|
||||||
|
fileSize = voice.value("file_size").toInt();
|
||||||
|
}
|
35
types/voice.h
Normal file
35
types/voice.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef VOICE_H
|
||||||
|
#define VOICE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace Telegram {
|
||||||
|
|
||||||
|
class Voice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Voice() {}
|
||||||
|
Voice(QJsonObject voice);
|
||||||
|
|
||||||
|
QString fileId;
|
||||||
|
quint64 duration;
|
||||||
|
QString mimeType;
|
||||||
|
quint64 fileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<< (QDebug dbg, const Voice &voice)
|
||||||
|
{
|
||||||
|
dbg.nospace() << qUtf8Printable(QString("Telegram::Voice(fileId=%1; duration=%2; mimeType=%3; fileSize=%4)")
|
||||||
|
.arg(voice.fileId)
|
||||||
|
.arg(voice.duration)
|
||||||
|
.arg(voice.mimeType)
|
||||||
|
.arg(voice.fileSize));
|
||||||
|
|
||||||
|
return dbg.maybeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VOICE_H
|
Reference in New Issue
Block a user