####################################################
# by wiebe @ QuakeNet
#
# adds these tcl commands:
# privmsg   cprivmsg   action   notice   cnotice   wallchops   wallvoices
#
# too long lines are broken up
####################################################

####################################################
# privmsg
#
# usage: privmsg <targets> <text> <queue> [<prefix>]
#
# example: privmsg #chan1,#chan2,nick1,nick2 "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc privmsg { d t q {p ""}} {
  if {[string equal $d ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set c "PRIVMSG"; set d [irc:targets $d]
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  foreach e $d { set o [irc:breakup $c $e $t $p]; foreach l $o { $q "$c $e :$l" } }
  return 1
}


####################################################
# cprivmsg
#
# usage: cprivmsg <nick> <text> <queue> [<prefix>]
#
# example: cprivmsg nick "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc cprivmsg { n t q {p ""}} {
  if {[string equal $n ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set m "CPRIVMSG"; set x 1
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  if {[string equal [info procs isupport] ""]} { set x [isupport cprivmsg] }
  if {[string equal $x "-1"]} { set x 0 }
  if {![onchan $n] || (![botisop] && ![botishalfop] && ![botisvoice]) || !$x} {
    privmsg $n $t $q $p; return 1
  }
  foreach c [channels] {
    if {[channel get $c inactive]} { continue }
    if {![botonchan $c]} { continue }
    if {![onchan $n $c]} { continue }
    if {![botisop $c] && ![botishalfop $c] && ![botisvoice $c]} { continue }
    set o [irc:breakup $m $n $t $p $c]; foreach l $o { $q "$m $n $c :$l" }; return 1
  }
  privmsg $n $t $q $p; return 1
}


####################################################
# action / ctcp action / me
#
# usage: action <targets> <text> <queue> [<prefix>]
#
# example: action #chan1,#chan2,nick1,nick2 "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc action { d t q {p ""}} {
  if {[string equal $d ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set d [irc:targets $d]
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  foreach e $d {
    set o [irc:breakup action $e $t $p]; foreach l $o { $q "PRIVMSG $e :\001ACTION $l\001" }
  }
  return 1
}


####################################################
# notice
#
# usage: notice <targets> <text> <queue> [<prefix>]
#
# example: notice #chan1,#chan2,nick1,nick2 "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc notice { d t q {p ""}} {
  if {[string equal $d ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set c "NOTICE"; set d [irc:targets $d]
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  foreach e $d { set o [irc:breakup $c $e $t $p]; foreach l $o { $q "$c $e :$l" } }
  return 1
}


####################################################
# cnotice
#
# usage: cnotice <nick> <text> <queue> [<prefix>]
#
# example: cnotice nick "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc cnotice { n t q {p ""}} {
  if {[string equal $n ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set m "CNOTICE"; set x 1
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  if {[string equal [info procs isupport] ""]} { set x [isupport cnotice] }
  if {[string equal $x "-1"]} { set x 0 }
  if {![onchan $n] || (![botisop] && ![botishalfop] && ![botisvoice]) || !$x} {
    notice $n $t $q $p; return 1
  }
  foreach c [channels] {
    if {[channel get $c inactive]} { continue }
    if {![botonchan $c]} { continue }
    if {![onchan $n $c]} { continue }
    if {![botisop $c] && ![botishalfop $c] && ![botisvoice $c]} { continue }
    set o [irc:breakup $m $n $t $p $c]; foreach l $o { $q "$m $n $c :$l" }; return 1
  }
  notice $n $t $q $p; return 1
}


####################################################
# wallchops
# sents notice to channel operators
#
# usage: wallchops <chan> <text> <queue> [<prefix>]
#
# example: wallchops #chan "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc wallchops { c t q {p ""}} {
  if {[string equal $c ""]} { return }
  if {[string equal $t ""]} { return }
  set q [string tolower $q]; set o [irc:breakup wallchops $c $t $p]
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  foreach l $o { $q "NOTICE @$c :$l" }
}


####################################################
# wallvoices
# sents notice to channel voices and operators
#
# usage: wallvoices <chan> <text> <queue> [<prefix>]
#
# example: wallvoices #chan "hello there .." puthelp
#
# too long lines are broken up,
# the extra lines are prefixed with the text given in <prefix>
####################################################
proc wallvoices { c t q {p ""}} {
  if {[string equal $c ""]} { return 0 }
  if {[string equal $t ""]} { return 0 }
  set q [string tolower $q]; set x "WALLVOICES"
  if {[string equal [lsearch -exact "puthelp putserv putquick" $q] -1]} { set q puthelp }
  if {[string equal [info procs isupport] ""]} { set x [isupport wallvoices] }
  if {[string equal $x "-1"]} { set x "NOTICE"; set c "+$c" }
  set o [irc:breakup $x $c $t $p]; foreach l $o { $q "$x $c :$l" }; return 1
}


####################################################
# irc:targets
#
# breakup targets
####################################################
proc irc:targets { d } {
  set z ""; set x ""
  foreach e [split $d ,] {
    if {[string length $e] > "200"} { continue }
    if {[string length $e] > "90"} { lappend x $z
    } elseif {[string length [join $z ,],$e] > "90"} { lappend x [join $z ,]; set z $e
    } else { lappend z $e }
  }
  if {![string equal $z ""]} { lappend x [join $z ,] }; return $x
}


####################################################
# irc:breakup
#
# breakup lines
####################################################
# break too long lines
proc irc:breakup { x d t p {c ""} } {
  global botname
  set a [string length "$x $d :"]; set e [irc:longest $d]
  set b [string length ":$botname $x $e :"]
  if {[string equal -nocase $x "cprivmsg"] || [string equal -nocase $x "cnotice"]} {
    incr a [string length "$c "]; incr b -1
  }
  if {[string equal -nocase $x "wallchops"]} { incr a -2 }
  if {[string equal -nocase $x "wallvoices"]} { incr b -1 }
  if {[string equal -nocase $x "action"]} { incr b 9; incr a 9 }
  set m $b; if {$a > $m} { set m $a }; set m [expr 510 - $m]; if {$m < 100} { return $t }
  if {[string length $t] <= $m} { lappend o $t; return $o }
  while {[string length $t] > $m} {
    set z 0; set y 0
    while {[string length [join [lrange [split $t] 0 [expr $z +1]]]] <= $m} {
      set y [string length [join [lrange [split $t] 0 $z]]]; incr z 1
    }
    if {$z > "1" && $y >= [expr $m * 80 / 100]} {
      lappend o [join [lrange [split $t] 0 [expr $z -1]]]
      set t $p[join [lrange [split $t] $z end]]
    } else { lappend o [string range $t 0 [expr $m -1]]; set t $p[string range $t $m end] }
  }
  if {![string equal $t ""]} { lappend o $t }; return $o
}


####################################################
# irc:longest
#
# returns the longest target
# needed to calculate the length of the line that is shown to the targets
####################################################
proc irc:longest { d } {
  set d [split $d ,]; set z "0"
  if {[string equal [llength $d] "1"]} { return [join $d] }
  foreach t $d { set l [string length $t]; if {$l < $z} { continue }; set z $l; set x $t }
  return $x
}


set scriptdb(irc) {
  "provides various commands for sending messages on IRC: privmsg cprivmsg action notice cnotice wallchops wallvoices. too long lines and targets are broken up, whatever this script is told to send over IRC, it will do it and reach its destination."
}

