Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: data/trunk/Media/tcl8.5/irk/examples/mysaint.tcl @ 5180

Last change on this file since 5180 was 5180, checked in by dafrick, 16 years ago
File size: 6.9 KB
Line 
1# mysaint.tcl
2#
3# I got the inspiration to write this bot from the SmallSaints
4# bot on DalNet and the request of some Malay friends to create a clone.
5#
6# The bot sits on a channel and simply counts words that each user says.
7
8package require irk
9
10namespace eval ::mysaint {
11
12    variable state
13
14    set state(thisdir) [file dir [info script]]
15    set state(words,save) [file join $state(thisdir) savedwords.dat]
16    set state(save,interval) 30000
17
18    # For each identified user, there are several entries in the state array:
19    #
20    # state($user,words)        How many words they have total.
21    # state($user,session)      How many words they said this time.
22    # state($user,password)     What's their password
23    # state($user,ident)        What's their ident
24    #
25    # We also keep a mapping from nicknames to users:
26    #
27    # state($nick,user)         What's the user mask associated with this
28    #                           nick name
29
30    proc initialize {} {
31        variable state
32        variable thisdir
33
34        # Set up a timer to save words:
35
36        set state(saver) [after $state(save,interval) ::mysaint::save]
37
38        # See if we have a saved words file. If so, read it in.
39
40        if {[file exists $state(words,save)]} {
41            uplevel #0 source $state(words,save)
42        }
43    }
44
45    proc userSays {token nick user comm dest rest} {
46        if {[string match "!*" [lindex $rest 0]]} {
47            userSaysCommand $token $dest $nick $user \
48                    [lindex $rest 0] [lrange $rest 1 end]
49        } else {
50            userSaysWords $nick $user [llength $rest]
51        }
52    }
53
54    proc userSaysWords {nick user n} {
55        variable state
56
57        set seconds [clock seconds]
58        if {![info exists state($user,session,time)]} {
59            set state($user,session,time) [clock seconds]
60        }
61        set state($user,time) $seconds
62
63        if {![info exists state($user,session)]} {
64            set state($user,session) $n
65        } else {
66            incr state($user,session) $n
67        }
68        if {![info exists state($user,words)]} {
69            set state($user,words) $n
70        } else {
71            incr state($user,words) $n
72        }
73
74        set state($nick,user) $user
75    }
76
77    proc userSaysCommand {token dest nick user cmd rest} {
78        variable state
79
80        # Determine destination of any reply we're going to send:
81
82        if {![string compare $dest $state(nick)]} {
83            set dest $nick
84        }
85
86        switch -exact $cmd {
87            "!help"     {userAsksHelp $token $nick}
88            "!time"     {userAsksTime $token $nick $user $rest $dest}
89            "!heard"    {userAsksHeard $token $nick $user $rest $dest}
90            "!words"    {userAsksWords $token $nick $user $rest $dest}
91            "!donate"   {userDonates $token $nick $user $rest $dest}
92            "!pass"     {::irk::pass $token mysaint $nick $user $rest}
93            "!ident"    {::irk::id $token mysaint $nick $user $rest}
94            "!newpass"  {::irk::np $token mysaint $nick $user $rest}
95        }
96    }
97
98    proc userAsksHelp {token nick} {
99        ::irk::say $token $nick \
100                [list Hello $nick, the following commands are supported: ]
101        ::irk::say $token $nick "!help ---- prints this message"
102        ::irk::say $token $nick "!words --- how many words you have"
103        ::irk::say $token $nick "!donate -- to donate words to someone"
104        after 2000 [list ::irk::say $token $nick \
105                                "!heard --- when did some speak last time"]
106        after 2500 [list ::irk::say $token $nick \
107                                "!time ---- when someone connected"]
108        after 5000 [list ::irk::say $token $nick \
109                    "Note: To donate you have to have a password"]
110        after 7500 [list ::irk::say $token $nick \
111                    "Note: You can get a password with !pass"]
112    }
113
114    proc userAsksWords {token nick user rest dest} {
115        variable state
116
117        set target [lindex $rest 0]
118        if {[string compare $target ""]} {
119            if {[catch {set user $state($target,user)}]} {
120                set who "The unknown user $target"
121                set target "The unknown user $target"
122            } else {
123                set who $user
124            }
125        } else {
126            set who ""
127        }
128        if {[string compare $who ""]} {
129            if {[catch {set words $state($who,words)}]} {
130                set words 0
131            }
132            if {[catch {set session $state($who,session)}]} {
133                set session 0
134            }
135            set reply \
136                    "$nick, $target has $session words now, total $words words"
137        } else {
138            if {[catch {set words $state($user,words)}]} {
139                set words 0
140            }
141            if {[catch {set session $state($user,session)}]} {
142                set session 0
143            }
144            set reply \
145                    "$nick, you have $session words now, $words total words"
146        }
147        ::irk::say $token $dest $reply
148    }
149
150    proc userAsksHeard {token nick user rest dest} {
151        variable state
152
153        set target [lindex $rest 0]
154        if {[string compare $target ""]} {
155            if {[catch {set user $state($target,user)}]} {
156                set answer "I haven't heard $target speak recently."
157            } else {
158                set time $state($user,time)
159                set time [clock format $time]
160                set answer "I heard $target speak last at $time"
161            }
162        } else {
163            set answer "I'm talking to you just now, $nick"
164        }
165
166        ::irk::say $token $dest $answer
167    }
168
169    proc userAsksTime {token nick user rest dest} {
170        variable state
171
172        set target [lindex $rest 0]
173        if {[string compare $target ""]} {
174            if {[catch {set user $state($target,user)}]} {
175                set answer "I don't know when $target connected"
176            } else {
177                if {[catch {set time $state($user,session,time)}]} {
178                    set answer "I don't know when $target connected"
179                } else {
180                    set time [clock format $time]
181                    set answer \
182                            "I first noticed $target at $time"
183                }
184            }
185        } else {
186            if {[catch {set user $state($nick,user)}]} {
187                set answer "$nick, I don't know when you connected"
188            } else {
189                if {[catch {set time $state($user,session,time)}]} {
190                    set answer "$nick, I don't know when you connected"
191                } else {
192                    set time [clock format $time]
193                    set answer \
194                            "$nick, I first noticed you at $time"
195                }
196            }
197        }
198
199        ::irk::say $token $dest $answer
200    }
201
202    # Start the bot:
203
204    proc start {token} {
205        variable state
206
207        set state($token,token) $token
208
209        set symsrv $::irk::state($token,symsrv)
210        set state(nick) $::irk::state(-$symsrv,nick)
211        set nick $state(nick)
212
213        foreach chan [::irk::onchannels $token] {
214            ::irk::setaction2 $token PRIVMSG $chan ::mysaint::userSays
215        }
216        ::irk::setaction2 $token PRIVMSG $nick ::mysaint::userSays
217
218        # Set up a timer to save the words info.
219
220        if {![info exists state(saver)]} {
221            initialize
222        }
223
224        return ""
225    }
226
227    # Stop the bot:
228
229    proc stop {} {
230        variable state
231
232        foreach conn [array names state *,token] {
233            stopcon $state($conn)
234        }
235
236        after cancel $state(saver)
237        catch {unset state(saver)}
238
239        return ""
240    }
241    proc stopcon {token} {
242        variable state
243
244        if {[catch {set symsrv $::irk::state($token,symsrv)}]} {
245            return
246        }
247        set nick $state(nick)
248
249        foreach chan [::irk::onchannels $token] {
250            ::irk::remaction2 $token PRIVMSG $chan ::mysaint::userSays
251        }
252        ::irk::remaction2 $token PRIVMSG $nick ::mysaint::userSays
253
254        return ""
255    }
256
257    # Save words to a disk file:
258
259    proc save {} {
260        variable state
261
262        puts "Saving words in $state(words,save)"
263
264        # First of all reschedule ourselves:
265
266        set state(saver) [after $state(save,interval) ::mysaint::save]
267
268        # Save the words:
269
270        set pt "*,words"
271        if {![catch {set fd [open $state(words,save) w]}]} {
272            puts $fd "array set ::mysaint::state [list [array get state $pt]]"
273
274            catch {close $fd}
275        }
276    }   
277}
Note: See TracBrowser for help on using the repository browser.