# #W5Net Op-Voter v1 (PUBLIC) release.
# pathos@ns2.clever.net 
# DATE: 07 DEC 1996
# TOOLKIT.TCL Required!
#
# This was written specifically for the bots/chans in W5Net to vote on who
# should get ops, automagically add the user, and if the creator so chooses,
# to auto-op the prospect after a successful election. This tcl also uses notes
# to let whoever know what's going on, and is configurable to your needs.
# **READ THE README**                    -= pAth0s =-
                                            #W5Net

#### BEGIN MODIFIABLE STUFF ####
# file for prospects and accesses are kept. (users votes kept in userfile) 
set votefl "text/vote"

# Channel for this tcl to be active.  MUST be #channel
set chn "#texasnet"

# Username on the bot to send user-submitted names to be added as prospect
set submit "pAth0s"

# Username on the bot to send all messages about validations or removals
set vop "pAth0s"

# Notify the above nick when a botuser is created via VOTE ADD? 0=no 1=yes
set noteadd "1"

# flag required for VOTE ADD and VOTE REMOVE command
set addlvl "m"

# default flag for prospect
set defflag "+p"

# On/off switch for the prospect voicer (+v prospects on join) 0=no 1=yes
set vswitch "1"

# flag to use for the auto-voicer. Put a # in front of if vswitch is set to 0
set flag9 v

# Default flag(s) for validated op
set valop "+ox"

# Number of Yes Votes to validate op
set yesop "5"

# Number of No Votes to delete user
set noop "5"

# Path to vote result files. # this out if you dont wish to save results
set resfile "~/bot/text"

# Change the 'o' in the next 2 lines to whatever flag you wish to have access 
# to the .vote command.

bind dcc o vote dcc_vote
bind msg o vote msg_vote

######## END MODIFIABLE STUFF ########

# vote msg handler
proc msg_vote {nick uhost hand arg} {
  switch [string tolower [lindex $arg 0]] {
    "add"       {set r [vote_add $nick $hand  0 $arg]}
    "cast"      {set r [vote_cast $nick $hand 0 $arg]}
    "list"      {set r [vote_list $nick $hand 0 $arg]}
    "remove"    {set r [vote_remove $nick $hand 0 $arg]}
    "result"    {set r [vote_show $nick $hand 0 $arg]}
    "submit"    {set r [vote_submit $nick $hand 0 $arg]}
    "help"      {set r [vote_help $nick $hand 0 $arg]}
    default     {set r [vote_help $nick $hand 0 $arg]}
  }
  return $r
}

# vote dcc handler
proc dcc_vote {hand idx arg} {
  switch [string tolower [lindex $arg 0]] {
    "add"       {set r [vote_add "" $hand $idx $arg]}
    "cast"      {set r [vote_cast "" $hand $idx $arg]}
    "list"      {set r [vote_list "" $hand $idx $arg]}
    "remove"    {set r [vote_remove "" $hand $idx $arg]}
    "result"    {set r [vote_show "" $hand $idx $arg]}
    "submit"    {set r [vote_submit "" $hand $idx $arg]}
    "help"      {set r [vote_help "" $hand $idx $arg]}
    default     {set r [vote_help "" $hand $idx $arg]}
  }
  return $r
}

