diff --git a/.gitmodules b/.gitmodules index f1a5f351a..25b40e3d1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -38,3 +38,6 @@ [submodule "lib/miniaudio"] path = lib/miniaudio url = https://github.com/mackron/miniaudio.git +[submodule "lib/lua"] + path = lib/lua + url = https://github.com/lua/lua diff --git a/CMakeLists.txt b/CMakeLists.txt index 27c434bf3..3211e9622 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,30 @@ else() add_subdirectory("${CMAKE_SOURCE_DIR}/lib/settings" EXCLUDE_FROM_ALL) endif() +#find_package(Lua REQUIRED) +add_custom_target( + Lua ALL + COMMAND make + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/lua +) +#include(ExternalProject) +# +#ExternalProject_Add(lua +# URL "https://www.lua.org/ftp/lua-5.4.4.tar.gz" +# CONFIGURE_COMMAND "" +# BUILD_COMMAND make generic +# BUILD_ALWAYS true +# BUILD_IN_SOURCE true +# INSTALL_COMMAND "" +# SOURCE_DIR "${CMAKE_SOURCE_DIR}/lib/lua" +#) +#add_library(liblua +# STATIC +# IMPORTED +#) +#ExternalProject_Get_property(lua SOURCE_DIR) +#message("liblua will be found at \'${SOURCE_DIR}/src\'") + set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/lib/lua b/lib/lua new file mode 160000 index 000000000..d69789da1 --- /dev/null +++ b/lib/lua @@ -0,0 +1 @@ +Subproject commit d69789da1ccfa4db7c241de6b471d6b729f1561e diff --git a/src/Application.cpp b/src/Application.cpp index 7d02b3931..6df7ef647 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -10,6 +10,7 @@ #include "controllers/hotkeys/HotkeyController.hpp" #include "controllers/ignores/IgnoreController.hpp" #include "controllers/notifications/NotificationController.hpp" +#include "controllers/plugins/PluginController.hpp" #include "controllers/sound/SoundController.hpp" #include "controllers/userdata/UserDataController.hpp" #include "debug/AssertInGuiThread.hpp" @@ -52,7 +53,6 @@ #include namespace chatterino { - static std::atomic isAppInitialized{false}; Application *Application::instance = nullptr; @@ -85,6 +85,7 @@ Application::Application(Settings &_settings, Paths &_paths) , seventvBadges(&this->emplace()) , userData(&this->emplace()) , sound(&this->emplace()) + , plugins(&this->emplace()) , logging(&this->emplace()) { this->instance = this; @@ -143,7 +144,8 @@ void Application::initialize(Settings &settings, Paths &paths) if (auto channel = split->getChannel(); !channel->isEmpty()) { channel->addMessage(makeSystemMessage( - "Chatterino unexpectedly crashed and restarted. " + "Chatterino unexpectedly crashed and " + "restarted. " "You can disable automatic restarts in the " "settings.")); } diff --git a/src/Application.hpp b/src/Application.hpp index dada8d02a..a4d1de114 100644 --- a/src/Application.hpp +++ b/src/Application.hpp @@ -20,6 +20,7 @@ class HotkeyController; class IUserDataController; class UserDataController; class SoundController; +class PluginController; class Theme; class WindowManager; @@ -95,6 +96,8 @@ public: UserDataController *const userData{}; SoundController *const sound{}; + PluginController *const plugins{}; + /*[[deprecated]]*/ Logging *const logging{}; Theme *getThemes() override diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d2105dc1..da300ab68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -136,6 +136,9 @@ set(SOURCE_FILES controllers/pings/MutedChannelModel.cpp controllers/pings/MutedChannelModel.hpp + controllers/plugins/PluginController.hpp + controllers/plugins/PluginController.cpp + controllers/userdata/UserDataController.cpp controllers/userdata/UserDataController.hpp controllers/userdata/UserData.hpp @@ -597,6 +600,7 @@ if (CHATTERINO_GENERATE_COVERAGE) ) endif () +add_dependencies(${LIBRARY_PROJECT} Lua) target_link_libraries(${LIBRARY_PROJECT} PUBLIC Qt${MAJOR_QT_VERSION}::Core @@ -615,7 +619,9 @@ target_link_libraries(${LIBRARY_PROJECT} RapidJSON::RapidJSON LRUCache MagicEnum + "${CMAKE_SOURCE_DIR}/lib/lua/liblua.a" ) + if (BUILD_WITH_QTKEYCHAIN) target_link_libraries(${LIBRARY_PROJECT} PUBLIC diff --git a/src/common/QLogging.cpp b/src/common/QLogging.cpp index 8679e7a8d..2d58fa4ad 100644 --- a/src/common/QLogging.cpp +++ b/src/common/QLogging.cpp @@ -24,6 +24,7 @@ Q_LOGGING_CATEGORY(chatterinoIrc, "chatterino.irc", logThreshold); Q_LOGGING_CATEGORY(chatterinoIvr, "chatterino.ivr", logThreshold); Q_LOGGING_CATEGORY(chatterinoLiveupdates, "chatterino.liveupdates", logThreshold); +Q_LOGGING_CATEGORY(chatterinoLua, "chatterino.lua", logThreshold); Q_LOGGING_CATEGORY(chatterinoMain, "chatterino.main", logThreshold); Q_LOGGING_CATEGORY(chatterinoMessage, "chatterino.message", logThreshold); Q_LOGGING_CATEGORY(chatterinoNativeMessage, "chatterino.nativemessage", diff --git a/src/common/QLogging.hpp b/src/common/QLogging.hpp index 0aa50fae6..1922133ee 100644 --- a/src/common/QLogging.hpp +++ b/src/common/QLogging.hpp @@ -19,6 +19,7 @@ Q_DECLARE_LOGGING_CATEGORY(chatterinoImage); Q_DECLARE_LOGGING_CATEGORY(chatterinoIrc); Q_DECLARE_LOGGING_CATEGORY(chatterinoIvr); Q_DECLARE_LOGGING_CATEGORY(chatterinoLiveupdates); +Q_DECLARE_LOGGING_CATEGORY(chatterinoLua); Q_DECLARE_LOGGING_CATEGORY(chatterinoMain); Q_DECLARE_LOGGING_CATEGORY(chatterinoMessage); Q_DECLARE_LOGGING_CATEGORY(chatterinoNativeMessage); diff --git a/src/controllers/plugins/PluginController.cpp b/src/controllers/plugins/PluginController.cpp new file mode 100644 index 000000000..cefb0dbc1 --- /dev/null +++ b/src/controllers/plugins/PluginController.cpp @@ -0,0 +1,55 @@ +#include "PluginController.hpp" + +#include "common/QLogging.hpp" + +#include + +extern "C" { +#include +#include +#include +#include +} + +namespace chatterino { + +void PluginController::initialize(Settings &settings, Paths &paths) +{ + (void)(settings); + + auto dir = QDir(paths.pluginsDirectory); + qCDebug(chatterinoLua) << "loading plugins from " << dir; + for (const auto &info : dir.entryInfoList()) + { + if (info.isDir()) + { + // look for index.lua + auto pluginDir = QDir(info.absoluteFilePath()); + auto index = QFileInfo(pluginDir.filePath("index.lua")); + qCDebug(chatterinoLua) + << "trying" << info << "," << index << "at" << pluginDir; + if (!index.exists()) + { + qCDebug(chatterinoLua) + << "Missing index.lua in plugin directory" << pluginDir; + continue; + } + qCDebug(chatterinoLua) << "found index.lua, running it!"; + + this->load(index, pluginDir); + } + } + // QApplication::exit(); +} + +void PluginController::load(QFileInfo index, QDir pluginDir) +{ + qCDebug(chatterinoLua) << "Running lua file" << index; + lua_State *l = luaL_newstate(); + luaL_openlibs(l); + + luaL_dofile(l, index.absoluteFilePath().toStdString().c_str()); + lua_close(l); +} + +}; // namespace chatterino diff --git a/src/controllers/plugins/PluginController.hpp b/src/controllers/plugins/PluginController.hpp new file mode 100644 index 000000000..b2db728a2 --- /dev/null +++ b/src/controllers/plugins/PluginController.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "common/Singleton.hpp" +#include "singletons/Paths.hpp" + +#include +#include + +namespace chatterino { + +class PluginController : public Singleton +{ +public: + void initialize(Settings &settings, Paths &paths) override; + void save() override{}; + +private: + void load(QFileInfo index, QDir pluginDir); +}; + +}; // namespace chatterino diff --git a/src/singletons/Paths.cpp b/src/singletons/Paths.cpp index 437e27619..8c6c42660 100644 --- a/src/singletons/Paths.cpp +++ b/src/singletons/Paths.cpp @@ -141,6 +141,7 @@ void Paths::initSubDirectories() this->messageLogDirectory = makePath("Logs"); this->miscDirectory = makePath("Misc"); this->twitchProfileAvatars = makePath("ProfileAvatars"); + this->pluginsDirectory = makePath("Plugins"); //QDir().mkdir(this->twitchProfileAvatars + "/twitch"); } diff --git a/src/singletons/Paths.hpp b/src/singletons/Paths.hpp index aa717d896..5cada9594 100644 --- a/src/singletons/Paths.hpp +++ b/src/singletons/Paths.hpp @@ -31,6 +31,9 @@ public: // Profile avatars for Twitch /cache/twitch QString twitchProfileAvatars; + // Plugin files live here. /Plugins + QString pluginsDirectory; + bool createFolder(const QString &folderPath); bool isPortable();