ssc.bot 0.1.0

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.
@@ -0,0 +1,193 @@
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
+
26
+ require 'ssc.bot/chat_log/message'
27
+
28
+
29
+ module SSCBot
30
+ class ChatLog
31
+ ###
32
+ # @author Jonathan Bradley Whited (@esotericpig)
33
+ # @since 0.1.0
34
+ ###
35
+ class PlayerMessage < Message
36
+ attr_reader :message
37
+ attr_reader :name
38
+
39
+ def initialize(line,type:,name:,message:)
40
+ super(line,type: type)
41
+
42
+ @message = message
43
+ @name = name
44
+ end
45
+ end
46
+
47
+ ###
48
+ # @author Jonathan Bradley Whited (@esotericpig)
49
+ # @since 0.1.0
50
+ ###
51
+ class ChatMessage < PlayerMessage
52
+ attr_reader :channel
53
+
54
+ def initialize(line,channel:,name:,message:)
55
+ super(line,type: :chat,name: name,message: message)
56
+
57
+ @channel = channel
58
+ end
59
+ end
60
+
61
+ ###
62
+ # @author Jonathan Bradley Whited (@esotericpig)
63
+ # @since 0.1.0
64
+ ###
65
+ class FreqMessage < PlayerMessage
66
+ def initialize(line,name:,message:)
67
+ super(line,type: :freq,name: name,message: message)
68
+ end
69
+ end
70
+
71
+ ###
72
+ # @author Jonathan Bradley Whited (@esotericpig)
73
+ # @since 0.1.0
74
+ ###
75
+ class KillMessage < Message
76
+ attr_reader :bounty
77
+ attr_reader :killed
78
+ attr_reader :killer
79
+
80
+ def initialize(line,killed:,bounty:,killer:)
81
+ super(line,type: :kill)
82
+
83
+ @bounty = bounty
84
+ @killed = killed
85
+ @killer = killer
86
+ end
87
+ end
88
+
89
+ ###
90
+ # @author Jonathan Bradley Whited (@esotericpig)
91
+ # @since 0.1.0
92
+ ###
93
+ class PrivateMessage < PlayerMessage
94
+ def initialize(line,name:,message:,type: :private)
95
+ super(line,type: type,name: name,message: message)
96
+ end
97
+ end
98
+
99
+ ###
100
+ # @author Jonathan Bradley Whited (@esotericpig)
101
+ # @since 0.1.0
102
+ ###
103
+ class PubMessage < PlayerMessage
104
+ def initialize(line,name:,message:)
105
+ super(line,type: :pub,name: name,message: message)
106
+ end
107
+ end
108
+
109
+ ###
110
+ # @author Jonathan Bradley Whited (@esotericpig)
111
+ # @since 0.1.0
112
+ ###
113
+ class QFindMessage < Message
114
+ attr_reader :arena
115
+ attr_reader :days
116
+ attr_reader :find_type # [:arena,:days,:hours,:zone]
117
+ attr_reader :hours
118
+ attr_reader? :more
119
+ attr_reader :player
120
+ attr_reader? :private
121
+ attr_reader :zone
122
+
123
+ def initialize(line,find_type:,arena: nil,days: nil,hours: nil,more: false,player: nil,private: false,zone: nil)
124
+ super(line,type: %s{?find})
125
+
126
+ @arena = arena
127
+ @days = days
128
+ @find_type = find_type
129
+ @hours = hours
130
+ @more = more
131
+ @player = player
132
+ @private = private
133
+ @zone = zone
134
+ end
135
+ end
136
+
137
+ ###
138
+ # @author Jonathan Bradley Whited (@esotericpig)
139
+ # @since 0.1.0
140
+ ###
141
+ class QLogMessage < Message
142
+ attr_reader :filename
143
+ attr_reader :log_type # [:open,:close]
144
+
145
+ def initialize(line,log_type:,filename: nil)
146
+ super(line,type: %s{?log})
147
+
148
+ @filename = filename
149
+ @log_type = log_type
150
+ end
151
+ end
152
+
153
+ ###
154
+ # @author Jonathan Bradley Whited (@esotericpig)
155
+ # @since 0.1.0
156
+ ###
157
+ class QNamelenMessage < Message
158
+ attr_reader :namelen
159
+
160
+ def initialize(line,namelen:)
161
+ super(line,type: %s{?namelen})
162
+
163
+ @namelen = namelen
164
+ end
165
+ end
166
+
167
+ ###
168
+ # @author Jonathan Bradley Whited (@esotericpig)
169
+ # @since 0.1.0
170
+ ###
171
+ class RemoteMessage < PrivateMessage
172
+ attr_reader? :own
173
+ attr_reader? :squad
174
+
175
+ def initialize(line,own:,squad:,name:,message:)
176
+ super(line,type: :remote,name: name,message: message)
177
+
178
+ @own = own
179
+ @squad = squad
180
+ end
181
+ end
182
+
183
+ ###
184
+ # @author Jonathan Bradley Whited (@esotericpig)
185
+ # @since 0.1.0
186
+ ###
187
+ class TeamMessage < PlayerMessage
188
+ def initialize(line,name:,message:)
189
+ super(line,type: :team,name: name,message: message)
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,52 @@
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 'ssc.bot/ssc_file'
25
+
26
+ require 'ssc.bot/chat_log/message'
27
+ require 'ssc.bot/chat_log/message_parsable'
28
+ require 'ssc.bot/chat_log/message_parser'
29
+ require 'ssc.bot/chat_log/messages'
30
+
31
+
32
+ module SSCBot
33
+ ###
34
+ # @author Jonathan Bradley Whited (@esotericpig)
35
+ # @since 0.1.0
36
+ ###
37
+ class ChatLogFile < SSCFile
38
+ include ChatLog::MessageParsable
39
+
40
+ def initialize(filename,mode=DEFAULT_MODE,parser: ChatLog::MessageParser.new(),**file_kargs)
41
+ super(filename,mode,**file_kargs)
42
+
43
+ @parser = parser
44
+ end
45
+
46
+ def parse_line()
47
+ line = get_line()
48
+
49
+ return line.nil?() ? nil : parse(line)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,61 @@
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
+ module SSCBot
25
+ ###
26
+ # @author Jonathan Bradley Whited (@esotericpig)
27
+ # @since 0.1.0
28
+ ###
29
+ class Error < ::StandardError; end
30
+
31
+ ###
32
+ # @author Jonathan Bradley Whited (@esotericpig)
33
+ # @since 0.1.0
34
+ ###
35
+ class AbstractMethodError < Error
36
+ def initialize(msg=nil)
37
+ if msg.nil?()
38
+ method_name = caller[1]
39
+
40
+ if !method_name.nil?()
41
+ index = method_name.rindex('`')
42
+
43
+ if !index.nil?() && (index += 1) < method_name.length
44
+ method_name = method_name[index..-2]
45
+
46
+ msg = "abstract method{#{method_name}(...)} not implemented"
47
+ end
48
+ end
49
+ end
50
+
51
+ super(msg)
52
+ end
53
+ end
54
+
55
+ ###
56
+ # @author Jonathan Bradley Whited (@esotericpig)
57
+ # @since 0.1.0
58
+ ###
59
+ class ParseError < Error
60
+ end
61
+ end
@@ -0,0 +1,132 @@
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 'ssc.bot/util'
25
+
26
+
27
+ module SSCBot
28
+ ###
29
+ # @author Jonathan Bradley Whited (@esotericpig)
30
+ # @since 0.1.0
31
+ ###
32
+ class SSCFile < ::File
33
+ DEFAULT_BUFFER_LEN = 520
34
+ DEFAULT_ENCODING = 'Windows-1252:UTF-8'
35
+ DEFAULT_MODE = 'rt'
36
+ DEFAULT_SEPARATOR = /\r?\n|\r/ # Instead, could use +/\R/+ for Ruby v2.0+
37
+
38
+ # Clear (truncate) the contents of +filename+.
39
+ #
40
+ # @param filename [String] the file to clear
41
+ # @param strip [Boolean] +true+ to strip +filename+ to help prevent fat-fingering, else +false+ to not
42
+ def self.clear_content(filename,strip: true,textmode: true,**opt)
43
+ filename = Util.u_strip(filename) if strip
44
+
45
+ return if filename.empty?()
46
+ return if !File.file?(filename) # Also checks if exists
47
+
48
+ # Clear the file.
49
+ # - Do NOT call truncate() as it's not available on all platforms.
50
+ open(filename,'w',textmode: textmode,**opt) do |file|
51
+ end
52
+ end
53
+
54
+ # If +filename+ exists, then it does nothing (does *not* update time),
55
+ # else, it creates the file.
56
+ #
57
+ # I just prefer this over +FileUtils.touch+.
58
+ #
59
+ # @param filename [String] the file to soft touch
60
+ # @param strip [Boolean] +true+ to strip +filename+ to help prevent fat-fingering, else +false+ to not
61
+ def self.soft_touch(filename,strip: true,textmode: true,**opt)
62
+ filename = Util.u_strip(filename) if strip
63
+
64
+ return if filename.empty?()
65
+ return if File.exist?(filename)
66
+
67
+ # Create the file.
68
+ open(filename,'a',textmode: textmode,**opt) do |file|
69
+ end
70
+ end
71
+
72
+ def initialize(filename,mode=DEFAULT_MODE,buffer_len: DEFAULT_BUFFER_LEN,encoding: DEFAULT_ENCODING,separator: DEFAULT_SEPARATOR,**opt)
73
+ super(filename,mode,encoding: encoding,**opt)
74
+
75
+ @sscbot_buffer = nil
76
+ @sscbot_buffer_len = buffer_len
77
+ @sscbot_separator = separator
78
+ end
79
+
80
+ def get_line()
81
+ if @sscbot_buffer.nil?()
82
+ # See comment at loop below.
83
+ # - Use gets() instead of eof?() because of this method's name.
84
+ line = gets(nil,@sscbot_buffer_len)
85
+
86
+ return nil if line.nil?() # Still EOF?
87
+
88
+ @sscbot_buffer = line
89
+ end
90
+
91
+ lines = @sscbot_buffer.split(@sscbot_separator,2)
92
+
93
+ # Will only have 2 if there was a separator.
94
+ if lines.length == 2
95
+ @sscbot_buffer = lines[1]
96
+
97
+ return lines[0]
98
+ end
99
+
100
+ # - Use a separator of nil to get all of the different types of newlines.
101
+ # - Use gets() [instead of read(), etc.] to work probably with text (e.g., UTF-8)
102
+ # and to not throw an error at EOF (returns nil).
103
+ while !(line = gets(nil,@sscbot_buffer_len)).nil?()
104
+ lines = line.split(@sscbot_separator,2)
105
+
106
+ # Will only have 2 if there was a separator.
107
+ if lines.length == 2
108
+ line = "#{@sscbot_buffer}#{lines[0]}"
109
+ @sscbot_buffer = lines[1]
110
+
111
+ return line
112
+ else
113
+ @sscbot_buffer << line
114
+ end
115
+ end
116
+
117
+ # EOF reached with text in the buffer.
118
+ line = @sscbot_buffer
119
+ @sscbot_buffer = nil
120
+
121
+ return line
122
+ end
123
+
124
+ def seek_to_end()
125
+ result = seek(0,:END)
126
+
127
+ get_line() # Justin Case
128
+
129
+ return result
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,194 @@
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
+ begin
25
+ require 'java'
26
+ rescue LoadError => e
27
+ raise e.exception('Must use JRuby for JRobotMessageSender')
28
+ end
29
+
30
+ require 'attr_bool'
31
+
32
+ require 'ssc.bot/util'
33
+
34
+ require 'ssc.bot/user/message_sender'
35
+
36
+ java_import 'java.awt.Robot'
37
+ java_import 'java.awt.Toolkit'
38
+
39
+ java_import 'java.awt.datatransfer.Clipboard'
40
+ java_import 'java.awt.datatransfer.ClipboardOwner'
41
+ java_import 'java.awt.datatransfer.StringSelection'
42
+
43
+ java_import 'java.awt.event.KeyEvent'
44
+
45
+
46
+ module SSCBot
47
+ module User
48
+ ###
49
+ # @author Jonathan Bradley Whited (@esotericpig)
50
+ # @since 0.1.0
51
+ ###
52
+ class JRobotMessageSender < MessageSender
53
+ attr_accessor :clipboard
54
+ attr_accessor :msg_key
55
+ attr_accessor :os
56
+ attr_accessor :robot
57
+ attr_accessor :shortcut_paste
58
+ attr_accessor :shortcut_paste_default
59
+ attr_accessor :shortcut_paste_macos
60
+ attr_accessor? :warn_user
61
+ attr_accessor :warn_user_key
62
+ attr_accessor :warn_user_sleep
63
+
64
+ def initialize(auto_delay: 110,msg_key: nil,os: Util::OS,warn_user: false,warn_user_key: KeyEvent::VK_BACK_SPACE,warn_user_sleep: 0.747,**kargs)
65
+ super(**kargs)
66
+
67
+ @clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
68
+ @msg_key = msg_key
69
+ @os = os
70
+ @robot = Robot.new()
71
+ @warn_user = warn_user
72
+ @warn_user_key = warn_user_key
73
+ @warn_user_sleep = warn_user_sleep
74
+
75
+ @robot.setAutoDelay(auto_delay)
76
+
77
+ @shortcut_paste = ->(ms) do
78
+ if ms.os == :macos
79
+ @shortcut_paste_macos.call(ms)
80
+ else
81
+ @shortcut_paste_default.call(ms)
82
+ end
83
+ end
84
+ @shortcut_paste_default = ->(ms) { ms.roll_keys(KeyEvent::VK_CONTROL,KeyEvent::VK_V) }
85
+ @shortcut_paste_macos = ->(ms) { ms.roll_keys(KeyEvent::VK_META,KeyEvent::VK_V) }
86
+ end
87
+
88
+ def backspace()
89
+ return type_key(KeyEvent::VK_BACK_SPACE)
90
+ end
91
+
92
+ def copy(str)
93
+ @clipboard.setContents(StringSelection.new(str),nil)
94
+
95
+ return self
96
+ end
97
+
98
+ def enter()
99
+ return type_key(KeyEvent::VK_ENTER)
100
+ end
101
+
102
+ def paste(str=nil)
103
+ copy(str) unless str.nil?()
104
+
105
+ @shortcut_paste.call(self)
106
+
107
+ return self
108
+ end
109
+
110
+ def press_key(*key_codes)
111
+ key_codes.each() do |key_code|
112
+ @robot.keyPress(key_code)
113
+ end
114
+
115
+ return self
116
+ end
117
+
118
+ def put(message)
119
+ # If do type_msg_key() and then warn_user(), then a backspace from
120
+ # warn_user() will cancel out the msg key.
121
+ # Could do type_msg_key().warn_user().type_msg_key(), but then if the
122
+ # client is in windowed mode and msg key is a tab, then a backspace
123
+ # from warn_user() will do nothing.
124
+ return warn_user().
125
+ type_msg_key().
126
+ paste(message)
127
+ end
128
+
129
+ def release_key(*key_codes)
130
+ key_codes.each() do |key_code|
131
+ @robot.keyRelease(key_code)
132
+ end
133
+
134
+ return self
135
+ end
136
+
137
+ def roll_keys(*key_codes)
138
+ key_codes.each() do |key_code|
139
+ @robot.keyPress(key_code)
140
+ end
141
+
142
+ (key_codes.length - 1).downto(0) do |i|
143
+ @robot.keyRelease(key_codes[i])
144
+ end
145
+
146
+ return self
147
+ end
148
+
149
+ def send_message()
150
+ enter()
151
+ end
152
+
153
+ def type(message)
154
+ # TODO: implement type(message)
155
+ super(message)
156
+ end
157
+
158
+ def type_key(*key_codes)
159
+ key_codes.each() do |key_code|
160
+ @robot.keyPress(key_code)
161
+ @robot.keyRelease(key_code)
162
+ end
163
+
164
+ return self
165
+ end
166
+
167
+ def type_msg_key()
168
+ if @msg_key
169
+ if @msg_key.respond_to?(:call)
170
+ @msg_key.call(self)
171
+ else
172
+ type_key(@msg_key)
173
+ end
174
+ end
175
+
176
+ return self
177
+ end
178
+
179
+ def warn_user()
180
+ if @warn_user
181
+ if @warn_user_key.respond_to?(:call)
182
+ @warn_user_key.call(self)
183
+ else
184
+ press_key(@warn_user_key)
185
+ sleep(@warn_user_sleep)
186
+ release_key(@warn_user_key)
187
+ end
188
+ end
189
+
190
+ return self
191
+ end
192
+ end
193
+ end
194
+ end