Heatherr

Heatherr is a bunch of friendly Slack helper tools.

https://travis-ci.org/praekeltfoundation/heatherr.svg?branch=develop https://coveralls.io/repos/github/praekeltfoundation/heatherr/badge.svg?branch=develop

Writing a Slash command

from heatherr.views import dispatcher
from random import random

eight_ball = dispatcher.commands('/8ball')

@eight_ball.respond('(?P<anything>.+)')
def fortune_teller(request, match):
    (anything,) = match.groups()
    if random() < 0.5:
        return 'All signs for `%s` point to *yes*.' % (anything,)
    return 'All signs for `%s` point to *no*.' % (anything,)

If you configure this for Slack then /8ball will I find true love? will randomly return either yes or no.

Writing a Bot

from heatherr.views import dispatcher
from random import random

bot = dispatcher.commands('Jokes')

@bot.ambient('@BOTUSERID: joke\??')
def knock_knock(request, match):
    return request.message.reply('I don\'t do jokes.')

@BOTUSERID is automatically replaced with the bot user id that’s been registered with Slack. So if your bot is called @heatherr then @BOTUSERID will match @heatherr. On a low level Slack sends the <@bot-user-id> but the clients display this as @heatherr.

BOTUSERNAME is also automatically replaced and that will match heatherr.

Timezone

heatherr.timezone.commands.for_(request, match)

Print the local timezone and time for a friend on Slack:

/time for @smn

@smn is in Central European Time, local time is 5:29 PM

The timezone is retrieved from the person’s Slack account profile. If it’s incorrect then have it updated there.

Patterns it responds to after /time:

^for @?(?P<name>.+)$

Daily or Weekly team check-ins

heatherr.checkin.commands.daily_or_weekly(request, match)

Set a daily checkin for you for the current channel at 9am in according to the timezone your Slack account profile:

/checkin daily or
/checkin weekly

Returns:

I'll prompt you daily for a #testing team check-in at
9am your time.

Patterns it responds to after /checkin:

^(?P<interval>daily|weekly)$
heatherr.checkin.commands.list_checkins(request, match)

List all of the checkins you’re subscribed to:

/checkin list

Returns:

You have the following checkins set:
- #5, a daily checkin for #testing

Patterns it responds to after /checkin:

^list$
heatherr.checkin.commands.remove_checking(request, match)

Remove a checkin, the #number matches the #number returned by list:

/checkin remove #5

Returns:

Daily for #testing was removed.

Patterns it responds to after /checkin:

^remove #?(?P<pk>\d+)$

Definitions

heatherr.definitions.bots.add_definition(request, match)

Teach the bot a definition:

@BOTUSERID: UNICEF is The United Nations Children's Emergency Fund

@BOTUSERID will respond by adding a :thumbsup: reaction to your message once the definition has been added.

Patterns it responds to for Definitions:

@BOTUSERID: (?P<acronym>[A-Za-z]+) is (?P<definition>.+)$
heatherr.definitions.bots.get_definition(request, match)

Ask the bot for a definition:

@BOTUSERID: what does UNICEF mean?
@BOTUSERID: what is UNICEF?
@BOTUSERID: UNICEF?

@BOTUSERID will respond with the definitions it knows about. Each definition has a unique number which one can use should it need to be removed.

Patterns it responds to for Definitions:

@BOTUSERID: (?P<acronym>[A-Za-z]+)\?
@BOTUSERID: what is (?P<acronym>[A-Za-z]+)\??
@BOTUSERID: what does (?P<acronym>[A-Za-z]+) mean\??
heatherr.definitions.bots.remove_definition(request, match)

Remove a definition:

@BOTUSERID: remove 1 for UNICEF

@BOTUSERID will respond by adding a :thumbsup: reaction to your message once it’s been removed.

Patterns it responds to for Definitions:

@BOTUSERID: remove (?P<pk>\d+) for (?P<acronym>[A-Za-z]+)$

Group Announcements

heatherr.groups.commands.announce(request, match)

Broadcast a message to all the members in a group:

/bellman announce foo hello world!

Patterns it responds to after /bellman:

^announce (?P<group_name>[\w-]+) (?P<message>.+)$
heatherr.groups.commands.create(request, match)

Create a new group:

/bellman create foo

Returns:

The group foo has been created.

Patterns it responds to after /bellman:

^create (?P<group_name>[\w-]+)$
heatherr.groups.commands.join(request, match)

Join a group:

/bellman join foo

Returns:

You've joined foo and will start receiving announcements for
this group.

Patterns it responds to after /bellman:

^join (?P<group_name>[\w-]+)$
heatherr.groups.commands.leave(request, match)

Leave a group:

/bellman leave foo

Returns:

You've been removed from foo.

Patterns it responds to after /bellman:

^leave (?P<group_name>[\w-]+)$
heatherr.groups.commands.list(request, match)

List the known groups:

/bellman list

Returns:

Groups:
- testing (member)

Patterns it responds to after /bellman:

^list$
heatherr.groups.commands.members(request, match)

List the members in a group:

/bellman members foo

Returns:

There are no people in foo.

Patterns it responds to after /bellman:

^members (?P<group_name>[\w-]+)$

Random things

heatherr.random.commands.poll(request, match)

Create a poll:

/poll Should we jump off a bridge? Yes, No, Maybe?

Returns:

Poll from @smn:
Should we jump off a bridge?
:one: Yes
:two: No
:three: Maybe?

It will also automatically attach as many reactions as there are options to the message posted. Voting is done by people clicking the reactions that match their choices.

Patterns it responds to after /poll:

^(?P<question>.+)\? (?P<options>.+)$
^(?P<question>.+)\?$
heatherr.random.commands.slap(request, match)

Slaps someone around a bit with a large trout:

/slap @userid

Returns:

@smn slaps @userid around a bit with a large trout.

Patterns it responds to after /slap:

^@(?P<target>[A-Za-z\-\.0-9]+)$