summaryrefslogtreecommitdiff
path: root/luamods/event.lua
diff options
context:
space:
mode:
Diffstat (limited to 'luamods/event.lua')
-rw-r--r--luamods/event.lua376
1 files changed, 376 insertions, 0 deletions
diff --git a/luamods/event.lua b/luamods/event.lua
new file mode 100644
index 0000000..be27622
--- /dev/null
+++ b/luamods/event.lua
@@ -0,0 +1,376 @@
+local function parse_target(value)
+ local parts = str_split(value, ':')
+ if #parts ~= 2 then
+ return nil
+ end
+
+ local data = {
+ target = parts[1],
+ type = str_to_event_type(parts[2])
+ }
+
+ if data.type == nil then
+ return data
+ end
+
+ if data.type < 10 then
+ local users = twitch_get_users({ logins = { data.target } })
+ if #users == 0 then
+ data.target = nil
+ return data
+ end
+
+ data.target = users[1]
+ end
+
+ return data
+end
+
+local lines = {
+ english = {
+ ["no_subcommand"] =
+ "{sender.alias_name}: No subcommand provided. Use {channel.prefix}help event for more information.",
+ ["no_message"] = "{sender.alias_name}: No message provided.",
+ ["not_parseable"] = "{sender.alias_name}: This value cannot be parsed. (%s)",
+ ["unknown_type"] = "{sender.alias_name}: Unknown event type. (%s)",
+ ["user_not_found"] = "{sender.alias_name}: User not found. (%s)",
+ ["not_found"] = "{sender.alias_name}: Event %s not found.",
+ ["no_target"] = "{sender.alias_name}: Next event target must be provided.",
+ ["namesake"] = "{sender.alias_name}: Same event already exists.",
+ ["list"] = "{sender.alias_name}: %s",
+ ["empty_list"] = "{sender.alias_name}: There are no events in this channel.",
+ ["on"] =
+ "{sender.alias_name}: Successfully created a new event %s. Use '{channel.prefix}notify sub %s' to subscribe.",
+ ["off"] = "{sender.alias_name}: Successfully deleted event %s",
+ ["edit"] = "{sender.alias_name}: Edited a message for event %s",
+ ["settarget"] = "{sender.alias_name}: Changed event target from %s to %s",
+ ["flag_disabled"] = "{sender.alias_name}: Flag %s has been disabled for event %s",
+ ["flag_enabled"] = "{sender.alias_name}: Flag %s has been enabled for event %s",
+ ["view"] = "{sender.alias_name}: ID %s | %s | %s subs | Flags: %s | %s"
+ },
+ russian = {
+ ["no_subcommand"] =
+ "{sender.alias_name}: Подкоманда не предоставлена. Используйте {channel.prefix}help event для большей информации.",
+ ["no_message"] = "{sender.alias_name}: Сообщение не предоставлено.",
+ ["not_parseable"] = "{sender.alias_name}: Это значение не может быть использовано. (%s)",
+ ["unknown_type"] = "{sender.alias_name}: Неизвестный тип события. (%s)",
+ ["user_not_found"] = "{sender.alias_name}: Пользователь не найден. (%s)",
+ ["not_found"] = "{sender.alias_name}: Событие %s не найдено.",
+ ["no_target"] = "{sender.alias_name}: Следующие значение события должно быть предоставлено.",
+ ["namesake"] = "{sender.alias_name}: Такое же событие уже существует.",
+ ["list"] = "{sender.alias_name}: %s",
+ ["empty_list"] = "{sender.alias_name}: На этом канале нету событий.",
+ ["on"] =
+ "{sender.alias_name}: Успешно создано событие %s. Используйте '{channel.prefix}notify sub %s' для подписки.",
+ ["off"] = "{sender.alias_name}: Успешно удалено событие %s",
+ ["edit"] = "{sender.alias_name}: Сообщение для события %s было отредактировано.",
+ ["settarget"] = "{sender.alias_name}: Цель события было изменено с %s на %s",
+ ["flag_disabled"] = "{sender.alias_name}: Флаг %s был отключен для события %s",
+ ["flag_enabled"] = "{sender.alias_name}: Флаг %s был включен для события %s",
+ ["view"] = "{sender.alias_name}: ID %s | %s | %s подписчиков | Флаги: %s | %s"
+ },
+}
+
+return {
+ name = "event",
+ description = [[
+> This command is for broadcaster and moderators only.
+
+
+The `!event` command gives the ability to manage events.
+
+
+## Event types
+
++ live
++ offline
++ title
++ game
++ github (Placeholders for messages: `%0` - Commit hash, `%1` - Committer name, `%2` - Commit message)
++ custom
+
+## Syntax
+
+### Create a new event
+
+`!event on [name]:[type] [message...]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
++ `[message]` - The message that will be sent with the event.
+
+
+> Events with types *category* and *title* use *{0}* and *{1}* placeholders
+> for old and new values respectively.
+> This means that the bot can show changes if you set them
+> (e.g. *forsen changed the title from **{0}** to **{1}*** will replace
+> with *forsen changed the game from **Just Chatting** to **PUBG***).
+
+
+### Delete the event
+
+`!event off [name]:[type]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
+
+### Make the event massping everytime
+
+`!event setmassping [name]:[type]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
+
+### Edit the event message
+
+`!event edit [name]:[type] [message...]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
++ `[message]` - New message.
+
+### Set a new target for the event
+
+`!event settarget [name]:[type] [new_name]:[new_type]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
++ `[new_name]` - New Twitch username or event name *(custom type only)*.
++ `[new_type]` - [New event type](#event-types).
+
+
+### Call the event
+
+
+> The bot requires moderator privileges on events with the **"massping"** flag.
+
+
+`!event call [name]:[type]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
+
+### View the event
+
+`!event view [name]:[type]`
+
++ `[name]` - Twitch username or event name *(custom type only)*.
++ `[type]` - [Event type](#event-types).
+]],
+ delay_sec = 1,
+ options = {},
+ subcommands = { "on", "off", "list", "edit", "settarget", "setmassping", "call", "view" },
+ minimal_rights = "moderator",
+ handle = function(request)
+ if request.subcommand_id == nil then
+ return l10n_custom_formatted_line_request(request, lines, "no_subcommand", {})
+ end
+
+ local scid = request.subcommand_id
+
+ if scid == "list" then
+ local names = {}
+
+ local events = db_query('SELECT name, event_type FROM events WHERE channel_id = $1',
+ { request.channel.id })
+ local user_ids = {}
+ for i = 1, #events, 1 do
+ local e = events[i]
+ local t = tonumber(e.event_type)
+ if t < 10 then
+ local id = tonumber(e.name)
+ table.insert(names, { name = id, type = t })
+ table.insert(user_ids, id)
+ print(id)
+ else
+ table.insert(names, { name = e.name, type = event_type_to_str(t) })
+ end
+ end
+ if #user_ids > 0 then
+ local users = twitch_get_users({ ids = user_ids })
+ for i = 1, #users, 1 do
+ local user = users[i]
+ for j = 1, #names, 1 do
+ if type(names[j].name) == "number" and
+ type(names[j].type) == "number" and
+ names[j].type < 10 and names[j].name == user.id
+ then
+ names[j].name = user.login
+ names[j].type = event_type_to_str(names[j].type)
+ end
+ end
+ end
+ end
+
+ -- finalizing
+ local n = {}
+ for i = 1, #names, 1 do
+ table.insert(n, names[i].name .. ':' .. names[i].type)
+ end
+
+ local line_id = "list"
+ if #n == 0 then
+ line_id = "empty_list"
+ end
+
+ return l10n_custom_formatted_line_request(request, lines, line_id, { table.concat(n, ', ') })
+ end
+
+ if request.message == nil then
+ return l10n_custom_formatted_line_request(request, lines, "no_message", {})
+ end
+
+ local parts = str_split(request.message, ' ')
+
+ local data_original = parts[1]
+ local data = parse_target(data_original)
+ table.remove(parts, 1)
+ local data_name = nil
+
+ if data == nil then
+ return l10n_custom_formatted_line_request(request, lines, "not_parseable", { data_original })
+ elseif data.type == nil then
+ return l10n_custom_formatted_line_request(request, lines, "unknown_type", { data_original })
+ elseif type(data.target) == "nil" then
+ return l10n_custom_formatted_line_request(request, lines, "user_not_found", { data_original })
+ elseif type(data.target) == "string" then
+ data_name = data.target
+ elseif type(data.target) == "table" then
+ data_name = data.target.id
+ end
+
+ local events = db_query(
+ 'SELECT id, message, array_to_json(flags) as flags FROM events WHERE name = $1 AND event_type = $2',
+ { data_name, data.type })
+
+ if scid == "on" then
+ if #events > 0 then
+ return l10n_custom_formatted_line_request(request, lines, "namesake", { data_original })
+ end
+
+ local message = table.concat(parts, ' ')
+ if #message == 0 then
+ return l10n_custom_formatted_line_request(request, lines, "no_message", {})
+ end
+
+ db_execute('INSERT INTO events(channel_id, name, event_type, message) VALUES ($1, $2, $3, $4)',
+ { request.channel.id, data_name, data.type, message })
+
+ return l10n_custom_formatted_line_request(request, lines, "on", { data_original, data_original })
+ end
+
+ if #events == 0 then
+ return l10n_custom_formatted_line_request(request, lines, "not_found", { data_original })
+ end
+
+ local event = events[1]
+
+ if scid == "off" then
+ db_execute('DELETE FROM events WHERE id = $1', { event.id })
+ return l10n_custom_formatted_line_request(request, lines, "off", { data_original })
+ elseif scid == "edit" then
+ local message = table.concat(parts, ' ')
+ if #message == 0 then
+ return l10n_custom_formatted_line_request(request, lines, "no_message", {})
+ end
+
+ db_execute('UPDATE events SET message = $1 WHERE id = $2', { message, event.id })
+
+ return l10n_custom_formatted_line_request(request, lines, "edit", { data_original })
+ elseif scid == "settarget" then
+ if #parts == 0 then
+ return l10n_custom_formatted_line_request(request, lines, "no_target", {})
+ end
+
+ local new_data_original = parts[1]
+ local data = parse_target(new_data_original)
+ local data_name = nil
+ if data == nil then
+ return l10n_custom_formatted_line_request(request, lines, "not_parseable", { new_data_original })
+ elseif data.type == nil then
+ return l10n_custom_formatted_line_request(request, lines, "unknown_type", { new_data_original })
+ elseif type(data.target) == "nil" then
+ return l10n_custom_formatted_line_request(request, lines, "user_not_found", { new_data_original })
+ elseif type(data.target) == "string" then
+ data_name = data.target
+ elseif type(data.target) == "table" then
+ data_name = data.target.id
+ end
+
+ local existing_events = db_query(
+ 'SELECT id FROM events WHERE channel_id = $1 AND name = $2 AND event_type = $3',
+ { request.channel.id, data_name, data.type })
+
+ if #existing_events > 0 then
+ return l10n_custom_formatted_line_request(request, lines, "namesake", { new_data_original })
+ end
+
+ db_execute('UPDATE events SET name = $1, event_type = $2 WHERE id = $3',
+ { data_name, data.type, event.id })
+
+ return l10n_custom_formatted_line_request(request, lines, "settarget", { data_original, new_data_original })
+ elseif scid == "setmassping" then
+ local flags = json_parse(event.flags)
+
+ local line_id = ""
+ local query = ""
+ if array_contains_int(flags, 0) then
+ line_id = "flag_disabled"
+ query = "UPDATE events SET flags = array_remove(flags, $1) WHERE id = $2"
+ else
+ line_id = "flag_enabled"
+ query = "UPDATE events SET flags = array_append(flags, $1) WHERE id = $2"
+ end
+
+ db_execute(query, { 0, event.id })
+
+ return l10n_custom_formatted_line_request(request, lines, line_id, { event_flag_to_str(0), data_original })
+ elseif scid == "call" then
+ local flags = json_parse(event.flags)
+ local names = {}
+
+ if array_contains_int(flags, 0) then
+ local chatters = twitch_get_chatters()
+ for i = 1, #chatters, 1 do
+ table.insert(names, chatters[i].login)
+ end
+ else
+ local subscriptions = db_query([[
+SELECT u.alias_name FROM users u
+INNER JOIN event_subscriptions es ON es.user_id = u.id
+INNER JOIN events e ON e.id = es.event_id
+WHERE e.id = $1
+]], { event.id })
+
+ for i = 1, #subscriptions, 1 do
+ table.insert(names, subscriptions[i].alias_name)
+ end
+ end
+
+ local base = '⚡️ ' .. event.message
+ if #names > 0 then
+ base = base .. ' · '
+ end
+
+ return str_make_parts(base, names, "@", " ", 500)
+ elseif scid == "view" then
+ local subscription_count = db_query([[
+SELECT COUNT(es.id) AS count FROM event_subscriptions es
+INNER JOIN events e ON e.id = es.event_id
+WHERE e.id = $1
+]], { event.id })
+
+ local f = json_parse(event.flags)
+ local flags = {}
+ for i = 1, #f, 1 do
+ table.insert(flags, event_type_to_str(f[i]))
+ end
+ if #flags == 0 then
+ table.insert(flags, '-')
+ end
+
+ return l10n_custom_formatted_line_request(request, lines, "view",
+ { event.id, data_original, subscription_count[1].count, table.concat(flags, ', '), event.message })
+ end
+ end
+}