git-svn-id: svn://db.shs.com.ru/libs@129 a8b55f48-bf90-11e4-a774-851b48703e85

This commit is contained in:
2016-10-19 13:20:53 +00:00
parent 81f9c82679
commit 724d9652bd
14 changed files with 2023 additions and 0 deletions

123
telegram_test/execbot.cpp Normal file
View File

@@ -0,0 +1,123 @@
#include "execbot.h"
#include <QDebug>
#include <QTextCodec>
ExecBot::ExecBot(QObject *parent) : TelegramBotBase(parent) {
}
QString ExecBot::loginMessage(uint id) {
if (sessions.contains(id)) {
if (sessions[id] == Password) return tr("Enter password");
if (sessions[id] == NotLogged) return tr("Please send me /start");
}
return tr("Error");
}
QString ExecBot::help() {
return tr("Input command for exec on server, after exec finished result will be sended to you");
}
bool ExecBot::loginUser(uint id, const QString &msg) {
if (sessions.contains(id)) {
switch (sessions[id]) {
case NotLogged:
if (msg == "/start") sessions[id] = Password;
break;
case Password:
if (msg == "a") {
sessions[id] = Ready;
return true;
}
break;
case Ready:
case CommandExec:
return true;
default:
break;
return false;
}
} else {
if (msg == "/start") sessions[id] = Password;
else sessions[id] = NotLogged;
}
return false;
}
void ExecBot::messageFromUser(uint id, const QString &msg) {
if (sessions.contains(id)) {
if (msg == "/exit") {
sessions[id] = NotLogged;
disconnectUser(id);
getAPI()->sendMessage(id, tr("Logout"));
return;
}
if (sessions[id] == CommandExec) {
if (msg == "/kill") {
int rm = -1;
for (int i=0; i<run_commands.size(); i++) {
if (run_commands[i].user == id) {
run_commands[i].cmd->kill();
getAPI()->sendMessage(id, tr("Process killed"));
sessions[id] = Ready;
rm = i;
}
}
if (rm >= 0) run_commands.remove(rm);
} else
getAPI()->sendMessage(id, tr("Command is running, please wait for finish"));
return;
}
if (sessions[id] == Ready) {
getAPI()->sendMessage(id, "exec: " + msg);
UserCommand uc;
uc.user = id;
uc.cmd = new QProcess();
// uc.cmd->setProcessChannelMode(QProcess::MergedChannels);
connect(uc.cmd, SIGNAL(readyRead()), this, SLOT(cmdRead()));
// connect(uc.cmd, SIGNAL(started()), this, SLOT(cmdStart()));
connect(uc.cmd, SIGNAL(finished(int)), this, SLOT(cmdFinish(int)));
uc.cmd->start(msg);
if (uc.cmd->waitForStarted(3000)) {
sessions[id] = CommandExec;
run_commands.append(uc);
} else getAPI()->sendMessage(id, tr("Can't run command %1").arg(msg));
}
}
}
void ExecBot::cmdRead() {
// qDebug() << "cmdRead()";
QProcess * p = (QProcess *)sender();
for (int i=0; i<run_commands.size(); i++) {
if (run_commands[i].cmd == p) {
int id = run_commands[i].user;
QTextCodec *codec = QTextCodec::codecForName("IBM 866");
QString s = codec->toUnicode(p->readAll());
getAPI()->sendMessage(id, s);
}
}
}
void ExecBot::cmdFinish(int code) {
qDebug() << "cmdFinish()" << code;
QProcess * p = (QProcess *)sender();
int rm = -1;
for (int i=0; i<run_commands.size(); i++) {
if (run_commands[i].cmd == p) {
int id = run_commands[i].user;
QTextCodec *codec = QTextCodec::codecForName("IBM 866");
QString s = codec->toUnicode(p->readAll());
getAPI()->sendMessage(id, s);
rm = i;
sessions[id] = Ready;
}
}
if (rm >= 0) run_commands.remove(rm);
}

46
telegram_test/execbot.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef EXECBOT_H
#define EXECBOT_H
#include "telegrambotbase.h"
#include <QProcess>
class ExecBot : public TelegramBotBase
{
Q_OBJECT
public:
explicit ExecBot(QObject *parent = 0);
public slots:
private:
enum UserState {
NotLogged,
Password,
Ready,
CommandExec
};
struct UserCommand {
uint user;
QProcess * cmd;
};
virtual QString loginMessage(uint id);
virtual QString help();
virtual bool loginUser(uint id, const QString & msg);
virtual void messageFromUser(uint id, const QString & msg);
void runCMD(UserCommand uc);
QMap<uint, UserState> sessions;
QVector<ExecBot::UserCommand> run_commands;
private slots:
void cmdRead();
void cmdFinish(int code);
signals:
};
#endif // EXECBOT_H

603
telegram_test/json.cpp Normal file
View File

