ssc.bot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,378 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ #--
6
+ # This file is part of SSC.Bot.
7
+ # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig)
8
+ #
9
+ # SSC.Bot is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU Lesser General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # SSC.Bot is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public License
20
+ # along with SSC.Bot. If not, see <https://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ require 'attr_bool'
25
+ require 'time'
26
+
27
+ require 'ssc.bot/error'
28
+ require 'ssc.bot/util'
29
+
30
+
31
+ module SSCBot
32
+ module User
33
+ ###
34
+ # @author Jonathan Bradley Whited (@esotericpig)
35
+ # @since 0.1.0
36
+ ###
37
+ class MessageSender
38
+ DEFAULT_ESCAPE_STR = '.'
39
+ DEFAULT_FLOOD_COUNT = 8
40
+ DEFAULT_FLOOD_MIN_SLEEP = 0.001
41
+ DEFAULT_FLOOD_SECS = 6
42
+
43
+ # Message Macros
44
+ # - In order of F1 Help box.
45
+ MM_TICKNAME = '%tickname'
46
+ MM_SELFNAME = '%selfname'
47
+ MM_SQUAD = '%squad'
48
+ MM_FREQ = '%freq'
49
+ MM_BOUNTY = '%bounty'
50
+ MM_FLAGS = '%flags'
51
+ MM_ENERGY = '%energy'
52
+ MM_KILLER = '%killer'
53
+ MM_KILLED = '%killed'
54
+ MM_COORD = '%coord'
55
+ MM_AREA = '%area'
56
+ MM_RED = '%red'
57
+ MM_REDNAME = '%redname'
58
+ MM_REDBOUNTY = '%redbounty'
59
+ MM_REDFLAGS = '%redflags'
60
+
61
+ attr_accessor? :escape_percent
62
+ attr_accessor? :escape_space
63
+ attr_accessor :escape_str
64
+ attr_accessor :flood_count
65
+ attr_accessor :flood_min_sleep
66
+ attr_accessor :flood_secs
67
+ attr_reader :message_count
68
+ attr_reader :message_time
69
+ attr_accessor? :staff
70
+
71
+ def put(message)
72
+ raise AbstractMethodError
73
+ end
74
+
75
+ def send_message()
76
+ raise AbstractMethodError
77
+ end
78
+
79
+ def type(message)
80
+ raise AbstractMethodError
81
+ end
82
+
83
+ def initialize(escape_percent: false,escape_space: true,escape_str: DEFAULT_ESCAPE_STR,flood_count: DEFAULT_FLOOD_COUNT,flood_min_sleep: DEFAULT_FLOOD_MIN_SLEEP,flood_secs: DEFAULT_FLOOD_SECS,staff: false)
84
+ super()
85
+
86
+ @escape_percent = escape_percent
87
+ @escape_space = escape_space
88
+ @escape_str = escape_str
89
+ @flood_count = flood_count
90
+ @flood_min_sleep = flood_min_sleep
91
+ @flood_secs = flood_secs
92
+ @message_count = 0
93
+ @message_time = Time.now()
94
+ @staff = staff
95
+ end
96
+
97
+ def escape_pub(message,escape_percent: @escape_percent,escape_space: @escape_space,escape_str: @escape_str,staff: @staff)
98
+ if escape_percent
99
+ message = message.gsub('%','%%')
100
+ end
101
+
102
+ escape = false
103
+
104
+ case message[0]
105
+ when '#'
106
+ escape = true
107
+ else
108
+ if escape_space && message[0] =~ /[[:space:]]/
109
+ escape = true
110
+ else
111
+ stripped_message = Util.u_lstrip(message)
112
+
113
+ case stripped_message[0]
114
+ when ':'
115
+ if stripped_message.index(':',1)
116
+ escape = true
117
+ end
118
+ when '/',%q{'},'"',';','='
119
+ escape = true
120
+ when '?'
121
+ if stripped_message[1] =~ /[[:alpha:]]/
122
+ escape = true
123
+ end
124
+ when '*','-'
125
+ escape = true if staff
126
+ end
127
+ end
128
+ end
129
+
130
+ if escape
131
+ message = "#{escape_str}#{message}"
132
+ end
133
+
134
+ return message
135
+ end
136
+
137
+ def prevent_flood()
138
+ @message_count += 1
139
+
140
+ if @message_count >= @flood_count
141
+ diff_time = Time.now() - @message_time
142
+
143
+ if diff_time <= @flood_secs
144
+ sleep_secs = (@flood_secs - diff_time).round(4) + 0.001
145
+ sleep_secs = @flood_min_sleep if sleep_secs < @flood_min_sleep
146
+ else
147
+ sleep_secs = @flood_min_sleep
148
+ end
149
+
150
+ sleep(sleep_secs)
151
+
152
+ @message_count = 0
153
+ end
154
+
155
+ @message_time = Time.now()
156
+ end
157
+
158
+ def put_or_type(message)
159
+ put(message)
160
+ end
161
+
162
+ def send(message)
163
+ put(message)
164
+ send_message()
165
+ end
166
+
167
+ def send_or_types(message)
168
+ send(message)
169
+ end
170
+
171
+ def send_or_types_safe(message)
172
+ send_or_types(message)
173
+ prevent_flood()
174
+ end
175
+
176
+ def send_safe(message)
177
+ send(message)
178
+ prevent_flood()
179
+ end
180
+
181
+ def types(message)
182
+ type(message)
183
+ send_message()
184
+ end
185
+
186
+ def types_safe(message)
187
+ types(message)
188
+ prevent_flood()
189
+ end
190
+
191
+ def send_chat(message)
192
+ send_safe(";#{message}")
193
+ end
194
+
195
+ def send_chat_to(channel,message)
196
+ send_safe(";#{channel};#{message}")
197
+ end
198
+
199
+ def send_freq(message)
200
+ send_safe(%Q{"#{message}})
201
+ end
202
+
203
+ def send_freq_eq(freq)
204
+ send_safe("=#{freq}")
205
+ end
206
+
207
+ def send_private(message)
208
+ send_safe("/#{message}")
209
+ end
210
+
211
+ def send_private_to(name,message)
212
+ send_safe(":#{name}:#{message}")
213
+ end
214
+
215
+ def send_private_to_last(message,last=1)
216
+ put_or_type('::')
217
+
218
+ while (last -= 1) > 0
219
+ put_or_type(':')
220
+ end
221
+
222
+ send_safe(message)
223
+ end
224
+
225
+ def send_pub(message,**kargs)
226
+ send_safe(escape_pub(message,**kargs))
227
+ end
228
+
229
+ def send_q_chat()
230
+ send_safe('?chat')
231
+ end
232
+
233
+ def send_q_chat_eq(*names)
234
+ send_safe("?chat=#{names.join(',')}")
235
+ end
236
+
237
+ def send_q_enter()
238
+ send_safe('?enter')
239
+ end
240
+
241
+ def send_q_find(player)
242
+ send_safe("?find #{player}")
243
+ end
244
+
245
+ def send_q_kill()
246
+ send_safe('?kill')
247
+ end
248
+
249
+ def send_q_leave()
250
+ send_safe('?leave')
251
+ end
252
+
253
+ def send_q_loadmacro(filename)
254
+ send_safe("?loadmacro #{filename}")
255
+ end
256
+
257
+ def send_q_log()
258
+ send_safe('?log')
259
+ end
260
+
261
+ def send_q_log_to(filename)
262
+ send_safe("?log #{filename}")
263
+ end
264
+
265
+ def send_q_logbuffer()
266
+ send_safe('?logbuffer')
267
+ end
268
+
269
+ def send_q_logbuffer_to(filename)
270
+ send_safe("?logbuffer #{filename}")
271
+ end
272
+
273
+ def send_q_namelen()
274
+ send_safe('?namelen')
275
+ end
276
+
277
+ def send_q_namelen_eq(namelen)
278
+ send_safe("?namelen=#{namelen}")
279
+ end
280
+
281
+ def send_q_lines()
282
+ send_safe('?lines')
283
+ end
284
+
285
+ def send_q_lines_eq(lines)
286
+ send_safe("?lines=#{lines}")
287
+ end
288
+
289
+ def send_q_savemacro(filename)
290
+ send_safe("?savemacro #{filename}")
291
+ end
292
+
293
+ def send_q_spec()
294
+ send_safe('?spec')
295
+ end
296
+
297
+ def send_q_team()
298
+ send_safe('?team')
299
+ end
300
+
301
+ def send_squad(message)
302
+ send_safe("##{message}")
303
+ end
304
+
305
+ def send_squad_to(squad,message)
306
+ send_safe(":##{squad}:#{message}")
307
+ end
308
+
309
+ def send_team(message)
310
+ send_safe("//#{message}")
311
+ end
312
+
313
+ def send_team2(message)
314
+ send_safe("'#{message}")
315
+ end
316
+
317
+ def mm_tickname()
318
+ return MM_TICKNAME
319
+ end
320
+
321
+ def mm_selfname()
322
+ return MM_SELFNAME
323
+ end
324
+
325
+ def mm_squad()
326
+ return MM_SQUAD
327
+ end
328
+
329
+ def mm_freq()
330
+ return MM_FREQ
331
+ end
332
+
333
+ def mm_bounty()
334
+ return MM_BOUNTY
335
+ end
336
+
337
+ def mm_flags()
338
+ return MM_FLAGS
339
+ end
340
+
341
+ def mm_energy()
342
+ return MM_ENERGY
343
+ end
344
+
345
+ def mm_killer()
346
+ return MM_KILLER
347
+ end
348
+
349
+ def mm_killed()
350
+ return MM_KILLED
351
+ end
352
+
353
+ def mm_coord()
354
+ return MM_COORD
355
+ end
356
+
357
+ def mm_area()
358
+ return MM_AREA
359
+ end
360
+
361
+ def mm_red()
362
+ return MM_RED
363
+ end
364
+
365
+ def mm_redname()
366
+ return MM_REDNAME
367
+ end
368
+
369
+ def mm_redbounty()
370
+ return MM_REDBOUNTY
371
+ end
372
+
373
+ def mm_redflags()
374
+ return MM_REDFLAGS
375
+ end
376
+ end
377
+ end
378
+ end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ #--
6
+ # This file is part of SSC.Bot.
7
+ # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig)
8
+ #
9
+ # SSC.Bot is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU Lesser General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # SSC.Bot is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public License
20
+ # along with SSC.Bot. If not, see <https://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ require 'rbconfig'
25
+
26
+
27
+ module SSCBot
28
+ ###
29
+ # Your typical utility methods that
30
+ # should be moved into a separate Gem one day...
31
+ #
32
+ # @author Jonathan Bradley Whited (@esotericpig)
33
+ # @since 0.1.0
34
+ ###
35
+ module Util
36
+ def self.os(host_os=RbConfig::CONFIG['host_os'])
37
+ os = :unknown
38
+
39
+ case host_os
40
+ when /darwin/i
41
+ os = :macos
42
+ # I think 'cygwin' here makes sense.
43
+ when /linux|arch|cygwin/i
44
+ os = :linux
45
+ else
46
+ # Here so that 'win' doesn't capture 'darwin'.
47
+ case host_os
48
+ # windows|mswin|bccwin|wince
49
+ when /win|mingw|emx/i
50
+ os = :windows
51
+ end
52
+ end
53
+
54
+ return os
55
+ end
56
+
57
+ OS = os()
58
+
59
+ def self.quote_str_or_regex(value)
60
+ if value.respond_to?(:source)
61
+ return value.source.gsub(' ','\\ ') # For //x
62
+ else
63
+ return Regexp.quote(value)
64
+ end
65
+ end
66
+
67
+ # Universally, is +str+ empty after stripping or +nil+?
68
+ def self.u_blank?(str)
69
+ return str.nil?() || strip(str).empty?()
70
+ end
71
+
72
+ # Universally, left strip +str+'s leading (head) space.
73
+ def self.u_lstrip(str)
74
+ return nil if str.nil?()
75
+ return str.gsub(/\A[[:space:]]+/,'')
76
+ end
77
+
78
+ # Universally, right strip +str+'s trailing (tail) space.
79
+ def self.u_rstrip(str)
80
+ return nil if str.nil?()
81
+ return str.gsub(/[[:space:]]+\z/,'')
82
+ end
83
+
84
+ # Universally, strip +str+'s space.
85
+ def self.u_strip(str)
86
+ return nil if str.nil?()
87
+ return str.gsub(/\A[[:space:]]+|[[:space:]]+\z/,'')
88
+ end
89
+ end
90
+ end