proc vote_help {nick hand idx arg} {
	global botnick
	if {[llength $arg] == 1} {
	  if {$idx == 0} {
	    putserv "NOTICE $nick :All commands are preceeded by: VOTE"
	    putserv "NOTICE $nick :================================================"
	    putserv "NOTICE $nick :ADD - Adds a prospect to vote on"
            putserv "NOTICE $nick :CAST - Cast a vote on a prospect"
            putserv "NOTICE $nick :LIST - List all prospects"
            putserv "NOTICE $nick :REMOVE - Removes a prospect"
	    putserv "NOTICE $nick :RESULT - See results of a vote"
	    putserv "NOTICE $nick :SUBMIT - Request the addition of a prospect"
	    putserv "NOTICE $nick :HELP <ADD|CAST> - See the syntax for ADD or CAST"

	  } {
	    putdcc $idx "All commands are preceeded by: VOTE"
	    putdcc $idx "================================================"
            putdcc $idx "ADD - Adds a prospect to vote on"
            putdcc $idx "CAST - Cast a vote on a prospect"
            putdcc $idx "LIST - List all prospects"
            putdcc $idx "REMOVE - Removes a prospect"
	    putdcc $idx "RESULT - See results of a vote"
	    putdcc $idx "SUBMIT - Request the addition of a prospect"
	    putdcc $idx "HELP <ADD|CAST> - See the syntax for ADD or CAST"
	  }
	return 0
	}
	set hlpcmd [lindex $arg 1]
	set hlpcmd [string tolower $hlpcmd]
	if {$hlpcmd == "add"} {
	  if {$idx == 0} {
	    putserv "NOTICE $nick :USAGE: /MSG $botnick VOTE ADD <prospect> <display> <auto>"
	    putserv "NOTICE $nick :This command adds a prospect to allow voting"
	    putserv "NOTICE $nick :If <display> is 1 then people can see who voted what"
	    putserv "NOTICE $nick :If <auto> is 1 then prospect will be auto validated and"
            putserv "NOTICE $nick :  must be in-channel when added to Op-Vote."
            putserv "NOTICE $nick :If <auto-delete> is 1 then prospect's bot acct will be deleted"
            putserv "NOTICE $nick :  if he fails Op-Vote."
	    putserv "NOTICE $nick :-------END-------"
	  } {
	    putdcc $idx "USAGE: /MSG $botnick VOTE ADD <prospect> <display> <auto-mode> <auto-delete>"
	    putdcc $idx "This command adds a prospect to allow voting"
	    putdcc $idx "If <display> is 1 then people can see who voted what"
	    putdcc $idx "If <auto-mode> is 1 then prospect will be auto validated and"
            putdcc $idx "  must be in-channel when added to Op-Vote."
            putdcc $idx "If <auto-delete> is 1 then prospect's bot acct will be deleted"
            putdcc $idx "  if he fails Op-Vote."
	    putdcc $idx "-------END-------"
	  }
	return 0
	}
	if {$hlpcmd == "cast"} {
	  if {$idx == 0} {
	    putserv "NOTICE $nick :USAGE: /MSG $botnick VOTE CAST <prospect> <yes|no>"
	    putserv "NOTICE $nick :to vote on <prospect>"
	    putserv "NOTICE $nick :the vote must be <yes or no>"
	    putserv "NOTICE $nick :-------END-------"
	  } {
	    putdcc $idx "USAGE: /MSG $botnick VOTE CAST <prospect> <yes|no>"
	    putdcc $idx "to vote on <prospect>"
	    putdcc $idx "the vote must be <yes or no>"
	    putdcc $idx "-------END-------"
	  }
	return 0
	}
        if {$idx == 0} {
          putserv "NOTICE $nick :Sorry no help on that..Try VOTE HELP"
        } {
	  putdcc $idx "Sorry no help on that...Try VOTE HELP"
        }
}	