@@ -0,0 +1,603 @@
/**
* QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
* Copyright (C) 2011 Eeli Reilin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file json.cpp
*/
#include <QDateTime>
#include <QStringList>
#include "json.h"
namespace QtJson {
static QString dateFormat, dateTimeFormat;
static QString sanitizeString(QString str);
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep);
static QVariant parseValue(const QString &json, int &index, bool &success);
static QVariant parseObject(const QString &json, int &index, bool &success);
static QVariant parseArray(const QString &json, int &index, bool &success);
static QVariant parseString(const QString &json, int &index, bool &success);
static QVariant parseNumber(const QString &json, int &index);
static int lastIndexOfNumber(const QString &json, int index);
static void eatWhitespace(const QString &json, int &index);
static int lookAhead(const QString &json, int index);
static int nextToken(const QString &json, int &index);
template<typename T>
QByteArray serializeMap(const T &map, bool &success) {
QByteArray str = "{ ";
QList<QByteArray> pairs;
for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) {
QByteArray serializedValue = serialize(it.value());
if (serializedValue.isNull()) {
success = false;
break;
}
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
}
str += join(pairs, ", ");
str += " }";
return str;
}
void insert(QVariant &v, const QString &key, const QVariant &value);
void append(QVariant &v, const QVariant &value);
template<typename T>
void cloneMap(QVariant &json, const T &map) {
for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) {
insert(json, it.key(), (*it));
}
}
template<typename T>
void cloneList(QVariant &json, const T &list) {
for (typename T::const_iterator it = list.begin(), itend = list.end(); it != itend; ++it) {
append(json, (*it));
}
}
/**
* parse
*/
QVariant parse(const QString &json) {
bool success = true;
return parse(json, success);
}
/**
* parse
*/
QVariant parse(const QString &json, bool &success) {
success = true;
// Return an empty QVariant if the JSON data is either null or empty
if (!json.isNull() || !json.isEmpty()) {
QString data = json;
// We'll start from index 0
int index = 0;
// Parse the first value
QVariant value = parseValue(data, index, success);
// Return the parsed value
return value;
} else {
// Return the empty QVariant
return QVariant();
}
}
/**
* clone
*/
QVariant clone(const QVariant &data) {
QVariant v;
if (data.type() == QVariant::Map) {
cloneMap(v, data.toMap());
} else if (data.type() == QVariant::Hash) {
cloneMap(v, data.toHash());
} else if (data.type() == QVariant::List) {
cloneList(v, data.toList());
} else if (data.type() == QVariant::StringList) {
cloneList(v, data.toStringList());
} else {
v = QVariant(data);
}
return v;
}
/**
* insert value (map case)
*/
void insert(QVariant &v, const QString &key, const QVariant &value) {
if (!v.canConvert<QVariantMap>()) v = QVariantMap();
QVariantMap *p = (QVariantMap *)v.data();
p->insert(key, clone(value));
}
/**
* append value (list case)
*/
void append(QVariant &v, const QVariant &value) {
if (!v.canConvert<QVariantList>()) v = QVariantList();
QVariantList *p = (QVariantList *)v.data();
p->append(value);
}
QByteArray serialize(const QVariant &data) {
bool success = true;
return serialize(data, success);
}
QByteArray serialize(const QVariant &data, bool &success) {
QByteArray str;
success = true;
if (!data.isValid()) { // invalid or null?
str = "null";
} else if ((data.type() == QVariant::List) ||
(data.type() == QVariant::StringList)) { // variant is a list?
QList<QByteArray> values;
const QVariantList list = data.toList();
Q_FOREACH(const QVariant& v, list) {
QByteArray serializedValue = serialize(v);
if (serializedValue.isNull()) {
success = false;
break;
}
values << serializedValue;
}
str = "[ " + join( values, ", " ) + " ]";
} else if (data.type() == QVariant::Hash) { // variant is a hash?
str = serializeMap<>(data.toHash(), success);
} else if (data.type() == QVariant::Map) { // variant is a map?
str = serializeMap<>(data.toMap(), success);
} else if ((data.type() == QVariant::String) ||
(data.type() == QVariant::ByteArray)) {// a string or a byte array?
str = sanitizeString(data.toString()).toUtf8();
} else if (data.type() == QVariant::Double) { // double?
double value = data.toDouble(&success);
if (success) {
str = QByteArray::number(value, 'g');
if (!str.contains(".") && ! str.contains("e")) {
str += ".0";
}
}
} else if (data.type() == QVariant::Bool) { // boolean value?
str = data.toBool() ? "true" : "false";
} else if (data.type() == QVariant::ULongLong) { // large unsigned number?
str = QByteArray::number(data.value<qulonglong>());
} else if (data.canConvert<qlonglong>()) { // any signed number?
str = QByteArray::number(data.value<qlonglong>());
} else if (data.canConvert<long>()) { //TODO: this code is never executed because all smaller types can be converted to qlonglong
str = QString::number(data.value<long>()).toUtf8();
} else if (data.type() == QVariant::DateTime) { // datetime value?
str = sanitizeString(dateTimeFormat.isEmpty()
? data.toDateTime().toString()
: data.toDateTime().toString(dateTimeFormat)).toUtf8();
} else if (data.type() == QVariant::Date) { // date value?
str = sanitizeString(dateTimeFormat.isEmpty()
? data.toDate().toString()
: data.toDate().toString(dateFormat)).toUtf8();
} else if (data.canConvert<QString>()) { // can value be converted to string?
// this will catch QUrl, ... (all other types which can be converted to string)
str = sanitizeString(data.toString()).toUtf8();
} else {
success = false;
}
if (success) {
return str;
}
return QByteArray();
}
QString serializeStr(const QVariant &data) {
return QString::fromUtf8(serialize(data));
}
QString serializeStr(const QVariant &data, bool &success) {
return QString::fromUtf8(serialize(data, success));
}
/**
* \enum JsonToken
*/
enum JsonToken {
JsonTokenNone = 0,
JsonTokenCurlyOpen = 1,
JsonTokenCurlyClose = 2,
JsonTokenSquaredOpen = 3,
JsonTokenSquaredClose = 4,
JsonTokenColon = 5,
JsonTokenComma = 6,
JsonTokenString = 7,
JsonTokenNumber = 8,
JsonTokenTrue = 9,
JsonTokenFalse = 10,
JsonTokenNull = 11
};
static QString sanitizeString(QString str) {
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
str.replace(QLatin1String("\""), QLatin1String("\\\""));
str.replace(QLatin1String("\b"), QLatin1String("\\b"));
str.replace(QLatin1String("\f"), QLatin1String("\\f"));
str.replace(QLatin1String("\n"), QLatin1String("\\n"));
str.replace(QLatin1String("\r"), QLatin1String("\\r"));
str.replace(QLatin1String("\t"), QLatin1String("\\t"));
return QString(QLatin1String("\"%1\"")).arg(str);
}
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep) {
QByteArray res;
Q_FOREACH(const QByteArray &i, list) {
if (!res.isEmpty()) {
res += sep;
}
res += i;
}
return res;
}
/**
* parseValue
*/
static QVariant parseValue(const QString &json, int &index, bool &success) {
// Determine what kind of data we should parse by
// checking out the upcoming token
switch(lookAhead(json, index)) {
case JsonTokenString:
return parseString(json, index, success);
case JsonTokenNumber:
return parseNumber(json, index);
case JsonTokenCurlyOpen:
return parseObject(json, index, success);
case JsonTokenSquaredOpen:
return parseArray(json, index, success);
case JsonTokenTrue:
nextToken(json, index);
return QVariant(true);
case JsonTokenFalse:
nextToken(json, index);
return QVariant(false);
case JsonTokenNull:
nextToken(json, index);
return QVariant();
case JsonTokenNone:
break;
}
// If there were no tokens, flag the failure and return an empty QVariant
success = false;
return QVariant();
}
/**
* parseObject
*/
static QVariant parseObject(const QString &json, int &index, bool &success) {
QVariantMap map;
int token;
// Get rid of the whitespace and increment index
nextToken(json, index);
// Loop through all of the key/value pairs of the object
bool done = false;
while (!done) {
// Get the upcoming token
token = lookAhead(json, index);
if (token == JsonTokenNone) {
success = false;
return QVariantMap();
} else if (token == JsonTokenComma) {
nextToken(json, index);
} else if (token == JsonTokenCurlyClose) {
nextToken(json, index);
return map;
} else {
// Parse the key/value pair's name
QString name = parseString(json, index, success).toString();
if (!success) {
return QVariantMap();
}
// Get the next token
token = nextToken(json, index);
// If the next token is not a colon, flag the failure
// return an empty QVariant
if (token != JsonTokenColon) {
success = false;
return QVariant(QVariantMap());
}
// Parse the key/value pair's value
QVariant value = parseValue(json, index, success);
if (!success) {
return QVariantMap();
}
// Assign the value to the key in the map
map[name] = value;
}
}
// Return the map successfully
return QVariant(map);
}
/**
* parseArray
*/
static QVariant parseArray(const QString &json, int &index, bool &success) {
QVariantList list;
nextToken(json, index);
bool done = false;
while(!done) {
int token = lookAhead(json, index);
if (token == JsonTokenNone) {
success = false;
return QVariantList();
} else if (token == JsonTokenComma) {
nextToken(json, index);
} else if (token == JsonTokenSquaredClose) {
nextToken(json, index);
break;
} else {
QVariant value = parseValue(json, index, success);
if (!success) {
return QVariantList();
}
list.push_back(value);
}
}
return QVariant(list);
}
/**
* parseString
*/
static QVariant parseString(const QString &json, int &index, bool &success) {
QString s;
QChar c;
eatWhitespace(json, index);
c = json[index++];
bool complete = false;
while(!complete) {
if (index == json.size()) {
break;
}
c = json[index++];
if (c == '\"') {
complete = true;
break;
} else if (c == '\\') {
if (index == json.size()) {
break;
}
c = json[index++];
if (c == '\"') {
s.append('\"');
} else if (c == '\\') {
s.append('\\');
} else if (c == '/') {
s.append('/');
} else if (c == 'b') {
s.append('\b');
} else if (c == 'f') {
s.append('\f');
} else if (c == 'n') {
s.append('\n');
} else if (c == 'r') {
s.append('\r');
} else if (c == 't') {
s.append('\t');
} else if (c == 'u') {
int remainingLength = json.size() - index;
if (remainingLength >= 4) {
QString unicodeStr = json.mid(index, 4);
int symbol = unicodeStr.toInt(0, 16);
s.append(QChar(symbol));
index += 4;
} else {
break;
}
}
} else {
s.append(c);
}
}
if (!complete) {
success = false;
return QVariant();
}
return QVariant(s);
}
/**
* parseNumber
*/
static QVariant parseNumber(const QString &json, int &index) {
eatWhitespace(json, index);
int lastIndex = lastIndexOfNumber(json, index);
int charLength = (lastIndex - index) + 1;
QString numberStr;
numberStr = json.mid(index, charLength);
index = lastIndex + 1;
bool ok;
if (numberStr.contains('.')) {
return QVariant(numberStr.toDouble(NULL));
} else if (numberStr.startsWith('-')) {
int i = numberStr.toInt(&ok);
if (!ok) {
qlonglong ll = numberStr.toLongLong(&ok);
return ok ? ll : QVariant(numberStr);
}
return i;
} else {
uint u = numberStr.toUInt(&ok);
if (!ok) {
qulonglong ull = numberStr.toULongLong(&ok);
return ok ? ull : QVariant(numberStr);
}
return u;
}
}
/**
* lastIndexOfNumber
*/
static int lastIndexOfNumber(const QString &json, int index) {
int lastIndex;
for(lastIndex = index; lastIndex < json.size(); lastIndex++) {
if (QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1) {
break;
}
}
return lastIndex -1;
}
/**
* eatWhitespace
*/
static void eatWhitespace(const QString &json, int &index) {
for(; index < json.size(); index++) {
if (QString(" \t\n\r").indexOf(json[index]) == -1) {
break;
}
}
}
/**
* lookAhead
*/
static int lookAhead(const QString &json, int index) {
int saveIndex = index;
return nextToken(json, saveIndex);
}
/**
* nextToken
*/
static int nextToken(const QString &json, int &index) {
eatWhitespace(json, index);
if (index == json.size()) {
return JsonTokenNone;
}
QChar c = json[index];
index++;
switch(c.toLatin1()) {
case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose;
case '[': return JsonTokenSquaredOpen;
case ']': return JsonTokenSquaredClose;
case ',': return JsonTokenComma;
case '"': return JsonTokenString;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-': return JsonTokenNumber;
case ':': return JsonTokenColon;
}
index--; // ^ WTF?
int remainingLength = json.size() - index;
// True
if (remainingLength >= 4) {
if (json[index] == 't' && json[index + 1] == 'r' &&
json[index + 2] == 'u' && json[index + 3] == 'e') {
index += 4;
return JsonTokenTrue;
}
}
// False
if (remainingLength >= 5) {
if (json[index] == 'f' && json[index + 1] == 'a' &&
json[index + 2] == 'l' && json[index + 3] == 's' &&
json[index + 4] == 'e') {
index += 5;
return JsonTokenFalse;
}
}
// Null
if (remainingLength >= 4) {
if (json[index] == 'n' && json[index + 1] == 'u' &&
json[index + 2] == 'l' && json[index + 3] == 'l') {
index += 4;
return JsonTokenNull;
}
}
return JsonTokenNone;
}
void setDateTimeFormat(const QString &format) {
dateTimeFormat = format;
}
void setDateFormat(const QString &format) {
dateFormat = format;
}
QString getDateTimeFormat() {
return dateTimeFormat;
}
QString getDateFormat() {
return dateFormat;
}
} //end namespace

