Skip to content

Instantly share code, notes, and snippets.

@Eibwen
Last active July 8, 2020 15:24
Show Gist options
  • Save Eibwen/c9b072dc67999f3b6bad67433c238f87 to your computer and use it in GitHub Desktop.
Save Eibwen/c9b072dc67999f3b6bad67433c238f87 to your computer and use it in GitHub Desktop.
// TODO write up a basic logic structure for it
# Description
# A Hubot script that bitches at people who haven't said anything within 12 hours of the time limit
# Only tested with slack...
#
# Configuration:
# Hardcoded below
#
# Commands:
# None
#
# Author:
# gwalker
#
util = require('util')
settings = [
{
Team: "ScrumChannel",
room: "scrum-updates",
excludedUsers: [
"hubot",
"gwalker"
],
dueTime: {
hour: 10,
minute: 50
}
}
]
checkEverySeconds = 60
minimumMessageSize = 50
cutoffHours = 12
_roomsToWatch = null
_heardMessageFrom = {}
initalize = () ->
roomsArray = (teamSettings.room for teamSettings in settings)
_roomsToWatch = {}
for room in roomsArray
_roomsToWatch[room] = true
return
getUsersFromGroup = (client, groupName) ->
members = client.dataStore.getGroupByName(groupName).members;
users = [];
for id in members
do (id) ->
member = client.dataStore.getUserById(id);
if member && !member.deleted
users.push(member)
return users
getUsersFromChannel = (client, channel) ->
members = client.dataStore.getChannelByName(channel).members;
users = [];
for id in members
do (id) ->
member = client.dataStore.getUserById(id);
if member && !member.deleted
users.push(member)
return users
module.exports = (robot) ->
# Hear messages that are at least 50 chars long (an update should have detail)
robot.hear /[\s\S]{50,}/i, (msg) ->
roomObj = robot.adapter.client.rtm.dataStore.getGroupById(msg.message.user.room)
if !roomObj
return
room = roomObj.name
console.log "heard long message from room #{room}"
if _roomsToWatch && _roomsToWatch[room]
console.log "listened to jira update from room #{room}"
username = msg.message.user.name
console.log "listened to jira update from room #{room} user #{username}"
_heardMessageFrom[room] = _heardMessageFrom[room] || {}
_heardMessageFrom[room][username] = new Date()
robot.hear /omgbbq/i, (msg) ->
robot.send {room: "gwalker"}, "Whatever brah: #{msg.message.user.name}"
robot.send {room: "gwalker"}, util.inspect(msg.message.user)
#robot.send {room: "gwalker"}, "Whatever brah: #{msg}"
#console.log msg.robot.adapter.client.getChannelGroupOrDMByName("hubot-test").members
buildUsersToMentionReport({ room:"hubot-test" })
robot.respond /lookup (.*)/i, (res) ->
console.log robot.adapter.client.getUserByName(res.match[1])
robot.respond /gaveUpdate (.*)/i, (res) ->
#TODO add security:
console.log "Marking as gave update: #{res.match[1]}"
thisSettings = settings[0]
room = thisSettings.room
_heardMessageFrom[room] = _heardMessageFrom[room] || {}
_heardMessageFrom[room][res.match[1]] = new Date()
usersToNag = buildUsersToMentionReport(thisSettings)
robot.send {room: "gwalker"}, "Still left to give update: " + ("<@#{user.id}|#{user.name}>" for user in usersToNag).join(", ")
# GLOBALish
buildUsersToMentionReport = (teamSettings) ->
members = getUsersFromGroup(robot.adapter.client.rtm, teamSettings.room)
memberNames = ({ name: user?.name, id: user?.id } for user in members)
console.log "===memberNames==="
console.log memberNames
console.log "===teamSettings.excludedUsers==="
console.log teamSettings.excludedUsers
console.log "===heardUpdate==="
console.log heardUpdate
# Filter the good children
heardUpdate = _heardMessageFrom[teamSettings.room] || {}
cutoffDate = new Date()
cutoffDate.setHours(cutoffDate.getHours() - cutoffHours)
for k,v of heardUpdate
if new Date(v) < cutoffDate
delete heardUpdate[k]
memberNames.filter (x) -> x.name not of heardUpdate && x.name not in teamSettings.excludedUsers
updateDueDateIfNull = (teamSettings) ->
if !teamSettings._dueDate
teamSettings._dueDate = new Date()
teamSettings._dueDate.setHours(teamSettings.dueTime.hour)
teamSettings._dueDate.setMinutes(teamSettings.dueTime.minute)
if teamSettings._dueDate < new Date()
teamSettings._dueDate.setDate(teamSettings._dueDate.getDate()+1)
robot.send {room: "gwalker"}, ":totoro: Updated time to #{teamSettings._dueDate}"
checkTime = () ->
resetTimeout()
## make sure everything has a dueDate set, updated in place
##(updateDueDateIfNull(item) for item in settings)
# for any dates in the past
# See who hasn't messaged the channel
for teamSettings in settings
#Make sure we have a dueDate set
updateDueDateIfNull(teamSettings)
dateNow = new Date()
if teamSettings._dueDate < dateNow
# if today is NOT the weekend, send the message
if dateNow.getDay() != 0 && dateNow.getDay() != 6
usersToNag = buildUsersToMentionReport(teamSettings)
robot.send {room: "gwalker"}, "-----"
robot.send {room: "gwalker"}, "if #{teamSettings._dueDate} < #{dateNow}"
# ##robot.send {room: "gwalker"}, "Timeout Info: #{DEBUGResetTimes} --- #{util.inspect(DEBUGTimeoutIds, {breakLength: 180})}"
robot.send {room: "gwalker"}, "TODO will be messaging #{teamSettings.Team}, in the room #{teamSettings.room} now"
robot.send {room: "gwalker"}, "Users to nag: " + util.inspect(usersToNag)
robot.send {room: "gwalker"}, "Users seen talk: " + util.inspect(_heardMessageFrom[teamSettings.room])
# ##robot.send {room: "gwalker"}, "-----"
# ##robot.send {room: "gwalker"}, if usersToNag.length > 0 then "Have anything to update us with " + ("<@#{user.id}|#{user.name}>" for user in usersToNag).join(", ") + "?" else "Everybody gave an update! Good job #{teamSettings.Team}!"
robot.send {room: "gwalker"}, "-----"
robot.send {room: "#{teamSettings.room}"}, if usersToNag.length > 0 then "Have anything to update us with " + ("<@#{user.id}|#{user.name}>" for user in usersToNag).join(", ") + "?" else "Everybody gave an update! Good job #{teamSettings.Team}!"
# Reset this teamSettings:
delete _heardMessageFrom[teamSettings.room]
teamSettings._dueDate = null
DEBUGResetTimes = ["","","","",""]
DEBUGTimeoutIds = ["","","","",""]
timeoutId = null
resetTimeout = () ->
timeoutId = setTimeout(checkTime, checkEverySeconds * 1000)
DEBUGTimeoutIds.shift()
DEBUGTimeoutIds.push(timeoutId.toString())
DEBUGResetTimes.shift()
DEBUGResetTimes.push(new Date())
# ON-STARTUP INITALIZATION
initalize()
resetTimeout()
robot.send {room: "gwalker"}, "I just restarted!"
robot.send {room: "gwalker"}, "Rooms To Watch: " + util.inspect(_roomsToWatch)

