source: trunk/modules/events.tcl @ 1143

Revision 1141, 17.0 KB checked in by james, 4 weeks ago (diff)

Fix TCL 8.4 not supporting lsearch -nocase

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1# bMotion - Event handling
2#
3
4###############################################################################
5# bMotion - an 'AI' TCL script for eggdrops
6# Copyright (C) James Michael Seward 2000-2008
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21###############################################################################
22
23### bMotionDoEventResponse
24proc bMotionDoEventResponse { type nick host handle channel text } {
25#check our global toggle
26        global bMotionGlobal bMotionInfo bMotionDebug
27        if {$bMotionGlobal == 0} {
28                return 0
29        }
30
31        if [matchattr $handle J] {
32                return 0
33        }
34
35        set channel [string tolower $channel]
36
37        if {[lsearch $bMotionDebug $channel] > -1} {
38                set debug 1
39        } else {
40                set debug 0
41        }
42
43        #ignore other bots
44        if {[matchattr $handle b] && (![matchattr $handle I])} {
45                set bMotionCache($channel,last) 0
46                return 0
47        }
48
49        bMotion_putloglev 4 * "entering bMotionDoEventResponse: $type $nick $host $handle $channel $text"
50        if { ![regexp -nocase "nick|join|quit|part|split" $type] } {
51                return 0
52        }
53
54        global bMotionInfo
55        set response [bMotion_plugin_find_irc_event $text $type $bMotionInfo(language) $debug]
56        if {[llength $response] > 0} {
57                foreach callback $response {
58                        if {!$debug} {
59                                bMotion_putloglev 2 * "adding flood for callback $callback"
60                                bMotion_flood_add $nick $callback $text
61                                if [bMotion_flood_check $nick] { return 0 }
62                        }
63
64                        bMotion_putloglev 1 * "bMotion: matched irc event plugin, running callback $callback"
65                        set result [$callback $nick $host $handle $channel $text ]
66                        bMotion_putloglev 2 * "returned from callback $callback"
67                        if {$result == 1} {
68                                bMotion_putloglev 2 * "bMotion: $callback returned 1, breaking out..."
69                                break
70                        }
71                        return 1
72                }
73                return 0
74        }
75        return 0
76}
77
78### bMotion_event_onjoin
79proc bMotion_event_onjoin {nick host handle channel} {
80        #ignore me
81        if [isbotnick $nick] {
82                return 0
83        }
84
85        #ignore the J flag users
86        if [matchattr $handle J] {
87                return 0
88        }
89
90        #ignore bots without the I flag
91        if [matchattr $handle b-I] {
92                return 0
93        }
94
95        if {![channel get $channel bmotion]} {
96                return 0
97        }
98
99        set result [bMotionDoEventResponse "join" $nick $host $handle $channel ""]
100}
101
102### bMotion_event_onpart
103proc bMotion_event_onpart {nick host handle channel {msg ""}} {
104#check our global toggle
105        global bMotionGlobal
106        if {$bMotionGlobal == 0} {
107                return 0
108        }
109
110        # channel is missing when the bot itself is parting, so ignore itself
111        if [isbotnick $nick] {
112                return 0
113        } 
114
115        if {![channel get $channel bmotion]} {
116                return 0
117        }
118
119        bMotion_putloglev 3 * "entering bmotion_event_onpart: $nick $host $handle $channel $msg"
120
121        bMotion_plugins_settings_set "system" "lastleft" $channel "" $nick
122
123        #TODO: Fix this? Passing a cleaned nick around can break things
124        set nick [bMotion_cleanNick $nick $handle]
125
126        set result [bMotionDoEventResponse "part" $nick $host $handle $channel $msg]
127}
128
129### bMotion_event_onquit
130proc bMotion_event_onquit {nick host handle channel reason} {
131        global bMotionSettings bMotionInfo
132
133        #check our global toggle
134        global bMotionGlobal
135        if {$bMotionGlobal == 0} {
136                return 0
137        }
138
139        # channel is missing when the bot itself is quiting, so ignore itself
140        if [isbotnick $nick] {
141                return 0
142        } 
143
144        if {![channel get $channel bmotion]} {
145                return 0
146        }
147
148        set nick [bMotion_cleanNick $nick $handle]
149
150        bMotion_plugins_settings_set "system" "lastleft" $channel "" $nick
151
152        if {$bMotionInfo(brig) != ""} {
153        #check if that person was in the brig
154                regexp -nocase "(.+)@(.+)" $bMotionInfo(brig) pop brigNick brigChannel
155                if [string match -nocase $nick $brigNick] {
156                        set bMotionInfo(brig) ""
157                        bMotionDoAction $brigChannel "" "Curses! They escaped from the brig."
158                        return 0
159                }
160        }
161        set result [bMotionDoEventResponse "quit" $nick $host $handle $channel $reason ]
162}
163
164### bMotion_event_main
165proc bMotion_event_main {nick host handle channel text} {
166#check our global toggle
167        global bMotionGlobal bMotionPluginHistory
168        if {$bMotionGlobal == 0} {
169                return 0
170        }
171
172        ## Global definitions ##
173        global mood botnick
174        global bMotionLastEvent bMotionSettings botnicks bMotionCache bMotionInfo
175        global bMotionThisText bMotionOriginalInput bMotionOriginalNick
176
177        if [matchattr $handle J] {
178                return 0
179        }
180
181        set bMotionOriginalNick $nick
182
183        set channel [string tolower $channel]
184
185        #ignore other bots
186        if {[matchattr $handle b] && (![matchattr $handle I])} {
187                set bMotionCache($channel,last) 0
188                return 0
189        }
190
191        #make sure we're allowed to talk in here
192        if {![channel get $channel bmotion]} {
193                return 0
194        }
195
196        #don't trigger on !seen etc
197        if [regexp -nocase "^!(last)?seen" $text] {
198                return 0
199        }
200
201        #no bMotion plugin triggers on /^,/ so we can filter them out too
202        if [string match ",*" $text] {
203                return 0
204        }
205
206        bMotion_putloglev 4 * "bMotion: entering bMotion_event_main with nick: $nick host: $host handle: $handle chan: $channel text: $text"
207
208        bMotion_queue_dupecheck $text $channel
209
210        set bMotionOriginalInput $text
211
212        #filter bold, etc codes out
213        regsub -all "\002" $text "" text
214        regsub -all "\022" $text "" text
215        regsub -all "\037" $text "" text
216
217        # thanks, anonymous ticket poster (ticket #125)
218        regsub -all "\003\[0-9\]{0,2}(,\[0-9\]{1,2})?" $text "" text
219
220        #try stripcodes (eggdrop 1.6.17+)
221        catch {
222                set text [stripcodes bcruag $text]
223        }
224
225        bMotion_check_botnicks
226
227        #does this look like a paste?
228        if [regexp -nocase {^[([]?[0-9]{2}[-:.][0-9]{2}. ?[[<(]?[%@+]?[a-z0-9` ]+[@+%]?. \w+} $text] {
229                return 0
230        }
231
232        ## Update the channel idle tracker
233        set bMotionLastEvent($channel) [clock seconds]
234
235        #don't let people break us
236        if {![matchattr $handle n]} {
237                if [regexp -nocase "%(pronoun|me|noun|colen|percent|VAR|\\|)" $text] {
238                        regsub -all "%" $text "%percent" text
239                }
240        }
241        regsub -all "\</" $text "%slash" text
242
243        #If this isn't just a smiley of some kind, trim smilies
244        if {[string length $text] >= ([string length $botnick] + 4)} {
245                regsub -all -nocase {[;:=]-?[()d<>/sp9x]} $text "" text
246                regsub -all {([\-^])_*[\-^];*} $text "" text
247                regsub -all {\\o/} $text "" text
248        }
249
250        #Trim stuff
251        set text [string trim $text]
252
253        ## Dump double+ spaces
254        regsub -all "  +" $text " " text
255
256        ## Update the last-talked flag for the join system
257        bMotion_plugins_settings_set "system:join" "lasttalk" $channel "" 0
258
259        set bMotionThisText $text
260
261        global bMotionDebug
262        if {[lsearch $bMotionDebug $channel] > -1} {
263                set debug 1
264        } else {
265                set debug 0
266        }
267
268        #if we spoke last, add "$botnick: " if it's not in the line
269        if {![regexp -nocase $botnicks $text] && ([bMotion_did_i_speak_last $channel] || ([bMotion_setting_get "bitlbee"] == "1"))} {
270                if [regexp {^[^:]+:.+} $text] {
271                #since our nick isn't in the line and they're addressing someone, drop this line
272                        return 0
273                }
274                set text "${botnick}: $text"
275        }
276
277        if {[bMotion_setting_get "bitlbee"] == "1"} {
278                bMotion_putloglev d * "bitlbee incoming from $nick: $text"
279        }
280
281        #check for someone breaking the loop of lastSpoke
282        if {[regexp -nocase "(i'm not talking to|not) you" $text] && [bMotion_did_i_speak_last $channel]} {
283                bMotionDoAction $channel $nick "oh"
284                set bMotionCache($channel,last) 0
285                return 0
286        }
287        set bMotionCache($channel,last) 0
288
289        #Run the simple plugins
290        set response [bMotion_plugin_find_simple $text $bMotionInfo(language) $debug]
291        if {$response != ""} {
292                if {!$debug} {
293                        bMotion_flood_add $nick "" $text
294                        if [bMotion_flood_check $nick] { return 0 }
295                        if [bMotion_flood_check $channel] { return 0 }
296                        bMotion_flood_add $channel "" $text
297                }
298                set nick [bMotionGetRealName $nick $host]
299                bMotionDoAction $channel $nick [pickRandom $response]
300                return 0
301        }
302
303        #Run the complex plugins
304        set response [bMotion_plugin_find_complex $text $bMotionInfo(language) $debug]
305        if {[llength $response] > 0} {
306        #set nick [bMotionGetRealName $nick $host]
307                if {!$debug && [bMotion_flood_check $channel]} { return 0 }
308                bMotion_putloglev 1 * "going to run plugins: $response"
309                foreach callback $response {
310                        if (!$debug) {
311                                bMotion_putloglev 1 * "bMotion: doing flood for $callback..."
312                                if [bMotion_flood_check $nick] { return 0 }
313                        }
314
315                        bMotion_putloglev 1 * "bMotion: `- running callback $callback"
316                        set result 0
317                        set result [$callback $nick $host $handle $channel $text]
318                        bMotion_putloglev 2 * "returned from $callback"
319                        set bMotionCache(lastPlugin) $callback
320                        bMotion_plugin_history_add $channel "complex" $callback
321
322                        #plugins should return 1 if they trigger, and 2 if they trigger without output
323                        # (i.e. return 2 to not increment flood)
324                        # they should return 0 if they don't trigger
325
326                        if {$result > 0} {
327                                if {!$debug && ($result == 1)} {
328                                        bMotion_putloglev 1 * "adding flood counters"
329                                        bMotion_flood_add $nick $callback $text
330                                        bMotion_flood_add $channel $callback $text
331                                }
332                                bMotion_putloglev 2 * "bMotion:          `-$callback returned $result, breaking out..."
333                                break
334                        }
335                }
336        }
337
338        #Check for all caps
339        regsub -all {[^A-Za-z]} $text "" textChars
340        regsub -all {[a-z]} $textChars "" textLowerChars
341        if {(([string length $textChars] > 4) && ([expr [string length $textLowerChars] / [string length $textChars]] > 0.9)) ||
342                 [regexp ".+!{4,}" $text]} {
343                global blownAways
344                if {[rand 60] >= 55} {
345                        bMotionDoAction $channel $nick "%VAR{blownAways}"
346                        return 0
347                }
348        }
349
350        #Reload config files
351        #TODO: move this into a plugin?
352        if [regexp -nocase "${botnicks},?:? re(hash|load)( your config files?)?" $text] {
353        #putlog "bMotion: $nick asked me to rehash in $channel"
354                global bMotion_testing bMotionRoot
355
356                if [matchattr $handle m] {
357                #check we're not going to die
358                catch {
359                bMotion_putloglev d * "bMotion: Testing new code..."
360                set bMotion_testing 1
361                source "$bMotionRoot/bMotion.tcl"
362                } msg
363
364                if {$msg != ""} {
365                        putlog "bMotion: FATAL: Cannot rehash due to error: $msg"
366                        putserv "NOTICE $nick :FATAL: Cannot rehash: $msg"
367                        putchan $channel "A tremendous error occurred!"
368                        return 0
369                } else {
370                        bMotion_putloglev d * "bMotion: New code ok, rehashing..."
371                        bMotion_plugins_settings_set "system" "rehash" "" "" $channel
372                        set bMotion_testing 0
373                        if {[matchattr $handle m]} {
374                                putchan $channel [bMotion_abstract_get "rehashes"]
375                                rehash
376                                return 0
377                        }
378                }
379                } else {
380                #don't respond here because there's no flood protection
381                        return 0
382                }
383        }
384
385        #tell the names we have
386        #TODO: move this into a plugin?
387        if [regexp -nocase "${botnicks}:?,? (say my names?|what'?s my name)" $text] {
388                if {($handle == "*") || ($handle == "")}        {
389                #no handle = no saving IRL
390                        set lastnick [bMotion_plugins_settings_get "events" "last_irl_fail" $channel ""]
391                        if {$lastnick == $nick} {
392                                bMotion_putloglev d * "Ignoring 'say my names' from $nick because they've asked twice in a row"
393                                return 0
394                        }
395                        bMotion_plugins_settings_set "events" "last_irl_fail" $channel "" $nick
396                        bMotionDoAction $channel $nick "%%: Sorry, you aren't in my userfile so I can't store an IRL name for you."
397                        return 0
398                }
399
400                set realnames [getuser $handle XTRA irl]
401                if {$realnames == ""} {
402                        bMotionDoAction $channel $nick "Ah, you must be %%. (You have not set any IRL names.)" "" 1
403                } else {
404                        bMotionDoAction $channel $nick "Your IRL name(s) are:\002 %2 \002" $realnames 1
405                }
406                puthelp "NOTICE $nick :To update your IRL names, do \002/msg $botnick IRL name1 name2 name3 ...\002"
407                return 0
408        }
409
410        #shut up
411        #TODO: move this into a plugin?
412        if [regexp -nocase "^${botnicks}:?,? (silence|shut up|be quiet|go away)" $text] {
413                driftFriendship $nick -10
414                bMotionSilence $nick $host $channel
415                return 0
416        }
417
418        if [regexp -nocase "(silence|shut up|be quiet|go away),?;? ${botnicks}" $text] {
419                driftFriendship $nick -10
420                bMotionSilence $nick $host $channel
421                return 0
422        }
423
424        #catch actions in stars
425        #This is the clever bit. If the text is "*blah blah blah*" reinject it into bMotion as an action ##
426        if [regexp {^\*(.+)\*$} $text blah action] {
427                bMotion_putloglev 1 * "Unhandled *$action* by $nick in $channel... redirecting to action handler"
428                bMotion_event_action $nick $host $handle $channel "" $action
429                return 0
430        }
431}
432
433### bMotion_event_action
434proc bMotion_event_action {nick host handle dest keyword text} {
435
436#check our global toggle
437        global bMotionGlobal
438        if {$bMotionGlobal == 0} {
439                return 0
440        }
441
442        global botnick mood rarrs smiles unsmiles botnicks bMotionCache bMotionSettings bMotionInfo
443        set dest [channame2dname $dest]
444        set channel $dest
445
446        if [matchattr $handle J] {
447                return 0
448        }
449
450        #ignore other bots
451        if {[matchattr $handle b]} {
452                return 0
453        }
454
455        if {![channel get $channel bmotion]} {
456                return 0
457        }
458
459        bMotion_putloglev 4 * "bMotion: entering bMotion_event_action with $nick $host $handle $dest $keyword $text"
460
461        set nick [bMotion_cleanNick $nick $handle]
462        set channel [string tolower $channel]
463
464        #Trim
465        set text [string trim $text]
466
467        ## Dump double+ spaces ##
468        regsub -all "  +" $text " " text
469
470        #ignore lines with <nobotnick> tags
471        if [regexp -nocase "\</?no$botnicks\>" $text] {return 0}
472        if [regexp -nocase "\<no$botnicks\>" $text] {return 0}
473
474        bMotion_check_botnicks
475
476        global bMotionDebug
477        if {[lsearch $bMotionDebug $channel] > -1} {
478                set debug 1
479        } else {
480                set debug 0
481        }
482
483        #Run the simple plugins
484        set response [bMotion_plugin_find_action_simple $text $bMotionInfo(language) $debug]
485        if {$response != ""} {
486                if (!$debug) {
487                        bMotion_flood_add $nick "" $text
488                        if [bMotion_flood_check $nick] { return 0 }
489                        if [bMotion_flood_check $channel] { return - }
490                        bMotion_flood_add $channel "" $text
491                }
492                bMotion_putloglev 1 * "bMotion: matched simple action plugin, outputting $response..."
493                set nick [bMotionGetRealName $nick $host]
494                bMotionDoAction $channel $nick [pickRandom $response]
495                return 0
496        }
497
498        #Run the complex plugins
499        set response [bMotion_plugin_find_action_complex $text $bMotionInfo(language) $debug]
500        if {[llength $response] > 0} {
501        #set nick [bMotionGetRealName $nick $host]
502                if {!$debug && [bMotion_flood_check $channel]} { return 0 }
503                bMotion_putloglev 1 * "going to run action plugins: $response"
504                foreach callback $response {
505                        if (!$debug) {
506                                bMotion_putloglev 1 * "bMotion: doing flood for $callback..."
507                                if [bMotion_flood_check $nick] { return 0 }
508                        }
509                        bMotion_putloglev 1 * "bMotion: matched complex action plugin, running callback $callback"
510                        set result 0
511                        set result [$callback $nick $host $handle $channel $text]
512                        if {$result > 0} {
513                                if {(!$debug) && ($result == 1)} {
514                                        bMotion_flood_add $nick $callback $text
515                                        bMotion_flood_add $channel $callback $text
516                                }
517                                bMotion_putloglev 2 * "bMotion:          `-$callback returned $result, breaking out..."
518                                break
519                        }
520                }
521                return 0
522        }
523}
524
525### bMotion_event_mode
526proc bMotion_event_mode {nick host handle channel mode victim} {
527#check our global toggle
528        global bMotionGlobal
529        if {$bMotionGlobal == 0} {
530                return 0
531        }
532
533        if {![channel get $channel bmotion]} {
534                return 0
535        }
536
537        bMotion_putloglev 4 * "bMotion: entering bMotion_event_mode with $nick $host $handle $channel $mode $victim"
538
539        global botnick
540        if {$victim != $botnick} {return 0}
541
542        if {$mode == "+o"} {
543                if {$nick == ""} {
544                        return 0
545                }
546
547                #check to see if i was opped before
548                if [wasop $botnick $channel] { return 0 }
549
550                set deoptime [bMotion_plugins_settings_get "system" "deoptime" $channel ""]
551                set diff 901
552                if {$deoptime != ""} {
553                        set diff [expr [clock seconds] - $deoptime]
554                }
555                if {$diff > 900} {
556                        if [bMotion_interbot_is_bmotion $handle] {
557                                bMotionDoAction $channel $nick "%VAR{thanks}"
558                                bMotionDoAction $channel $nick "%BOT[@$handle,VAR{welcomes}"
559                        } else {
560                                bMotionDoAction $channel $nick "%VAR{opped}"
561                        }
562                } else {
563                        bMotion_putloglev d * "Not responding to +o in $channel as I was only deopped $diff seconds ago"
564                }
565                bMotion_plugins_settings_set "system" "optime" $channel "" [clock seconds]
566                return 0
567        }
568
569        if {$mode == "-o"} {
570                if {![wasop $botnick $channel]} {
571                        return 0
572                }
573
574                # stop this spamming so much; won't do anything unless we were opped > 15mins ago
575                set optime [bMotion_plugins_settings_get "system" "optime" $channel ""]
576                set diff 901
577                if {$optime != ""} {
578                        set diff [expr [clock seconds] - $optime]
579                }
580                if {$diff > 900} {
581                        bMotionDoAction $channel $nick "%VAR{deopped}"
582                } else {
583                        bMotion_putloglev d * "Not responding to -o in $channel as I was only opped $diff seconds ago"
584                }
585                bMotion_plugins_settings_set "system" "deoptime" $channel "" [clock seconds]
586                return 0
587        }
588
589        #removed voice stuff because there is no "wasvoice" function
590
591}
592
593### bMotion_event_nick
594proc bMotion_event_nick { nick host handle channel newnick } {
595
596#check our global toggle
597        global bMotionGlobal
598        if {$bMotionGlobal == 0} {
599                return 0
600        }
601
602        if {![channel get $channel bmotion]} {
603                return 0
604        }
605
606        if [matchattr $handle J] {
607                return 0
608        }
609
610        set nick [bMotion_cleanNick $nick $handle]
611        set newnick [bMotion_cleanNick $newnick $handle]
612
613        set result [bMotionDoEventResponse "nick" $nick $host $handle $channel $newnick ]
614}
615
616bMotion_putloglev d * "bMotion: events module loaded"
Note: See TracBrowser for help on using the repository browser.