All pastes #497397 Raw Edit

Something

public text v1 · immutable
·published 2007-05-19 20:43 UTC
rendered paste body
##
#
# alice.tcl v1.2.0 - by strikelight ([sL] @ EFNet) (September 16, 2002)
#
# - Read the README.TXT for script details, help, and contact info.
#
##

#### CONFIGURATION ####

## File to save alice cookies to ##
set alice_cookiesfile "$nick.cookies"

## Every night, expire cookies that have not been accessed in how many days? ##
set alice_cookiesexpire 5

## Let your bot respond to private messages? (0 = No, 1 = Yes) ##
set alice_respondpriv 1

## Let your bot respond to comments in channel when bot's name is mentioned? ##
# (0 = No, 1 = Yes) [ For eggdrop versions less than 1.5.x
# ( 1.5.x+ users should use .chanset #channel +alice ) ]
set alice_respondchan 1

## Require bot's nick to be in all lines of a public conversation in order
# for it to respond, after initial contact? (ie. <someone> alice: hello there)
# (if alice_respondchan is set to 1, or channel is set to +alice, else ignore this)
# (0 = No, 1 = Yes)
set alice_respondrequirenick 1

## Respond with user's nick? (ie. <alice> user: Hi, how are you?)
# (if alice_respondchan is set to 1, or channel is set to +alice, else ignore this)
# (0 = No, 1 = Yes)
set alice_respondwithnick 1

## Channels to listen on (if alice_respondchan is set to 1, else ignore this) ##
# (Separate multiple channels by space, use * to indicate all channels)
# [ For eggdrop versions less than 1.5.x only , 1.5.x+ users should
#   use .chanset #channel +alice ]
# eg. set alice_channels "#channel1 #channel2 #etc"  .. or :
set alice_channels "#linuxtalk #mswindows"

## Also if alice_respondchan is set to 1 or channel is set to +alice,
# (otherwise ignore this), how long a silence should the bot wait for
# user's text in a channel after the first contact is made before
# giving up on their conversation? (in minutes)
set alice_timeoutchat 5

## Log conversations?
# 0 = No
# 1 = Yes
set alice_logging 0

## If logging on, what directory should the logs be stored in?
# (Note1: If directory doesn't exist, you must create it)
# (Note2: Ignore this if you don't want to log)
set alice_log_path "logs/"

## Which server should I use for the alice engine?
# 0 = www.alicebot.org (Alice)
# 1 = www.agentruby.com (Ruby)
# 2 = a program E server (Phillip)
# 3 = jaczone.com (Cyber-Ivar)
# 4 = neodave.civ.pl (Hippie)
# 5 = your own program-D alice server
# 6 = Actual Hippie Program-C
# 7 = Actual Hippie Program-C 
# 8 = your own pandorabots engine (www.pandorabots.com) 
# 9 = A runabot.com AOL Instant Messenger bot (www.runabot.com) 
set alice_engine 9

# If using your own alice server (program-D), enter the url here:
#set alice_url "http://yourserver.here.com:2001/"

# If using your own actual Hippie Program-C, set path here:
#set alice_hippie_path "/home/user/eggdrop/C/command_alice"

# If using your own actual Hippie Program-C, set path to ini file here:
#set alice_hippie_inipath "/home/user/eggdrop/C/data/alice.ini"

# If using your own actual Hippie Program-C, set path to log info here:
#set alice_hippie_logpath "/home/user/eggdrop/C/log/"

#### END OF CONFIGURATION (STOP EDITTING HERE!!) ####