178
telegram_test/json.h Normal file
View File

@@ -0,0 +1,178 @@
/**
* QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
* Copyright (C) 2011 Eeli Reilin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file json.h
*/
#ifndef JSON_H
#define JSON_H
#include <QVariant>
#include <QString>
/**
* \namespace QtJson
* \brief A JSON data parser
*
* Json parses a JSON data into a QVariant hierarchy.
*/
namespace QtJson {
typedef QVariantMap JsonObject;
typedef QVariantList JsonArray;
/**
* Clone a JSON object (makes a deep copy)
*
* \param data The JSON object
*/
QVariant clone(const QVariant &data);
/**
* Insert value to JSON object (QVariantMap)
*
* \param v The JSON object
* \param key The key
* \param value The value
*/
void insert(QVariant &v, const QString &key, const QVariant &value);
/**
* Append value to JSON array (QVariantList)
*
* \param v The JSON array
* \param value The value
*/
void append(QVariant &v, const QVariant &value);
/**
* Parse a JSON string
*
* \param json The JSON data
*/
QVariant parse(const QString &json);
/**
* Parse a JSON string
*
* \param json The JSON data
* \param success The success of the parsing
*/
QVariant parse(const QString &json, bool &success);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
*
* \return QByteArray Textual JSON representation in UTF-8
*/
QByteArray serialize(const QVariant &data);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*
* \return QByteArray Textual JSON representation in UTF-8
*/
QByteArray serialize(const QVariant &data, bool &success);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
*
* \return QString Textual JSON representation
*/
QString serializeStr(const QVariant &data);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*
* \return QString Textual JSON representation
*/
QString serializeStr(const QVariant &data, bool &success);
/**
* This method sets date(time) format to be used for QDateTime::toString
* If QString is empty, Qt::TextDate is used.
*
* \param format The JSON data generated by the parser.
*/
void setDateTimeFormat(const QString& format);
void setDateFormat(const QString& format);
/**
* This method gets date(time) format to be used for QDateTime::toString
* If QString is empty, Qt::TextDate is used.
*/
QString getDateTimeFormat();
QString getDateFormat();
/**
* QVariant based Json object
*/
class Object : public QVariant {
template<typename T>
Object& insertKey(Object* ptr, const QString& key) {
T* p = (T*)ptr->data();
if (!p->contains(key)) p->insert(key, QVariant());
return *reinterpret_cast<Object*>(&p->operator[](key));
}
template<typename T>
void removeKey(Object *ptr, const QString& key) {
T* p = (T*)ptr->data();
p->remove(key);
}
public:
Object() : QVariant() {}
Object(const Object& ref) : QVariant(ref) {}
Object& operator=(const QVariant& rhs) {
setValue(rhs);
return *this;
}
Object& operator[](const QString& key) {
if (type() == QVariant::Map)
return insertKey<QVariantMap>(this, key);
else if (type() == QVariant::Hash)
return insertKey<QVariantHash>(this, key);
setValue(QVariantMap());
return insertKey<QVariantMap>(this, key);
}
const Object& operator[](const QString& key) const {
return const_cast<Object*>(this)->operator[](key);
}
void remove(const QString& key) {
if (type() == QVariant::Map)
removeKey<QVariantMap>(this, key);
else if (type() == QVariant::Hash)
removeKey<QVariantHash>(this, key);
}
};
}
#endif //JSON_H

