Bummer! This is just a preview. You need to be signed in with a Pro account to view the entire video.
Start a free Basic trial
to watch this video
The first bot plugin I want to create is based on [!m](http://motivate.im/) from numerous IRC channels. This is a great, simple way to help keep people motivated in your channels.
-
0:00
So the way that Slack's RTM bot project works
-
0:04
is that all of your Slack bots plugins live in this plugins directory.
-
0:08
Now they can be a single file or they can be a directory of files.
-
0:12
If you find that you need more than one file for
-
0:14
a plugin you definitely want to use a directory, and
-
0:16
then put stuff wherever it makes sense in individual modules.
-
0:20
If everything's compact and simple, then one file is fine.
-
0:23
I'm gonna be using directories for both of these plugins,
-
0:26
even though they're really simple and could be done with single files.
-
0:29
I like the directories, just because things might grow.
-
0:33
So the first thing I'm gonna do here is I'm gonna make a new folder.
-
0:36
The first one I'm gonna do is the motivation plugin.
-
0:39
So I'm gonna make a folder in here called motivation.
-
0:42
And then inside of this motivation directory,
-
0:46
I'm gonna make a file inside there that's named motivation.py.
-
0:52
Okay, so now I have this file and it's blank.
-
0:55
And the kinda cool thing, is that the Slackbot doesn't really have
-
1:00
a whole lot of requirements for how these plugins are created.
-
1:04
You can do a lot of just kind of however you want.
-
1:07
But there are two special important variables that you'll find yourself
-
1:11
using a lot.
-
1:12
So the first one is outputs, which is an empty list, and
-
1:16
the next one is crontable, which is also an empty list.
-
1:20
Now the outputs variable lets you send output to different channels and users,
-
1:25
which are one and the same thing in Slack.
-
1:27
The crontable controls timed operations, like if you were doing a plugin to
-
1:32
remind users about something after a certain time, or you wanted to send out
-
1:36
an update every day at noon saying hey everybody, go get lunch.
-
1:41
I can delete the crontable one,
-
1:42
because I'm not gonna be doing any crontable stuff.
-
1:45
I'm going to leave it though, just because it's good to have as a reminder.
-
1:50
Maybe I find myself wanting to use it later.
-
1:52
The only other thing that is definitely
-
1:56
required by the slack bot is the functions that are used to handle different events.
-
2:01
So they all start with the word process, so def process.
-
2:07
And then after that is whatever event you want to handle.
-
2:10
So for both the plugins that I'm gonna be building, I wanna trigger things based on
-
2:14
message events, so when someone types a message into a channel.
-
2:18
So I'm going to name these process_message,
-
2:20
because we're processing messages and they always take a variable named data.
-
2:25
It doesn't have to be named data, but I have a single variable which represents
-
2:29
all the data from the event that's coming in.
-
2:31
Now inside of here I can do whatever I need to do.
-
2:35
So let's see, to start I'm just gonna look for
-
2:38
messages that start with an exclamation mark and an M, or !m.
-
2:42
So if data ("text"), which is the key that contains the text of the message
-
2:48
.lower().startswith("!m"), then I need to do something.
-
2:54
Now I wanna make some sort of output for the plugin, and to do that,
-
2:59
I have to append something to the outputs list.
-
3:02
Each item in the outputs list is itself a list with two items.
-
3:07
The first item is the channel to send the output to.
-
3:09
This can be a public channel, a private channel, a user's DM,
-
3:13
a group DM, whatever.
-
3:14
Anywhere that the bot is present, the bot has to be there.
-
3:18
So if you're talking to the bot, then the bot 's there.
-
3:23
If the bot 's in your channel, which right now you can see there's only one member,
-
3:26
then the bot 's there.
-
3:28
So we'll have to invite the bot into the channel before we can actually use the bot
-
3:31
in the channel.
-
3:33
And the second thing you send back is the text you wanna send to the channel.
-
3:37
So I'll do outputs.append, and then the first thing I want to append,
-
3:41
which let's see, let's make this a list here.
-
3:47
And like that and okay.
-
3:51
So the first thing I need to send is the data ["channel"].
-
3:54
So this is the channel that the message came in on.
-
3:57
I'm just gonna send it right back to that channel.
-
4:00
And I'm gonna send "Great job!".
-
4:04
Okay, so pretty simple.
-
4:06
So we'll start the bot.
-
4:12
And then like I said, the bot's online, but
-
4:14
I need to invite the bot to the channel.
-
4:17
So I'll do /invite@frog_bot, And now frog_bot's in the channel.
-
4:24
Okay, so now if I send a message, hey froggy,
-
4:29
then nothing shows up anywhere.
-
4:33
But if I do !m froggy, then frog_bot comes back with great job.
-
4:39
So great, I have the bot working super basic how I want.
-
4:45
Now I want this plugin to be more sophisticated though, so
-
4:49
I need to add some more functionality to it.
-
4:52
So the first thing that I wanna do, is I wanna have a bit better of a trigger for
-
4:55
messages that are appropriate for the bot to respond to.
-
4:59
As part of that, I think I can catch whether or
-
5:00
not an individual person was mentioned in the message.
-
5:04
So to do that, I'm gonna import the RE library.
-
5:09
No, not review, what are you doing, Adam?
-
5:13
[LAUGH] And then I'm gonna make a new variable here that I'll call
-
5:17
trigger_message, which those are just a way for
-
5:20
me to know whether or not the message triggered the bot.
-
5:24
So I'll do re.compile, and then if the beginning
-
5:29
of the string is !m, maybe a space maybe not.
-
5:33
And then @, And then a username,
-
5:42
And then whenever you're looking at usernames in Slack,
-
5:46
the actual message always ends up with the username being inside of less than and
-
5:52
greater than symbols, kind of like HTML tags.
-
5:55
So if there's that, then, And that can be re.I.
-
6:02
There we go, make this a little wider.
-
6:07
Okay, so it starts with !m.
-
6:09
It may or may not have a space, and it may or may not have a user name inside of it.
-
6:15
Okay, so that's cool.
-
6:17
So if that happens, then I want to do the message.
-
6:20
So I'm gonna do a new thing here.
-
6:22
I'm gonna do catch = trigger_message,match(data'[text']),
-
6:32
and if catch.
-
6:34
So if something got caught, then username = catch.groupdict and ['user'].
-
6:42
Now the groupdict is always gonna have a user in it, no matter what.
-
6:46
But there may or may not be something inside of there, maybe none.
-
6:50
So if username is not None:, so
-
6:53
if there is a username, then user = _lookup_user.
-
6:58
Which I'm gonna have to write in the minute with the username that came in.
-
7:02
And I want the message to be, That
-
7:07
.format (user['user'] and [name].
-
7:13
So this _lookup_user method that I'm going to write in a minute, or
-
7:17
function I'm gonna write in a minute, will go and look up the user in Slack's API and
-
7:22
send us back their user object, which has a user field.
-
7:25
And inside of that user field, there's a name field.
-
7:28
If I don't have a user name, then text is going to be = data['text'],
-
7:34
whatever came out there, and then everything that's past that, right?
-
7:40
So I've got the exclamation mark as 0, I've got the m as 1,
-
7:47
I have a space as 2, so I want from 3 on, right?
-
7:52
And then the message is going to be text if there's anything there,
-
7:57
or random.choice from (group_pronouns).
-
8:03
All right, and then outputs.append.
-
8:07
This is the same idea as before, data["channel"], and
-
8:11
then I'm gonna add a little bit of emoji to this.
-
8:14
So, I'm going to add in a ":tada:, and then that, an !, and another :tada:".
-
8:23
And then let's format this with random.choice(congratulations),
-
8:27
which is another list I'm gonna have to create in a minute.
-
8:31
And the message that was generated by our stuff, by this one or this one.
-
8:39
Okay, so let's go back over this and then I'll add in the methods and
-
8:43
stuff that we need.
-
8:44
So we have a regex that catches !m and
-
8:48
then an optional space and an optional username.
-
8:52
And then we have the, (data['text'], all right?
-
8:58
There has to be some text there.
-
9:00
And we try to catch it, we catch to see if the thing gets triggered.
-
9:04
If it does, then we check to see if there's a username.
-
9:07
If there's a username then we're gonna look up that user and
-
9:10
use their name in the message.
-
9:11
If there's not, then we're gonna grab whatever comes out after the !m.
-
9:19
And then we're gonna send either that back if there's something there, or
-
9:22
we're going to send back a random group pronoun.
-
9:24
So great work everyone kind of thing, and
-
9:27
then we're gonna pin that to the channel with a little bit of emoji.
-
9:33
Okay, so what about this _lookup_user and these other two things?
-
9:37
Well, first of all, I'm using random in here twice,
-
9:40
so let's go ahead and import random.
-
9:44
And then I want to create a couple of new lists.
-
9:50
And the first of these is gonna be the congratulations list,
-
9:53
which I always had to think about how to spell that.
-
9:55
So I'm just gonna add in a few things here.
-
9:57
I'll do "Great job", "Amazing", "You rock",
-
10:04
"OMG", and "You're awesome".
-
10:09
And maybe one more, let's just do "Great work".
-
10:13
Okay, and look, I talked about I had to think about it every time, and
-
10:17
then I misspelled it still, crongratulations, congratulations.
-
10:21
Okay, and then the other one I need to do is the group_pronouns.
-
10:28
And in here I'll just do good words for everyone as a group,
-
10:32
because I'm congratulating the whole room at that point.
-
10:36
"everyone", "everybody",
-
10:40
"y'all" one of my favorites, "mortals",
-
10:44
"peeps", "folks", and how about "minions"?
-
10:49
Some of those are a little tongue-in-cheek, I guess.
-
10:52
All right, so those are good.
-
10:55
Now though, I need to create this _lookup_user method or function.
-
11:01
So lookup_user is gonna take a (user):, and it's gonna return
-
11:05
slack_client.api_call, which uses the Slack client to make an API call.
-
11:11
And then, you specify the endpoint, which is gonna be "users.info".
-
11:15
And then, you specify any arguments that you want to send through.
-
11:18
And the user is gonna be the user that comes through there.
-
11:21
Now to use this, I need to import slack_client, and that is
-
11:26
from client import slack_client.
-
11:31
So this is a little library you can see right here client.py.
-
11:35
That's the one that will connect to Slack and
-
11:38
give you a client out to the user, or out to the API.
-
11:44
Okay, so more complicated plugin, but
-
11:47
nothing really weird here, all fairly simple stuff.
-
11:52
So, let's restart the bot, And
-
11:58
so now, I should be able to do !m with my name,
-
12:01
nd the frog_bot should respond with Great job@kennethlove, all right.
-
12:07
One thing to notice is this doesn't highlight my name.
-
12:10
I don't believe bot users are allowed to mention people, so it'll have their name.
-
12:15
If they have highlight set up or whatever, it should highlight because of that but,
-
12:19
it's not gonna ping them if they're, for instance, away.
-
12:24
And let's see, if I just put in !m Kenneth then I get You rock Kenneth.
-
12:29
And if I just do !m I get You rock peeps!, so that's the message for the whole group.
-
12:35
So that's awesome, got the whole thing working.
You need to sign up for Treehouse in order to download course files.
Sign up