egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Alice v1.2.0 want run pandorabot

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Script Requests
View previous topic :: View next topic  
Author Message
majaschet
Voice


Joined: 14 Mar 2009
Posts: 2
Location: cambodia

PostPosted: Mon Mar 23, 2009 10:41 pm    Post subject: Alice v1.2.0 want run pandorabot Reply with quote

this is alice.tcl version 1.2.0 but it has not choose to run with www.pandorabots.com .. so i want to this version work with pandorabots.com
help fix for me Smile
this is coder default alice.tcl 1.2.0

Code:
##
#
# 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 "*"

## 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
set alice_engine -1

# 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."
}
Back to top
View user's profile Send private message Send e-mail Yahoo Messenger
Thanhas
Op


Joined: 02 Sep 2006
Posts: 124
Location: Ottawa, Canada

PostPosted: Sat Aug 29, 2009 7:09 am    Post subject: Reply with quote

hello
i been searching some TCL like this
but its truly not workin if somoene make it Work?
Back to top
View user's profile Send private message Yahoo Messenger MSN Messenger
Koach
Voice


Joined: 19 Apr 2009
Posts: 21

PostPosted: Tue Sep 01, 2009 10:49 am    Post subject: Reply with quote

try a google search for alice.tcl v1.4.0
I think that's the latest version.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Script Requests All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber