Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic lua scripting capabilities #4341

Merged
merged 157 commits into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
511a720
Add VERY basic lua scripting capabilities
Mm2PL Jan 29, 2023
b904dbc
Add some callbacks back and forth
Mm2PL Jan 29, 2023
fd41b45
Add callEveryWithArgs
Mm2PL Jan 29, 2023
3067851
Make lualol test command use callEveryWithArgs
Mm2PL Jan 29, 2023
307722c
Try to make it compile xd
Mm2PL Jan 30, 2023
50653af
Frankenstein some more
Mm2PL Jan 30, 2023
64a1e71
Use recommended way to include lua
Mm2PL Jan 30, 2023
9a866c6
Try to add include dirs
Mm2PL Jan 30, 2023
28e0209
Forward decl
Mm2PL Jan 30, 2023
a74e7a8
Add support for custom commands
Mm2PL Jan 30, 2023
6eb509c
Add error handling to command execution
Mm2PL Jan 30, 2023
ea2eb8b
Add luaC2SendMsg
Mm2PL Jan 30, 2023
40c8e9e
Remove lualol command
Mm2PL Jan 30, 2023
995301f
Move pushing stuff to lua stack to LuaUtilities
Mm2PL Jan 30, 2023
9f8bce9
Clean up CMakeLists
Mm2PL Jan 30, 2023
a483797
Add more push/peek/pop functions to LuaUtilities
Mm2PL Jan 30, 2023
75073b2
Add a StackIdx type alias
Mm2PL Jan 30, 2023
2af9e05
Code cleanup
Mm2PL Jan 30, 2023
aee4088
Add a Plugins settings page
Mm2PL Jan 30, 2023
cc5654d
Add support for reloading plugins
Mm2PL Jan 30, 2023
3d48cb4
Try this way
Mm2PL Jan 30, 2023
61deede
i hate you, msvc so fucking much
Mm2PL Jan 31, 2023
a1498ab
Add lua::humanErrorText
Mm2PL Jan 31, 2023
3e92f5d
Add a basic permission system based on lua stdlib loading
Mm2PL Jan 31, 2023
39d1af1
please compiler overlords
Mm2PL Jan 31, 2023
05163c3
"package" is also dangerous
Mm2PL Jan 31, 2023
71afe14
Rebuild plugin settings UI on plugin reload
Mm2PL Jan 31, 2023
119b3e2
Add a listing of plugin commands
Mm2PL Jan 31, 2023
b44c608
Make plugins directory a link
Mm2PL Jan 31, 2023
c306095
Improve plugin settings
Mm2PL Jan 31, 2023
054b910
Fix up completion for plugin commands
Mm2PL Jan 31, 2023
fb6c9ff
Includes?
Mm2PL Jan 31, 2023
382fe85
Use placeholder values for PluginMeta
Mm2PL Feb 1, 2023
deeea01
Add lua license
Mm2PL Feb 1, 2023
edbcfce
Clean up PluginsPage
Mm2PL Feb 1, 2023
280836e
Clean up PluginsPage some more
Mm2PL Feb 1, 2023
d114032
Don't actually load disabled plugins lol
Mm2PL Feb 1, 2023
d48adcd
Move dangerous stdlib logic to PluginMeta
Mm2PL Feb 1, 2023
323867e
Move chatterino global namespace shit into a namespace
Mm2PL Feb 1, 2023
179af53
Move Plugin and PluginMeta into plugin.{c,h}pp
Mm2PL Feb 1, 2023
27347b3
Add CHATTERINO_HAVE_PLUGINS define
Mm2PL Feb 2, 2023
44bcecf
Try to add CI that builds with CHATTERINO_HAVE_PLUGINS
Mm2PL Feb 2, 2023
1489e92
Remove libraryPermissions in favor of loading safe(ish) stdlib part
Mm2PL Feb 2, 2023
21fc895
Make c2.register_command() return a boolean if it went ok
Mm2PL Feb 2, 2023
b8bd3c1
Add a markdown doc explaining the lua environment
Mm2PL Feb 2, 2023
b6664fe
Add a section on plugin structure
Mm2PL Feb 2, 2023
23f2d96
Make clang-tidy complain a little less
Mm2PL Feb 2, 2023
9d92cdf
I hate prettier SO FUCKING MUCH
Mm2PL Feb 2, 2023
9ffbc7b
Move shit around, add g_load()
Mm2PL Feb 3, 2023
d6beac9
Add lua::peek for QByteArray
Mm2PL Feb 4, 2023
3ef0197
Replace Lua loadfile/dofile with execfile()
Mm2PL Feb 4, 2023
c8999fd
Check for invalid utf8 better
Mm2PL Feb 4, 2023
eb7156c
Fix up docs
Mm2PL Feb 4, 2023
8aadf18
Document load() and execfile() changes
Mm2PL Feb 4, 2023
c3a5a07
Remove useless lua version set() calls
Mm2PL Feb 4, 2023
2050776
Clean up diff
Mm2PL Feb 4, 2023
d59e55b
Begone stupid include
Mm2PL Feb 4, 2023
0ec141a
Rename ApiChatterino -> LuaApi
Mm2PL Feb 4, 2023
bca89a1
Use lua convention for main file in package: init.lua
Mm2PL Feb 4, 2023
2c49ec9
Add an icon for the plugins tab
Mm2PL Feb 4, 2023
aedd398
Use target_compile_definitions for -DCHATTERINO_HAVE_PLUGINS
Mm2PL Feb 6, 2023
5b07c7e
Apply Nerixyz's documentation suggestion
Mm2PL Feb 6, 2023
cebab00
Add a info.json schema
Mm2PL Feb 6, 2023
6acfd4f
Validate info.json harder and show what's wrong
Mm2PL Feb 6, 2023
378a15b
Improve chatterino.lua logs + remove . and .. from plugin search
Mm2PL Feb 7, 2023
03d5805
Fix double plugin initialization problem
Mm2PL Feb 7, 2023
b85c931
Add all the missing .path() calls
Mm2PL Feb 7, 2023
fbb3cb6
Clean up NOLINT comments
Mm2PL Feb 7, 2023
d6aff4a
Get rid of REPLACEMENT_CHARACTER constant
Mm2PL Feb 7, 2023
545fae7
Rename constant C2LIB -> c2lib
Mm2PL Feb 7, 2023
48436c9
Remove unused include in CommandController.cpp
Mm2PL Feb 7, 2023
44b22b1
Add missing new line in CommandController.cpp
Mm2PL Feb 7, 2023
81e07df
Remove useless new line in src/CMakeLists.txt
Mm2PL Feb 7, 2023
dbf7171
Clean up includes in PluginController.{c,h}pp
Mm2PL Feb 7, 2023
8ab3f99
Tell clang-tidy that `L` is a fine name for a local pointer
Mm2PL Feb 7, 2023
8c7e9c7
Add missing #ifdef CHATTERINO_HAVE_PLUGINS
Mm2PL Feb 7, 2023
4bb9985
Use Plugin destructor to call lua_close in most cases
Mm2PL Feb 7, 2023
7e06408
diff cleanup
Mm2PL Feb 7, 2023
57e83e1
Add missing QDir::NoFilter to the directory filter
Mm2PL Feb 7, 2023
bdedb79
Clean up header generation code
Mm2PL Feb 7, 2023
8dfe859
Add lua::{peek,push} support for std::string
Mm2PL Feb 8, 2023
faf4d43
Add lua::toString which converts value to a string
Mm2PL Feb 8, 2023
5cdd89e
Add lua::{peek,push} support for enums with magic_enum
Mm2PL Feb 8, 2023
679e03c
Add proper support for logging from lua
Mm2PL Feb 8, 2023
e265548
docs: make sure all code blocks have an appropriate language
Mm2PL Feb 8, 2023
4e474dc
Remove unused PluginController::callEvery{,WithArgs}
Mm2PL Feb 10, 2023
04b8b65
Update docs
Mm2PL Feb 11, 2023
638f62a
Make pop work better (:
Mm2PL Feb 11, 2023
e0a4ef2
Move CHANGELOG to Dev category
Mm2PL Feb 11, 2023
4b6f56d
Update library notes
Mm2PL Feb 11, 2023
a909569
Add stackDump lua utility, for debugging or tests
Mm2PL Feb 11, 2023
e0dabb8
Make load() only usable in debug mode
Mm2PL Feb 12, 2023
9a7d44c
Remove erroneous mention of lua loadfile
Mm2PL Feb 12, 2023
90e95b3
Pin lua version to 5.4.4
Mm2PL Feb 12, 2023
8195b59
Rename LuaApi -> LuaAPI
Mm2PL Feb 12, 2023
1984bee
absolute include path
Mm2PL Feb 12, 2023
d09e3d1
Fix up CI
Mm2PL Feb 12, 2023
843c4cb
Thank you clang-format for at least having a diff
Mm2PL Feb 12, 2023
fb438ab
Rename execfile -> import
Mm2PL Feb 13, 2023
8a7ddab
Reformat src/controllers/plugins/Plugin.cpp
Mm2PL Feb 13, 2023
b37254b
Reformat src/widgets/settingspages/PluginsPage.hpp
Mm2PL Feb 13, 2023
1846665
Reformat src/widgets/settingspages/PluginsPage.cpp
Mm2PL Feb 13, 2023
803a2f7
Reformat src/controllers/plugins/Plugin.hpp
Mm2PL Feb 13, 2023
e2600a1
Reformat src/controllers/plugins/LuaUtilities.hpp
Mm2PL Feb 13, 2023
d014e22
Reformat src/controllers/plugins/LuaAPI.hpp
Mm2PL Feb 13, 2023
ce143c1
Replace "local" #includes with <global> #includes for lua
Mm2PL Feb 13, 2023
582a946
reformat
Mm2PL Feb 13, 2023
52d547e
Change setting names
Mm2PL Feb 13, 2023
61f30db
Update comment on chatterino::lua::api::g_import
Mm2PL Feb 13, 2023
1216565
Remove PluginController save override
Mm2PL Feb 13, 2023
b767255
Make PluginMeta::authors a std::vector<QString>
Mm2PL Feb 13, 2023
4ebb9d6
Handle plugin metadata errors better
Mm2PL Feb 14, 2023
81ef1ba
Make the reload button reload metadata when plugin is disabled
Mm2PL Feb 14, 2023
6281b3a
Add comments to PluginMeta definition
Mm2PL Feb 14, 2023
a20b35d
Handle info.json homepage type mismatches
Mm2PL Feb 14, 2023
1e20e04
Improve UI if homepage is missing
Mm2PL Feb 14, 2023
dac160a
Rip out redundant enable check
Mm2PL Feb 14, 2023
0e8137f
Rename PluginController::{actuallyInitialize,loadPlugins}
Mm2PL Feb 14, 2023
aaaf77c
rename codename -> id
Mm2PL Feb 14, 2023
54b4e31
Make chatterino::lua::api::LogLevel an enum class
Mm2PL Feb 14, 2023
1f62aeb
Rename variables in PluginsPage
Mm2PL Feb 14, 2023
5ccd9ef
Add parents for every widget in PluginsPage
Mm2PL Feb 14, 2023
ceb168a
Move logHelper and its namespace to the top of LuaAPI.cpp
Mm2PL Feb 14, 2023
ae48bb6
Rip out the duplicate name logic
Mm2PL Feb 14, 2023
ab3d490
prettier is shitty
Mm2PL Feb 14, 2023
ac656a7
Rename CommandContext.channelName -> channel_name on lua side
Mm2PL Feb 28, 2023
b36d92c
Add a basic .d.ts file for TypescriptToLua
Mm2PL Feb 28, 2023
ecd75a6
Add doc section on Typescript
Mm2PL Feb 28, 2023
e56daa1
Rename settings again :)
Mm2PL Apr 1, 2023
4aa3d16
Clean up PluginController.hpp by moving stuff into .cpp
Mm2PL Apr 1, 2023
9c2da10
Rename PluginController::isEnabled() to PluginController::isPluginEna…
Mm2PL Apr 1, 2023
edcde8d
Don't check Settings::pluginsEnabled in PluginController::isPluginEna…
Mm2PL Apr 1, 2023
2fd546d
Merge branch 'master' of github.com:Chatterino/chatterino2 into featu…
Mm2PL Apr 1, 2023
24d9925
Add additionalProperties: false to plugin info schema
Mm2PL Apr 1, 2023
deade90
docs/wip-plugins.md: Use full sentences.
Mm2PL Apr 1, 2023
3a0693a
docs/wip-plugins.md: Use full sentences (part 2).
Mm2PL Apr 1, 2023
b87b13d
Improve macro expansion comments in LuaAPI.cpp
Mm2PL Apr 1, 2023
2c24b97
Adjust log levels in PluginController.cpp
Mm2PL Apr 1, 2023
e1d1a21
Move PluginMeta::PluginMeta(const QJsonObject&) to cpp file
Mm2PL Apr 1, 2023
305a847
Clean up includes
Mm2PL Apr 1, 2023
0e1d856
Use string_view::data() instead of std::string(std::string_view)
Mm2PL Apr 1, 2023
407f14a
Extract QDebug helper from lua::api::g_log.
Mm2PL Apr 1, 2023
85b5506
Reorder cases in qdebugStreamForLogLevel(LogLevel)
Mm2PL Apr 1, 2023
cfb39f5
Improve log messages for lua::api::{system,send}_msg
Mm2PL Apr 1, 2023
e9f06ac
Fix up error messages in LuaAPI.cpp
Mm2PL Apr 1, 2023
30fa4f5
Remove useless OK debug message
Mm2PL Apr 1, 2023
19144d5
Improve error message for register_command()
Mm2PL Apr 2, 2023
cade008
Add missing argument errors for c2_send_msg and c2_system_msg
Mm2PL Apr 2, 2023
f4cf553
Improve system_msg missing args error
Mm2PL Apr 2, 2023
3349f30
Move utf-8 comment down a couple lines
Mm2PL Apr 2, 2023
4dbe9c1
Change change Plugin::listRegisteredCommands() to return std::unorder…
Mm2PL Apr 2, 2023
e34ab61
Clean up includes
Mm2PL Apr 2, 2023
2879943
Use unordered_map for storing plugin command callbacks
Mm2PL Apr 2, 2023
005e524
Merge plugins builder into !PCH + LTO one
Mm2PL Apr 2, 2023
950df48
Merge branch 'master' of github.com:Chatterino/chatterino2 into featu…
Mm2PL Apr 2, 2023
28933de
Remove artifact description stuff
Mm2PL Apr 2, 2023
11c7333
Merge branch 'master' into feature/lua_scripting
pajlada Apr 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ CheckOptions:
value: camelBack
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: true

# Lua state
- key: readability-identifier-naming.LocalPointerIgnoredRegexp
value: ^L$
15 changes: 13 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
qt-version: [5.15.2, 5.12.12]
pch: [true]
force-lto: [false]
plugins: [false]
skip_artifact: ["no"]
crashpad: [true]
include:
Expand All @@ -45,19 +46,21 @@ jobs:
qt-version: 6.2.4
pch: false
force-lto: false
# Test for disabling Precompiled Headers & enabling link-time optimization
# Test for disabling Precompiled Headers & enabling link-time optimization and plugins
- os: ubuntu-22.04
qt-version: 5.15.2
pch: false
force-lto: true
skip_artifact: "yes"
plugins: true
# Test for disabling crashpad on Windows
- os: windows-latest
qt-version: 5.15.2
pch: false
force-lto: true
skip_artifact: "yes"
crashpad: false

fail-fast: false

steps:
Expand All @@ -67,6 +70,12 @@ jobs:
echo "C2_ENABLE_LTO=ON" >> "$GITHUB_ENV"
shell: bash

- name: Enable plugin support
if: matrix.plugins == true
run: |
echo "C2_PLUGINS=ON" >> "$GITHUB_ENV"
shell: bash

- name: Set Crashpad
if: matrix.crashpad == true
run: |
Expand Down Expand Up @@ -160,6 +169,7 @@ jobs:
-DUSE_PRECOMPILED_HEADERS=${{ matrix.pch }} `
-DBUILD_WITH_CRASHPAD="$Env:C2_ENABLE_CRASHPAD" `
-DCHATTERINO_LTO="$Env:C2_ENABLE_LTO" `
-DCHATTERINO_PLUGINS="$Env:C2_PLUGINS" `
-DBUILD_WITH_QT6="$Env:C2_BUILD_WITH_QT6" `
..
set cl=/MP
Expand Down Expand Up @@ -246,6 +256,7 @@ jobs:
-DUSE_PRECOMPILED_HEADERS=${{ matrix.pch }} \
-DCMAKE_EXPORT_COMPILE_COMMANDS=On \
-DCHATTERINO_LTO="$C2_ENABLE_LTO" \
-DCHATTERINO_PLUGINS="$C2_PLUGINS" \
-DBUILD_WITH_QT6="$C2_BUILD_WITH_QT6" \
..
make -j"$(nproc)"
Expand Down Expand Up @@ -310,6 +321,7 @@ jobs:
-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl \
-DUSE_PRECOMPILED_HEADERS=${{ matrix.pch }} \
-DCHATTERINO_LTO="$C2_ENABLE_LTO" \
-DCHATTERINO_PLUGINS="$C2_PLUGINS" \
-DBUILD_WITH_QT6="$C2_BUILD_WITH_QT6" \
..
make -j"$(sysctl -n hw.logicalcpu)"
Expand All @@ -331,7 +343,6 @@ jobs:
with:
name: chatterino-osx-${{ matrix.qt-version }}.dmg
path: build/chatterino-osx.dmg

create-release:
needs: build
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
[submodule "lib/miniaudio"]
path = lib/miniaudio
url = https://github.com/mackron/miniaudio.git
[submodule "lib/lua/src"]
path = lib/lua/src
url = https://github.com/lua/lua
[submodule "lib/crashpad"]
path = lib/crashpad
url = https://github.com/getsentry/crashpad
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- Dev: Only log debug messages when NDEBUG is not defined. (#4442)
- Dev: Cleaned up theme related code. (#4450)
- Dev: Ensure tests have default-initialized settings. (#4498)
- Dev: Add scripting capabilities with Lua (#4341)
- Dev: Conan 2.0 is now used instead of Conan 1.0. (#4417)

## 2.4.2
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ option(CHATTERINO_GENERATE_COVERAGE "Generate coverage files" OFF)
option(BUILD_TRANSLATIONS "" OFF)
option(BUILD_SHARED_LIBS "" OFF)
option(CHATTERINO_LTO "Enable LTO for all targets" OFF)
option(CHATTERINO_PLUGINS "Enable EXPERIMENTAL plugin support in Chatterino" OFF)

if(CHATTERINO_LTO)
include(CheckIPOSupported)
Expand Down Expand Up @@ -156,6 +157,11 @@ else()
add_subdirectory("${CMAKE_SOURCE_DIR}/lib/settings" EXCLUDE_FROM_ALL)
endif()

if (CHATTERINO_PLUGINS)
set(LUA_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/lib/lua/src")
add_subdirectory(lib/lua)
endif()

if (BUILD_WITH_CRASHPAD)
add_subdirectory("${CMAKE_SOURCE_DIR}/lib/crashpad" EXCLUDE_FROM_ALL)
endif()
Expand Down
22 changes: 22 additions & 0 deletions docs/chatterino.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/** @noSelfInFile */

declare module c2 {
enum LogLevel {
Debug,
Info,
Warning,
Critical,
}
class CommandContext {
words: String[];
channel_name: String;
}

function log(level: LogLevel, ...data: any[]): void;
function register_command(
name: String,
handler: (ctx: CommandContext) => void
): boolean;
function send_msg(channel: String, text: String): boolean;
function system_msg(channel: String, text: String): boolean;
}
49 changes: 49 additions & 0 deletions docs/plugin-info.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "https://raw.githubusercontent.com/Chatterino/chatterino2/master/docs/plugin-info.schema.json",
"title": "Plugin info",
"description": "Describes a Chatterino2 plugin (draft)",
"type": "object",
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "Plugin name shown to the user."
},
"description": {
"type": "string",
"description": "Plugin description shown to the user."
},
"authors": {
"type": "array",
"description": "An array of authors of this Plugin.",
"items": {
"type": "string"
}
},
"homepage": {
"type": "string",
"description": "Optional URL to your Plugin's homepage. This could be your GitHub repo for example."
},
"tags": {
"description": "Something that could in the future be used to find your plugin.",
"type": "array",
"items": {
"type": "string",
"examples": ["moderation", "utility", "commands"]
},
"uniqueItems": true
},
"version": {
"type": "string",
"description": "Semver version string, for more info see https://semver.org.",
"examples": ["0.0.1", "1.0.0-rc.1"]
},
"license": {
"type": "string",
"description": "A small description of your license.",
"examples": ["MIT", "GPL-2.0-or-later"]
}
},
"required": ["name", "description", "authors", "version", "license"]
}
177 changes: 177 additions & 0 deletions docs/wip-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Plugins

If Chatterino is compiled with the `CHATTERINO_PLUGINS` CMake option, it can
load and execute Lua files. Note that while there are attempts at making this
decently safe, we cannot guarantee safety.

## Plugin structure

Chatterino searches for plugins in the `Plugins` directory in the app data, right next to `Settings` and `Logs`.

Each plugin should have its own directory.

```
Chatterino Plugins dir/
└── plugin_name/
├── init.lua
└── info.json
```

`init.lua` will be the file loaded when the plugin is enabled. You may load other files using [`import` global function](#importfilename=).

`info.json` contains metadata about the plugin, like its name, description,
authors, homepage link, tags, version, license name. The version field **must**
be [semver 2.0](https://semver.org/) compliant. The general idea of `info.json`
will not change however the exact contents probably will, for example with
permission system ideas.
Example file:

```json
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved
{
"$schema": "https://raw.githubusercontent.com/Chatterino/chatterino2/master/docs/plugin-info.schema.json",
"name": "Test plugin",
"description": "This plugin is for testing stuff.",
"authors": "Mm2PL",
"homepage": "https://github.com/Chatterino/Chatterino2",
"tags": ["test"],
"version": "0.0.0",
"license": "MIT"
}
```

An example plugin is available at [https://github.com/Mm2PL/Chatterino-test-plugin](https://github.com/Mm2PL/Chatterino-test-plugin)

## Plugins with Typescript

If you prefer, you may use [TypescriptToLua](https://typescripttolua.github.io)
to typecheck your plugins. There is a `chatterino.d.ts` file describing the API
in this directory. However this has several drawbacks like harder debugging at
runtime.

## API

The following parts of the Lua standard library are loaded:

- `_G` (most globals)
- `table`
- `string`
- `math`
- `utf8`

The official manual for them is available [here](https://www.lua.org/manual/5.4/manual.html#6).

### Chatterino API

All Chatterino functions are exposed in a global table called `c2`. The following members are available:

#### `log(level, args...)`

Writes a message to the Chatterino log. The `level` argument should be a
`LogLevel` member. All `args` should be convertible to a string with
`tostring()`.

Example:

```lua
c2.log(c2.LogLevel.Warning, "Hello, this should show up in the Chatterino log by default")