proc vote_add {nick hand idx arg} {
global votefl addlvl chn noteadd defflag vop vswitch
	if {![matchattr $hand $addlvl]} {
         if {$idx == 0} {
	  putserv "NOTICE $nick :No access to ADD command"
 	 } {
	  putdcc $idx "No access to ADD command"
         }
	  return "!!$nick!! has no access to VOTE ADD"
     	}
	if {[llength $arg] < 5} {
         if {$idx == 0} {
	  putserv "NOTICE $nick :.vote add <prospect> <display 0|1> <auto 0|1> <auto-delete 0|1>"
 	 } {
	  putdcc $idx ".vote add <prospect> <display 0|1> <auto-mode 0|1> <auto-delete 0|1>"
         }
	  return 0
     	}
        set prspct [string tolower [lindex $arg 1]]
	set displ [lindex $arg 2]
	set auto_o [lindex $arg 3]
        set auto_d [lindex $arg 4]
        if {($displ != 1) &&  ($displ != 0)} {
          if {$idx == 0} {
            putserv "NOTICE $nick : display must be set to 1 or 0"
            return 0
          } {
            putdcc $idx "display must be set to 1 or 0"
            return 0
          }	
        }
        if {($auto_o != 1) &&  ($auto_o != 0)} {
          if {$idx == 0} {
            putserv "NOTICE $nick : <auto-mode> must be set to 1 or 0"
            return 0
          } {
            putdcc $idx "<auto-mode> must be set to 1 or 0"
            return 0
          }
        }	
        if {($auto_d != 1) &&  ($auto_d != 0)} {
          if {$idx == 0} {
            putserv "NOTICE $nick : <auto-delete> must be set to 1 or 0."
            return 0
          } {
            putdcc $idx "<auto-delete> must be set to 1 or 0."
            return 0
          }
        }
        if {($auto_d == 1) &&  ($auto_o != 1)} {
          if {$idx == 0} {
            putserv "NOTICE $nick : <auto-mode> must be set to 1 for auto-delete."
            return 0
          } {
            putdcc $idx "<auto-mode> must be set to 1 for auto-delete."
            return 0
          }
        }
        if {$auto_o == 1} {
          set tmph [lindex $prspct 0]
          if {[onchan $tmph $chn] == 0} {
            if {$idx == 0} {
              putserv "NOTICE $nick :OP-VOTE $prspct isn't here. Use <auto-mode> 0 instead"
              return 0
            } {
              putdcc $idx "OP-VOTE $prspct isn't here. Use <auto-mode> 0 instead"
              return 0
            }
          } { 
            append userhost $tmph "!" [getchanhost $tmph $chn]
            set hostmask [maskhost $userhost]
            set target [finduser $hostmask]
            if {$target != "*"} {
              if {$idx ==0} {
                putserv "NOTICE $nick :OP-VOTE Someone is already using: \"$hostmask\""
                return 0
              } {
                putdcc $idx "OP-VOTE Someone is already using: \"$hostmask\""
                return 0
              }
            }
            set valid [validuser $prspct] 
            if {[adduser $tmph $hostmask] == 0} {
              if {$idx == 0} {
                putserv "NOTICE $nick :OP-VOTE \"$prspct\" is already a user!"
                return 0
              } {
                putdcc $idx "OP-VOTE \"$prspct\" is already a user!"
                return 0
              }
            } {
              chattr $tmph -omnpxfbsa0123456789
              chattr $tmph $defflag
              if {$vswitch == 1} {
                chattr $tmph +v
              }
            }
          }
        } {
          set valid [validuser $prspct]
          if {$valid == 1} {
            if {$idx == 0} {
              putserv "NOTICE $nick :$prspct is already a valid user."
              return 0
            } {
              putdcc $idx "$prspct is already a already a valid user."
              return 0
            }            
          }
        }
        set found 0
        exec touch $votefl
 	set fd [open $votefl r]
        while {![eof $fd]} {
          set inp [gets $fd]
          if {[eof $fd]} {
            break
          }
          if {[lsearch -exact $inp $prspct] != -1} {
            set found 1
 	  }
        }
        close $fd
	if {$found == 0} {
          set vote [open $votefl a]
          puts $vote "$prspct $displ $auto_o $auto_d"
          close $vote
        } {
          if {$idx == 0} {
            putserv "NOTICE $nick :$prspct is already a prospect."
            return 0
          } {
            putdcc $idx "$prspct is already a prospect."
            return 0
          }
        }
        putlog "#$hand# OP-VOTE: ADD $prspct"
        if {$noteadd == 1} {
          if {$auto_o == 1} {
            sendnote "OP-VOTE" $vop "Prospect \"$prspct\" added to the Op-Vote with flags:\"$defflag\" and hostmask: $hostmask"
          } {
            sendnote "OP-VOTE" $vop "Prospect \"$prspct\" has been added to the Op-Vote."
          }
          if {$idx == 0} {
            putserv "NOTICE $nick :$prspct is now a prospect."
            return 0
          } {
            putdcc $idx "$prspct is now a prospect."
            return 0
          }
        } {
          if {$idx == 0} {
            putserv "NOTICE $nick :$prspct is now a prospect."
            return 0
          } {
            putdcc $idx "$prspct is now a prospect."
            return 0
          }
        }
}

