git-svn-id: svn://db.shs.com.ru/libs@129 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
123
telegram_test/execbot.cpp
Normal file
123
telegram_test/execbot.cpp
Normal 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
46
telegram_test/execbot.h
Normal 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
603
telegram_test/json.cpp
Normal 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
178
telegram_test/json.h
Normal 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
11
telegram_test/main.cpp
Normal 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();
|
||||||
|
}
|
||||||
67
telegram_test/mainwindow.cpp
Normal file
67
telegram_test/mainwindow.cpp
Normal 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();
|
||||||
|
}
|
||||||
37
telegram_test/mainwindow.h
Normal file
37
telegram_test/mainwindow.h
Normal 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
|
||||||
67
telegram_test/mainwindow.ui
Normal file
67
telegram_test/mainwindow.ui
Normal 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>
|
||||||
26
telegram_test/telegram_test.pro
Normal file
26
telegram_test/telegram_test.pro
Normal 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
|
||||||
255
telegram_test/telegram_test.pro.user
Normal file
255
telegram_test/telegram_test.pro.user
Normal 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>
|
||||||
358
telegram_test/telegrambotapi.cpp
Normal file
358
telegram_test/telegrambotapi.cpp
Normal 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)));
|
||||||
|
}
|
||||||
119
telegram_test/telegrambotapi.h
Normal file
119
telegram_test/telegrambotapi.h
Normal 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
|
||||||
79
telegram_test/telegrambotbase.cpp
Normal file
79
telegram_test/telegrambotbase.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
54
telegram_test/telegrambotbase.h
Normal file
54
telegram_test/telegrambotbase.h
Normal 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
|
||||||
Reference in New Issue
Block a user