forked from wrxck/mattata
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mattata.lua
3355 lines (3260 loc) · 101 KB
/
mattata.lua
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
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--[[
_ _ _
_ __ ___ __ _| |_| |_ __ _| |_ __ _
| '_ ` _ \ / _` | __| __/ _` | __/ _` |
| | | | | | (_| | |_| || (_| | || (_| |
|_| |_| |_|\__,_|\__|\__\__,_|\__\__,_|
v25.1
Copyright 2017 Matthew Hesketh <[email protected]>
See LICENSE for details
]]
local mattata = {}
local http = require('socket.http')
local https = require('ssl.https')
local url = require('socket.url')
local ltn12 = require('ltn12')
local multipart = require('multipart-post')
local json = require('dkjson')
local redis = require('mattata-redis')
local configuration = require('configuration')
local api = require('telegram-bot-lua.core').configure(configuration.bot_token)
local tools = require('telegram-bot-lua.tools')
local socket = require('socket')
local plugin_list = {}
local inline_plugin_list = {}
function mattata:init()
self.info = api.info -- Set the bot's information to the object fetched from the Telegram bot API.
self.plugins = {} -- Make a table for the bot's plugins.
for k, v in ipairs(configuration.plugins) -- Iterate over all of the configured plugins.
do
local plugin = require('plugins.' .. v) -- Load each plugin.
self.plugins[k] = plugin
self.plugins[k].name = v
if plugin.init -- If the plugin has an `init` function, run it.
then
plugin.init(
self,
configuration
)
end
plugin.is_inline = plugin.on_inline_query
and true
or false -- By default, a plugin doesn't have inline functionality; but, if it does, set it to `true` appropriately.
plugin.commands = plugin.commands
or {} -- If the plugin hasn't got any commands configured, then set a blank table,
-- so when it comes to iterating over the commands later on, the bot won't encounter any problems.
if plugin.help
then -- If the plugin has help documentation, then insert it into other tables (where necessary).
table.insert(
plugin_list,
plugin.help
)
if plugin.is_inline
then -- If the plugin is inline and has documentation, then insert the documentation into the `inline_plugin_list`
-- table.
table.insert(
inline_plugin_list,
plugin.help
)
end
plugin.help = 'Usage:\n' .. plugin.help:gsub('%. (Alias)', '.\n%1') -- Make the plugin's documentation style all
-- nicely unified, for consistency.
end
end
print('Connected to the Telegram bot API!')
print('\n\tUsername: @' .. self.info.username .. '\n\tName: ' .. self.info.name .. '\n\tID: ' .. self.info.id .. '\n')
self.version = 'v25.1'
if not redis:get('mattata:version')
or redis:get('mattata:version') ~= self.version
then -- Make necessary database changes if the version has changed.
redis:set(
'mattata:version',
self.version
)
end
self.last_update = self.last_update
or 0 -- If there is no last update known, make it 0 so the bot doesn't encounter any
-- problems when it tries to add the necessary increment.
self.last_backup = self.last_backup
or os.date('%V')
self.last_cron = self.last_cron
or os.date('%H')
return true
end
-- Set a bunch of function aliases, for consistency and legacy compatibility.
mattata.request = api.request
mattata.forward_message = api.forward_message
mattata.send_photo = api.send_photo
mattata.send_audio = api.send_audio
mattata.send_document = api.send_document
mattata.send_sticker = api.send_sticker
mattata.send_video = api.send_video
mattata.send_voice = api.send_voice
mattata.send_location = api.send_location
mattata.send_venue = api.send_venue
mattata.send_contact = api.send_contact
mattata.send_chat_action = api.send_chat_action
mattata.get_user_profile_photos = api.get_user_profile_photos
mattata.get_file = api.get_file
mattata.ban_chat_member = api.ban_chat_member
mattata.kick_chat_member = api.kick_chat_member
mattata.unban_chat_member = api.unban_chat_member
mattata.restrict_chat_member = api.restrict_chat_member
mattata.promote_chat_member = api.promote_chat_member
mattata.export_chat_invite_link = api.export_chat_invite_link
mattata.set_chat_photo = api.set_chat_photo
mattata.delete_chat_photo = api.delete_chat_photo
mattata.set_chat_title = api.set_chat_title
mattata.set_chat_description = api.set_chat_description
mattata.pin_chat_message = api.pin_chat_message
mattata.unpin_chat_message = api.unpin_chat_message
mattata.leave_chat = api.leave_chat
mattata.get_chat_administrators = api.get_chat_administrators
mattata.get_chat_members_count = api.get_chat_members_count
mattata.get_chat_member = api.get_chat_member
mattata.answer_callback_query = api.answer_callback_query
mattata.edit_message_text = api.edit_message_text
mattata.edit_message_caption = api.edit_message_caption
mattata.edit_message_reply_markup = api.edit_message_reply_markup
mattata.delete_message = api.delete_message
mattata.answer_inline_query = api.answer_inline_query
mattata.send_invoice = api.send_invoice
mattata.answer_shipping_query = api.answer_shipping_query
mattata.answer_pre_checkout_query = api.answer_pre_checkout_query
mattata.send_game = api.send_game
mattata.set_game_score = api.set_game_score
mattata.get_game_high_scores = api.get_game_high_scores
mattata.input_text_message_content = api.input_text_message_content
mattata.input_location_message_content = api.input_location_message_content
mattata.input_venue_message_content = api.input_venue_message_content
mattata.input_contact_message_content = api.input_contact_message_content
mattata.url_button = api.url_button
mattata.callback_data_button = api.callback_data_button
mattata.switch_inline_query_button = api.switch_inline_query_button
mattata.switch_inline_query_current_chat_button = api.switch_inline_query_current_chat_button
mattata.callback_game_button = api.callback_game_button
mattata.pay_button = api.pay_button
mattata.row = api.row
mattata.inline_keyboard = api.inline_keyboard
mattata.keyboard = api.keyboard
mattata.remove_keyboard = api.remove_keyboard
mattata.commands = tools.commands
mattata.escape_markdown = tools.escape_markdown
mattata.escape_html = tools.escape_html
mattata.escape_bash = tools.escape_bash
mattata.send_inline_article = api.send_inline_article
mattata.send_inline_photo = api.send_inline_photo
mattata.inline_result = api.inline_result
mattata.trim = tools.trim
mattata.comma_value = tools.comma_value
mattata.format_ms = tools.format_ms
mattata.round = tools.round
mattata.symbols = tools.symbols
mattata.utf8_len = tools.utf8_len
mattata.get_linked_name = tools.get_linked_name
mattata.table_size = tools.table_size
mattata.download_file = tools.download_file
mattata.create_link = tools.create_link
function mattata:run(configuration, token)
-- mattata's main long-polling function which repeatedly checks the Telegram bot API for updates.
-- The objects received in the updates are then further processed through object-specific functions.
token = token
or configuration.bot_token
assert(
token,
'You need to enter your Telegram bot API token in configuration.lua, or pass it as the second argument when using the mattata:run() function!'
)
local is_running = mattata.init(self) -- Initialise the bot.
while is_running -- Perform the main loop whilst the bot is running.
do
local success = api.get_updates( -- Check the Telegram bot API for updates.
1,
self.last_update + 1,
100,
json.encode(
{
'message',
-- 'edited_message',
'channel_post',
-- 'edited_channel_post',
'inline_query',
-- 'chosen_inline_result',
'callback_query',
-- 'shipping_query',
'pre_checkout_query'
}
),
configuration.use_beta_endpoint
or false
)
if success
and success.result
then
for k, v in ipairs(success.result)
do
self.message = nil
self.inline_query = nil
self.callback_query = nil
self.language = nil
self.last_update = v.update_id
self.execution_time = socket.gettime()
if v.message
then
if v.message.reply_to_message
then
v.message.reply = v.message.reply_to_message -- Make the `update.message.reply_to_message`
-- object `update.message.reply` to make any future handling easier.
v.message.reply_to_message = nil -- Delete the old value by setting its value to nil.
end
self.message = v.message
mattata.on_message(self)
if v.message.successful_payment
and configuration.debug
then
mattata.send_message(
configuration.admins[1],
json.encode(v.message)
)
end
if configuration.debug
then
print(
string.format(
'%s[36m[Update #%s] Message from %s to %s%s[0m',
string.char(27),
v.update_id,
v.message.from.id,
v.message.chat.id,
string.char(27)
)
)
end
elseif v.channel_post
then
if v.channel_post.reply_to_message
then
v.channel_post.reply = v.channel_post.reply_to_message
v.channel_post.reply_to_message = nil
end
self.message = v.channel_post
mattata.on_message(self)
if configuration.debug
then
print(
string.format(
'%s[37m[Update #%s] Channel post from %s%s[0m',
string.char(27),
v.update_id,
v.channel_post.chat.id,
string.char(27)
)
)
end
elseif v.inline_query
then
self.inline_query = v.inline_query
mattata.on_inline_query(self)
if configuration.debug
then
print(
string.format(
'%s[35m[Update #%s] Inline query from %s%s[0m',
string.char(27),
v.update_id,
v.inline_query.from.id,
string.char(27)
)
)
end
elseif v.callback_query
then
if v.callback_query.message
and v.callback_query.message.reply_to_message
then
v.callback_query.message.reply = v.callback_query.message.reply_to_message
v.callback_query.message.reply_to_message = nil
end
self.callback_query = v.callback_query
self.message = v.callback_query.message
or false
mattata.on_callback_query(self)
if configuration.debug
then
print(
string.format(
'%s[33m[Update #%s] Callback query from %s%s[0m',
string.char(27),
v.update_id,
v.callback_query.from.id,
string.char(27)
)
)
end
elseif v.pre_checkout_query
then
mattata.send_message(
configuration.admins[1],
json.encode(v)
) -- To be improved.
-- Sends the object containing payment-related info to the first configured
-- admin, then answers the pre checkout query.
mattata.answer_pre_checkout_query(
v.pre_checkout_query.id,
true
)
end
self.execution_time = socket.gettime() - self.execution_time
if configuration.debug
then
print('Update #' .. v.update_id .. ' took ' .. self.execution_time .. ' seconds to process.')
end
end
else
print(
string.format(
'%s[31m[Error] There was an error retrieving updates from the Telegram bot API!%s[0m',
string.char(27),
string.char(27)
)
)
end
success = nil
if self.last_backup ~= os.date('%V')
then -- If it's been a week since the last backup, perform another backup.
self.last_backup = os.date('%V') -- Set the last backup time to now, since we're
-- now performing one!
print(
io.popen('./backup.sh'):read('*all')
)
end
if self.last_cron ~= os.date('%H')
then -- Perform hourly CRON jobs.
self.last_cron = os.date('%H')
for i = 1, #self.plugins
do
local plugin = self.plugins[i]
if plugin.cron
then
local success, res = pcall(
function()
plugin.cron(
self,
configuration
)
end
)
if not success
then
mattata.exception(
self,
res,
'CRON: ' .. i,
configuration.log_chat
)
end
else
plugin = nil
end
end
mattata.export_ai_responses(true)
end
collectgarbage()
end
print('mattata is shutting down...')
end
function mattata:on_message()
local message = self.message
if not mattata.is_valid(message) -- If the message is old or is missing necessary fields/values,
-- then we'll stop and allow the bot to start processing the next update(s).
or redis:get('blacklisted_chats:' .. message.chat.id) -- If the message was sent from a blacklisted
-- chat, then we'll stop because we don't want the bot to respond there.
then
return false
end
message = mattata.sort_message(message) -- Process the message.
local language = require(
'languages.' .. mattata.get_user_language(message.from.id)
)
if mattata.is_group(message)
and mattata.get_setting(
message.chat.id,
'force group language'
)
then
language = require(
'languages.' .. (
mattata.get_value(
message.chat.id,
'group language'
)
or 'en_gb'
)
)
end
self.language = language
self.info.nickname = redis:get('chat:' .. message.chat.id .. ':name')
or self.info.name -- If the chat doesn't have a custom nickname for the bot to respond by, we'll
-- stick with the default one that was set through @BotFather.
if message.forward_from
or message.forward_from_chat
or mattata.process_spam(message)
then
return false -- We don't want to process these messages any further!
end
mattata.process_afk(message)
mattata.process_language(message)
message = mattata.process_stickers(message)
if mattata.process_deeplinks(message)
then
return true
end
-- If there's a new chat member and the bot is the added member, introduce it with
-- a brief description of the primary features and how to set things up.
if message.new_chat_member
and message.new_chat_member.id == self.info.id
then
return mattata.send_message(
message.chat.id,
string.format(
'My name is %s and I\'m here to help. If you\'re an administrator, use /plugins to choose which features you want to enable in this group and use /administration to set up my administrative functionality. For more information, use /help.',
self.info.nickname -- Since there's a chance the bot has previously been used
-- in the chat but was removed, it could still have a nickname. If not, then
-- this won't cause any issues since it will just fallback to the bot's actual
-- name instead.
)
)
end
-- If the user isn't current AFK, and they say they're going to be right back, we can
-- assume that they are now going to be AFK, so we'll help them out and set them that
-- way by making the message text the /afk command, which will later trigger the plugin.
if (
message.text:lower():match('^i?\'?l?l? ?brb.?$')
and not redis:hget(
'afk:' .. message.chat.id .. ':' .. message.from.id,
'since'
)
)
then
message.text = '/afk'
end
self.is_command = false -- A boolean value to decide later on, whether the message
-- is intended for the current plugin from the iterated table.
-- This is the main loop which iterates over configured plugins and runs the
-- appropriate functions.
self.is_done = false
for _, plugin in ipairs(self.plugins)
do
local commands = #plugin.commands
or {}
for i = 1, commands
do
if message.text:match(plugin.commands[i])
then
self.is_command = true
if plugin.on_message
then
if (
plugin.name == 'administration'
and not redis:hget(
string.format(
'chat:%s:settings',
message.chat.id
),
'use administration'
)
and not message.text:match('^[!/#]administration')
and not message.text:match('^[!/#]administration%@' .. self.info.username)
and not message.text:match('^[!/#]groups')
and not message.text:match('^[!/#]groups%@' .. self.info.username)
)
or (
plugin.name ~= 'administration'
and mattata.is_plugin_disabled(
plugin.name,
message
)
)
then
if message.chat.type ~= 'private'
and not redis:get(
string.format(
'chat:%s:dismiss_disabled_message:%s',
message.chat.id,
plugin.name
)
)
then
return mattata.send_message(
message.chat.id,
string.format(
'%s is disabled in this chat.',
plugin.name:gsub('^%l', string.upper)
),
nil,
true,
false,
nil,
mattata.inline_keyboard()
:row(
mattata.row()
:callback_data_button(
'Dismiss',
'plugins:' .. message.chat.id .. ':dismiss_disabled_message:' .. plugin.name
)
:callback_data_button(
'Enable',
'plugins:' .. message.chat.id .. ':enable_via_message:' .. plugin.name
)
)
)
end
return false
end
local success, result = pcall(
function()
return plugin.on_message(
self,
message,
configuration,
language
)
end
)
if not success
then
mattata.exception(
self,
result,
string.format(
'%s: %s',
message.from.id,
message.text
),
configuration.log_chat
)
end
if mattata.get_setting(
message.chat.id,
'delete commands'
)
and self.is_command
and not redis:sismember(
'chat:' .. message.chat.id .. ':no_delete',
tostring(plugin.name)
)
then
mattata.delete_message(
message.chat.id,
message.message_id
)
end
self.is_done = true
end
end
end
end
mattata.process_message(self)
if self.is_done
then
return true
end
-- If the myspotify plugin is enabled and the user's current access token has expired,
-- use their refresh token (if they have one) to re-authorise their Spotify account.
if not mattata.is_plugin_disabled(
'myspotify',
message
)
and redis:get('spotify:' .. message.from.id .. ':refresh_token')
and not redis:get('spotify:' .. message.from.id .. ':access_token')
then
local myspotify = require('plugins.myspotify')
local success = myspotify.reauthorise_account(
message.from.id,
configuration
)
if success
then
redis:set(
'spotify:' .. message.from.id .. ':access_token',
success.access_token
)
redis:expire(
'spotify:' .. message.from.id .. ':access_token',
3600
)
end
end
-- Process custom commands with #hashtag triggers.
if message.chat.type ~= 'private'
and message.text:match('^%#%a+')
and mattata.get_setting(
message.chat.id,
'use administration'
)
then
local trigger = message.text:match('^(%#%a+)')
local custom_commands = redis:hkeys(
string.format(
'administration:%s:custom',
message.chat.id
)
)
if custom_commands
then
for k, v in ipairs(custom_commands)
do
if trigger == v
then
local value = redis:hget(
string.format(
'administration:%s:custom',
message.chat.id
),
trigger
)
if value
then
mattata.send_message(
message.chat.id,
value
)
end
end
end
end
end
if not mattata.is_plugin_disabled(
'captionbotai',
message
)
and (
message.photo
or (
message.reply
and message.reply.photo
)
)
then
if message.reply
then
message = message.reply
end
if message.text
:lower()
:match('^wh?at .- th[ia][st].-')
or message.text
:lower()
:match('^who .- th[ia][st].-')
then
local captionbotai = require('plugins.captionbotai')
captionbotai.on_message(
self,
message,
configuration,
language
)
end
end
if mattata.is_global_admin(message.from.id)
and message.chat.id == configuration.bug_reports_chat
and message.reply
and message.reply.forward_from
and not message.text:match('^[/!#]')
then
mattata.send_message(
message.reply.forward_from.id,
string.format(
'Message from the developer regarding bug report #%s:\n<pre>%s</pre>',
message.reply.forward_date,
mattata.escape_html(message.text)
),
'html'
)
elseif not message.text:match('^Cancel$')
and not message.text:match('^/?s/.-/.-/?$')
and not message.photo
and not message.text:match('^[!/#]')
and not message.forward_from
and (
message.text:lower():gsub('%W', '') ~= ''
)
then
if mattata.is_plugin_disabled(
'ai',
message
)
then
if (
message.text:lower():match('^' .. self.info.nickname:lower() .. '.? .-$')
or message.text:match('^.-%,? ' .. self.info.nickname:lower() .. '%??%.?%!?$')
or message.chat.type == 'private'
or (
message.reply
and message.reply.from.id == self.info.id
)
)
and message.text:lower() ~= self.info.nickname:lower()
and not redis:get('ai_notify:' .. message.chat.id .. ':' .. message.from.id)
then
redis:set(
'ai_notify:' .. message.chat.id .. ':' .. message.from.id,
true
) -- Mark the user as notified.
mattata.send_reply(
message,
'Sorry pal, but my AI is switched off in this chat. This is the only time I\'m going to remind you of this, so be sure to remember (it\'ll save you from looking crazy next time!) If you believe this is a mistake, you should contact a group admin as soon as possible!'
)
end
else
if (
message.text:lower():match('^' .. self.info.nickname:lower() .. '.? .-$')
or message.text:match('^.-%,? ' .. self.info.nickname:lower() .. '%??%.?%!?$')
or message.chat.type == 'private'
or (
message.reply
and message.reply.from.id == self.info.id
)
)
and message.text:lower() ~= self.info.nickname:lower()
then
message.text = message.text:lower():gsub(self.info.nickname:lower(), '')
local ai = require('plugins.ai')
ai.on_message(
self,
message,
configuration,
language
)
elseif message.text:lower() == self.info.nickname:lower()
then
mattata.send_chat_action(message.chat.id)
mattata.send_reply(
message,
'Yes?'
)
end
end
end
if configuration.respond_to_misc
and not self.is_command
and not mattata.get_setting(
message.chat.id,
'misc responses'
) -- Ensure the AI functionality hasn't been turned off, since the user probably
-- won't want the miscellaneous responses if it has been.
then
mattata.on_message_misc(self)
end
if ( -- If a user executes a command and it's not recognised, provide a response
-- explaining what's happened and how it can be resolved.
message.text:match('^[!/#]')
and message.chat.type == 'private'
and not self.is_commmand
)
or (
message.chat.type ~= 'private'
and message.text:match('^[!/#]%a+@' .. self.info.username)
and not self.is_command
)
then
mattata.send_reply(
message,
'Sorry, I don\'t understand that command.\nTip: Use /help to discover what else I can do!'
)
end
return true
end
function mattata:on_message_misc()
local message = self.message
local matches = {
['^what the fuck did you just fucking say about me%??$'] = 'Um, ' .. message.from.name .. '? What the fuck did you just fucking say about me, you little bitch? I\'ll have you know I graduated top of my class in the Navy Seals, and I\'ve been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I\'m the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You\'re fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that\'s just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn\'t, you didn\'t, and now you\'re paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You\'re fucking dead, kiddo.',
['^gr8 b8,? m8$'] = 'Gr8 b8, m8. I rel8, str8 appreci8, and congratul8. I r8 this b8 an 8/8. Plz no h8, I\'m str8 ir8. Cre8 more, can\'t w8. We should convers8, I won\'t ber8, my number is 8888888, ask for N8. No calls l8 or out of st8. If on a d8, ask K8 to loc8. Even with a full pl8, I always have time to communic8 so don\'t hesit8.',
['^bone? appetite?%??!?%.?$'] = {
'Bone apple tea, ' .. message.from.name .. '!',
'Bone app the teeth, ' .. message.from.name .. '!',
'Boney African feet, ' .. message.from.name .. '!',
'Bong asshole sneeze, ' .. message.from.name .. '!',
'Boner apple sneeze, ' .. message.from.name .. '!'
},
['^y?o?u a?re? a ?p?r?o?p?e?r? fucc?k?boy?i?%??!?%.?$'] = message.from.name .. ', I am writing to you on this fateful day to inform you of a tragic reality. While it is unfortunate that I must be the one to let you know, it is for the greater good that this knowledge is made available to you as soon as possible. m8. u r a proper fukboy.',
['^top%s?kek.?$'] = 'Toppest of keks!',
['content cop'] = 'SAY THE "N" WORD ' .. message.from.name:upper() .. '!',
['tana mong[eo][ao][us]e?'] = 'SAY THE "N" WORD ' .. message.from.name:upper() .. '!',
['good night'] = 'Good night, ' .. message.from.name .. '. Sleep well! ' .. utf8.char(128516),
['good morning?'] = 'Good morning, ' .. message.from.name .. '! Did you sleep well? ' .. utf8.char(9786),
['^[ia]\'?m back.?$'] = 'Welcome back, ' .. message.from.name .. '!',
['winrar'] = 'Please note that WinRAR is not free software. After a 40 day trial period you must either buy a license or remove it from your computer.',
[utf8.char(127814)] = utf8.char(127825),
[utf8.char(127825)] = utf8.char(127814),
['^nsa$'] = utf8.char(128065),
['ric?[ck] harr?iss?on'] = 'I\'m Rick Harrison, and this is my pawn shop. I work here with my old man and my son, Big Hoss. Everything in here has a story and a price. One thing I\'ve learned after 21 years – you never know WHAT is gonna come through that door.',
['haramba?e'] = '*gets dick out*',
['owo'] = 'OwO, what\'s THIS?',
['trump'] = 'Trump? He\'s not MY president! ' .. utf8.char(128560),
['pennis'] = '... and also dicke and balls?',
['^stop$'] = 'stop',
['^no u$'] = 'fight me boi',
['fritzypoo'] = 'SORRY MUM, IT\'S A FRITZISM',
['vicar'] = 'fml not this again *unzips jeans*',
['catholic priests?'] = 'pretty sure you mean boy diddlers m8',
['vegan'] = 'nuuuuu i dun like vegans xdd',
['^fritzy$'] = 'poo',
['^gay$'] = 'I fully support LGBTQ+ rights! You should too, ' .. message.from.name .. '! ' .. utf8.char(127987) .. utf8.char(8205) .. utf8.char(127752)
}
for trigger, response in pairs(matches)
do
if type(response) == 'table'
then
math.randomseed(
socket.gettime()
)
math.random()
math.random()
math.random()
-- Seed and "pop" some random numbers to increase the chances of the results
-- ACTUALLY being random.
response = response[math.random(#response)]
end
if message.text
:lower()
:match(trigger)
then
return mattata.send_message(
message.chat.id,
'<pre>' .. mattata.escape_html(response) .. '</pre>',
'html'
)
end
end
if message.text:lower():match('^w?h?y so salty%??!?%.?$')
then
return mattata.send_sticker(
message.chat.id,
'BQADBAADNQIAAlAYNw2gRrzQfFLv9wI'
)
elseif message.text:lower():match('^do you have the time,? to listen to me whine%??$')
then
return mattata.send_sticker(
message.chat.id,
'BQADBAADOwIAAlAYNw0I9ggFrg4HigI'
)
elseif message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? wh?at time is it.?$')
or message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? wh?at%\'?s the time.?$')
then
message.text = '/time'
return mattata.on_message(
self,
message,
configuration
)
elseif message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? how do i .-$')
then
message.text = '/google how do i ' .. message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? how do i (.-)$')
return mattata.on_message(
self,
message,
configuration
)
elseif message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? search %a+ for %"?%\'?.-%"?%\'?$')
then
local service, query = message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? search (%a+) for %"?%\'?(.-)%"?%\'?$')
if service ~= 'youtube'
and service ~= 'bing'
and service ~= 'google'
and service ~= 'flickr'
and service ~= 'itunes'
then
return mattata.send_reply(
message,
'I\'m sorry, I don\'t recognise that service.'
)
end
message.text = string.format(
'/%s %s',
service,
query
)
return mattata.on_message(
self,
message,
configuration
)
elseif message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? who is .-$')
or message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? wh?at is .-$')
or message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? who are .-$')
or message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? what are .-$')
then
message.text = '/ddg ' .. message.text:lower():match('^' .. self.info.nickname:lower() .. '%,? (.-)$')
return mattata.on_message(
self,
message,
configuration
)
elseif message.text:lower():match('^show me message .-%.?%!?$')
and message.chat.type == 'supergroup'
then
local message_id = message.text:lower():match('ge .-%.?%!?$')
message_id = mattata.trim(message_id):gsub('number', '')
if tonumber(message_id) == nil
then
return
end
local user = message.from.first_name
if message.from.username
then
user = '@' .. message.from.username
end
return mattata.send_message(
message.chat.id,
string.format(
'Here you go %s!',
user
),
nil,
true,
false,
message_id
)
elseif message.text:lower() == 'pek'
or message.text:lower():match('trash dove')
then
return mattata.send_document(
message.chat.id,
'CgADBAADqwADEbgxUVfN63j_mEYYAg'
)
elseif message.text:lower():match('make admin')
or message.text:lower():match('make %a+ an admin')
or message.text:lower():match('make %a+ admin')
then
return mattata.send_document(
message.chat.id,
'CgADBAADFwADJ5WxUim0qGqr-gYQAg'
)
elseif message.text:lower() == 'coo'
then
return mattata.send_photo(
message.chat.id,
'AgADBAAD46gxG6e3EVHYSQNx3Fq-7x8-aRkABONfdSHFUmyNx_oDAAEC'
)
elseif message.text:lower():match('^happy new year%.?%??%!?$')
then
local output = string.format(
'But it\'s not %s yet!',
os.date(
'*t',
os.time()
).year + 1
)
if os.date(
'*t',
os.time()
).month == 1
then
output = string.format(
'Thanks, %s - Happy New Year to you too! I can\'t believe it\'s %s already?!',
message.from.first_name,
os.date(
'*t',
os.time()
).year
)
end
return mattata.send_reply(
message,
output
)
elseif message.text:lower():match('^' .. self.info.nickname:lower() .. ' what.?s? the weather')
and not message.text:lower():match('in')
then
message.text = '/weather'
return mattata.on_message(