Written Stand-up Bot

Idea, a written log of standup updates is a very useful log to keep track of a fast moving team. Keeps all the team members very aware of what everyone is working on, better than standup as you can review any days you're OOO and be able to use the search features to figure out "who said that they fixed the one bug in that one thing a week or two ago?"

If this isn't used as a helpful, joking around type reminder, you are likely in a very unhealthy team, developers are in demand, you can find a new better job. Or you are a bad manager if you think that enforcing any of this would be helpful if enforced.

At a set time, every day, the bot will look at the list of people in the channel, and look at the conversation hitory, see what names have sent a message longer than 100 characters (or 20 words?)(TODO configable?). Any username which hasn't said anything in the last 5 hours (TODO config), will have a friendly reminder ping them in the channel. Or if everyone in the channel did say something, a congratulations message. Maybe make that give a random cat photo or something.

My suggestion on how to use this, is to schedule a normal standup at 10am, set this bot to alert at 9:55am. The idea being throughout the morning every person can type a short update, and read other people's update. Going into as much detail as they would like to. Or if they don't type anything, they get a notification 5 minutes before they would have to think about what their standup update is, breaking their concentration anyway, maximizing flow time possibilities;

NOTE: No need to send any reminders, other than the tagged on, because /remind exists

Commands

{bot} set standup at {time}
{bot} sleep until {date}
{bot} I'm on vacation until {date}
{bot} {name} is on vacation until {date}
{bot} set yearly holiday {date}
{bot} no standup on {date}

// future
{bot} set how long before standup to count the message as a standup update

Interaction Example

// Original setup:
@greg {bod} set standup at 10am
@bot Standup set every weekday at 10am


// At 10am on a weekday
// 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment