 Okay, so I I'm not very prepared so you'll get to see me like do this from scratch But the ember bot I'll delete this afterwards So a couple of weeks ago we our team moved to slack And Yep, so a couple of weeks ago our team moved to slack And one of the things that I really wanted to do was take advantage of their API which is a Lot better than flow docs and like things like I find things like reactions and stuff like that really interesting and And ways that that can kind of help manage workflows So what I did was I set out so there's bots like who bought and things like that So there's a lot of like talk around slack bots and and bots in general But I kind of wanted to not write it in javascript, but also I kind of thought that elixir would be a good fit for something like this because it is Very process driven So as I kind of show you what I've built to To kind of like facilitate this slack bot You'll kind of notice how it's different from like who bought or javascript bot That you might typically find I just need to like pop their keys into my config file Sorry, I'm a little bit unprepared Yes, just ignore the secret tokens Now I'm gonna have to rotate them up no because this is recorded Shit Okay, that would be much appreciated Okay, so Why don't we start with Marvin? so Marvin is the framework That allows you to build these kind of Bots built in elixir is that large enough? Okay, so it started like I can probably tell you even maybe four weeks ago the 27th of December 2016 So I Started kind of messing around with this idea and initially what I had was a Very simple thing. So I started with like slack elixir, which is built by Blake Williams who works at Thoughtbot And it's just a really rudimentary kind of basic low-level thing to listen to slack messages and then you can like handle them and send messages and I was like, okay, so how do I take this and then build like a proper Thing where you can create like modules that react to different messages and then they react to maybe they react to a Rack a reaction like someone thumbing up a PR or something like that in the slack and then fire off these These things in a much more modular way and like less of having like everything in one file And then how do I make that into like a framework that then allows other people to like put it in their projects And just make these bots and with very little lines of code start like Creating really fun little workflows that will respond to messages or like do certain actions on certain things So I used this to build Marvin and Marvin kind of abstracts all that nitty-gritty stuff away Like connecting to slack handling the messages. What's them like it? It passes like what the type of messages So whether it's a reaction or a channel join or whether it's like a there's all this like weird stuff that the slack API will do and Then just nuts it down to at the moment two things So the idea is that you have a module So this is like an example of like a bot module and you can see here I've called it echo bot even though it doesn't echo so I have to update the read me And all you have to do is add use Marvin dot bot in there and then this bot is going to become like a listener Okay, so then you declare what you want to match it against So this is called a tuple and you would pass in two things. So you would say This particular bot is going to listen for direct messages and I've classified those as like at bot Or if you have a direct conversation with that bot in slack and then it's going to do a regex pattern match against the sentence is really hard to avoid using regex with bots But there's another bot that I'm building That actually avoids using this that uses like some AI to determine what you're trying to talk to it about And then all you need to do is declare this method or this function Which is handle message you get past the message and then like the slack state So that has like the connection back to slack and things like that And then you just need to go send message the message and then the channel that you want to send it back to and then it will talk into the thing So it's like super simple and that's all you have to do it Then you just let you set your slack token and then that's it this bot you hit run and it'll connect You can write hello and it'll respond in the thing So After you declare like the type of the bots that you want to run And then you can do things like match against reactions so you can have like Does everyone use slack when I say a reaction does everyone know what that means? so like for those who don't you someone can post a message and then you can like Put like an emoji next to it, which is like a thumb or really any emoji So one of the things that we do or one of the things that I do is if someone posts something really Interesting or funny or whatever will add the like spinning Mario coin to it So now we have this bot which listens for a reaction It cases the type of reaction that someone posted and then counts the amount of coins that that individual who posts that message gets And then that person can like check how many coins they have and then spend the coins on nothing We like to try to determine what we will spend the coins on so you can you can say like match reaction and then What that's going to do is just listen for reaction And then you can part you get past the message which is the message from slack You can check the type of the reaction and if it's the coin then you can like puts like log a coin was given So this is like how you use Marvin. It's very or I like to think it's kind of simple That being said I Have changed this Multiple times in the last like you can see like my last commit was eight hours I've changed the way matching and stuff works. So but I've tried to keep it versioned Anyway, so yeah, that's that's Marvin any questions about like that particular part Okay, cool So we can close that so with any luck Sure so Marvin is broken down into Into like two modules really there's core and bot. So this is core And this uses that original slack implementation by Blake Williams to handle the connection and stuff like that and then I just listen for like different events and then what happens is if There's like different message types So I rely really heavily on on message on pattern matching Sorry to pull out the right types of messages that I want to listen to and then ignore the ones that I don't want to ignore Or that I don't that I don't care about Which is one of the reasons why I think this suits Alexa so well is because it's incredibly hard to bring this bot down Because if someone sends a message that it doesn't know about Down the bottom I've pattern matched against Anything like anything that I haven't said I want to listen to before and then I just ignore it It's just the the one thing that got me like a few times was that slack has these like subtypes So it has a type of message and then these this would run and then like message user wouldn't be there So then I realized okay. Well, there's these subtypes. So now I pattern match So now since I've done that this bot like hasn't gone down Due to like getting some sort of like weird message that it doesn't understand Um So then what it does is it actually boots up Each of those bots so like echo bot and things like that It'll actually boot up each of those bots as a separate process and it'll monitor them so if I send a message it'll hit call bot and Then call bot will actually go through each of the bots and check for a match before executing any code and Then it will push the message through to that bot and then that bot will take it and it'll like do whatever at that Point call bot doesn't care about it anymore And then the beauty of that is that if that particular like if something happens in that like loop That causes that particular bot to crash all the others stay up and the core bot stays up as well so if you're thinking like a Conversational bot say where you might have five people having different conversations with that bot you can spin up a process for each conversation and then If one person's conversation goes down for whatever reason you lose none of the state of all the other conversations So that's essentially what core bot is it's like a dispatch thing it just pulls in the message and then Like it throws it around in here for a little while until it makes it to a bot And then all a bot is is a gen server. So it's like a module that will like loop state through itself and just keep every function will return the state so that it like remembers different things, but you pass messages into it and then it will Do something with that message and then the message will either return something or it'll just say I have nothing to return to you And it'll continue So in this case we never really return anything to the core bot because There's nothing that we need to return So you'll see here. This is where the message comes in And then I cast it to this function here Which then calls handle message on the bot that you implement So I've obstructed all of that kind of gen server stuff and all that state management away And I've knotted it down to this like one function, which is handle message which you would override in your own bot And even then I've pattern matched it. So if you don't if you forget to do it, it's not going to crash and Yeah, yeah So this just means that because if I was to If I was to use use and then not say that this was overwriteable, this would actually Capture all the messages And it their their handle message would never run. So by saying that this is overwriteable It means that when they declare this then mine will be gone Yeah, yeah, yeah, yeah, yeah, yeah And same with match Because you need to declare a match in order to have the bot listen. So by default they'll listen to everything But this is actually broken because it should return a tuple And then you can do things like macros so So Basically, this is how I define those those match functions that you saw earlier in In echo bot so this thing so at compile time It will take these two arguments direct or this one argument this tuple and it will generate a function within that bot called is match and it will It just it's kind of like Because you have no state you can't like store that thing like anywhere when you first create that that bot You can't have match that then saves to an instance variable You have to store that state somewhere. So I've like declared this or created this function to hold on to that for me So in reality what will happen is this unquote will actually unquote that and it's kind of like writing that function by hand Does that make sense And then I just like is match So I have to match against the tuple, but also against just the atom, which is the symbol So there's two there and you can have these guards as well, right? So I can say Match this type when this type is an atom or I can say match against this one when match pair is a tuple So then I'm only running those Anyway, that's like pretty much how Marvin works. So it's quite simple, but then you can have You can write bots. So If I look at so the tube status Let me just boot the bot up. Okay, so it's connected to ember London as ember bot Let me find him Okay, so you can see it's online so I can say like if we were to look at tube status Um, so all I've done is I've declared alpha bot tube Oh, yeah, sorry Is that better? bit more Then I've I've said okay use Marvin bot and that's going to import all of those bot functions that we saw before And then I match it against the direct message and I match it to like a sentence that includes tube status So then if I go tube status in here It will paste all of the tube status and you kind of didn't see it But it will also indicate that the bot is typing it. I really like that. I think it's pretty cool so in like long running stuff, so there's one where I Go and fetch all the open PRs for like certain repositories and that's like Goes through like a fairly hefty amount of steps. It takes a little bit longer for that stuff to To run so you kind of see this like ember bot is typing and it's like it's a human So the way I kind of format my bots is I will try and use piping as much as possible So I'll take the initial message and then I'll like fetch the status and then that will format the response and then format the response will actually be the First argument of this send the attachment So if you're not familiar with piping all you're doing is you're taking the result of the previous function call and passing it in as the argument of the next one So the in this instance it results in the attachment being this list of Line line statuses, which is what we see here sent as an attachment So there's another one. So if we want to look at like a much simpler one There's greeting bot and if you say hello, it'll just say hey And again like super simple like this that's all that bot that bot has So then if we were to look at the coin one Okay, so This is hard to demo Because I would need someone to log into Slack who is in like ember London Thanks So if I was to go into here and then ah, who's here that I can find Okay, so hopefully this works and I have read it. Oh, we don't have the coin. I can change it. I can change it I'll just do cry because I saw that one Okay So I have to just reboot the bot so it is possible to hot reload code So if I was to change this just this one file I could actually push that up without click without killing the bot and then tell it to like just reload this one file And then the bot never dies So hopefully this works, but if I go and give McGill cry Just check it didn't crash. So then if McGill writes Alphabet, how many coins do I have? Sorry ember bot? How many coins? Do I have? Oh, I have to invite it you get used to like copying and pasting codes So I have zero coins, but if McGill does it he'll have hopefully one coin But it'll actually be a cry. I have to at our at ember bot. Sorry. Oh, it has to be a new message You're killing me man It does I just don't respond to it yet. Mm-hmm. Yeah, so he has zero coins Our well, maybe it's because it didn't match against cry properly. Oh wait. I didn't change it. What did I do? Oh That's if you remove a cry Okay, okay, I'm with it now. All right, let me give you another cry Well, let's not test it because that's embarrassing Okay, so now if you just copy and paste that oh, well you have to oh someone else cried on cried on you So yeah, I mean it's pretty it's I mean this is like so a lot of this stuff at this point is experimentation but the idea is to Take the like uniqueness of slack and like reactions and all these other integrations that it has and then Kind of work off that so I can imagine What I'm working on next for Marvin is adding Like a router which can accept web hooks So then when you open a PR on github and you can go like I need a review It will hit the bot which will then post it in the channel and then if someone adds the eyes emoji to it It will then allocate them to that PR which will then post in the thing Hey will is gonna look at this and then you can go like you know ember bot What PRs do I have to review and then it'll list the PRs and things like that? So I have like big aspirations for ember bot Um If you pay for slack they have an email ingestion service, yeah I think it's like the standard tier so yeah like yeah any any company that's using that and like More than five integrations would would have an email ingestion service Which you could hook up today and we use it The other thing I would say about like building a bot is that like get ready to talk to your bot a lot And for it to never talk back to you a lot either It's quite a lonely life So one other thing that I'll show off just before and I'm not gonna demo this because it's I can't guarantee that it will work Is that on another branch? I've actually integrated this bot with wit.ai So wit.ai is an interesting company has anyone heard of Facebook em The the messaging thing so you can like ask it anything so they bought this company and that's what they turned into Facebook em So what I've done is when you ask it a question It will send that string to wit.ai which will then determine the intent of that message So rather than saying like tube status you can say like what is What is the state of the lines at the moment? Or what is the state of the tube or how's the tube looking and things like that and it will determine from that that you mean? Tube status and you can see here like me trying to teach this bot how to like understand the tube status So you can do all types of things and then you use that response to match rather than regex So you send it off to this like service which determines the intent and then sends back Okay, you actually mean like it normalizes it says okay It's tube underscore status and these are the entities so these is like they wanted the Victoria line or something like that So I think this is really interesting as well But it's a lot harder to do Conversations and things like that because you kind of have to I haven't quite worked out how this would look And then relying on another service is also something that I don't particularly want to do especially one that's like bought by Facebook Or Google or any of those so I'm a bit cautious about building a whole bot that like relies on this type of thing But I still think it's really interesting and it was Pretty trivial to integrate this into the bot initially Any questions? I can show more bots. I have heaps It'd be easy to make I can make it right now Yes, so you can you can get the bot to message specific people so in this example Yeah As an example so similar but not swearing so we have like The moment I think we have 150 people and they have like different channels all over the place so in each channel I put ember alpha bot and then they can just ask alpha bot for help and then it will Message me and say hey this person needs help in this channel So then I don't have to have like 50 channels open on the side So I'm like making the bot do my dirty work Which is the goal? So this this one just goes and grabs all the PRs for a particular GitHub repo and then displays them in like a formatted way so like it's very easy to create Like just little recipes. I guess that do do things That's it