1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
local function parse_target(value)
local parts = str_split(value, ':')
if #parts < 2 then
return nil
end
local type = parts[#parts]
local target = ""
for i = 1, #parts - 1, 1 do
target = target .. parts[i]
if i + 1 < #parts then
target = target .. ":"
end
end
local data = {
target = target,
type = str_to_event_type(type)
}
if event_type_to_str(data.type) ~= type then
data.type = nil
end
if data.type == nil then
return data
end
if data.type < 40 then
local users = {}
-- kick
if data.type >= 4 and data.type <= 7 then
users = kick_get_channels(data.target)
else
users = twitch_get_users({ logins = { data.target } })
end
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",
["massping_disabled"] = "{sender.alias_name}: Massping has been disabled for event %s",
["massping_enabled"] = "{sender.alias_name}: Massping has been enabled for event %s",
["view"] = "{sender.alias_name}: ID %s | %s | %s subs | Massping: %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 (and their placeholders)
+ live
+ offline
+ title *(`{new}` - new title, `{old}` - old title)*
+ game *(`{new}` - new game, `{old}` - old game)*
+ kick_live
+ kick_offline
+ kick_title *(`{new}` - new title, `{old}` - old title)*
+ kick_game *(`{new}` - new game, `{old}` - old game)*
+ github *(`{sha}` - commit ID, `{author}` - committer, `{msg}` - message)*
+ 7tv_new_emote *(`{emote}` - emote name, `{old_emote}` - original emote name, `{author}` - name of the person who added it)*
+ 7tv_deleted_emote *(`{emote}` - emote name, `{old_emote}` - original emote name, `{author}` - name of the person who added it)*
+ 7tv_updated_emote *(`{emote}` - new emote name, `{old_emote}` - previous emote name, `{author}` - name of the person who added it)*
+ rss *(`{channel_name}` - channel name, `{title}` - message title, `{message}` - message content, `{link}` - message link)*
+ twitter *(`{channel_name}` - account name, `{title}` - post title, `{message}` - post content, `{link}` - post link)*
+ telegram *(`{channel_name}` - channel name, `{title}` - post title, `{message}` - post content, `{link}` - post link)*
+ custom
## How to use placeholders?
Some event types have placeholders that can enrich your event message. You can easily use them by simply inserting them into your message.
Here are some basic examples to inspire you:
+ `!event on forsen:game Forsen is now playing {new} (previously, he played {old})`
+ `!event on torvalds/linux:github {author} made a new commit in linux kernel: {msg} (ID {sha})` - Please also note that the event name has the following format: **username/repository** *(https://github.com/ **username/repository**)*
+ `!event on forsen:7tv_new_emote {author} added a new 7TV emote: {emote}`
+ `!event on forsen:7tv_updated_emote {author} renamed a 7TV emote from {old_emote} to {emote}`
+ `!event on https://ilt.su/rss.php:rss new post on ilt.su: {title} ({link})
+ `!event on durov:telegram Durov posted a new Telegram post: {title} ({link})
+ `!event on forsen:twitter New post ({channel_name}): {title} ({link})
## 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.
### 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 = {},
aliases = {},
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, is_massping 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 line_id = ""
local query = ""
if event.is_massping == "1" then
line_id = "massping_disabled"
query = "UPDATE events SET is_massping = 0 WHERE id = $1"
else
line_id = "massping_enabled"
query = "UPDATE events SET is_massping = 1 WHERE id = $1"
end
db_execute(query, { event.id })
return l10n_custom_formatted_line_request(request, lines, line_id, { data_original })
elseif scid == "call" then
local names = {}
if event.is_massping == "1" 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 massping_flag = "OFF"
if event.is_massping == "1" then
massping_flag = "ON"
end
return l10n_custom_formatted_line_request(request, lines, "view",
{ event.id, data_original, subscription_count[1].count, massping_flag, event.message })
end
end
}
|