ezii-discord 0.test
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/TUTORIAL.md +2 -0
- data/chat-bot-1.rb +701 -0
- data/ezii-discord-integration.gemspec +14 -0
- data/lib/ezii_curl_manager.rb +58 -0
- data/lib/test/test_ezii_curl_manager.rb +7 -0
- data/test/test-chat-bot-1.rb +10 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 16eff586b4ef4f772d1c6626b7fdd51a70fb4582922b0b87c1289819a2ea99d1
|
4
|
+
data.tar.gz: eed8da7949bedf39add6d15153a7e4c7dd3184807cfaae84248f3a8cae6ae420
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd2b89bd23c6d60e77efce60c9c14d8eff7ca58b5e7fd54a2d83cb22be7cc5096bc4eb62ce8343e917d34598c16abbab0f971353631c29b9b71f27f36f9d95d6
|
7
|
+
data.tar.gz: 9659f623af82656d3efd416a1acf2ea541892022783f30a158543832a93aac2bcdf1f27839af5c22eebc6f726d7bd074cf1be6bc71027e9f4e60bb8e49040dad
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/eZii-jester-data/ladder-gem.git
|
3
|
+
revision: f387e0fd49f1a0dffea5488afc0366bba1c8b713
|
4
|
+
specs:
|
5
|
+
ladder (11.test)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
specs:
|
9
|
+
byebug (11.0.1)
|
10
|
+
discordrb (3.3.0)
|
11
|
+
discordrb-webhooks (~> 3.3.0)
|
12
|
+
ffi (>= 1.9.24)
|
13
|
+
opus-ruby
|
14
|
+
rbnacl (~> 3.4.0)
|
15
|
+
rest-client (>= 2.1.0.rc1)
|
16
|
+
websocket-client-simple (>= 0.3.0)
|
17
|
+
discordrb-webhooks (3.3.0)
|
18
|
+
rest-client (>= 2.1.0.rc1)
|
19
|
+
domain_name (0.5.20190701)
|
20
|
+
unf (>= 0.0.5, < 1.0.0)
|
21
|
+
event_emitter (0.2.6)
|
22
|
+
ffi (1.11.1)
|
23
|
+
http-accept (1.7.0)
|
24
|
+
http-cookie (1.0.3)
|
25
|
+
domain_name (~> 0.5)
|
26
|
+
mime-types (3.3)
|
27
|
+
mime-types-data (~> 3.2015)
|
28
|
+
mime-types-data (3.2019.0904)
|
29
|
+
netrc (0.11.0)
|
30
|
+
opus-ruby (1.0.1)
|
31
|
+
ffi
|
32
|
+
rbnacl (3.4.0)
|
33
|
+
ffi
|
34
|
+
rest-client (2.1.0.rc1)
|
35
|
+
http-accept (>= 1.7.0, < 2.0)
|
36
|
+
http-cookie (>= 1.0.2, < 2.0)
|
37
|
+
mime-types (>= 1.16, < 4.0)
|
38
|
+
netrc (~> 0.8)
|
39
|
+
unf (0.1.4)
|
40
|
+
unf_ext
|
41
|
+
unf_ext (0.0.7.6)
|
42
|
+
websocket (1.2.8)
|
43
|
+
websocket-client-simple (0.3.0)
|
44
|
+
event_emitter
|
45
|
+
websocket
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
byebug
|
52
|
+
discordrb
|
53
|
+
ladder (= 11.test)!
|
54
|
+
|
55
|
+
BUNDLED WITH
|
56
|
+
1.17.2
|
data/TUTORIAL.md
ADDED
data/chat-bot-1.rb
ADDED
@@ -0,0 +1,701 @@
|
|
1
|
+
require 'ladder'
|
2
|
+
require 'discordrb'
|
3
|
+
|
4
|
+
class FalseClass
|
5
|
+
def false?
|
6
|
+
self == false
|
7
|
+
end
|
8
|
+
end
|
9
|
+
class TrueClass
|
10
|
+
def false?
|
11
|
+
self == false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class GBotResponseNotCapture < Exception
|
17
|
+
end
|
18
|
+
|
19
|
+
module EZIIDiscordIntegration
|
20
|
+
|
21
|
+
TEST_COMMAND_STRING = "5 results for te123§§st"
|
22
|
+
MESSAGE = "gbot: #{TEST_COMMAND_STRING} | filter by curl response time | top 1"
|
23
|
+
|
24
|
+
|
25
|
+
VIRTUAL_EXCEPTION = {}
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
USER_ID_HOLDER = {gbot_id: nil}
|
30
|
+
FIRST_GBOT_MESSAGE_HOLDER = {first_gbot_message_id: nil}
|
31
|
+
|
32
|
+
|
33
|
+
ERR_ID_0 = "search string for gbot is not a string"# ,
|
34
|
+
ERR_ID_1 = "respoonse not delivered within 1 second"# ,
|
35
|
+
ERR_ID_2 = "Gbot discord user id was not configured, start the assignment after bot restart by '!pipeline gbot-id-capture"# ,
|
36
|
+
ERR_ID_3 = "Gbot didn't respond within timeframe"# ,
|
37
|
+
ERR_ID_4 = "Gbot answered more than once within timeframe (this bot must run in a channel where only this bot is allowed to write messages to gbot)"# ,
|
38
|
+
ERR_ID_5 = "ID of all following gbot messages must not equal the id of the first gbot message"
|
39
|
+
ERR_ID_6 = "ID of first gbot message received by this program must not be nil"
|
40
|
+
ERR_ID_7 = "DISCORD_MESSAGES must be synced globally"
|
41
|
+
ERR_ID_8 = "Curl not working dum dum"
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
def self.monkeypatching
|
46
|
+
yield
|
47
|
+
end
|
48
|
+
|
49
|
+
monkeypatching do
|
50
|
+
module Discordrb
|
51
|
+
# Represents a Discord bot, including servers, users, etc.
|
52
|
+
class Bot
|
53
|
+
|
54
|
+
def handle_dispatch(type, data)
|
55
|
+
# Check whether there are still unavailable servers and there have been more than 10 seconds since READY
|
56
|
+
if @unavailable_servers && @unavailable_servers > 0 && (Time.now - @unavailable_timeout_time) > 10
|
57
|
+
# The server streaming timed out!
|
58
|
+
LOGGER.debug("Server streaming timed out with #{@unavailable_servers} servers remaining")
|
59
|
+
LOGGER.debug('Calling ready now because server loading is taking a long time. Servers may be unavailable due to an outage, or your bot is on very large servers.')
|
60
|
+
|
61
|
+
# Unset the unavailable server count so this doesn't get triggered again
|
62
|
+
@unavailable_servers = 0
|
63
|
+
|
64
|
+
notify_ready
|
65
|
+
end
|
66
|
+
|
67
|
+
case type
|
68
|
+
when :READY
|
69
|
+
# As READY may be called multiple times over a single process lifetime, we here need to reset the cache entirely
|
70
|
+
# to prevent possible inconsistencies, like objects referencing old versions of other objects which have been
|
71
|
+
# replaced.
|
72
|
+
init_cache
|
73
|
+
|
74
|
+
@profile = Profile.new(data['user'], self)
|
75
|
+
|
76
|
+
# Initialize servers
|
77
|
+
@servers = {}
|
78
|
+
|
79
|
+
# Count unavailable servers
|
80
|
+
@unavailable_servers = 0
|
81
|
+
|
82
|
+
data['guilds'].each do |element|
|
83
|
+
# Check for true specifically because unavailable=false indicates that a previously unavailable server has
|
84
|
+
# come online
|
85
|
+
if element['unavailable'].is_a? TrueClass
|
86
|
+
@unavailable_servers += 1
|
87
|
+
|
88
|
+
# Ignore any unavailable servers
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
ensure_server(element)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Add PM and group channels
|
96
|
+
data['private_channels'].each do |element|
|
97
|
+
channel = ensure_channel(element)
|
98
|
+
if channel.pm?
|
99
|
+
@pm_channels[channel.recipient.id] = channel
|
100
|
+
else
|
101
|
+
@channels[channel.id] = channel
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Don't notify yet if there are unavailable servers because they need to get available before the bot truly has
|
106
|
+
# all the data
|
107
|
+
if @unavailable_servers.zero?
|
108
|
+
# No unavailable servers - we're ready!
|
109
|
+
notify_ready
|
110
|
+
end
|
111
|
+
|
112
|
+
@ready_time = Time.now
|
113
|
+
@unavailable_timeout_time = Time.now
|
114
|
+
when :GUILD_MEMBERS_CHUNK
|
115
|
+
id = data['guild_id'].to_i
|
116
|
+
server = server(id)
|
117
|
+
server.process_chunk(data['members'])
|
118
|
+
when :MESSAGE_CREATE
|
119
|
+
|
120
|
+
ladder(data)
|
121
|
+
|
122
|
+
|
123
|
+
if ignored?(data['author']['id'].to_i)
|
124
|
+
debug("Ignored author with ID #{data['author']['id']}")
|
125
|
+
return
|
126
|
+
end
|
127
|
+
|
128
|
+
if @ignore_bots && data['author']['bot']
|
129
|
+
debug("Ignored Bot account with ID #{data['author']['id']}")
|
130
|
+
return
|
131
|
+
end
|
132
|
+
|
133
|
+
# If create_message is overwritten with a method that returns the parsed message, use that instead, so we don't
|
134
|
+
# parse the message twice (which is just thrown away performance)
|
135
|
+
message = create_message(data)
|
136
|
+
message = Message.new(data, self) unless message.is_a? Message
|
137
|
+
|
138
|
+
return if message.from_bot? && !should_parse_self
|
139
|
+
|
140
|
+
event = MessageEvent.new(message, self)
|
141
|
+
raise_event(event)
|
142
|
+
|
143
|
+
if message.mentions.any? { |user| user.id == @profile.id }
|
144
|
+
event = MentionEvent.new(message, self)
|
145
|
+
raise_event(event)
|
146
|
+
end
|
147
|
+
|
148
|
+
if message.channel.private?
|
149
|
+
event = PrivateMessageEvent.new(message, self)
|
150
|
+
raise_event(event)
|
151
|
+
end
|
152
|
+
when :MESSAGE_UPDATE
|
153
|
+
update_message(data)
|
154
|
+
|
155
|
+
message = Message.new(data, self)
|
156
|
+
return if message.from_bot? && !should_parse_self
|
157
|
+
|
158
|
+
unless message.author
|
159
|
+
LOGGER.debug("Edited a message with nil author! Content: #{message.content.inspect}, channel: #{message.channel.inspect}")
|
160
|
+
return
|
161
|
+
end
|
162
|
+
|
163
|
+
event = MessageEditEvent.new(message, self)
|
164
|
+
raise_event(event)
|
165
|
+
when :MESSAGE_DELETE
|
166
|
+
delete_message(data)
|
167
|
+
|
168
|
+
event = MessageDeleteEvent.new(data, self)
|
169
|
+
raise_event(event)
|
170
|
+
when :MESSAGE_DELETE_BULK
|
171
|
+
debug("MESSAGE_DELETE_BULK will raise #{data['ids'].length} events")
|
172
|
+
|
173
|
+
data['ids'].each do |single_id|
|
174
|
+
# Form a data hash for a single ID so the methods get what they want
|
175
|
+
single_data = {
|
176
|
+
'id' => single_id,
|
177
|
+
'channel_id' => data['channel_id']
|
178
|
+
}
|
179
|
+
|
180
|
+
# Raise as normal
|
181
|
+
delete_message(single_data)
|
182
|
+
|
183
|
+
event = MessageDeleteEvent.new(single_data, self)
|
184
|
+
raise_event(event)
|
185
|
+
end
|
186
|
+
when :TYPING_START
|
187
|
+
start_typing(data)
|
188
|
+
|
189
|
+
begin
|
190
|
+
event = TypingEvent.new(data, self)
|
191
|
+
raise_event(event)
|
192
|
+
rescue Discordrb::Errors::NoPermission
|
193
|
+
debug 'Typing started in channel the bot has no access to, ignoring'
|
194
|
+
end
|
195
|
+
when :MESSAGE_REACTION_ADD
|
196
|
+
add_message_reaction(data)
|
197
|
+
|
198
|
+
return if profile.id == data['user_id'].to_i && !should_parse_self
|
199
|
+
|
200
|
+
event = ReactionAddEvent.new(data, self)
|
201
|
+
raise_event(event)
|
202
|
+
when :MESSAGE_REACTION_REMOVE
|
203
|
+
remove_message_reaction(data)
|
204
|
+
|
205
|
+
return if profile.id == data['user_id'].to_i && !should_parse_self
|
206
|
+
|
207
|
+
event = ReactionRemoveEvent.new(data, self)
|
208
|
+
raise_event(event)
|
209
|
+
when :MESSAGE_REACTION_REMOVE_ALL
|
210
|
+
remove_all_message_reactions(data)
|
211
|
+
|
212
|
+
event = ReactionRemoveAllEvent.new(data, self)
|
213
|
+
raise_event(event)
|
214
|
+
when :PRESENCE_UPDATE
|
215
|
+
# Ignore friends list presences
|
216
|
+
return unless data['guild_id']
|
217
|
+
|
218
|
+
now_playing = data['game'].nil? ? nil : data['game']['name']
|
219
|
+
presence_user = @users[data['user']['id'].to_i]
|
220
|
+
played_before = presence_user.nil? ? nil : presence_user.game
|
221
|
+
update_presence(data)
|
222
|
+
|
223
|
+
event = if now_playing != played_before
|
224
|
+
PlayingEvent.new(data, self)
|
225
|
+
else
|
226
|
+
PresenceEvent.new(data, self)
|
227
|
+
end
|
228
|
+
|
229
|
+
raise_event(event)
|
230
|
+
when :VOICE_STATE_UPDATE
|
231
|
+
old_channel_id = update_voice_state(data)
|
232
|
+
|
233
|
+
event = VoiceStateUpdateEvent.new(data, old_channel_id, self)
|
234
|
+
raise_event(event)
|
235
|
+
when :VOICE_SERVER_UPDATE
|
236
|
+
update_voice_server(data)
|
237
|
+
|
238
|
+
# no event as this is irrelevant to users
|
239
|
+
when :CHANNEL_CREATE
|
240
|
+
create_channel(data)
|
241
|
+
|
242
|
+
event = ChannelCreateEvent.new(data, self)
|
243
|
+
raise_event(event)
|
244
|
+
when :CHANNEL_UPDATE
|
245
|
+
update_channel(data)
|
246
|
+
|
247
|
+
event = ChannelUpdateEvent.new(data, self)
|
248
|
+
raise_event(event)
|
249
|
+
when :CHANNEL_DELETE
|
250
|
+
delete_channel(data)
|
251
|
+
|
252
|
+
event = ChannelDeleteEvent.new(data, self)
|
253
|
+
raise_event(event)
|
254
|
+
when :CHANNEL_RECIPIENT_ADD
|
255
|
+
add_recipient(data)
|
256
|
+
|
257
|
+
event = ChannelRecipientAddEvent.new(data, self)
|
258
|
+
raise_event(event)
|
259
|
+
when :CHANNEL_RECIPIENT_REMOVE
|
260
|
+
remove_recipient(data)
|
261
|
+
|
262
|
+
event = ChannelRecipientRemoveEvent.new(data, self)
|
263
|
+
raise_event(event)
|
264
|
+
when :GUILD_MEMBER_ADD
|
265
|
+
add_guild_member(data)
|
266
|
+
|
267
|
+
event = ServerMemberAddEvent.new(data, self)
|
268
|
+
raise_event(event)
|
269
|
+
when :GUILD_MEMBER_UPDATE
|
270
|
+
update_guild_member(data)
|
271
|
+
|
272
|
+
event = ServerMemberUpdateEvent.new(data, self)
|
273
|
+
raise_event(event)
|
274
|
+
when :GUILD_MEMBER_REMOVE
|
275
|
+
delete_guild_member(data)
|
276
|
+
|
277
|
+
event = ServerMemberDeleteEvent.new(data, self)
|
278
|
+
raise_event(event)
|
279
|
+
when :GUILD_BAN_ADD
|
280
|
+
add_user_ban(data)
|
281
|
+
|
282
|
+
event = UserBanEvent.new(data, self)
|
283
|
+
raise_event(event)
|
284
|
+
when :GUILD_BAN_REMOVE
|
285
|
+
remove_user_ban(data)
|
286
|
+
|
287
|
+
event = UserUnbanEvent.new(data, self)
|
288
|
+
raise_event(event)
|
289
|
+
when :GUILD_ROLE_UPDATE
|
290
|
+
update_guild_role(data)
|
291
|
+
|
292
|
+
event = ServerRoleUpdateEvent.new(data, self)
|
293
|
+
raise_event(event)
|
294
|
+
when :GUILD_ROLE_CREATE
|
295
|
+
create_guild_role(data)
|
296
|
+
|
297
|
+
event = ServerRoleCreateEvent.new(data, self)
|
298
|
+
raise_event(event)
|
299
|
+
when :GUILD_ROLE_DELETE
|
300
|
+
delete_guild_role(data)
|
301
|
+
|
302
|
+
event = ServerRoleDeleteEvent.new(data, self)
|
303
|
+
raise_event(event)
|
304
|
+
when :GUILD_CREATE
|
305
|
+
create_guild(data)
|
306
|
+
|
307
|
+
# Check for false specifically (no data means the server has never been unavailable)
|
308
|
+
if data['unavailable'].is_a? FalseClass
|
309
|
+
@unavailable_servers -= 1 if @unavailable_servers
|
310
|
+
@unavailable_timeout_time = Time.now
|
311
|
+
|
312
|
+
notify_ready if @unavailable_servers.zero?
|
313
|
+
|
314
|
+
# Return here so the event doesn't get triggered
|
315
|
+
return
|
316
|
+
end
|
317
|
+
|
318
|
+
event = ServerCreateEvent.new(data, self)
|
319
|
+
raise_event(event)
|
320
|
+
when :GUILD_UPDATE
|
321
|
+
update_guild(data)
|
322
|
+
|
323
|
+
event = ServerUpdateEvent.new(data, self)
|
324
|
+
raise_event(event)
|
325
|
+
when :GUILD_DELETE
|
326
|
+
delete_guild(data)
|
327
|
+
|
328
|
+
if data['unavailable'].is_a? TrueClass
|
329
|
+
LOGGER.warn("Server #{data['id']} is unavailable due to an outage!")
|
330
|
+
return # Don't raise an event
|
331
|
+
end
|
332
|
+
|
333
|
+
event = ServerDeleteEvent.new(data, self)
|
334
|
+
raise_event(event)
|
335
|
+
when :GUILD_EMOJIS_UPDATE
|
336
|
+
server_id = data['guild_id'].to_i
|
337
|
+
server = @servers[server_id]
|
338
|
+
old_emoji_data = server.emoji.clone
|
339
|
+
update_guild_emoji(data)
|
340
|
+
new_emoji_data = server.emoji
|
341
|
+
|
342
|
+
created_ids = new_emoji_data.keys - old_emoji_data.keys
|
343
|
+
deleted_ids = old_emoji_data.keys - new_emoji_data.keys
|
344
|
+
updated_ids = old_emoji_data.select do |k, v|
|
345
|
+
new_emoji_data[k] && (v.name != new_emoji_data[k].name || v.roles != new_emoji_data[k].roles)
|
346
|
+
end.keys
|
347
|
+
|
348
|
+
event = ServerEmojiChangeEvent.new(server, data, self)
|
349
|
+
raise_event(event)
|
350
|
+
|
351
|
+
created_ids.each do |e|
|
352
|
+
event = ServerEmojiCreateEvent.new(server, new_emoji_data[e], self)
|
353
|
+
raise_event(event)
|
354
|
+
end
|
355
|
+
|
356
|
+
deleted_ids.each do |e|
|
357
|
+
event = ServerEmojiDeleteEvent.new(server, old_emoji_data[e], self)
|
358
|
+
raise_event(event)
|
359
|
+
end
|
360
|
+
|
361
|
+
updated_ids.each do |e|
|
362
|
+
event = ServerEmojiUpdateEvent.new(server, old_emoji_data[e], new_emoji_data[e], self)
|
363
|
+
raise_event(event)
|
364
|
+
end
|
365
|
+
when :WEBHOOKS_UPDATE
|
366
|
+
event = WebhookUpdateEvent.new(data, self)
|
367
|
+
raise_event(event)
|
368
|
+
else
|
369
|
+
# another event that we don't support yet
|
370
|
+
debug "Event #{type} has been received but is unsupported. Raising UnknownEvent"
|
371
|
+
|
372
|
+
event = UnknownEvent.new(type, data, self)
|
373
|
+
raise_event(event)
|
374
|
+
end
|
375
|
+
|
376
|
+
# The existence of this array is checked before for performance reasons, since this has to be done for *every*
|
377
|
+
# dispatch.
|
378
|
+
if @event_handlers && @event_handlers[RawEvent]
|
379
|
+
event = RawEvent.new(type, data, self)
|
380
|
+
raise_event(event)
|
381
|
+
end
|
382
|
+
rescue Exception => e
|
383
|
+
LOGGER.error('Gateway message error!')
|
384
|
+
log_exception(e)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
|
391
|
+
def self.split_into_pipe_parts(message: '', pipe_unicode_symbol: '|')
|
392
|
+
message.split('|')
|
393
|
+
end
|
394
|
+
|
395
|
+
|
396
|
+
|
397
|
+
class PipelineDiscordBot
|
398
|
+
CURL_RESPONSES_HOLDER = {}
|
399
|
+
|
400
|
+
attr_reader :bot
|
401
|
+
|
402
|
+
|
403
|
+
def initialize
|
404
|
+
@bot = ::Discordrb::Bot.new token: ENV['BOT_TOKEN']
|
405
|
+
|
406
|
+
self.add_pipeline_command
|
407
|
+
self.add_gbot_id_fetch_command
|
408
|
+
end
|
409
|
+
|
410
|
+
def get_gbot_message(query, event, callback)
|
411
|
+
command = GbotCommandForBot2Bot.new(query, event)
|
412
|
+
capture = GbotCommandResponseCapture.new(command)
|
413
|
+
|
414
|
+
capture.command.send do
|
415
|
+
capture.pump_once do
|
416
|
+
if !capture.response.nil? && extract_urls_from_gbot_response(capture.response).any?
|
417
|
+
callback.call(capture.response)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def use(*args)
|
424
|
+
yield
|
425
|
+
end
|
426
|
+
|
427
|
+
def where_the_use_would_fail(*args)
|
428
|
+
yield
|
429
|
+
end
|
430
|
+
|
431
|
+
def §(*args)
|
432
|
+
yield if block_given?
|
433
|
+
end
|
434
|
+
|
435
|
+
ESSENTIAL_DECLARATINO_OF_LOCAL_VARIABLE = [self, 0]
|
436
|
+
|
437
|
+
def add_pipeline_command
|
438
|
+
bot.message(with_text: 'pipeline:') do |event|
|
439
|
+
|
440
|
+
if USER_ID_HOLDER[:gbot_id].nil?
|
441
|
+
event.respond("Please first initialize via !pipeline gbot-id-capture")
|
442
|
+
|
443
|
+
else
|
444
|
+
|
445
|
+
event.user.await(:pipeline_definition) do |pipeline_definition_message_event|
|
446
|
+
|
447
|
+
|
448
|
+
user_message = pipeline_definition_message_event.message.content
|
449
|
+
|
450
|
+
pipe_parts = EZIIDiscordIntegration.split_into_pipe_parts(message: MESSAGE.gsub('te123§§st', user_message), pipe_unicode_symbol: '|')
|
451
|
+
|
452
|
+
event.respond pipe_parts.inspect
|
453
|
+
|
454
|
+
pipeline = Pipeline.new
|
455
|
+
pipe_parts.each do |pipe_part| pipeline.add(pipe_part) end
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
pipeline.run { |message, left_commands_count, new_output_value_callback, last_output_value_callback|
|
460
|
+
|
461
|
+
|
462
|
+
|
463
|
+
event.respond("Commands to be run after this one: #{left_commands_count}, now running:")
|
464
|
+
|
465
|
+
thread = lambda { |est| est.call }
|
466
|
+
if message =~ /gbot/
|
467
|
+
get_gbot_message(
|
468
|
+
message.gsub('gbot:', ''),
|
469
|
+
event,
|
470
|
+
->(response_message) do
|
471
|
+
new_output_value_callback.call(response_message)
|
472
|
+
end)
|
473
|
+
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
|
478
|
+
if message =~ /curl/
|
479
|
+
CURL_RESPONSES_HOLDER[0] = lambda do |&block|
|
480
|
+
last_output_value_callback.call do |value|
|
481
|
+
block.call(prepare_curl_responses(value))
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
|
487
|
+
if message =~ /top/
|
488
|
+
CURL_RESPONSES_HOLDER[0].call do |value|
|
489
|
+
event.respond(value.wait_for_finish.winner)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
}
|
494
|
+
end
|
495
|
+
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
require_relative './lib/ezii_curl_manager.rb'
|
501
|
+
def prepare_curl_responses(gbot_message)
|
502
|
+
cm = CurlManager.new( extract_urls_from_gbot_response( gbot_message ) )
|
503
|
+
|
504
|
+
cm.start_calls_in_background
|
505
|
+
|
506
|
+
|
507
|
+
return cm
|
508
|
+
end
|
509
|
+
|
510
|
+
|
511
|
+
def extract_urls_from_gbot_response(gbot_message)
|
512
|
+
return gbot_message.scan(/<([^>]*)>/)
|
513
|
+
end
|
514
|
+
|
515
|
+
|
516
|
+
def add_gbot_id_fetch_command
|
517
|
+
bot.message(content: '!pipeline gbot-id-capture') do |event|
|
518
|
+
event.respond("Type start to begin")
|
519
|
+
event.user.await(:start) do |start_event|
|
520
|
+
event.respond('gbot: get-id')
|
521
|
+
|
522
|
+
ladder { |data|
|
523
|
+
if(data['author']['username'] == 'GBot')
|
524
|
+
USER_ID_HOLDER[:gbot_id] ||= data['author']['id']
|
525
|
+
FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id] ||= data['id']
|
526
|
+
|
527
|
+
event.respond('Google Bot Discord ID is ' + USER_ID_HOLDER[:gbot_id].inspect)
|
528
|
+
end
|
529
|
+
}
|
530
|
+
end
|
531
|
+
end
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
|
536
|
+
class Pipeline
|
537
|
+
attr_accessor :block
|
538
|
+
def initialize
|
539
|
+
@queue = []
|
540
|
+
end
|
541
|
+
|
542
|
+
def add(execute)
|
543
|
+
# §(USE_PUSH_OVER_UNSHIFT_FOR: QUEUE_IMPLEEMENTATION)
|
544
|
+
@queue.push(execute)
|
545
|
+
# end
|
546
|
+
end
|
547
|
+
|
548
|
+
def run
|
549
|
+
last_item = nil
|
550
|
+
while @queue.any?
|
551
|
+
last_item = yield(@queue.shift, @queue.size, new_output_value_callback, last_output_value_callback)
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
|
556
|
+
def new_output_value_callback
|
557
|
+
return Proc.new do |new_value|
|
558
|
+
self.block.call(new_value)
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
def last_output_value_callback
|
563
|
+
return Proc.new do |&block|
|
564
|
+
self.block = block
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
def inspect
|
569
|
+
"""
|
570
|
+
First run command #{@queue[0]}
|
571
|
+
Second run command #{@queue[1]}
|
572
|
+
Third run command #{@queue[2]}
|
573
|
+
"""
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
module Pipeline::ExpectResponseWithin
|
578
|
+
module ClassMethods
|
579
|
+
def timeframe_for_response=(timeframe_in_seconds)
|
580
|
+
@timeframe_in_seconds = timeframe_in_seconds
|
581
|
+
end
|
582
|
+
|
583
|
+
def timeframe_for_response
|
584
|
+
@timeframe_in_seconds
|
585
|
+
end
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
|
590
|
+
|
591
|
+
class GbotCommandResponseCapture
|
592
|
+
attr_accessor :command
|
593
|
+
def initialize(command)
|
594
|
+
@command = command
|
595
|
+
end
|
596
|
+
|
597
|
+
extend Pipeline::ExpectResponseWithin::ClassMethods
|
598
|
+
|
599
|
+
@user_id_of_message_to_be_captured = USER_ID_HOLDER
|
600
|
+
self.timeframe_for_response = 200 # Second
|
601
|
+
|
602
|
+
|
603
|
+
def ALL_FALSE(*args)
|
604
|
+
args.all?(&:false?)
|
605
|
+
end
|
606
|
+
|
607
|
+
def ALL_FALSE_INSPECT(*args)
|
608
|
+
args.each_slice(2).map { |boolean, explanation|
|
609
|
+
"#{explanation}: #{boolean}"
|
610
|
+
}.join(' <> ')
|
611
|
+
end
|
612
|
+
|
613
|
+
|
614
|
+
def pump_once(&block)
|
615
|
+
count = 0
|
616
|
+
self.pump do
|
617
|
+
@stop_ladder = true if count > 0
|
618
|
+
|
619
|
+
|
620
|
+
if @stop_ladder
|
621
|
+
ladder(stop: @ladder_1)
|
622
|
+
else
|
623
|
+
block.call
|
624
|
+
count += 1
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|
628
|
+
|
629
|
+
def pump(&block)
|
630
|
+
fail ERR_ID_2 if self.class.instance_variable_get(:@user_id_of_message_to_be_captured)[:gbot_id].nil?
|
631
|
+
|
632
|
+
|
633
|
+
gbot_id = self.class.instance_variable_get(:@user_id_of_message_to_be_captured)[:gbot_id]
|
634
|
+
|
635
|
+
message = nil
|
636
|
+
messages_by_gbot_in_timeframe = 0
|
637
|
+
@ladder_1 = ladder do |message_data|
|
638
|
+
|
639
|
+
puts message_data.inspect
|
640
|
+
|
641
|
+
puts ALL_FALSE_INSPECT(
|
642
|
+
message_data.nil?, "message_data.nil?",
|
643
|
+
FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id].nil?, "FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id].nil?",
|
644
|
+
message_data['id'] == FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id], "message_data['id'] == FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id]"
|
645
|
+
)
|
646
|
+
|
647
|
+
|
648
|
+
if ALL_FALSE(message_data.nil?, FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id].nil?, message_data['id'] == FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id])
|
649
|
+
fail ERR_ID_7 if message_data.nil?
|
650
|
+
fail ERR_ID_6 if FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id].nil?
|
651
|
+
fail ERR_ID_5 if message_data['id'] == FIRST_GBOT_MESSAGE_HOLDER[:first_gbot_message_id] # or fail ERR_ID_5
|
652
|
+
|
653
|
+
if message_data['author']['id'] == gbot_id
|
654
|
+
messages_by_gbot_in_timeframe += 1
|
655
|
+
|
656
|
+
message = message_data['content']
|
657
|
+
end
|
658
|
+
|
659
|
+
|
660
|
+
fail ERR_ID_3 if message.nil?
|
661
|
+
# next if message.nil?
|
662
|
+
fail ERR_ID_4 if messages_by_gbot_in_timeframe > 1
|
663
|
+
|
664
|
+
@message = message
|
665
|
+
|
666
|
+
puts "TEST TEST"
|
667
|
+
|
668
|
+
block.call
|
669
|
+
end
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
def response
|
674
|
+
@message
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
class GbotCommandForBot2Bot
|
679
|
+
def initialize(text, event)
|
680
|
+
@text = text
|
681
|
+
@event = event
|
682
|
+
end
|
683
|
+
|
684
|
+
def to_discord_message
|
685
|
+
"gbot: #{@text.to_s}"
|
686
|
+
end
|
687
|
+
|
688
|
+
def send
|
689
|
+
@event.respond(self.to_discord_message)
|
690
|
+
|
691
|
+
|
692
|
+
yield
|
693
|
+
end
|
694
|
+
end
|
695
|
+
end
|
696
|
+
|
697
|
+
|
698
|
+
|
699
|
+
ladder {}
|
700
|
+
|
701
|
+
EZIIDiscordIntegration::PipelineDiscordBot.new.bot.run
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ezii-discord'
|
3
|
+
s.version = '0.test'
|
4
|
+
s.date = '2019-10-23'
|
5
|
+
s.summary = "eZii Discord Integration RB"
|
6
|
+
s.description = "integrate eZii as a discord bot easily"
|
7
|
+
s.authors = ["Manuel Arno Korfmann"]
|
8
|
+
s.email = 'manu@korfmann.info'
|
9
|
+
s.files = Dir.glob("**/*")
|
10
|
+
s.homepage =
|
11
|
+
'https://google.com/?q=eZii'
|
12
|
+
s.license = 'MIT'
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module EZIIDiscordIntegration
|
2
|
+
class CurlManager
|
3
|
+
def initialize(website_urls)
|
4
|
+
@website_urls = website_urls.flatten
|
5
|
+
@threads = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def start_calls_in_background
|
9
|
+
@website_urls.each do |url|
|
10
|
+
# tst = -> { `curl #{CGI.escape(url)} -s -o /dev/null -w "%{time_starttransfer}\n"` }
|
11
|
+
#
|
12
|
+
# byebug
|
13
|
+
#
|
14
|
+
#
|
15
|
+
|
16
|
+
thread = Thread.new do
|
17
|
+
# §(INSECURE)
|
18
|
+
|
19
|
+
@threads[thread] = [`curl '#{url}' -s -o /dev/null -w "%{time_starttransfer}\n"`, url]
|
20
|
+
end
|
21
|
+
|
22
|
+
@threads[thread] = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def wait_for_finish
|
27
|
+
@threads.keys.each(&:join)
|
28
|
+
|
29
|
+
return self
|
30
|
+
end
|
31
|
+
|
32
|
+
def winner
|
33
|
+
return @threads.values.min_by do |value|
|
34
|
+
fail ERR_ID_8 if !(value[0].to_f > 0)
|
35
|
+
value[0].to_f
|
36
|
+
end.inspect
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
"""
|
41
|
+
EZIIDiscordIntegration::CurlManagers
|
42
|
+
Binding: #{binding}
|
43
|
+
File: #{__FILE__}
|
44
|
+
|
45
|
+
|
46
|
+
inspect of EZIIDiscordIntegration::CurlManagers# -> @website_urls (# is the symbol for an instance -> method edge in ruby)
|
47
|
+
|
48
|
+
|
49
|
+
#{@website_urls.inspect}
|
50
|
+
|
51
|
+
|
52
|
+
Threads
|
53
|
+
|
54
|
+
#{@threads.inspect}
|
55
|
+
"""
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# @bot = ::Discordrb::Bot.new token: ENV['TEST_BOT_TOKEN']
|
2
|
+
|
3
|
+
|
4
|
+
# bot.message(with_text: 'pipeline:') do |event| # message must only cntain the text
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# bot.message(content: '!pipeline gbot-id-capture') do |event| # message content must exactly match the content: value
|
8
|
+
# event.respond("Type start to begin")
|
9
|
+
# event.user.await(:start) do |start_event| # awaits any input by the user (or any user?)
|
10
|
+
# event.respond('gbot: get-id')
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ezii-discord
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.test
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Manuel Arno Korfmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: integrate eZii as a discord bot easily
|
14
|
+
email: manu@korfmann.info
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- Gemfile
|
20
|
+
- Gemfile.lock
|
21
|
+
- TUTORIAL.md
|
22
|
+
- chat-bot-1.rb
|
23
|
+
- ezii-discord-integration.gemspec
|
24
|
+
- lib/ezii_curl_manager.rb
|
25
|
+
- lib/test/test_ezii_curl_manager.rb
|
26
|
+
- test/test-chat-bot-1.rb
|
27
|
+
homepage: https://google.com/?q=eZii
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.3.1
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.0.3
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: eZii Discord Integration RB
|
50
|
+
test_files: []
|