git-svn-id: svn://db.shs.com.ru/libs@297 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
@@ -1,174 +0,0 @@
|
|||||||
#include "execbot.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QTextCodec>
|
|
||||||
|
|
||||||
ExecBot::ExecBot(QObject *parent) : TelegramBotBase(parent) {
|
|
||||||
connect(getAPI(), SIGNAL(newFile(TelegramBotAPI::File)), this, SLOT(saveFile(TelegramBotAPI::File)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 == "rootpasswd") {
|
|
||||||
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->terminate();
|
|
||||||
getAPI()->sendMessage(id, tr("Process killed"));
|
|
||||||
sessions[id] = Ready;
|
|
||||||
rm = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rm >= 0) {
|
|
||||||
run_commands[rm].cmd->deleteLater();
|
|
||||||
run_commands.remove(rm);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
getAPI()->sendMessage(id, tr("Command is running, please wait for finish"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sessions[id] == Ready) {
|
|
||||||
if (msg.startsWith("/download")) {
|
|
||||||
QFile f;
|
|
||||||
f.setFileName(msg.mid(9).trimmed());
|
|
||||||
if (f.open(QIODevice::ReadOnly)) {
|
|
||||||
QByteArray ba = f.readAll();
|
|
||||||
getAPI()->sendMessage(id, TelegramBotAPI::Document, ba, QFileInfo(f).fileName());
|
|
||||||
} else
|
|
||||||
getAPI()->sendMessage(id, tr("File not found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
#ifdef WIN32
|
|
||||||
QTextCodec *codec = QTextCodec::codecForName("IBM 866");
|
|
||||||
#else
|
|
||||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
#ifdef WIN32
|
|
||||||
QTextCodec *codec = QTextCodec::codecForName("IBM 866");
|
|
||||||
#else
|
|
||||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
|
||||||
#endif
|
|
||||||
QString s = codec->toUnicode(p->readAll());
|
|
||||||
getAPI()->sendMessage(id, s);
|
|
||||||
rm = i;
|
|
||||||
sessions[id] = Ready;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rm >= 0) {
|
|
||||||
run_commands[rm].cmd->deleteLater();
|
|
||||||
getAPI()->sendMessage(run_commands[rm].user, tr("Command finished with code %1").arg(code));
|
|
||||||
run_commands.remove(rm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ExecBot::saveFile(TelegramBotAPI::File fl) {
|
|
||||||
if (sessions.contains(fl.chat_id)) {
|
|
||||||
if (sessions[fl.chat_id] == Ready) {
|
|
||||||
QFile f;
|
|
||||||
QDir::current().mkdir("uploads");
|
|
||||||
f.setFileName("uploads/" + fl.filename);
|
|
||||||
if (f.open(QIODevice::ReadWrite)) {
|
|
||||||
f.resize(0);
|
|
||||||
f.write(fl.data);
|
|
||||||
getAPI()->sendMessage(fl.chat_id, tr("File received"));
|
|
||||||
} else {
|
|
||||||
getAPI()->sendMessage(fl.chat_id, tr("Can't write file"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getAPI()->sendMessage(fl.chat_id, loginMessage(fl.chat_id));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getAPI()->sendMessage(fl.chat_id, tr("Please send me /start"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#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);
|
|
||||||
void saveFile(TelegramBotAPI::File fl);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EXECBOT_H
|
|
||||||
@@ -1,603 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
//#include "mainwindow.h"
|
|
||||||
#include "execbot.h"
|
|
||||||
#include <QCoreApplication>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
QCoreApplication a(argc, argv);
|
|
||||||
//MainWindow w;
|
|
||||||
//w.show();
|
|
||||||
ExecBot bot;
|
|
||||||
bot.setBotToken("242608352:AAFrx51P_JhmCjV8CV11Mds-LJk89bpolXE");
|
|
||||||
return a.exec();
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#-------------------------------------------------
|
|
||||||
#
|
|
||||||
# Project created by QtCreator 2016-10-17T12:59:23
|
|
||||||
#
|
|
||||||
#-------------------------------------------------
|
|
||||||
|
|
||||||
QT += core gui network
|
|
||||||
|
|
||||||
TARGET = telegram_bot
|
|
||||||
TEMPLATE = app
|
|
||||||
|
|
||||||
|
|
||||||
SOURCES += main.cpp\
|
|
||||||
json.cpp \
|
|
||||||
telegrambotapi.cpp \
|
|
||||||
telegrambotbase.cpp \
|
|
||||||
execbot.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
json.h \
|
|
||||||
telegrambotapi.h \
|
|
||||||
telegrambotbase.h \
|
|
||||||
execbot.h
|
|
||||||
|
|
||||||
FORMS +=
|
|
||||||
@@ -1,358 +0,0 @@
|
|||||||
#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 && !m.text.isEmpty()) {
|
|
||||||
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 file" << double(it.value().toByteArray().size()) / (1024*1024) << "Mb";
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#include "telegrambotbase.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#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