11
telegram_test/main.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

View File

@@ -0,0 +1,67 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QBuffer>
#include <QGraphicsPixmapItem>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
connect(bot.getAPI(), SIGNAL(newMessage(TelegramBotAPI::Message)), this, SLOT(printMessage(TelegramBotAPI::Message)));
connect(bot.getAPI(), SIGNAL(newFile(TelegramBotAPI::File)), this, SLOT(printImage(TelegramBotAPI::File)));
// connect(&bot_timer, SIGNAL(timeout()), &bot, SLOT(updateBot()));
// bot_timer.start(1000);
bot.setBotToken("281218446:AAEaoS25kKZUevp98U-MKiaPGd2kS18d11g");
ui->graphicsView->setScene(new QGraphicsScene());
ui->graphicsView->setInteractive(false);
ui->graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
// bot.start();
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::on_pushButton_1_clicked() {
// bot.setBotToken("281218446:AAEaoS25kKZUevp98U-MKiaPGd2kS18d11g");
// bot.updateBot();
// QImage img(800, 600, QImage::Format_ARGB32);
// img.fill(Qt::yellow);
// QByteArray ba;
// QBuffer buffer(&ba);
// buffer.open(QIODevice::WriteOnly);
// img.save(&buffer, "PNG");
// if (!bot.sendMessageToAll(TelegramBotAPI::Photo, ba, "test.png")) ui->listWidget->addItem("send error");
}
void MainWindow::on_pushButton_2_clicked() {
if (!ui->lineEdit->text().isEmpty()) {
bot.sendMessageToAll(ui->lineEdit->text());
ui->listWidget->addItem(QDateTime::currentDateTime().toString() + " #" + bot.getAPI()->botName() + " : " + ui->lineEdit->text());
ui->lineEdit->clear();
}
}
void MainWindow::printMessage(TelegramBotAPI::Message msg) {
ui->listWidget->addItem(msg.time.toString() + " #" + msg.user_name + " : " + msg.text);
lid = msg.chat_id;
}
void MainWindow::printImage(TelegramBotAPI::File file) {
QImage img;
if (img.loadFromData(file.data)) {
QPixmap pix = QPixmap::fromImage(img);
QListWidgetItem * lwi = new QListWidgetItem(QIcon(pix), file.filename);
ui->listWidget->addItem(lwi);
ui->graphicsView->scene()->addPixmap(pix);
}
}
void MainWindow::on_lineEdit_editingFinished() {
on_pushButton_2_clicked();
}

