Skip to content
This repository has been archived by the owner on Nov 9, 2020. It is now read-only.

Commit

Permalink
Add votes to util handler
Browse files Browse the repository at this point in the history
Also fix timers and reformat code
  • Loading branch information
max-m committed Aug 20, 2014
1 parent 4c42b91 commit a6873df
Showing 1 changed file with 154 additions and 41 deletions.
195 changes: 154 additions & 41 deletions handlers/util.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,174 @@ handlers = require '../handlers'
winston = require 'winston'
{ __, __n } = require '../i18n'

# This objects holds the currently running timers
timers = {}

# This objects holds the currently running votes
votes = {}

###
# Sorts an object by value
#
# @param {Object} obj The object being sorted.
# @param {String} order The sorting order “ASC” or “DESC”.
# @return {Array} A sorted containing objects of the form {key: 'ABC', value: 10} or an empty array on invalid input.
###
sortObject = (obj, order = 'DESC') ->
return [] unless typeof obj is 'object'

Object.keys(obj).sort (a, b) ->
if order is 'DESC'
if obj[a] > obj[b]
-1
else if obj[a] < obj[b]
1
else
0
else # 'ASC'
if obj[a] > obj[b]
1
else if obj[a] < obj[b]
-1
else
0
.map (key) ->
key: key,
value: obj[key]

handleMessage = (message, callback) ->
# Don't match our own messages
if message.sender is config.userID
callback?()
return

if message.message[0] is '!'
text = message.message[1..].split /\s/
[ command, parameters ] = [ text.shift(), text.join ' ' ]
# Messages for this handler must start with an exclamation mark
unless message.message[0] is '!'
callback?()
return

switch command
when 'ping'
date = new Date()
api.replyTo message, __("Pong! Message time: %1$s; My time: %2$d:%3$d:%4$d; Difference: %5$d seconds", message.formattedTime, date.getHours(), date.getMinutes(), date.getSeconds(), date.getTime() / 1000 - message.time), no, message.roomID, callback
when 'timer'
db.checkPermissionByMessage message, 'util.timer', (hasPermission) ->
if hasPermission
if timers[message.room]? and timers[message.room] is 'preparing'
api.replyTo message, __("There is already a timer being prepared."), no, callback
else if timers[message.room]?
api.replyTo message, __("There is already a timer running in this room."), no, callback
else
[ seconds ] = parameters.split /[, ]/
seconds = parseInt seconds

return callback()? unless seconds > 0

timers[message.room] = 'preparing' # prevent starting of multiple timers while waiting for “api.replyTo”
api.sendMessage __("Starting timer of %1$d seconds.", seconds), no, message.room, ->
timers[message.room] = setTimeout ->
delete timers[message.room]
api.sendMessage __("Time’s up!"), no, message.room, null
, seconds * 1e3

callback?()
else
text = message.message[1..].split /\s/
[ command, parameters ] = [ text.shift(), text.join ' ' ]

switch command
when 'ping'
date = new Date()
api.replyTo message, __("Pong! Message time: %1$s; My time: %2$d:%3$d:%4$d; Difference: %5$d seconds", message.formattedTime, date.getHours(), date.getMinutes(), date.getSeconds(), date.getTime() / 1000 - message.time), no, message.roomIDID, callback
when 'timer'
db.checkPermissionByMessage message, 'util.timer', (hasPermission) ->
unless hasPermission
callback?()
return

# Prevent starting of multiple timers while waiting for “api.replyTo”
if timers[message.roomID]? and timers[message.roomID] is 'preparing'
api.replyTo message, __("There is already a timer being prepared."), no, callback
else if timers[message.roomID]? # Just one concurrent timer is allowed per room
api.replyTo message, __("There is already a timer running in this room."), no, callback
else
[ seconds ] = parameters.split /[, ]/
seconds = parseInt seconds

# Default to 60 seconds on invalid input
seconds = 60 if isNaN(seconds) or seconds <= 0