if {[info exists egghttp(version)]} {
  regsub -all "\\." $egghttp(version) "" egghttpnumvers 
}
if {($alice_engine < 6) && (![info exists egghttp(version)] || ($egghttpnumvers < 103))} {
  putlog "alice.tcl : Could not load alice.tcl, egghttp.tcl 1.0.3 or greater is required."
  putlog "alice.tcl : You may download it from http://www.TCLScript.com"
  catch {unset alice_url}
  catch {unset alice_timeoutchat}
  catch {unset alice_channels}
  catch {unset alice_respondchan}
  catch {unset alice_respondrequirenick}
  catch {unset alice_respondwithnick}
  catch {unset alice_respondpriv}
  catch {unset alice_cookiesexpire}
  catch {unset alice_cookiesfile}
  catch {unset alice_engine}
  catch {unset alice_logging}
  catch {unset alice_hippie_path}
  catch {unset alice_hippie_inipath}
  catch {unset alice_hippie_logpath}
} elseif {($alice_engine == 6) && (![info exists bgexec(version)])} {
  putlog "alice.tcl : Could not load alice.tcl, bgexec.tcl is required."
  putlog "alice.tcl : You may download it from http://www.TCLScript.com"
  catch {unset alice_url}
  catch {unset alice_timeoutchat}
  catch {unset alice_channels}
  catch {unset alice_respondchan}
  catch {unset alice_respondrequirenick}
  catch {unset alice_respondwithnick}
  catch {unset alice_respondpriv}
  catch {unset alice_cookiesexpire}
  catch {unset alice_cookiesfile}
  catch {unset alice_engine}
  catch {unset alice_logging}
  catch {unset alice_hippie_path}
  catch {unset alice_hippie_inipath}
  catch {unset alice_hippie_logpath}
} elseif {$alice_engine == -1} {
  putlog "alice.tcl : You have not fully configured your Alice.tcl script."
  putlog "alice.tcl : Please edit the configuration, and then restart."
  putlog "alice.tcl : alice.tcl has NOT been loaded."
} else {
  set alice_version "1.2.0"
  set alice_chanflag [catch {setudef flag alice}]
  switch $alice_engine {
    0 {
      set alice_url "http://alice.sunlitsurf.com:2009/a.l.i.c.e./"
      set alice_input "text"
      set alice_cookie_method 0
      set alice_query_method 0
    }
    1 {
      set alice_url "http://www.agentruby.com:2001/"
      set alice_input "text"
      set alice_cookie_method 0
      set alice_query_method 0
    }
    2 {
      set alice_url "http://217.6.247.139/alicebot/src/talk.php"
      set alice_input "input"
      set alice_cookie_method 0
      set alice_query_method 0
    }
    3 {
      set alice_url "http://213.67.11.109/"
      set alice_input "text"
      set alice_cookie_method 0
      set alice_query_method 0
    }
    4 {
      set alice_url "http://neodave.civ.pl/hippie/hippie.cgi"
      set alice_input "text"
      set alice_cookie_method 1
      set alice_query_method 1
    }
    5 {
      set alice_url $alice_url
      set alice_input "text"
      set alice_cookie_method 0
      set alice_query_method 0
    }
    6 {
      set alice_url ""
    }
    default {
      set alice_url "http://alice.sunlitsurf.com:2009/a.l.i.c.e./"
      set alice_input "text"
      set alice_cookie_method 0
      set alice_query_method 0
    }
  }

# MISC PROCS

## strip_html : remove text that begins with <, ends with >, and everything in between
  proc strip_html {text} {
    regsub -all ">" $text \x81 text
    regsub -all "<\[^\x81\]*\x81" $text {} text
    regsub -all "&nbsp;" $text " " text
    regsub -all "&amp;" $text {\&} text
    regsub -all "&quot;" $text "\'" text
    regsub -all "&copy;" $text "(c)" text
    regsub -all "&#" $text "#" text
    regsub -all "&lt;" $text "<" text
    regsub -all "&gt;" $text ">" text
    regsub -all "%20" $text " " text
    return $text
  }

## lstring_remove : remove all elements from a list that contain the matching remove pattern
  proc lstring_remove {list remove} {
    set newlist ""
    foreach item $list {
      if {![string match "*[string tolower $remove]*" [string tolower $item]]} {
        lappend newlist $item
      }
    }
    return $newlist
  }

## nearestindex : return the string index where char occurs in text, nearest to
#                 a specified index
  proc nearestindex {text index {char " "}} {
    set tchar [string index $text $index]
    while {($tchar != $char) && ($index >= 0)} {
      incr index -1
      set tchar [string index $text $index]
    }
    return $index
  }

## istoldquiet : check to see if the text says for the bot to be quiet
  proc istoldquiet {text} {
    set exprs {shush {be *quiet} bye cya ttyl {talk* later} {i* leav} {got* go} {shut *up} shutup {leave me *alone} {go away} quiet shh}
    foreach item $exprs {
      if {[string match "*$item*" [string tolower $text]]} { return 1 }
    }
    return 0
  }

# Alice Formatting Procs

## alice:corrections : replace any occurances of the alice name with the bot's name instead
#                      also fix misc. html codes to plain text
  proc alice:corrections {text} {
    global nick
    regsub -all -- "alice" $text "$nick" text
    regsub -all -- "Alice" $text "$nick" text
    regsub -all -- "ALICE" $text "$nick" text
    regsub -all -- "A.L.I.C.E." $text "$nick" text
    regsub -all -- "A.L.I.C.E" $text "$nick" text
    regsub -all -- "a.l.i.c.e." $text "$nick" text
    regsub -all -- "a.l.i.c.e" $text "$nick" text
    regsub -all -- "ruby" $text "$nick" text
    regsub -all -- "Ruby" $text "$nick" text
    regsub -all -- "sofia" $text "$nick" text
    regsub -all -- "Sofia" $text "$nick" text
    regsub -all -- "testbot" $text "$nick" text
    regsub -all -- "TestBot" $text "$nick" text
    regsub -all -- "ivar" $text "$nick" text
    regsub -all -- "Ivar" $text "$nick" text
    regsub -all -- "[format %c 9]" $text "" text
    regsub -all -- "parent.noAnswer=1;" $text "" text
    regsub -all -- "charNoAnswer \\(\\);" $text "" text
    regsub -all -- "charSpeak\\(\"" $text "" text
    regsub -all -- "\"\\);" $text "" text
    return $text
  }

## alice:fixquery : replace all spaces with "%20" or "+" depending on query_method
# first line of this proc by Wcc (thanks mate) (27/6/02)
  proc alice:fixquery {text} {
    regsub -all -- {\002|\037|\026|\017|\003([0-9][0-9]?(,[0-9][0-9]?)?)?|||([0-9][0-9]?(,[0-9][0-9]?)?)?|} $text "" text
    global alice_query_method
    if {$alice_query_method == 0} {
      regsub -all -- " " $text "%20" text
    } elseif {$alice_query_method == 1} {
      regsub -all -- " " $text "+" text
    }
    return $text
  }

# Alice Logging Procs

## alice:logdata : save data to logfile
  proc alice:logdata {where who what} {
    global alice_logging alice_log_path
    if {!$alice_logging} { return 0 }
    set file "${where}.alice.log"
    regsub -all -nocase \\| $file _ file
    if {[catch {set outfile [open "${alice_log_path}${file}" a+]}]} {
      return 0
    }
    set dtime [clock format [clock seconds] -format "\[(%m.%d.%y) %H:%M\]"]
    puts $outfile "$dtime <$who> $what"
    close $outfile
    return 1
  }

# Alice Cookie Procs

## alice:getcookies : return the saved cookie for a person
#                     (cookies are used so that alice remembers the person)
  proc alice:getcookies {who} {
    global alice_cookies
    set who [string tolower $who]
    if {![info exists alice_cookies($who,data)]} {
      return ""
    }
    return $alice_cookies($who,data)
  }

## alice:setcookies : store a cookie for a person
  proc alice:setcookies {who cookies} {
    global alice_cookies
    set who [string tolower $who]
    set ocookies [alice:getcookies $who]
    if {($ocookies != "") && ([llength [split $cookies]] == 2)} {
      set ncookies ""
      foreach ck $ocookies {
        if {[string match "*jsessionid*" $ck]} {
          if {[string index $ck [expr [string length $ck] - 1]] != ";"} {
            append ck ";"
          }
          append ncookies "$ck "
        }
      }
      append ncookies $cookies
      set cookies $ncookies
    } elseif {($ocookies != "") && ([llength [split $cookies]] == 1)} {
      set ncookies ""
      foreach ck $ocookies {
        if {[string match "*alicebot_*" $ck]} {
          if {[string index $ck [expr [string length $ck] - 1]] != ";"} {
            append ck ";"
          }
          append ncookies "$ck "
        }
      }
      append ncookies $cookies
      set cookies $ncookies
    }
    set alice_cookies($who,data) "$cookies"
    set alice_cookies($who,time) "[clock seconds]"
    return 1
  }

## alice:savecookies : save cookies to file
  proc alice:savecookies {} {
    global alice_cookiesfile alice_cookies
    set outfile [open "$alice_cookiesfile" w]
    puts $outfile [list array set alice_cookies [array get alice_cookies]]
    close $outfile
    return 1
  }

## alice:loadcookies : load cookies from file
  proc alice:loadcookies {} {
    global alice_cookiesfile alice_cookies
    catch {unset alice_cookies}
    source $alice_cookiesfile
  }

## alice:expirecookies : remove old cookies
  proc alice:expirecookies {} {
    global alice_cookies alice_cookiesexpire
    set seconds [expr $alice_cookiesexpire * 24 * 60 * 60]
    foreach cookie [array names alice_cookies *,time] {
      if {[expr [clock seconds] - $alice_cookies($cookie)] >= $seconds} {
        set who [lindex [split $cookie ","] 0]
        catch {unset alice_cookies($who,time)}
        catch {unset alice_cookies($who,data)}
      }
    }
  }

## alice:time_cookie : call the expire cookies procedure
  bind time - "16 * * * *" alice:time_cookie
  proc alice:time_cookie {mi ho da mo yr} {
    putloglev o * "ALICE: Expiring old alice cookies ..."
    alice:expirecookies
    putloglev o * "ALICE: Saving alice cookie data ..."
    alice:savecookies
  }

# Alice Connection Procs

## alice:query : send user's text to the alice engine on the web to wait for a reply
  proc alice:query {who where text} {
    global alice_url alice_input alice_cookie_method alice_engine
    global alice_hippie_path alice_hippie_inipath alice_hippie_logpath
    if {$alice_engine == 6} {
      if {[catch {bgexec "$alice_hippie_path -i $alice_hippie_inipath -u ${alice_hippie_logpath}${who} \"$text\"" [list alice:execresponse $who $where]} err]} {
        putlog "alice.tcl : Error executing hippie command program. ($err) Did you install it?"
      }
      return -1
    }
    set text [alice:fixquery $text]
    set cookies [alice:getcookies $who]
    if {$cookies != ""} {
      if {$alice_cookie_method == 0} {
        set sock [egghttp:geturl $alice_url [list alice:response $who $where] -query $alice_input=$text -headers "Cookie: $cookies"]
      } elseif {$alice_cookie_method == 1} {
        set sock [egghttp:geturl $alice_url [list alice:response $who $where] -query $alice_input=$text&$cookies]
      }
      alice:setcookies $who "$cookies"
    } else {
      if {$alice_cookie_method == 0} {
        set sock [egghttp:geturl $alice_url [list alice:response $who $where] -query $alice_input=$text]
      } elseif {$alice_cookie_method == 1} {
        if {$alice_engine == 4} {
          set cookies "&virtual=none"
        }
        set sock [egghttp:geturl $alice_url [list alice:response $who $where] -query $alice_input=${text}${cookies}]
      }
    }
    return $sock
  }

## alice:response : parse alice's response and show the user
  proc alice:response {who where sock} {
    global alice_engine alice_respondwithnick botnick
    set headers [egghttp:headers $sock]
    set data [egghttp:data $sock]
    set response ""
    if {([egghttp:errormsg $sock] != "Ok") || ($data == "")} {
      catch {alice:timeoutchat $who $where}
      egghttp:cleanup $sock
      return
    }
    egghttp:cleanup $sock
    set cookies ""
    foreach line [split $headers "\n"] {
      if {[string match "*Set-Cookie:*" $line]} {
        set what [lindex [split $line " "] 1]
        if {$alice_engine != 4} {
          if {[string match "*Expires*" $what]} {
            set what [string range $what 0 [expr [string first "Expires" $what] - 2]]
          }
          if {[string match "*Path*" $what]} {
            set what [string range $what 0 [expr [string first "Path" $what] - 2]]
          }
        }
        if {($alice_engine == 4) && ([string match "*VIR=*" $what])} {
          set what [string range $what [expr [string first "VIR=" $what] + 4] [expr [string first $what ";"] - 1]]
          set what "virtual=$what"
        }          
        if {$what != ""} {
          append cookies "; $what"
        }
      }
    }
    set cookies [string range $cookies 2 end]
    if {$cookies != ""} {
      alice:setcookies $who "$cookies"
    }
    set a 0
    foreach line [split $data "\n"] {
      # programE specific instructions
      if {$alice_engine == 2} {
        if {[string match "*#FFFFFF*" $line]} {
          incr a
        }
        if {($a >= 1) && ([string match "*#ffff66*" $line])} {
          set apos [expr [string last "#ffff66" $line] + 9]
          set response [string range $line $apos [string length $line]]
        } elseif {($a >= 1)} {
          append response [string trim $line]
        }
        if {($a >= 1) && ([string match "*</tr>*" $line])} {
          break
        }
        continue
      }
      # hippie cgi specific instructions
      if {$alice_engine == 4} {
        if {[string match "*Hippie said*" $line]} {
          incr a
          set line [string range $line [expr [string first "said:" $line] + 5] end]
        }
        if {($a >= 1) && (![string match "*\"http://neodave*" $line])} {
          append response [string trim $line]
        }
        if {[string match "*\"http://neodave*" $line]} {
          break
        }
        continue
      }
      if {($a >= 1) && ![string match "*</p>*" $line]} {
        append response [string trim $line]
      }
      if {($a >= 1) && ([string match "*</p>*" $line] || [string match "*check_return()*" $line] || [string match "*</form>*" $line] || [string match "*jaczone.com*" $line])} {
        break
      }
      if {[string match "*response-line*" $line] || [string match "*\"botresponse\"*" $line] || ([string match "*offline for maint*" $line] && ($alice_engine != 3)) \
       || [string match "*</td></td></tr><tr><td align=center>*" $line] || [string match "*Perhaps that*" $line]} {
        incr a
      }
    }
    if {$response != ""} {
      set response [strip_html $response]
      set response [alice:corrections $response]
      set response [string trimleft $response "\}"]
      set response [string trim $response]
      if {[string length $response] >= 256} {
        while {($response != "") && ([string length $response] >= 256)} {
          set tmp [nearestindex "$response" 256]
          if {$tmp != -1} {
            set text [string range $response 0 [expr $tmp - 1]]
            set response [string range $response [expr $tmp + 1] end]
          } else {
            set text [string range $response 0 256]
            set response [string range $response 257 end]
          }
          if {[validchan $where] && $alice_respondwithnick} {
            set text "$who: $text"
          }
          alice:logdata "$where" "$botnick" "$text"
          puthelp "PRIVMSG $where :$text"
        }
      }
      if {$response != ""} {
        if {[validchan $where] && $alice_respondwithnick} {
          set response "$who: $response"
        }
        alice:logdata "$where" "$botnick" "$response"
        puthelp "PRIVMSG $where :$response"
      }
    }
  }

## alice:execresponse : parse alice's response and show the user
  proc alice:execresponse {who where data} {
    global alice_engine alice_respondwithnick botnick
    set response ""
    foreach line [split $data "\n"] {
      append response [string trim $line]
    }
    if {$response != ""} {
      set response [strip_html $response]
      set response [alice:corrections $response]
      set response [string trimleft $response "\}"]
      set response [string trim $response]
      if {[string length $response] >= 256} {
        while {($response != "") && ([string length $response] >= 256)} {
          set tmp [nearestindex "$response" 256]
          if {$tmp != -1} {
            set text [string range $response 0 [expr $tmp - 1]]
            set response [string range $response [expr $tmp + 1] end]
          } else {
            set text [string range $response 0 256]
            set response [string range $response 257 end]
          }
          if {[validchan $where] && $alice_respondwithnick} {
            set text "$who: $text"
          }
          alice:logdata "$where" "$botnick" "$text"
          puthelp "PRIVMSG $where :$text"
        }
      }
      if {$response != ""} {
        if {[validchan $where] && $alice_respondwithnick} {
          set response "$who: $response"
        }
        alice:logdata "$where" "$botnick" "$response"
        puthelp "PRIVMSG $where :$response"
      }
    }
  }

  proc alice:timeoutchat {who where} {
    global alice_chat
    catch {unset alice_chat($who,$where)}
  }

# Alice Chat Binding Procs

  if {$alice_respondpriv} {
    bind msgm - * alice:msg_query
    proc alice:msg_query {nick uhost hand text} {
      global botnick
      if {([string tolower $nick] == [string tolower $botnick]) || ([matchattr $hand b])} {
        return
      }
      # let's not bother looking at passwords and stuff ... -sL (6/13/02)
      if {[regexp pass|op|invite|ident|addhost [string tolower [lindex [split $text] 0]]]} {
        set text ""
        return 0
      }
      set where "[string tolower $nick]"
      if {($hand != "") && ($hand != "*")} {
        set who "[string tolower $hand]"
      } else {
        set who "[string tolower $nick]"
      }
      alice:logdata $where $who "$text"
      alice:query $who $where "$text"
      return 0
    }
  }
  
  if {($alice_respondchan) || (!$alice_chanflag)} {

    proc alice:isrespondchan {chan} {
      global alice_chanflag alice_channels
      if {!$alice_chanflag} {
        if {[lsearch -exact [channel info $chan] +alice] != -1} {
          return 1
        } else {
          return 0
        }
      } else {
        if {($alice_channels == "*") || ([lsearch [split [string tolower $alice_channels]] $chan] != -1)} {
          return 1
        } else {
          return 0
        }
      }
    }

    bind pubm - * alice:pub_query
    proc alice:pub_query {nick uhost hand chan text} {
      global botnick alice_channels alice_timeoutchat alice_chat alice_respondrequirenick
      if {([string tolower $nick] == [string tolower $botnick]) || ([matchattr $hand b])} {
        return
      }
      set chan [string tolower $chan]
      if {![alice:isrespondchan $chan]} {
        return
      }
      set where "$chan"
      if {($hand != "") && ($hand != "*")} {
        set who "[string tolower $hand]"
      } else {
        set who "[string tolower $nick]"
      }
      if {(![string match "*[string tolower $botnick]*" [string tolower $text]]) && (![info exists alice_chat($who,$chan)])} {
        return
      }
      if {(![string match "*[string tolower $botnick]*" [string tolower $text]] && $alice_respondrequirenick)} {
        return
      }
      if {![info exists alice_chat($who,$chan)]} {
        set alice_chat($who,$chan) [utimer [expr $alice_timeoutchat * 60] "alice:timeoutchat $who $chan"]
      } else {
        catch {killutimer $alice_chat($who,$chan)}
        set alice_chat($who,$chan) [utimer [expr $alice_timeoutchat * 60] "alice:timeoutchat $who $chan"]
      }
      if {[istoldquiet $text]} {
        alice:timeoutchat $who $where
      }
      set text [join [lstring_remove [split $text] $botnick]]
      alice:logdata $where $who "$text"
      alice:query $who $where "$text"
    }
  }

## create cookies file if it doesn't exist
  if {![file exists $alice_cookiesfile]} {
    set outfile [open $alice_cookiesfile w]
    close $outfile
    catch {unset outfile}
  }

## load cookies file
  alice:loadcookies
  putlog "alice.tcl $alice_version by strikelight is now loaded."
}