View File

@@ -0,0 +1,37 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimerEvent>
#include <QTimer>
#include "telegrambotbase.h"
#include "execbot.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_1_clicked();
void on_pushButton_2_clicked();
void printMessage(TelegramBotAPI::Message msg);
void printImage(TelegramBotAPI::File file);
void on_lineEdit_editingFinished();
private:
Ui::MainWindow *ui;
ExecBot bot;
uint lid;
QTimer bot_timer;
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>333</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_1">
<property name="text">
<string>Send image</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QGraphicsView" name="graphicsView">
<property name="dragMode">
<enum>QGraphicsView::RubberBandDrag</enum>
</property>
<property name="transformationAnchor">
<enum>QGraphicsView::AnchorUnderMouse</enum>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,26 @@
#-------------------------------------------------
#
# Project created by QtCreator 2016-10-17T12:59:23
#
#-------------------------------------------------
QT += core gui network
TARGET = telegram_test
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
json.cpp \
telegrambotapi.cpp \
telegrambotbase.cpp \
execbot.cpp
HEADERS += mainwindow.h \
json.h \
telegrambotapi.h \
telegrambotbase.h \
execbot.h
FORMS += mainwindow.ui

View File

@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.2.1, 2016-10-19T16:10:33. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{948faa78-0b50-402e-a285-1bca3b08de64}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">false</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">DesktopBuild</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">DesktopBuild</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3c749452-9483-442d-b011-933a1b5dac10}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Qt_projects/build-telegram_test-DesktopBuild-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Отладка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Qt_projects/build-telegram_test-DesktopBuild-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Выпуск</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Установка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Локальная установка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">3</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">telegram_test</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Qt_projects/telegram_test/telegram_test.pro</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">telegram_test.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">16</value>
</data>
<data>
<variable>Version</variable>
<value type="int">16</value>
</data>
</qtcreator>

View File

@@ -0,0 +1,358 @@
#include "telegrambotapi.h"
//#include <QMessageBox>
#include <QSslError>
#include <QDebug>
#include <QStringList>
#include <QDateTime>
#include <QHttpMultiPart>
#include "json.h"
const char * TelegramBotAPI::send_methods[] = {
"sendMessage",
"sendPhoto",
"sendDocument",
};
const char * TelegramBotAPI::param_filename = "__filename";
TelegramBotAPI::TelegramBotAPI(QObject *parent) : QObject(parent) {
is_connected = false;
wait_server = false;
has_stop = false;
qRegisterMetaType<TelegramBotAPI::Message>("TelegramBotAPI::Message");
qnam = new QNetworkAccessManager();
// connect(qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(httpFinished(QNetworkReply*)));
connect(qnam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
}
TelegramBotAPI::~TelegramBotAPI() {
has_stop = true;
// msleep(60);
}
void TelegramBotAPI::setBotToken(QString arg) {
if (m_botToken == arg) {
checkBot();
return;
}
is_connected = false;
m_botToken = arg;
botUrl = "https://api.telegram.org/bot"+m_botToken+"/";
checkBot();
}
bool TelegramBotAPI::sendMessage(uint chat_id, TelegramBotAPI::MessageType mtype, QByteArray data, QString filename) {
if (!is_connected || chat_id == 0 || data.isEmpty()) return false;
SendQuery sq;
sq.params["chat_id"] = chat_id;
sq.method = send_methods[mtype];
bool ok = false;
switch (mtype) {
case Text:
sq.params["text"] = QString::fromUtf8(data.data(), data.size());
ok = true;
break;
case Photo:
if (!filename.isEmpty()) {
sq.params[param_filename] = filename;
sq.params["photo"] = data;
ok = true;
}
break;
case Document:
if (!filename.isEmpty()) {
sq.params[param_filename] = filename;
sq.params["document"] = data;
ok = true;
}
break;
default:
break;
}
if (ok) {
sendmsg_que.enqueue(sq);
if (wait_server) {
if (reply->url().toString().split("/").last() == "getUpdates") reply->abort();
}
}
return ok;
}
//void TelegramBot::run() {
// while (!has_stop) {
// mutex.lock();
// if (qnam == 0) {
// qnam = new QNetworkAccessManager();
// connect(qnam, SIGNAL(finished(QNetworkReply*)),
// this, SLOT(httpFinished(QNetworkReply*)));
// connect(qnam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
// }
// if (!wait_server) {
// if (!is_connected) checkBot();
// updateBot();
// }
// mutex.unlock();
// msleep(50);
// }
//}
void TelegramBotAPI::updateBot() {
if (!is_connected) return;
QVariantMap vm;
vm["timeout"] = 50;
vm["offset"] = last_update;
sendRequest("getUpdates", vm);
}
bool TelegramBotAPI::fileDownload() {
if (download_list.isEmpty()) return false;
bool ok = false;
int rm = -1;
for(int i=0; i<download_list.size(); i++) {
DownloadFile & df = download_list[i];
qDebug() << df.id << df.url << df.filename;
if (df.url.isEmpty()) {
QVariantMap fm;
fm["file_id"] = df.id;
sendRequest("getFile", fm);
return true;
} else {
if (!df.downloaded) {
QNetworkRequest nr;
nr.setUrl(df.url);
reply = qnam->get(nr);
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
return true;
} else {
File f;
f.chat_id = df.chat_id;
f.filename = df.filename;
f.data = df.data;
emit newFile(f);
rm = i;
break;
}
}
}
if (rm >= 0) download_list.removeAt(rm);
return ok;
}
void TelegramBotAPI::checkBot() {
sendRequest("getMe", QVariantMap());
}
bool TelegramBotAPI::parseHeader(QString json, QVariant & res) {
bool ok;
QVariantMap map = QtJson::parse(json, ok).toMap();
if (!ok) {
emit errorOccured("parse JSON error");
return false;
}
if (!map.value("ok").toBool()) {
emit errorOccured("query error");
return false;
}
res = map.value("result");
return !res.isNull() && res.isValid();
}
void TelegramBotAPI::parseCheckBot(QString json) {
QVariant res;
if (!parseHeader(json, res)) {
is_connected = false;
emit botFail();
return;
}
QVariantMap resm = res.toMap();
m_botID = resm.value("id").toUInt();
m_botName = resm.value("username").toString();
is_connected = true;
last_update = 0;
emit botOK();
}
void TelegramBotAPI::parseFile(QString json) {
QVariant res;
if (!parseHeader(json, res)) {
emit errorOccured("can't get file");
return;
}
QVariantMap resm = res.toMap();
QString fpath = resm["file_path"].toString();
QString fid = resm["file_id"].toString();
if (fpath.isEmpty()) return;
QUrl furl = QUrl("https://api.telegram.org/file/bot"+m_botToken+"/"+fpath);
qDebug() << "new file :" << furl;
for (int i=0; i<download_list.size(); i++) {
if (download_list[i].id == fid) {
download_list[i].url = furl;
if (download_list[i].filename.isEmpty())
download_list[i].filename = fpath.split("/").last();
}
}
}
void TelegramBotAPI::parseMessages(QString json) {
QVariant res;
if (!parseHeader(json, res)) {
emit errorOccured("can't update");
return;
}
QVariantList resm = res.toList();
foreach (QVariant v, resm) {
QVariantMap mm = v.toMap();
last_update = mm.value("update_id").toInt();
Message m = parseMessage(mm.value("message"));
if (m.id > 0) {
emit newMessage(m);
emit newMessage(m.chat_id, m.text);
}
}
last_update++;
//qDebug() << "update_id" << last_update;
}
void TelegramBotAPI::startDownloadFile(uint chat_id, QVariantMap file) {
if (!file.isEmpty()) {
DownloadFile df;
df.downloaded = false;
df.id = file["file_id"].toString();
df.chat_id = chat_id;
df.filename = file["file_name"].toString();
qDebug() << "new incomming file" << df.id;
download_list << df;
}
}
TelegramBotAPI::Message TelegramBotAPI::parseMessage(QVariant msg) {
Message ret;
QVariantMap map = msg.toMap();
ret.id = map.value("message_id", 0).toUInt();
QVariantMap chat = map.value("chat").toMap();
ret.chat_id = chat.value("id", 0).toUInt();
QVariantMap user = map.value("from").toMap();
ret.user_id = user.value("id", 0).toUInt();
ret.user_name = user.value("first_name").toString();
ret.text = map.value("text").toString();
ret.time = QDateTime::fromTime_t(map.value("date").toUInt());
QVariantMap file;
QVariantList photo = map.value("photo").toList();
if (!photo.isEmpty()) {
startDownloadFile(ret.chat_id, photo.last().toMap());
}
QVariantMap docum = map.value("document").toMap();
startDownloadFile(ret.chat_id, docum);
return ret;
}
void TelegramBotAPI::sslErrors(QNetworkReply*,const QList<QSslError> &errors) {
QString errorString;
foreach (const QSslError &error, errors) {
if (!errorString.isEmpty())
errorString += ", ";
errorString += error.errorString();
}
emit errorOccured(errorString);
// if (QMessageBox::warning(0, QString("HTTP"), QString("One or more SSL errors has occurred: %1").arg(errorString),
// QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Ignore)
// == QMessageBox::Ignore) {
// reply->ignoreSslErrors();
// }
}
void TelegramBotAPI::httpFinished() {
// qDebug() << "reply finished";
// mutex.lock();
QByteArray ba = reply->readAll();
QStringList quest_path = reply->url().toString().split("/");
// qDebug() << "quest list =" << quest_path.size();
QString quest = quest_path.last();
reply->deleteLater();
wait_server = false;
// mutex.unlock();
if (quest_path.size() == 5) {
QString s = QString::fromUtf8(ba.data(), ba.size());
// qDebug() << quest << s;
// if (quest.indexOf("?") > 0)
// quest.resize(quest.indexOf('?'));
QVariant tmp;
if (quest == "getMe") parseCheckBot(s);
if (quest == "getFile") parseFile(s);
if (quest == "getUpdates") parseMessages(s);
if (quest == "sendMessage") parseHeader(s, tmp);
qDebug() << "parse done" << quest << s;
} else {
for (int i=0; i<download_list.size(); ++i) {
if (download_list[i].url == reply->url()) {
download_list[i].data = ba;
download_list[i].downloaded = true;
break;
}
}
}
if (is_connected) {
if (!fileDownload()) {
if (sendmsg_que.isEmpty()) updateBot();
else {
SendQuery sq = sendmsg_que.dequeue();
sendRequest(sq.method, sq.params);
}
}
} else checkBot();
}
//void TelegramBot::httpFinished(QNetworkReply *) {
// qDebug() << "get finished";
//}
void TelegramBotAPI::sendRequest(QString method, QVariantMap params) {
wait_server = true;
qDebug() << "startRequest:" << method;
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QString filename = params.take(param_filename).toString();
QMapIterator<QString, QVariant> it(params);
while (it.hasNext()) {
it.next();
QHttpPart part;
if (it.value().type() == QVariant::ByteArray) {
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; filename=\""+filename+"\"; name=\""+it.key()+"\""));
qDebug() << "sending photo" << double(it.value().toByteArray().size()) / (1024*1024);
part.setBody(it.value().toByteArray());
} else {
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\""+it.key()+"\""));
part.setBody(it.value().toString().toUtf8());
}
multiPart->append(part);
}
if (params.isEmpty()) {
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
multiPart->append(part);
}
QNetworkRequest nr;
nr.setUrl(QUrl(botUrl + method));
reply = qnam->post(nr, multiPart);
multiPart->setParent(reply); // delete the multiPart with the reply
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
// connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
// connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64)));
}

View File

@@ -0,0 +1,119 @@
#ifndef TELEGRAMBOTAPI_H
#define TELEGRAMBOTAPI_H
#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDateTime>
#include <QMutex>
#include <QQueue>
#include <QImage>
class TelegramBotAPI : public QObject
{
Q_OBJECT
Q_PROPERTY(uint botID READ botID)
Q_PROPERTY(QString botName READ botName)
Q_PROPERTY(QString botToken READ botToken WRITE setBotToken)
public:
explicit TelegramBotAPI(QObject *parent = 0);
~TelegramBotAPI();
enum MessageType {
Text,
Photo,
Document,
};
struct Message {
Message() {
chat_id = id = user_id = 0;
}
uint id;
uint chat_id;
uint user_id;
QString user_name;
QString text;
QDateTime time;
};
struct File {
uint chat_id;
QString filename;
QByteArray data;
};
uint botID() const {return m_botID;}
QString botToken() const {return m_botToken;}
QString botName() const {return m_botName;}
bool isConnected() const {return is_connected;}
public slots:
void setBotToken(QString arg);
bool sendMessage(uint chat_id, QString msg) {return sendMessage(chat_id, TelegramBotAPI::Text, msg.toUtf8());}
bool sendMessage(uint chat_id, MessageType mtype, QByteArray data, QString filename = QString());
private:
struct SendQuery {
QString method;
QVariantMap params;
};
struct DownloadFile {
bool downloaded;
int chat_id;
QString id;
QString filename;
QUrl url;
QByteArray data;
};
static const char * send_methods[];
static const char * param_filename;
// void run();
void sendRequest(QString method, QVariantMap params);
void checkBot();
void updateBot();
bool fileDownload();
bool parseHeader(QString json, QVariant &res);
void parseCheckBot(QString json);
void parseMessages(QString json);
void parseFile(QString json);
Message parseMessage(QVariant msg);
void startDownloadFile(uint chat_id, QVariantMap file);
QNetworkAccessManager * qnam;
QNetworkReply *reply;
// QMutex mutex;
uint m_botID;
QString m_botToken;
QString botUrl;
QString botUrlFile;
QString m_botName;
bool is_connected;
int last_update;
bool wait_server;
bool has_stop;
QQueue<SendQuery> sendmsg_que;
QList<DownloadFile> download_list;
private slots:
void sslErrors(QNetworkReply*, const QList<QSslError> &errors);
void httpFinished();
// void httpFinished(QNetworkReply*);
signals:
void botOK();
void botFail();
void errorOccured(QString error);
void newMessage(TelegramBotAPI::Message msg);
void newMessage(uint chat_id, QString msg);
void newFile(TelegramBotAPI::File file);
};
Q_DECLARE_METATYPE(TelegramBotAPI::Message)
#endif // TELEGRAMBOTAPI_H