timers[message.roomID] = 'preparing' # prevent starting of multiple timers while waiting for “api.replyTo”
api.sendMessage __("Starting timer of %1$d seconds.", seconds), no, message.roomID, ->
timers[message.roomID] = setTimeout ->
delete timers[message.roomID]
api.sendMessage __("Time’s up!"), no, message.roomID, null
, seconds * 1e3

callback?()
when 'cancelTimer'
db.checkPermissionByMessage message, 'util.cancelTimer', (hasPermission) ->
if hasPermission
if timers[message.room]? and timers[message.room] isnt 'preparing'
clearTimeout timers[message.room]
delete timers[message.room]
when 'cancelTimer'
db.checkPermissionByMessage message, 'util.cancelTimer', (hasPermission) ->
unless hasPermission
callback?()
return

if timers[message.roomID]? and timers[message.roomID] isnt 'preparing'
clearTimeout timers[message.roomID]
delete timers[message.roomID]

api.replyTo message, __("The timer running in this room has been canceled."), no, callback
else
api.replyTo message, __("There is no timer running in this room."), no, callback
when 'startVote'
db.checkPermissionByMessage message, 'util.startVote', (hasPermission) ->
unless hasPermission
callback?()
return

# Prevent starting of multiple votes while waiting for “api.replyTo”
if votes[message.roomID]? and votes[message.roomID].timeout is 'preparing'
api.replyTo message, __("There is already a vote being prepared."), no, callback
else if votes[message.roomID]? # Just one concurrent vote is allowed per room
api.replyTo message, __("There is already a vote running in this room."), no, callback
else
[ seconds ] = parameters.split /[, ]/
seconds = parseInt seconds

# Default to 60 seconds on invalid input
seconds = 60 if isNaN(seconds) or seconds <= 0

# Prepare the vote object
votes[message.roomID] =
timeout: 'preparing' # Prevent starting of multiple votes while waiting for “api.replyTo”
votes: {}
voters: []
timeoutFunction: null

# Start the vote after this message has been sent
api.sendMessage __("Starting vote (duration: %1$d seconds).", seconds), no, message.roomID, ->
# Define the “onTimeout” function (this is also used in “stopVote”)
votes[message.roomID].timeoutFunction = ->
clearTimeout votes[message.roomID].timeout
delete votes[message.roomID].timeout
delete votes[message.roomID].timeoutFunction

api.replyTo message, __("The timer running in this room has been canceled."), no, callback
else
api.replyTo message, __("There is no timer running in this room."), no, callback
else
result = ''
# Build a sorted list (DESC) of votes/values
for key, option of sortObject votes[message.roomID].votes
do (key, option) ->
result += "#{option.key}”: #{option.value}\n"

api.sendMessage __("Vote’s ended!\nResult:") + "\n" + result, no, message.roomID, null, ->
delete votes[message.roomID]

# Set the timeout and assign the previously defined function to it
votes[message.roomID].timeout = setTimeout votes[message.roomID].timeoutFunction, seconds * 1e3

callback?()
when 'vote'
option = parameters.trim().toLowerCase()

# Stop further processing of this “vote command” if no vote is running or the voter has already voted during the vote period
if not votes[message.roomID]? or option is '' or votes[message.roomID].voters[message.sender]?
callback?()
return

# Mark “voter” like “has voted during this vote”
votes[message.roomID].voters[message.sender] = true

# Unless the given vote option is known add it to the voted options
unless votes[message.roomID].votes[option]?
votes[message.roomID].votes[option] = 1
else
votes[message.roomID].votes[option]++

callback?()
when 'stopVote'
db.checkPermissionByMessage message, 'util.startVote', (hasPermission) ->
unless hasPermission
callback?()
return

# Run the “onTimeout” function of the currently running vote for this room
votes[message.roomID].timeoutFunction() if votes[message.roomID]?.timeoutFunction? and typeof votes[message.roomID].timeoutFunction is 'function'

callback?()
else
callback?()
else
callback?()

module.exports =
handleMessage: handleMessage
Expand Down

0 comments on commit a6873df

Please sign in to comment.