Skip to content

Instantly share code, notes, and snippets.

@mwalling
Created January 21, 2012 16:08
Show Gist options
  • Save mwalling/1653168 to your computer and use it in GitHub Desktop.
Save mwalling/1653168 to your computer and use it in GitHub Desktop.
require 'cinch'
class Vote
class VoteStruct < Struct.new(:who, :score)
def to_s
"#{who} voted #{score}"
end
end
class ChannelConfig < Struct.new(:time_window, :voters, :votes_cast, :voting_closes, :sent_warning)
end
def initialize(*args)
super
@base_channel = "#marks-being-a-tool"
@configs = {}
end
include Cinch::Plugin
listen_to :channel
match /join (#.+)/, method: :join_channel
match /part (#.+)/, method: :part_channel
match /voters? add (.+)/, method: :add_voter
match /voters? list/, method: :list_voters
match /voters? (rm|del|remove|delete) (.+)/, method: :remove_voter
match /voters? clear/, method: :clear_voters
match /voters? register/, method: :register_voter
match /vote (yes|no|abstain)/, method: :vote
match /vote start/, method: :start_vote
match /vote status/, method: :vote_status
match /vote close/, method: :manual_close_voting
timer 1, method: :time_check
def join_channel(m, arg)
if m.channel == @base_channel
Channel(arg).join
@configs[arg] = ChannelConfig.new(30, [], {}, nil, false)
end
end
def part_channel(m, arg)
if m.channel == @base_channel
Channel(arg).part
@configs.delete(arg)
end
end
def time_check
@configs.each do |channel, config|
if not config.voting_closes.nil?
now = Time.now.to_i
if (config.voting_closes - 10) < now and not config.sent_warning
config.sent_warning = true
slackers = Array.new(config.voters)
slackers.keep_if{|n| not config.votes_cast.has_key?(n)}
nicks = slackers.join(", ")
Channel(channel).send "#{nicks}: Voting closes in 10 seconds!"
elsif config.voting_closes < now
Channel(channel).send "Times up!"
close_voting(channel)
elsif config.voters.length == config.votes_cast.length
Channel(channel).send "All votes are in!"
close_voting(channel)
end
end
end
end
def register_voter(m)
add_voter(m, m.user.nick)
end
def add_voter(m, arg)
@configs[m.channel].voters << arg
m.reply "Adding #{arg} as a voter"
end
def list_voters(m)
m.reply "Voters: #{@configs[m.channel].voters.join(", ")}"
end
def remove_voter(m, cmd, arg)
removed = @configs[m.channel].voters.delete(arg)
if removed.nil?
m.reply "Did not find #{arg} in the voter list"
else
m.reply "Removing #{removed} as a voter"
end
end
def clear_voters(m)
@configs[channel].voters.clear
m.reply "Voter list cleared"
end
def vote(m, arg)
arg.downcase!
if arg == "yes"
score = 1
elsif arg == "no"
score = -1
elsif arg == "abstain"
score = 0
else
m.reply "#{m.user.nick}: Unknown vote, say 'yes', 'no', or 'abstain'"
return
end
@configs[m.channel].votes_cast[m.user.nick] = VoteStruct.new(m.user.nick, score)
m.reply "#{m.user.nick}: Vote recorded."
end
def start_vote(m)
config = @configs[m.channel]
if config.voters.length == 0
m.reply "No voters registered, no voting"
return
end
config.sent_warning = false
config.votes_cast = {}
config.voting_closes = Time.now.to_i + config.time_window
m.reply "Voting opened! Vote with 'yes', 'no' or 'abstain'. Voting closes in #{config.time_window} seconds."
end
def manual_close_voting(m)
close_voting(m.channel)
end
def close_voting(channel)
config = @configs[channel]
config.voting_closes = nil
yes = 0
no = 0
config.votes_cast.values.each do |vote|
if vote.score > 0
yes += 1
elsif vote.score < 0
no += 1
end
end
nicks = config.votes_cast.keys.join(", ")
Channel(channel).send("Results: #{yes} yes, #{no} no. Votes cast by #{nicks}")
end
end
###
bot = Cinch::Bot.new do
configure do |c|
c.nick = 'votebot'
c.server = "irc.oftc.net"
c.channels = ["#marks-being-a-tool"]
c.verbose = true
c.plugins.plugins = [Vote]
c.ssl.use = true
c.ssl.client_cert = 'nick.pem'
c.port = 6697
end
end
bot.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment