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