c2.log(c2.LogLevel.Debug, "Hello world")
-- Equivalent to doing qCDebug(chatterinoLua) << "[pluginDirectory:Plugin Name]" << "Hello, world"; from C++
```

#### `LogLevel` enum

This table describes log levels available to Lua Plugins. The values behind the names may change, do not count on them. It has the following keys:

- `Debug`
- `Info`
- `Warning`
- `Critical`

#### `register_command(name, handler)`

Registers a new command called `name` which when executed will call `handler`.
Returns `true` if everything went ok, `false` if there already exists another
command with this name.

Example:

```lua
function cmdWords(ctx)
-- ctx contains:
-- words - table of words supplied to the command including the trigger
-- channelName - name of the channel the command is being run in
c2.system_msg(ctx.channelName, "Words are: " .. table.concat(ctx.words, " "))
end

c2.register_command("/words", cmdWords)
```

Limitations/known issues:

- Commands registered in functions, not in the global scope might not show up in the settings UI,
rebuilding the window content caused by reloading another plugin will solve this.
- Spaces in command names aren't handled very well (https://github.com/Chatterino/chatterino2/issues/1517).

#### `send_msg(channel, text)`

Sends a message to `channel` with the specified text. Also executes commands.

Example:

```lua
function cmdShout(ctx)
table.remove(ctx.words, 1)
local output = table.concat(ctx.words, " ")
c2.send_msg(ctx.channelName, string.upper(output))
end
c2.register_command("/shout", cmdShout)
```

Limitations/Known issues:

- It is possible to trigger your own Lua command with this causing a potentially infinite loop.

#### `system_msg(channel, text)`

Creates a system message and adds it to the twitch channel specified by
`channel`. Returns `true` if everything went ok, `false` otherwise. It will
throw an error if the number of arguments received doesn't match what it
expects.

Example:

```lua
local ok = c2.system_msg("pajlada", "test")
if (not ok)
-- channel not found
end
```

### Changed globals

#### `load(chunk [, chunkname [, mode [, env]]])`
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved

This function is only available if Chatterino is compiled in debug mode. It is meant for debugging with little exception.
This function behaves really similarity to Lua's `load`, however it does not allow for bytecode to be executed.
It achieves this by forcing all inputs to be encoded with `UTF-8`.

See [official documentation](https://www.lua.org/manual/5.4/manual.html#pdf-load)

#### `import(filename)`

This function mimics Lua's `dofile` however relative paths are relative to your plugin's directory.
You are restricted to loading files in your plugin's directory. You cannot load files with bytecode inside.

Example:

```lua
import("stuff.lua") -- executes Plugins/name/stuff.lua
import("./stuff.lua") -- executes Plugins/name/stuff.lua
import("../stuff.lua") -- tries to load Plugins/stuff.lua and errors
import("luac.out") -- tried to load Plugins/name/luac.out and errors because it contains non-utf8 data
```

#### `print(Args...)`

The `print` global function is equivalent to calling `c2.log(c2.LogLevel.Debug, Args...)`
Loading