View File

@@ -0,0 +1,79 @@
#include "telegrambotbase.h"
#include <QDebug>
#include <QApplication>
TelegramBotBase::TelegramBotBase(QObject *parent) : QObject(parent) {
// connect(&api, SIGNAL(newMessage(TelegramBotAPI::Message)), this, SLOT(processMessage(TelegramBotAPI::Message)), Qt::QueuedConnection);
connect(&api, SIGNAL(newMessage(TelegramBotAPI::Message)), this, SLOT(processMessage(TelegramBotAPI::Message)));
}
void TelegramBotBase::sendMessageToAll(const QString &message) {
QList<uint> keys = users.keys();
foreach (uint cid, keys) {
if (users[cid].logged_in)
api.sendMessage(cid, message);
}
}
void TelegramBotBase::processMessage(TelegramBotAPI::Message msg) {
// QApplication::processEvents();
qDebug() << "[TelegramBotBase]" << msg.text;
uint cid = msg.chat_id;
User m;
m.user_id = msg.user_id;
m.user_name = msg.user_name;
m.last_timestamp = msg.time;
if (!users.contains(cid)) users[cid] = m;
if (users[cid].logged_in) {
if (msg.text == "/help") {
api.sendMessage(cid, help());
return;
}
messageFromUser(cid, msg.text);
} else {
if (loginUser(cid, msg.text)) {
users[cid].logged_in = true;
api.sendMessage(cid, welcome(cid));
newUser(cid, users[cid]);
} else {
api.sendMessage(cid, loginMessage(cid));
}
return;
}
}
QString TelegramBotBase::welcome(uint id) {
User user = getUser(id);
return tr("Hello %1! I am @%2.").arg(user.user_name).arg(api.botName());
}
QString TelegramBotBase::loginMessage(uint) {
return tr("Please send me /start");
}
QString TelegramBotBase::help() {
return tr("Sorry, /help not implemented in @%1.").arg(api.botName());
}
bool TelegramBotBase::loginUser(uint , const QString &msg) {
return (msg == "/start");
}
void TelegramBotBase::messageFromUser(uint id, const QString &msg) {
if (msg.toLower() == "ping") api.sendMessage(id, "pong");
}
void TelegramBotBase::newUser(uint, User) {}
void TelegramBotBase::disconnectUser(uint id) {
users.remove(id);
}

View File

@@ -0,0 +1,54 @@
#ifndef TELEGRAMBOTBASE_H
#define TELEGRAMBOTBASE_H
#include <QObject>
#include "telegrambotapi.h"
class TelegramBotBase : public QObject
{
Q_OBJECT
public:
explicit TelegramBotBase(QObject *parent = 0);
TelegramBotAPI * getAPI() {return &api;}
public slots:
void sendMessageToAll(const QString & message);
void setBotToken(QString token) {api.setBotToken(token);}
protected:
struct User {
User() {
user_id = 0;
logged_in = false;
}
uint user_id;
bool logged_in;
QString user_name;
QDateTime last_timestamp;
};
const User & getUser(uint id) {return users[id];}
virtual QString welcome(uint id);
virtual QString loginMessage(uint id);
virtual QString help();
virtual bool loginUser(uint id, const QString & msg);
virtual void messageFromUser(uint id, const QString & msg);
virtual void newUser(uint id, User user);
void disconnectUser(uint id);
private slots:
void processMessage(TelegramBotAPI::Message msg);
private:
QMap<uint, User> users;
TelegramBotAPI api;
QString m_botToken;
signals:
};
#endif // TELEGRAMBOTBASE_H