Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/data/tcl/irk/examples/fortunebot.tcl @ 8011

Last change on this file since 8011 was 5781, checked in by rgrieder, 15 years ago

Reverted trunk again. We might want to find a way to delete these revisions again (x3n's changes are still available as diff in the commit mails).

  • Property svn:eol-style set to native
File size: 3.3 KB
Line 
1# fortunebot.tcl --
2#
3# Demo bot using the irc TCL client library. This is a VERY simple bot that
4# demonstrates some simple uses of the irc TCL library.
5#
6# The bot sits on any number of channels and networks. It periodically grabs
7# a fortune from a web site and sends the fortune with appropriate delays
8# between each line to all channels on all networks it is on.
9
10# Example use in Tcl:
11#
12# % source fortunebot.tcl
13# % set token [irc::connect ....]
14# % fortune::join $token #mychannel
15# % fortune::start 120
16#
17# What this does:
18# * Loads the bot, which in turn will load the IRC library and HTTP.
19# * Connect to IRC
20# * Send the bot to join #mychannel
21# * Start the bot, with 120 seconds delay. Now it'll do its actions every
22#   120 seconds.
23#
24# To stop the bot:
25#
26# % fortune::stop
27#
28# Make him leave a channel:
29#
30# % fortune::leave $token #mychannel
31
32package require irk
33package require http
34
35namespace eval fortune {
36    variable state
37
38    array set state {
39        linedelay               2000
40        fortuneurl              http://www.earth.com/fortune
41    }
42}
43
44# Bot control:
45
46proc ::fortune::start {{delay 60}} {
47    variable state
48
49    # Compute the delay in milliseconds:
50
51    set state(delay) [expr $delay * 1000]
52
53    # Schedule the bot to run each $delay milliseconds:
54
55    set state(after) [after $state(delay) [list ::fortune::doquote]]
56}
57
58proc ::fortune::stop {} {
59    variable state
60
61    # Stop the bot if its running:
62
63    if {[info exists state(after)]} {
64        after cancel $state(after)
65        unset state(after)
66    }
67}
68
69
70# This is the actual body of the bot:
71#
72# Grab a quote from a web page and post it to all channels we're on:
73
74proc ::fortune::doquote {} {
75    variable state
76
77    # Grab the quote. The command callback does all the work:
78
79    http::geturl $state(fortuneurl) -command ::fortune::httpdone
80
81    # Finally reschedule ourselves, after events are one-shots
82
83    set state(after) [after $state(delay) [list ::fortune::doquote]]
84}
85
86proc ::fortune::httpdone {http} {
87    variable state
88    upvar #0 $http response
89
90    # Scrape the fortune off of the page:
91
92    set fortune [grabfortune $response(body)]
93
94    # Discard the HTTP array:
95
96    unset response
97
98    # Check if the quote is too long. If it is then punt.
99
100    if {[llength $fortune] > 3} {
101        return
102    }
103
104    # Say this quote on all channels on all connections we're on:
105
106    foreach conn [irk::connections] {
107        tell $fortune $conn
108    }
109}
110
111# This procedure scrapes the quote off of an HTML page:
112
113proc ::fortune::grabfortune {body} {
114    set body [split $body "\n"]
115    set beg [lsearch $body <PRE>]
116    set end [lsearch $body </PRE>]
117    return [lrange $body [expr $beg+1] [expr $end-1]]
118}
119
120# This procedure sends the quote to all channels we want the bot to be on:
121
122proc ::fortune::tell {fort conn} {
123    variable state
124
125    # Send the fortune to each channel we're on:
126
127    foreach chan [irk::onchannels $conn] {
128        tellchan $fort $conn $chan
129    }
130}
131
132# Asynchronously send lines to the channel:
133
134proc ::fortune::tellchan {fort conn channel} {
135    variable state
136
137    # Check if we are still on the channel:
138
139    if {![irk::onchannel $conn $channel]} {
140        return
141    }
142
143    # OK we're still on this channel, so say the current line and schedule
144    # the next line for later:
145
146    if {[llength $fort] > 0} {
147        irk::say $conn $channel [lindex $fort 0]
148        after $state(linedelay) \
149            [list ::fortune::tellchan [lrange $fort 1 end] $conn $channel]
150    }
151}
Note: See TracBrowser for help on using the repository browser.