proc vote_cast {nick hand idx arg} {
global votefl valop vop yesop noop resfile vswitch
        set nukevote "0"
	if {[llength $arg] < 3} {
	  if {$idx == 0} {
 	    putserv "NOTICE $nick :Usage .VOTE CAST <prospect> <yes|no>"
	  } {
	    putdcc $idx "Usage .VOTE CAST <prospect> <yes|no>"
	  }
	  return 0
	}
	set prspct [string tolower [lindex $arg 1]]
	set uvote [string tolower [lindex $arg 2]]
        if {($uvote != "yes") && ($uvote != "no")} {
	  if {$idx == 0} {
 	    putserv "NOTICE $nick :Vote MUST be YES or NO!"
	  } { 
	    putdcc $idx "Vote MUST be YES or NO!"
	  }
	  return 0
	}
	set cvote [user-get $hand vote]
	set found 0
 	set fd [open $votefl r]
        while {![eof $fd]} {
         set inp [gets $fd]
          if {[eof $fd]} {break}
          if {[lsearch -exact $inp $prspct] != -1} {
           set found 1
           break
 	  }
        }
        close $fd
	if {!($found)} { 
	    if {$idx == 0} {
 	      putserv "NOTICE $nick :No such prospect"
	    } {
	      putdcc $idx "No such prospect"
	    }
	  return 0
	}
        set prspct [lindex $inp 0]
	set displ [lindex $inp 1]
	set auto_o [lindex $inp 2]	
        set auto_d [lindex $inp 3]
        if {[lsearch -exact $cvote $prspct] == -1} {
          if {$idx == 0} {
            putserv "NOTICE $nick :your vote has been recorded"
          } {
            putdcc $idx "your vote has been recorded"
          }
          user-set $hand vote "$prspct $uvote $cvote"
        } {
          if {$idx == 0} {
            putserv "NOTICE $nick :You can't vote twice"
          } {
            putdcc $idx "You can't vote twice"
          }
        }
        set cnt 0 ; set ycnt 0 ; set ncnt 0
        foreach usr [userlist] {
          set uvote [user-get $usr vote]
          set ridx [lsearch -exact $uvote $prspct]
          if {$ridx != -1} {
            set vidx [expr $ridx + 1]
	    set cast [lindex $uvote $vidx]
            if {$cast == "yes"} {incr ycnt} {incr ncnt}
            incr cnt
          }
        }
        putlog "#$hand# OP-VOTE: Vote $prspct ..."
        if {$ycnt >= $yesop} {
          if {$auto_o == 1} {
            chattr $prspct $valop
            if {$vswitch == 1} {
              chattr $prspct -v
            }
            save
            sendnote OP-VOTE $vop "User $prspct has passed OP-Vote and has been auto-validated"
            sendnote ADMIN $prspct "Congatulations, $prspct You made it! You have been validated."
            putlog "OP-VOTE: $prspct passed Op-Vote and was autovalidated."
          } {
            sendnote OP-VOTE $vop "User $prspct passed the OP-Vote and needs to be validated."
            sendnote ADMIN $prspct "Congratulations, #prspct you made it! Wait for a master to upgrade your access."
            putlog "OP-VOTE: $prspct passed Op-Vote and should be validated."
            }        
          set nukevote 1
        }
        if {$ncnt >= $noop} {
          if {$auto_d == 1} {
            deluser $prspct
            sendnote OP-VOTE $vop "User $prspct failed OP-Vote and has been auto-deleted."
            putlog "OP-VOTE: User $prspct failed op-vote and was autodeleted"
            save
          } {
            chattr $prspct -v
            sendnote OP-VOTE #vop "User $prspct failed the Op-Vote, won't be voiced, and should be deleted"
            putlog "OP-VOTE: $prspct failed Op-Vote and should be deleted."
            }
          set nukevote 1
        }
        if {$nukevote == 1} {
          set utop [string tolower [lindex $prspct 0]]
          set vutop $utop
          set fd [open $votefl r]
          set td [open text/vote.tmp a]
          while {![eof $fd]} {
            set inp [gets $fd]
            if {[eof $fd]} {break}
            if {[lsearch -exact $inp $utop] != -1} {
	    continue
	    }
            puts $td $inp
          }
          close $fd
          close $td
          exec mv text/vote.tmp $votefl
          if {[info exists resfile]} {
            set vtres [open $resfile/$utop.vote a]
            puts $vtres "OP-VOTE Results for $utop"
            puts $vtres "-- User -------- Vote -----"
            set cnt 0 ; set ycnt 0 ; set ncnt 0
            foreach usr [userlist] {
              set pvote [user-get $usr vote]
	      set ridx [lsearch -exact $pvote $prspct]
              if {$ridx != -1} {
                set vidx [expr $ridx + 1]
	        set uivt [lindex $pvote $vidx]
	        if {$uivt == "yes"} {incr ycnt} {incr ncnt}
	        incr cnt
                puts $vtres " $usr  	$uivt" 
              }
            }
            puts $vtres "---------------------------" 
            puts $vtres " "
            puts $vtres " Total Votes: $cnt"
            puts $vtres " Yes: $ycnt	No: $ncnt"
            puts $vtres " "
            puts $vtres "--Op-Vote-v1--by--pAth0s---"
            close $vtres
          }
          set usr {}
          foreach usr [userlist] {
            set uvote [user-get $usr vote]
            if {[lsearch -exact $uvote $utop] != -1} {
              set uidx [lsearch -exact $uvote $utop] 
              set nvote [lreplace $uvote $uidx [expr $uidx + 1]]
              user-set $usr vote $nvote
            }
          }
        save
        return 0
        }
}

