· 9 years ago · Feb 16, 2017, 10:50 AM
1=begin
2 Documentation: https://elanthipedia.play.net/Lich_script_repository#status-monitor
3=end
4
5
6## *** MAIL ADDITION
7## *** v.01 by Iloru
8
9## *** THERE IS 1 CHANGE NEAR THE END OF FILE
10*** Commented out Slack and added sendMail
11***
12require 'mail'
13
14@sendAddress = "smtp.gmail.com"
15@sendPort = 587
16@sendDomain = "gmail.com"
17## CHANGE THIS TO YOUR USER NAME
18@sendUserName = "gemstoneruby.smtp" # this is your username excluding @gmail.com
19@sendPassword = "xxxxx" # CHANGE
20@fromEmail = "gemstoneruby.smtp@gmail.com" # ex, gemstoneruby@gmail.com
21
22## TO EMAILS - Max of 2 emails currently
23@email1 = "555555@msg.fi.google.com" # example of email to text for google fi. each server has this
24@email2 = "emailname@gmail.com" # Email notification is sent here.
25
26
27options = { :address => @sendAddress,
28 :port => @sendPort,
29 :domain => @sendDomain,
30 :user_name => @sendUserName,
31 :password => @sendPassword,
32 :authentication => 'plain', # this might need to change if you don't use gmail.
33 :enable_starttls_auto => true }
34
35Mail.defaults do
36 delivery_method :smtp, options
37end
38
39def sendMail(message, type)
40 for toEmail in [@email1, @email2]
41 Mail.new(
42 to: toEmail,
43 from: @fromEmail,
44 subject: type,
45 body: message
46 ).deliver!
47 end
48end
49
50## *** END MAIL ADDITION
51
52status_tags
53
54arg_definitions = [
55 [
56 { name: 'debug', regex: /debug/i, optional: true },
57 { name: 'nowindow', regex: /nowindow/i, optional: true }
58 ]
59]
60
61args = parse_args(arg_definitions)
62
63nowindow = args.nowindow || get_settings.status_monitor_no_window
64
65class GameFilter
66 attr_accessor :seen_lines, :spam_line
67
68 def initialize(slackbot)
69 @seen_cache_name = "seen_messages_#{checkname}.dat"
70 @seen_lines = if File.exist?(@seen_cache_name)
71 Marshal.load(File.open(@seen_cache_name, 'rb'))
72 else
73 {}
74 end
75 @recent_seen_lines = {}
76 @valid_commands = %w(ACTION ADVICE AFT AGREE ANSWER APPLAUD ASK AVOID AWAKEN BABBLE BALANCE BANDAGE BARK BARTER BASK BAWL BEAM BEARD BECKON BELCH BITE BLAME BLANCH BLAZE BLINK BLOCK BLUFF BLUSH BONDED BOO BOP BOUNCE BOW BRAWL BREAK BREATHE BRUSH BUTT BUY CACKLE CARDS CARVE CENTER CHANT CHAT CHECK CHEER CHIRR CHOKE CHOOSE CHOP CHORTLE CHORUS CHUCKLE CLAIM CLAP CLEAN CLENCH CLIMB CLOSE CLUTCH COIN COLLECT COMBAT COMPARE CONCENTRATE CONTACT COUGH COUNT COVER COWER CRAWL CRINGE CRUSH CRY CURSE CURTSY CUT DANCE DANCE FLOOR DAYDREAM DEAD DESCRIBE DRAG DRINK DROOL DROP DUCK DUMP EAR EAT ELBOW EMAIL EMPTY ENCUMBRANCE ENGAGE EXAMINE EXCHANGE EXHALE EXPRESS FACE FAINT FALL FATIGUE FEED FEMALE FIDGET FIGURE FIND FIRE FIT FIX FLAGS FLAIL FLAP FLETCH FLINCH FLIRT FLUSTER FLY FOCUS FOLLOW FORAGE FRET FROWN FURROW GASP GAWK GAZE GEM GET GIGGLE GLANCE GLARE GLOWER GNASH GO GOBBLE GRIEVE GRIMACE GRIN GRIND GROAN GROVEL GROWL GRUMBLE GRUNT GUARD GULP GUZZLE HACK HAIL HAIR HANGBACK HELLO HICCUP HIDE HISS HOLD HOME HOOT HOWL HUG HUM HUZZAH IGNORE INFAMY INFO INFUSE INHALE INSTRUCT INSULT INTELLIGENCE INVENTORY INVFIX JAB JOIN JUGGLE JUMP KHRI KICK KILL KISS KNEE KNEEL KNOCK LANGUAGE LATCH LAUGH LEAD LEAN LEAP LEAVE LECTURE LICK LIE LIGHT LINK LISTEN LOAD LOAN LOCK LOOK LOWER LUNGE MAKE MALE MANA MARCH MARK MEDITATE MEETING MENU MEOW MESSAGE MIND MIX MOAN MOCK MONEY MOOR MORE MOTION MOUNT MUMBLE MUSS MUTTER NAG NAME NIBBLE NOCK NOD NOTE NUDGE OBSERVE OFFER OPEN ORDER PACE PANIC PANT PARRY PAT PATHWAY PAY PEER PERCEIVE PET PICK PIN PINCH PLANT PLAY PLAYACT POACH POINT POKE POLICY PONDER PORT PORTRAIT POSE POUND POUR POUT PRACTICE PRAISE PRAY PREACH PREDICT PREEN PREMIUM PREPARE PROCRASTINATE PROD PROTECT PUCKER PULL PUMMEL PUNCH PUNISH PURR PUSH PUT PUZZLE QUEST QUEUE QUIT RAISE RASPBERRY READ RECALL RECITE REFER REFLEX REFUSE RELEASE REMOVE REPAIR REPENT REROLL RETREAT RETURN RING ROAR ROFL ROLL ROSHAMBO ROW RPA RUB RUMMAGE SALUTE SCOFF SCOUT SCOWL SCRAPE SCRATCH SCREAM SCRIBE SEARCH SELL SHAKE SHAPE SHARE SHEATHE SHIFT SHIP SHIVER SHOOT SHOVE SHOW SHRIEK SHRUG SHUDDER SHUFFLE SHUN SIGH SIGN SIGNAL SIGNATURE SING SIT SKATE SKILLS SKIN SLAP SLEEP SLICE SLINK SLIP SMELL SMILE SMIRK SMOOCH SNAP SNARL SNEAK SNEER SNEEZE SNICKER SNIFFLE SNORE SNORT SNUFF SNUGGLE SOB SONG SORT SPECULATE SPELLS SPIT SPLASH SPLUTTER SPRINKLE SQUINT SQUIRM STABLE STALK STAMINA STANCE STAND STARBOARD STARE STATUS STEAL STIR STITCH STOMP STOP STOW STRENGTH STRETCH STRING STUBBLE STUDY SULK SUMMON SURPRISE SURRENDER SURVEY SWAP SWEAR SWEAT SWEEP SWIM SWIMMING SWING TACKLE TAG TAIL TAKE TALK TAP TARGET TEACH TEASE TELL TEND THINK THROW THRUST THUMP TICKLE TIE TILT TIME TIP TITLE TOSS TOUCH TRACE TRACK TRAIN TRANSFER TRILL TUNE TURN TYPO UNBRAID UNBUNDLE UNCOIL UNHIDE UNLATCH UNLOAD UNLOCK UNTIE UNWRAP VAULT VOTE WAIL WAIT WAKE WARN WATCH WAVE WEALTH WEAR WEAVE WEDDING WEEP WHEEZE WHIMPER WHINE WHIRLWIND WHISTLE WHO WIELD WINCE WINK WIPE WITHDRAW WOBBLE WRING WRITE YANK YAWN YELP)
77 @room_players = []
78 @filter_strings = get_data('filters')['filter_strings'].map { |string| /#{string}/ }
79 @non_useful_tags = [
80 /<preset id='roomDesc'>/i,
81 /pushStream id="atmospherics"/i,
82 /pushStream id="thoughts"/i,
83 /pushStream id="talk"/i,
84 /pushStream id="death"/i,
85 /pushStream id="group"/i,
86 /pushStream id="percWindow"/i,
87 /component id='room/i,
88 /component id='exp/i,
89 %r{</prompt>$},
90 /preset id='roomDesc'/,
91 /style id="roomName"/,
92 /<spell exist='spell'>/,
93 %r{<spell>None</spell>},
94 /< .*/,
95 /<clearContainer/,
96 /<right/,
97 /<left/,
98 /<indicator id='IconINVISIBLE'/,
99 %r{<roundTime value='\d+'/>}
100 ]
101 @responses = ["'Hmmm?", "'Yes", "'Ok?"].shuffle
102 @recent_seen = []
103 @quit_on_flag = get_settings.quit_on_status_warning
104 @slackbot = slackbot
105 end
106
107 def clean_seen_with_filters
108 @seen_lines.reject! { |line, _| @filter_strings.find { |regex| line =~ regex } }
109 end
110
111 def save
112 base = {}
113 if File.exist?(@seen_cache_name)
114 base = Marshal.load(File.open(@seen_cache_name, 'rb'))
115 end
116 @seen_lines.merge!(base)
117 clean_seen_with_filters
118 File.open(@seen_cache_name, 'wb') { |file| Marshal.dump(@seen_lines, file) }
119 end
120
121 def migrate_recent
122 save_required = false
123 @recent_seen_lines.select { |_, timestamp| Time.now - timestamp > 60 }.each do |line, _|
124 save_required = true
125 @seen_lines[line] = true
126 @recent_seen_lines.delete(line)
127 end
128 save if save_required
129 end
130
131 def unseen?(line)
132 return nil if line.nil? || line.empty?
133 return nil if @filter_strings.find { |regex| line =~ regex }
134 return nil if @seen_lines[line]
135 spam_check(line)
136 return nil if @recent_seen_lines[line]
137 @recent_seen_lines[line] = Time.now
138 end
139
140 def find_pcs(room_players)
141 room_players.sub(/ and (.*)$/) { ", #{Regexp.last_match(1)}" }
142 .split(', ')
143 .map { |obj| obj.sub(/ who (has|is) .+/, '').sub(/ \(.+\)/, '') }
144 .map { |obj| obj.strip.scan(/\w+$/).first }
145 end
146
147 attr_reader :last_player_line
148
149 def update_players(line)
150 return unless line =~ %r{\'room players\'>Also here: (.*)\.</component>}
151
152 @last_player_line = line
153 @room_players += find_pcs(Regexp.last_match(1).dup)
154 @room_players.uniq!
155 end
156
157 def spam_check(line)
158 @recent_seen << line
159 @recent_seen = @recent_seen[1..10] if @recent_seen.length > 10
160 counts = @recent_seen.each_with_object(Hash.new(0)) { |phrase, count| count[phrase] += 1 }
161 return if counts.values.max < 5
162
163 echo("\a")
164 pause 0.25
165 echo("\a")
166 pause 0.25
167 echo("\a")
168 pause 0.25
169 command_check(line)
170 fput @responses.first
171 echo(counts.inspect)
172 @slackbot.direct_message(counts.inspect) if defined?(@slackbot)
173 fput('exit') if @quit_on_flag
174 @responses.rotate!
175 @spam_line = line
176 pause 2
177 @recent_seen = []
178 end
179
180 def command_check(line)
181 line.scan(/[A-Z]{3,}/)
182 .select { |item| @valid_commands.include?(item) }
183 .each do |prompt|
184 pause 3
185 fput(prompt)
186 pause 5
187 end
188 end
189
190 def clean(line)
191 update_players(line)
192 migrate_recent
193 return nil if line.nil? || line.empty? || @non_useful_tags.find { |bad_tag| bad_tag =~ line }
194 return nil if @room_players.find { |name| line.include?(name) } || UserVars.npcs.find { |name| line.include?(name) }
195 return nil if UserVars.players_online && UserVars.players_online.find { |name| line.include?(name) }
196 line.gsub!(/<[^>]+>/, '')
197 line
198 end
199end
200
201if get_settings['slack_username']
202 custom_require.call('slackbot')
203 slackbot = SlackBot.new
204end
205
206def update_health_bar(entry)
207 hp = health
208 if hp >= 75
209 entry.modify_base(Gtk::STATE_NORMAL, Gdk::Color.parse('green'))
210 else
211 entry.modify_base(Gtk::STATE_NORMAL, Gdk::Color.parse('red'))
212 end
213 entry.text = "#{hp}%"
214end
215
216filter = GameFilter.new(slackbot)
217
218if nowindow
219 loop do
220 line = script.gets
221 back = line.dup if args.debug
222 if filter.unseen?(filter.clean(line))
223 if args.debug
224 open("status-monitor-debug-#{checkname}.txt", 'a') do |f|
225 f.puts(back)
226 f.puts(line)
227 f.puts(filter.last_player_line)
228 end
229 end
230 end
231 if filter.spam_line
232 filter.spam_line.dup
233 filter.spam_line = nil
234 end
235 end
236end
237
238unless HAVE_GTK
239 respond
240 respond 'error: ruby-gtk bindings are not installed or failed to load'
241 respond
242 exit
243end
244
245window = nil
246window_done = false
247load_window_position = CharSettings['window_position'] || []
248load_window_width = CharSettings['window_width'] || 300
249load_window_height = CharSettings['window_height'] || 100
250window_title = "#{checkname} Status"
251save_window_position = nil
252save_window_width = nil
253save_window_height = nil
254healthbar_et = nil
255messages_tv = nil
256
257before_dying do
258 CharSettings['window_position'] = save_window_position if (save_window_position.class == Array) && (save_window_position[0].to_i >= 0) && (save_window_position[1].to_i >= 0)
259 CharSettings['window_width'] = save_window_width if (save_window_width.class == Integer) && (save_window_width > 100)
260 CharSettings['window_height'] = save_window_height if (save_window_height.class == Integer) && (save_window_height > 100)
261 Gtk.queue { window.destroy }
262 filter.save
263end
264
265begin
266 Gtk.queue do
267 messages_tv = Gtk::TextView.new
268 messages_tv.editable = false
269 messages_tv.cursor_visible = false
270
271 messages_sw = Gtk::ScrolledWindow.new
272 messages_sw.add(messages_tv)
273 messages_sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
274
275 healthbar_et = Gtk::Entry.new
276 healthbar_et.editable = false
277 healthbar_et.xalign = 0.5
278 health_font = Pango::FontDescription.new
279 health_font.weight = Pango::FontDescription::WEIGHT_BOLD
280 healthbar_et.modify_font(health_font)
281
282 vbox = Gtk::VBox.new
283 vbox.pack_start(messages_sw)
284 vbox.pack_start(healthbar_et, false)
285
286 window = Gtk::Window.new
287 window.title = window_title
288 window.keep_above = true
289 window.border_width = 1
290 window.resize(load_window_width, load_window_height)
291 unless load_window_position.empty?
292 window.move(load_window_position[0], load_window_position[1])
293 end
294 window.add(vbox)
295
296 window.signal_connect('delete_event') do
297 save_window_position = window.position
298 save_window_width = window.allocation.width
299 save_window_height = window.allocation.height
300 window_done = true
301 end
302 window.show_all
303 end
304 prev_health = 0
305
306 loop do
307 line = script.gets?
308 back = line.dup if args.debug
309 if prev_health != health
310 prev_health = health
311 Gtk.queue { update_health_bar(healthbar_et) }
312 end
313 if filter.unseen?(filter.clean(line))
314 if args.debug
315 open("status-monitor-debug-#{checkname}.txt", 'a') do |f|
316 f.puts(back)
317 f.puts(line)
318 f.puts(filter.last_player_line)
319 end
320 end
321 # Gtk.queue do
322 # text_buffer = messages_tv.buffer
323 # text_buffer.insert(text_buffer.end_iter, line)
324 # text_buffer.insert(text_buffer.end_iter, "\r\n")
325 # messages_tv.scroll_to_iter(text_buffer.end_iter, 0.0, true, 0, 0)
326 # end
327 else
328 pause 0.1 unless back
329 end
330 if filter.spam_line
331 spam = filter.spam_line.dup
332 filter.spam_line = nil
333 Gtk.queue do
334 text_buffer = messages_tv.buffer
335 text_buffer.insert(text_buffer.end_iter, "spam:'#{spam}'")
336 text_buffer.insert(text_buffer.end_iter, "\r\n")
337 messages_tv.scroll_to_iter(text_buffer.end_iter, 0.0, true, 0, 0)
338 end
339 sendMail(spam, "Status Monitor Alert!")
340 #slackbot.direct_message(spam) if defined?(slackbot)
341 end
342 break if window_done
343 end
344end