xmppbot 0.5

This commit is contained in:
Syping 2021-08-06 04:48:24 +02:00
parent 260d509f2e
commit b95369f254
6 changed files with 233 additions and 77 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
project(xmppbot VERSION 0.4 LANGUAGES CXX) project(xmppbot VERSION 0.5 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)

View File

@ -39,7 +39,7 @@ int main(int argc, char *argv[])
{ {
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
app.setApplicationName(QLatin1String("xmppbot")); app.setApplicationName(QLatin1String("xmppbot"));
app.setApplicationVersion(QLatin1String("0.4")); app.setApplicationVersion(QLatin1String("0.5"));
QCommandLineParser commandLineParser; QCommandLineParser commandLineParser;
commandLineParser.addPositionalArgument(QLatin1String("config"), QCoreApplication::translate("xmppbot", "Configuration file.")); commandLineParser.addPositionalArgument(QLatin1String("config"), QCoreApplication::translate("xmppbot", "Configuration file."));
@ -64,7 +64,7 @@ int main(int argc, char *argv[])
app.setProperty("XmppClient", QVariant::fromValue<QXmppClient*>(&client)); app.setProperty("XmppClient", QVariant::fromValue<QXmppClient*>(&client));
bool loginSet = false; bool loginSet = false;
QString jid, jpw; QString jid, jpw, script;
QHash<QString, QString> h_msg; QHash<QString, QString> h_msg;
QHash<QString, QString> h_lua; QHash<QString, QString> h_lua;
QHash<QString, QString> h_run; QHash<QString, QString> h_run;
@ -72,76 +72,81 @@ int main(int argc, char *argv[])
QSettings settings(settingsPath, QSettings::IniFormat); QSettings settings(settingsPath, QSettings::IniFormat);
for (const QString &group : settings.childGroups()) { for (const QString &group : settings.childGroups()) {
settings.beginGroup(group); settings.beginGroup(group);
for (const QString &key : settings.childKeys()) { if (group == QLatin1String("xmppbot")) {
if (key == QLatin1String("Password")) { script = settings.value(QLatin1String("Script"), QString()).toString();
if (!loginSet) { }
jid = group; else {
const QString instance = settings.value(QLatin1String("Instance"), QString()).toString(); for (const QString &key : settings.childKeys()) {
if (!instance.isEmpty()) { if (key == QLatin1String("Password")) {
jid += QLatin1String("/") + instance; if (!loginSet) {
jid = group;
const QString instance = settings.value(QLatin1String("Instance"), QString()).toString();
if (!instance.isEmpty()) {
jid += QLatin1String("/") + instance;
}
jpw = settings.value(key, QString()).toString();
loginSet = true;
}
else {
QTextStream(stderr) << "xmppbot: Login password can only be set once!" << xendl;
return 1;
} }
jpw = settings.value(key, QString()).toString();
loginSet = true;
} }
else { if (key == QLatin1String("Incoming")) {
QTextStream(stderr) << "xmppbot: Login password can only be set once!" << xendl; const QString incoming = settings.value("Incoming", QString()).toString();
return 1; if (incoming.startsWith(QLatin1String("message:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account message incoming ") << group << QLatin1String(" initialised") << xendl;
h_msg.insert(group, incoming.mid(8));
}
if (incoming.startsWith(QLatin1String("lua:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account lua incoming ") << group << QLatin1String(" initialised") << xendl;
h_lua.insert(group, incoming.mid(4));
}
if (incoming.startsWith(QLatin1String("run:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account run incoming ") << group << QLatin1String(" initialised") << xendl;
h_run.insert(group, incoming.mid(4));
}
} }
} if (key == QLatin1String(XmppSocketType)) {
if (key == QLatin1String("Incoming")) { XmppSocket *xmppSocket = new XmppSocket(&client, jid, group);
const QString incoming = settings.value("Incoming", QString()).toString();
if (incoming.startsWith(QLatin1String("message:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account message incoming ") << group << QLatin1String(" initialised") << xendl;
h_msg.insert(group, incoming.mid(8));
}
if (incoming.startsWith(QLatin1String("lua:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account lua incoming ") << group << QLatin1String(" initialised") << xendl;
h_lua.insert(group, incoming.mid(4));
}
if (incoming.startsWith(QLatin1String("run:"))) {
QTextStream(stderr) << QLatin1String("xmppbot: Account run incoming ") << group << QLatin1String(" initialised") << xendl;
h_run.insert(group, incoming.mid(4));
}
}
if (key == QLatin1String(XmppSocketType)) {
XmppSocket *xmppSocket = new XmppSocket(&client, jid, group);
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
const QString permission = settings.value(QLatin1String("SocketPermission"), QString()).toString(); const QString permission = settings.value(QLatin1String("SocketPermission"), QString()).toString();
if (permission == QLatin1String("UG") || permission == QLatin1String("UserGroup")) { if (permission == QLatin1String("UG") || permission == QLatin1String("UserGroup")) {
xmppSocket->setSocketOptions(QLocalServer::UserAccessOption | QLocalServer::GroupAccessOption); xmppSocket->setSocketOptions(QLocalServer::UserAccessOption | QLocalServer::GroupAccessOption);
} }
if (permission == QLatin1String("UO") || permission == QLatin1String("UserOther")) { if (permission == QLatin1String("UO") || permission == QLatin1String("UserOther")) {
xmppSocket->setSocketOptions(QLocalServer::UserAccessOption | QLocalServer::OtherAccessOption); xmppSocket->setSocketOptions(QLocalServer::UserAccessOption | QLocalServer::OtherAccessOption);
} }
if (permission == QLatin1String("U") || permission == QLatin1String("User")) { if (permission == QLatin1String("U") || permission == QLatin1String("User")) {
xmppSocket->setSocketOptions(QLocalServer::UserAccessOption); xmppSocket->setSocketOptions(QLocalServer::UserAccessOption);
} }
if (permission == QLatin1String("GO") || permission == QLatin1String("GroupOther")) { if (permission == QLatin1String("GO") || permission == QLatin1String("GroupOther")) {
xmppSocket->setSocketOptions(QLocalServer::GroupAccessOption | QLocalServer::OtherAccessOption); xmppSocket->setSocketOptions(QLocalServer::GroupAccessOption | QLocalServer::OtherAccessOption);
} }
if (permission == QLatin1String("G") || permission == QLatin1String("Group")) { if (permission == QLatin1String("G") || permission == QLatin1String("Group")) {
xmppSocket->setSocketOptions(QLocalServer::GroupAccessOption); xmppSocket->setSocketOptions(QLocalServer::GroupAccessOption);
} }
if (permission == QLatin1String("O") || permission == QLatin1String("Other")) { if (permission == QLatin1String("O") || permission == QLatin1String("Other")) {
xmppSocket->setSocketOptions(QLocalServer::OtherAccessOption); xmppSocket->setSocketOptions(QLocalServer::OtherAccessOption);
} }
if (permission == QLatin1String("A") || permission == QLatin1String("All") || permission == QLatin1String("UGO") || permission == QLatin1String("UserGroupOther")) { if (permission == QLatin1String("A") || permission == QLatin1String("All") || permission == QLatin1String("UGO") || permission == QLatin1String("UserGroupOther")) {
xmppSocket->setSocketOptions(QLocalServer::WorldAccessOption); xmppSocket->setSocketOptions(QLocalServer::WorldAccessOption);
} }
#endif #endif
const QString socketPath = settings.value(key, QString()).toString(); const QString socketPath = settings.value(key, QString()).toString();
bool listen = xmppSocket->listen(socketPath); bool listen = xmppSocket->listen(socketPath);
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
if (!listen) { if (!listen) {
QLocalServer::removeServer(socketPath); QLocalServer::removeServer(socketPath);
listen = xmppSocket->listen(socketPath); listen = xmppSocket->listen(socketPath);
} }
#endif #endif
if (listen) { if (listen) {
QTextStream(stderr) << QLatin1String("xmppbot: Account socket ") << group << QLatin1String(" initialised") << xendl; QTextStream(stderr) << QLatin1String("xmppbot: Account socket ") << group << QLatin1String(" initialised") << xendl;
} }
else { else {
delete xmppSocket; delete xmppSocket;
}
} }
} }
} }
@ -160,12 +165,22 @@ int main(int argc, char *argv[])
QTextStream(stderr) << QLatin1String("xmppbot: Account login ") << jid << QLatin1String(" initialised") << xendl; QTextStream(stderr) << QLatin1String("xmppbot: Account login ") << jid << QLatin1String(" initialised") << xendl;
XmppBotLuaThread xmppBotLuaGlobalThread(script, QLatin1String("jidInitialised"), QVariantList() << jid, true);
if (!script.isEmpty() && QFile::exists(script)) {
xmppBotLuaGlobalThread.start();
}
QObject::connect(&client, &QXmppClient::stateChanged, [&](QXmppClient::State state) { QObject::connect(&client, &QXmppClient::stateChanged, [&](QXmppClient::State state) {
switch (state) { switch (state) {
case QXmppClient::ConnectedState: { case QXmppClient::ConnectedState: {
QTextStream(stderr) << QLatin1String("xmppbot: Account ") << jid << QLatin1String(" connected") << xendl; QTextStream(stderr) << QLatin1String("xmppbot: Account ") << jid << QLatin1String(" connected") << xendl;
QXmppPresence xmppPresence(QXmppPresence::Available); QXmppPresence xmppPresence(QXmppPresence::Available);
client.setClientPresence(xmppPresence); client.setClientPresence(xmppPresence);
if (xmppBotLuaGlobalThread.isRunning()) {
const QString lua_function = QLatin1String("jidConnected");
const QVariantList lua_args = QVariantList() << jid;
QMetaObject::invokeMethod(&xmppBotLuaGlobalThread, "executeLuaFunction", Qt::QueuedConnection, Q_ARG(QString, lua_function), Q_ARG(QVariantList, lua_args));
}
break; break;
} }
case QXmppClient::ConnectingState: case QXmppClient::ConnectingState:
@ -175,6 +190,11 @@ int main(int argc, char *argv[])
QTimer::singleShot(5000, &client, [&]() { QTimer::singleShot(5000, &client, [&]() {
client.connectToServer(jid, jpw); client.connectToServer(jid, jpw);
}); });
if (xmppBotLuaGlobalThread.isRunning()) {
const QString lua_function = QLatin1String("jidDisconnected");
const QVariantList lua_args = QVariantList() << jid;
QMetaObject::invokeMethod(&xmppBotLuaGlobalThread, "executeLuaFunction", Qt::QueuedConnection, Q_ARG(QString, lua_function), Q_ARG(QVariantList, lua_args));
}
break; break;
default: default:
break; break;
@ -211,6 +231,11 @@ int main(int argc, char *argv[])
QTextStream(stderr) << QLatin1String("xmppbot: Account ") << from_jid << QLatin1String(" executed pid ") << pid << xendl; QTextStream(stderr) << QLatin1String("xmppbot: Account ") << from_jid << QLatin1String(" executed pid ") << pid << xendl;
} }
} }
if (xmppBotLuaGlobalThread.isRunning()) {
const QString lua_function = QLatin1String("messageReceived");
const QVariantList lua_args = QVariantList() << from << xmppMessage.to() << xmppMessage.body();
QMetaObject::invokeMethod(&xmppBotLuaGlobalThread, "executeLuaFunction", Qt::QueuedConnection, Q_ARG(QString, lua_function), Q_ARG(QVariantList, lua_args));
}
}); });
QObject::connect(&client, &QXmppClient::presenceReceived, [&](const QXmppPresence &xmppPresence) { QObject::connect(&client, &QXmppClient::presenceReceived, [&](const QXmppPresence &xmppPresence) {
@ -227,6 +252,11 @@ int main(int argc, char *argv[])
QObject::connect(xmppBotLuaThread, &XmppBotLuaThread::finished, xmppBotLuaThread, &XmppBotLuaThread::deleteLater); QObject::connect(xmppBotLuaThread, &XmppBotLuaThread::finished, xmppBotLuaThread, &XmppBotLuaThread::deleteLater);
xmppBotLuaThread->start(); xmppBotLuaThread->start();
} }
if (xmppBotLuaGlobalThread.isRunning()) {
const QString lua_function = QLatin1String("presenceReceived");
const QVariantList lua_args = QVariantList() << from << static_cast<int>(xmppPresence.type()) << static_cast<int>(xmppPresence.availableStatusType()) << xmppPresence.statusText();
QMetaObject::invokeMethod(&xmppBotLuaGlobalThread, "executeLuaFunction", Qt::QueuedConnection, Q_ARG(QString, lua_function), Q_ARG(QVariantList, lua_args));
}
}); });
client.connectToServer(jid, jpw); client.connectToServer(jid, jpw);

View File

@ -17,6 +17,10 @@
*****************************************************************************/ *****************************************************************************/
#include <QCoreApplication> #include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QProcess>
#include <QTextStream> #include <QTextStream>
#include "xmppbot.h" #include "xmppbot.h"
@ -30,11 +34,11 @@ XmppBotLua::XmppBotLua(QObject *parent) : QObject(parent)
L = luaL_newstate(); L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
// Functions // XMPP Functions
pushFunction("jid", jid); pushFunction("jid", jid);
pushFunction("jin", jin); pushFunction("jin", jin);
pushFunction("sendMessage", sendMessage); pushFunction("sendMessage", sendMessage);
pushFunction("setPresence", setPresence); pushFunction("setClientPresence", setClientPresence);
// XMPP Presence // XMPP Presence
pushVariant("PresenceAvailable", static_cast<int>(QXmppPresence::Available)); pushVariant("PresenceAvailable", static_cast<int>(QXmppPresence::Available));
@ -48,6 +52,15 @@ XmppBotLua::XmppBotLua(QObject *parent) : QObject(parent)
pushVariant("StatusSnooze", static_cast<int>(QXmppPresence::XA)); pushVariant("StatusSnooze", static_cast<int>(QXmppPresence::XA));
pushVariant("StatusBusy", static_cast<int>(QXmppPresence::DND)); pushVariant("StatusBusy", static_cast<int>(QXmppPresence::DND));
pushVariant("StatusChat", static_cast<int>(QXmppPresence::Chat)); pushVariant("StatusChat", static_cast<int>(QXmppPresence::Chat));
// JSON
pushFunction("jsonToTable", jsonToTable);
pushFunction("tableToJson", tableToJson);
pushVariant("JsonCompact", static_cast<int>(QJsonDocument::Compact));
pushVariant("JsonIndented", static_cast<int>(QJsonDocument::Indented));
// Process
pushFunction("executeProcess", executeProcess);
} }
XmppBotLua::~XmppBotLua() XmppBotLua::~XmppBotLua()
@ -371,7 +384,7 @@ int XmppBotLua::sendMessage(lua_State *L_p)
return 1; return 1;
} }
int XmppBotLua::setPresence(lua_State *L_p) int XmppBotLua::setClientPresence(lua_State *L_p)
{ {
bool presenceSet = false; bool presenceSet = false;
if (getArgumentCount(L_p) >= 2 && getArgumentCount(L_p) <= 3) { if (getArgumentCount(L_p) >= 2 && getArgumentCount(L_p) <= 3) {
@ -390,3 +403,89 @@ int XmppBotLua::setPresence(lua_State *L_p)
pushVariant(L_p, presenceSet); pushVariant(L_p, presenceSet);
return 1; return 1;
} }
int XmppBotLua::jsonToTable(lua_State *L_p)
{
if (getArgumentCount(L_p) >= 1) {
const QJsonDocument jsonDocument = QJsonDocument::fromJson(getVariant(L_p, 1).toString().toUtf8());
if (jsonDocument.isObject()) {
pushVariant(L_p, jsonDocument.object().toVariantMap());
return 1;
}
else if (jsonDocument.isArray()) {
pushVariant(L_p, jsonDocument.array().toVariantList());
return 1;
}
}
return 0;
}
int XmppBotLua::tableToJson(lua_State *L_p)
{
if (getArgumentCount(L_p) >= 1) {
QJsonDocument::JsonFormat jsonFormat = QJsonDocument::Compact;
if (getArgumentCount(L_p) >= 2) {
jsonFormat = static_cast<QJsonDocument::JsonFormat>(getVariant(L_p, 2).toInt());
}
pushVariant(L_p, QString::fromUtf8(QJsonDocument(QJsonObject::fromVariantMap(getVariant(L_p, 1).toMap())).toJson(jsonFormat)));
return 1;
}
return 0;
}
int XmppBotLua::executeProcess(lua_State *L_p)
{
if (getArgumentCount(L_p) >= 1) {
int processReturn = 0;
bool runInBackground = false;
bool processSuccessed = false;
if (getArgumentCount(L_p) >= 2) {
QStringList processArguments;
QString processPath = getVariant(L_p, 1).toString();
QVariant argument = getVariant(L_p, 2);
if (static_cast<QMetaType::Type>(argument.type()) == QMetaType::QVariantMap) {
const QVariantMap argumentMap = argument.toMap();
for (auto it = argumentMap.constBegin(); it != argumentMap.constEnd(); it++) {
processArguments << it.value().toString();
}
}
else if (argument.type() == QVariant::Bool) {
runInBackground = argument.toBool();
}
else {
processArguments << argument.toString();
}
if (getArgumentCount(L_p) >= 3) {
if (argument.type() == QVariant::Bool) {
processArguments << argument.toString();
}
runInBackground = getVariant(L_p, 3).toBool();
}
if (runInBackground) {
processSuccessed = QProcess::startDetached(processPath, processArguments);
}
else {
processReturn = QProcess::execute(processPath, processArguments);
}
}
else {
#if QT_VERSION >= 0x050F00
processReturn = system(getVariant(L_p, 1).toString().toUtf8().constData());
#else
processReturn = QProcess::execute(getVariant(L_p, 1).toString());
#endif
}
if (runInBackground && !processSuccessed) {
processReturn = -2;
}
else if (!runInBackground && processReturn == 0) {
processSuccessed = true;
}
pushVariant(L_p, processSuccessed);
pushVariant(L_p, processReturn);
return 2;
}
pushVariant(L_p, false);
pushVariant(L_p, -2);
return 2;
}

View File

@ -70,10 +70,20 @@ public:
static int getArgumentCount(lua_State *L_p); static int getArgumentCount(lua_State *L_p);
private: private:
// XMPP
static int jid(lua_State *L_p); static int jid(lua_State *L_p);
static int jin(lua_State *L_p); static int jin(lua_State *L_p);
static int sendMessage(lua_State *L_p); static int sendMessage(lua_State *L_p);
static int setPresence(lua_State *L_p); static int setClientPresence(lua_State *L_p);
// JSON
static int jsonToTable(lua_State *L_p);
static int tableToJson(lua_State *L_p);
// Process
static int executeProcess(lua_State *L_p);
// Lua
lua_State *L; lua_State *L;
}; };

View File

@ -16,13 +16,15 @@
* responsible for anything with use of the software, you are self responsible. * responsible for anything with use of the software, you are self responsible.
*****************************************************************************/ *****************************************************************************/
#include <QCoreApplication>
#include <QEventLoop>
#include <QFile> #include <QFile>
#include "xmppbotlua.h" #include "xmppbotlua.h"
#include "xmppbotluathread.h" #include "xmppbotluathread.h"
XmppBotLuaThread::XmppBotLuaThread(const QString &filePath, const QString &lua_function, const QVariantList &lua_args) : XmppBotLuaThread::XmppBotLuaThread(const QString &filePath, const QString &lua_function, const QVariantList &lua_args, const bool &lua_globalthread) :
filePath(filePath), lua_function(lua_function), lua_args(lua_args) filePath(filePath), lua_function(lua_function), lua_args(lua_args), lua_globalthread(lua_globalthread)
{ {
} }
@ -36,9 +38,20 @@ void XmppBotLuaThread::run()
scriptFile.close(); scriptFile.close();
} }
} }
if (!script.isEmpty()) {
XmppBotLua xmppBotLua; if (script.isEmpty())
xmppBotLua.executeLuaScript(script); return;
xmppBotLua.executeLuaFunction(lua_function.toUtf8().constData(), lua_args);
XmppBotLua xmppBotLua;
xmppBotLua.executeLuaScript(script);
xmppBotLua.executeLuaFunction(lua_function.toUtf8().constData(), lua_args);
if (lua_globalthread) {
QObject::connect(this, &XmppBotLuaThread::executeLuaFunction, this, [&](const QString &lua_function, const QVariantList &lua_args) {
xmppBotLua.executeLuaFunction(lua_function.toUtf8().constData(), lua_args);
});
QEventLoop threadLoop;
QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, &threadLoop, &QEventLoop::quit);
threadLoop.exec();
} }
} }

View File

@ -26,7 +26,7 @@ class XmppBotLuaThread : public QThread
{ {
Q_OBJECT Q_OBJECT
public: public:
XmppBotLuaThread(const QString &filePath, const QString &lua_function, const QVariantList &lua_args); XmppBotLuaThread(const QString &filePath, const QString &lua_function, const QVariantList &lua_args, const bool &lua_globalthread = false);
protected: protected:
void run(); void run();
@ -35,6 +35,10 @@ private:
QString filePath; QString filePath;
QString lua_function; QString lua_function;
QVariantList lua_args; QVariantList lua_args;
bool lua_globalthread;
signals:
void executeLuaFunction(const QString &lua_function, const QVariantList &lua_args);
}; };
#endif // XMPPBOTLUATHREAD_H #endif // XMPPBOTLUATHREAD_H