proc vote_show {nick hand idx arg} {
global votefl
	if {[llength $arg] < 2} {
	  if {$idx == 0} {
 	    putserv "NOTICE $nick :Usage .VOTE RESULT <prospect>"
	  } {
	    putdcc $idx "Usage .VOTE RESULT <prospect>"
	  }
	  return 0
	}
	set prspct [string tolower [lindex $arg 1]]
	set uvote [string tolower [lindex $arg 2]]
 	set fd [open $votefl r]
	set found 0
        while {![eof $fd]} {
         set inp [gets $fd]
          if {[eof $fd]} {break}
          if {[lsearch -exact $inp $prspct] != -1} {
           set found 1
           break
 	  }
        }
        close $fd
	if {!($found)} { 
	    if {$idx == 0} {
 	      putserv "NOTICE $nick :No such prospect"
	    } {
	      putdcc $idx "No such prospect"
	    }
	  return 0
	}
        set prspct [lindex $inp 0]
	set displ [lindex $inp 1]
	set auto_o [lindex $inp 2]
        set auto_d [lindex $inp 3]
	set cnt 0 ; set ycnt 0 ; set ncnt 0
	if {$displ == 0} {
        foreach usr [userlist] {
          set uvote [user-get $usr vote]
	  set ridx [lsearch -exact $uvote $prspct]
          if {$ridx != -1} {
            set vidx [expr $ridx + 1]
	    set cast [lindex $uvote $vidx]
	    if {$cast == "yes"} {incr ycnt} {incr ncnt}
	    incr cnt
          }
	}
	  if {$idx == 0} {
 	    putserv "NOTICE $nick :Voters are kept secret in this op-vote"
	    putserv "NOTICE $nick :Results for op-vote: $prspct"  
	    putserv "NOTICE $nick :$ycnt votes for YES"  
	    putserv "NOTICE $nick :$ncnt votes for NO"  
          } {
	    putdcc $idx "Voters are kept secret in this op-vote"
	    putdcc $idx "Results for op-vote: $prspct"  
	    putdcc $idx "$ycnt votes for YES"  
	    putdcc $idx "$ncnt votes for NO"  
	  }
	  putlog "#$hand# OP-VOTE: Result $prspct"
	  return 0
        }
	if {$displ == 1} {
        foreach usr [userlist] {
          set uvote [user-get $usr vote]
	  set ridx [lsearch -exact $uvote $prspct]
          if {$ridx != -1} {
            set vidx [expr $ridx + 1]
	    set cast [lindex $uvote $vidx]
	    if {$cast == "yes"} {incr ycnt} {incr ncnt}
	    incr cnt
            if {$idx == 0} {
	      putserv "NOTICE :$usr voted $cast"
            } {
              putdcc $idx "$usr voted $cast"
            }
          }
	}
	  if {$idx == 0} {
	    putserv "NOTICE $nick :Results for op-vote: $prspct"  
	    putserv "NOTICE $nick :$ycnt votes for YES"  
	    putserv "NOTICE $nick :$ncnt votes for NO"  
	    putserv "NOTICE $nick :Total votes: $cnt"
          } {
	    putdcc $idx "Results for op-vote: $prspct"  
	    putdcc $idx "$ycnt votes for YES"  
	    putdcc $idx "$ncnt votes for NO"  
	    putdcc $idx "Total votes: $cnt"
	  }
	  putlog "#$hand# OP-VOTE: Result $prspct"
	  return 0
          }
}


# vote submit
proc vote_submit {nick hand idx arg} {
global submit
   if {![info exists submit]} {
      if {$idx == 0} {
         putserv "NOTICE $nick :This feature has been disabled."
      } {
         putdcc $idx "This feature has been disabled."
      }
      return 0
   }
   if {[lindex $arg 1] == ""} {
      if {$idx == 0} {
         putserv "NOTICE $nick :Usage: VOTE SUBMIT <prospect>"
      } {
         putdcc $idx "Usage: VOTE SUBMIT <prospect>"
      }
      return 0
   }
   if {$hand == "*"} {
      set subfrom $nick
   } {
      set subfrom $hand
   }
   sendnote "SUBMIT" $submit "$subfrom submitted: [lrange $arg 1 end]"
   if {$idx == 0} {
      putserv "NOTICE $nick :Okay, submission sent, thanks."
   } {
      putdcc $idx "Okay, submission sent, thanks."
   }
   putlog "OP-VOTE: $hand submitted a prospect."
   return 0
}

proc vote_list {nick hand idx chan} {
global votefl
 	set fd [open $votefl r]
        while {![eof $fd]} {
         set inp [gets $fd]
          if {[eof $fd]} {
            if {$idx == 0} {
              putserv "NOTICE $nick :No more prospects."
            } { 
    	      putdcc $idx "No more prospects."
            }            
          break
          }
          set prspct [lindex $inp 0]
          set displ [lindex $inp 1]
	  set auto_o [lindex $inp 2]
	  set votes [user-get $hand vote]
          if {[lsearch -exact $votes $prspct] == -1} {
	    set stat "(No vote)"
	  } {
	    set stat "(YOU VOTED)"
	  }
          if {$idx == 0} {
            putserv "NOTICE $nick :$prspct $stat"
          } { 
    	    putdcc $idx "$prspct $stat"
          }
	}
        close $fd
}

proc vote_remove {nick hand idx arg} {
global votefl addlvl
	if {![matchattr $hand $addlvl]} {
         if {$idx == 0} {
	  putserv "NOTICE $nick :No access to REMOVE command"
 	 } {
	  putdcc $idx "No access to REMOVE command"
         }
          putlog "#$hand# OP-VOTE: Tried to REMOVE [lindex $arg 1] without access.
	  return 0
     	}
	if {[llength $arg] < 2} {
	  if {$idx == 0} {
 	    putserv "NOTICE $nick :Usage .VOTE REMOVE <prospect>"
	  } {
	    putdcc $idx "Usage .VOTE REMOVE <prospect>"
	  }
	  return 0
	}
	set utop [string tolower [lindex $arg 1]]
 	set fd [open $votefl r]
        set td [open text/vote.tmp a]
        while {![eof $fd]} {
          set inp [gets $fd]
          if {[eof $fd]} {break}
   	  if {[lsearch -exact $inp $utop] != -1} {
            if {$idx == 0} {
              putserv "NOTICE $nick :$utop has been removed"
            } { 
      	      putdcc $idx "$utop has been removed"
            }
          putlog "#$hand# OP-VOTE: $utop was removed."
	  continue
	  }
	puts $td $inp
	}
        close $fd
        close $td
	exec /bin/mv text/vote.tmp $votefl
        set usr {}
        foreach usr [userlist] {
          set uvote [user-get $usr vote]
            if {[lsearch -exact $uvote $utop] != -1} {
              set uidx [lsearch -glob $uvote $utop] 
              set nvote [lreplace $uvote $uidx [expr $uidx + 1]]
              user-set $usr vote $nvote
            }
        }
}
proc auto_vee {nick uhost handle chn}  {
global vswitch
  if {$vswitch == 1} {
    bind join v * auto_vee
    putserv "MODE $chn +v $nick"
  }
}

# DONE -If you understood all of that, you're sicker than I.
putlog "OP-VOTER v1(PUBLIC) loaded.   !!kAp0w!!"

