Ootoovak

Hello, Botket!

The Plan

There are a couple of new technologies I have been learning and playing with the past little while and I feel like I have now got to the point in learning where I can start working on a practice project with them. Coincidentally, I have been wanting to write a chat bot for a while so thought it might be a good fit as a first project. I have ambitious goals for building personal chat bots but for now I just want one to help me remember things (and maybe even let me play a couple text adventures) so that is what I have started on.

The technologies I would like to practice on for this project are:

  • Rust and Elm. By learning them both languages are introducing me new ideas or ideas I haven’t considered much since university. Also, both language teams seem to care about language design for people which is a big plus to me.
  • Rocket (a Rust web framework) for the back end server. I need a web server and Rocket not only seems nice but is quite well documented for such a new project.
  • For the front end administrative section as mentioned above I will be looking to use Elm. I will likely get to this later and for the most part I could probably just do what I want with server side rendered pages but this is about learning and I have wanted to use Elm in a personal project for quite some time.
  • WebSockets. I am a web developer by trade but I have yet to have found a reason to use WebSockets in any day-job projects so I would like to give them a go here. Also, I think it would be neat to see live updates and how that all works within Elm and Rust.
  • What ever chat service libraries that I need to start (likely starting with Slack).

The first goals for Botket are

  • To have Botket setup in a chat client.
  • Have Botket listen to and echo messages.
  • Show the registered bot in an administrative section.

Step 1

  • Get Rocket setup.
  • Investigate chat clients in Rust.
  • Sign up Botket with authentication.
  • Get Botket responding on the chat client.

Notes

Challenges

As mentioned, I am new to not only to Rust and Elm but also the whole ecosystem, so things that I know how to do pretty quickly in Ruby or Javascript have taken me a bit longer to figure out. This is totally to be expected and in part why I am doing this in the first place, it really puts you back in the newbie learning mindset which is great for both growth and humility.

How do I pull in environment variables?

The first one of these stumbling blocks I came across was how to load environment variables, specifically for passing in a secret API key that I did not want in version control for my source code. After little success with my first attempt to decipher the Rocket config system chose to just get on with things and temporarily specified the environment variable in the terminal when I started up the server. I then loaded it in the code with Rust’s standard library tools and that worked well to get me going.

But I knew it is not where I wanted to leave it, as from experience I knew it is nice to be able to specify and load different environment variables depending on what context the app is starting up in (development, test, production, etc.) There were a few third party options but I thought as I was using Rocket anyway it would be nice to use the system of tools it provided. So, after a bit more looking at the Rocket Guides and docs I also hopped into the Rocket community chat to see if I could get help there.

After asking in the chat room, Sergio, the author of Rocket was able to confirm some answers to questions I had about if I was using the Rocket config for the right use case and also point me to a link in the docs that had some reference code.

It still took me a bit of fiddling and figuring to get the Rocket config system to work (in part due to my newness to Rust) but I was able to eventually get it working. Yay! I have given feedback that the guides only show how to define environment variables and have yet to show examples of using them within your code but Sergio has said there are plans to open source the Rockets guides so I might be able to come back and contribute to that section once that is the case.

For now this what I did:

Rocket.toml

1
2
[global]
slack_api_key="<my super secret api key>"

main.rs

1
2
3
4
5
6
7
8
9
10
11
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
use rocket::config;
fn main() {
let rocket = rocket::ignite();
let config = config::active().unwrap();
let api_key = config.get_str("slack_api_key").unwrap();
}

The things I learned (in learning order not execution order you may note) were:

  • Explicitly using the rocket::config code to bring it into the project.
  • Finding out about the config::active() method to get the currently loaded Rocket config.
  • Making sure rocket::ignite() is called before trying to get the active config (which makes sense but took me a little while to figure out).
  • Knowing that .get_str(…) was the correct method to use and "slack_api_key" was the correct key style (vs "SLACK_API_KEY" or "ROCKET_SLACK_API_KEY" or …)

Blocking and threads I guess?

So, I ended up deciding to go with Slack as the first chat client my bot was going to talk on because I could not find any public API info for Riot (if anyone knows where that lives please tell me). Also, I use Slack quite extensively and thought a bot that works there would be useful. Their app registration site to register my chat bot was quite good (not surprising coming from the Slack team) so that was a nice experience.

There seemed to be a few Slack client libraries for Rust but I ended up going with the most popular one as I hoped it would be the most well tested and feature complete. It had a link to documentation (no need to make it harder on myself that it was going to be) and seemed to have examples so that cinched it.

I had to readjust my expectations on the documentation and examples front once I got into it, but that seems to be a common issue with community Rust libraries right now. I just attribute that to the newness of the ecosystem. In any case I managed to get a bot up and talking in Slack, double yay! But I noticed my Rocket web server had stopped running, so I moved the execution order of the code around and my web server started up but then my bot was no longer responsive.

Back to the Rocket community chat! Sergio kindly responded to my questions again suggesting it was because the .launch() method for Rocket is a blocking call. While I have not confirmed it yet I suspect the launching call for the Slack client library is also blocking.

This lead me to looking up Rust threads. Now, I have not had much experience with threads, they do not feature at all in Ruby code I use day-to-day, and Javascript has a whole different model for async so it is new territory for me. I have only just barely started using threads in my code and might be doing some memory things wrong or execution in a cumbersome way (in fact given the .join() methods at the end of my code I’m quite sure of it) but to Rust’s credit I was able to get it going pretty easily and my app was back in action running both the bot and the web server!

main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use std::thread;
fn main() {
// setup code here with some variables, some used in the threads
let rocket_handle = thread::spawn(|| {
println!("===== Starting Rocket Thread =====");
// Web server stuff here
"===== Done Rocket Thread ====="
});
let slack_handle = thread::spawn(move || {
println!("===== Starting Slack Client Thread =====");
// Slack client stuff here
"===== Done Slack Client Thread ====="
});
println!("{}", rocket_handle.join().unwrap());
println!("{}", slack_handle.join().unwrap());
}

A couple of things to note:

  • As you can see I used the move command for the initialisation of one of the threads. This was because it is using variables I have defined outside of that closure and without the move command the compiler to gave me borrow checking errors (Rust memory safety feature). I am unsure of the memory or performance implications of using the move command like this at the moment but that is a problem for another time.
  • As noted above and as you can see in the code snippet I have a couple of .join() method calls at the end of my main() method. Without these the app finished and shut down early because as far as it was concerned the threads had been spawned with no need to wait for either of them the program was considered finished. The .join() methods make the main() function wait for the threads to finish. Because Rocket’s .launch() never finishes neither does the main() function. I could probably get away with just one .join() function call as I’m pretty sure they are both blocking but my brain demands the symmetry so I wrote them both for now.

Pattern matching on complex types

The Slack client I chose to use has worked very well so far and seems to have quite a bit (if not all) of the Slack API surface area covered but… there is only one small example given of how to use it. That said example was quite good for getting you going and up and running talking to the Slack chat service. Once I feed it my secret API key that I signed up for with Slack I was sending and receiving messages pretty quickly. Through the WebSocket API no less!

When it came time to do some parsing of the chat messages though I felt a bit of a loss. The example didn’t give an indication on what to expect back from the chat service or do with messages and I didn’t find a place to start in the documentation that might tell me more about that. What I was getting (courtesy of the example provided) was a print out of the event object in my terminal though.

So, with that and rolled up my sleeves and planned to do Rust pattern matching like I’ve never pattern matched before (before meaning following simple examples and modifying them slightly.) This is why projects with goals beyond tutorials are a great next step I think, it requires you to build up a mental tool set on how to find answers. From my time teaching programming, I found it is the problem solving and answer finding tool set that is one of the biggest parts of learning how to code something and I was right back there on the learning side.

As mentioned, I knew a little bit about pattern matching having read through part of the The Rust Programming Language book. So, I rolled up my sleeves and started trying to peel away parts of the Event response being printed out in the terminal by println!(…) statements using the debugging format {:?}. What I ended up with in my match statement for my first pass at a solution is definitely cumbersome but I was pretty happy that I was able to get what I wanted by working from the Ok type inward and checking the Rust and Slack Client docs for examples or extra information as I went.

1
2
3
4
5
6
match event {
Ok(slack::Event::Message(slack::Message::Standard { text, .. })) => {
let _ = cli.send_message("#general", &text.unwrap());
}
_ => println!("\t{:?}", event),
}

I’m sure I can clean it up by using use statements to get rid of the client library name spacing and I will likely soon be matching on different types of messages but it was pretty fun using the type system and pattern matching to slowly get down to the content I wanted.

All the code from this step

Here is a link to the code I have so far. I’ll keep tagging and linking to the code as I go.

The next step

I want to try do a bit of blog post driven development so expect more posts on this ongoing project. The next step I am planning on is getting the bot to listen for specific messages and create reminders (well, a to do list to start) that I can then either view on a web page (Elm!) or call up via a chat interface.

New site is up!

Just a official announcement (if you haven’t seen it already by the different styling of the site) that I have got my new blog set up. I have been chipping away at it for a while moving from the Harp static site generator to Hexo. It is also a static site generator but with more of a focus on blogs as well as more support in terms of eyes on the code, plugins and themes available.

So yes, I did fall in to that typical developer trap of building my own blog and theme and it wasn’t a particularly fun process but glad I did it. I like having and owning my own written content, having it in plain text that I can edit anywhere. I also like the flexibility I have to modify my blog the way I see fit now that the base has been set up.

Another thing I did was that I realised that right now I don’t need a VPS to host this blog or any JS examples I had. I was using Digital Ocean for a while, and they were great, but for now all I need is a static site host, and so when Gitlab introduced hosted pages it seemed like a good fit (I did consider Surge prior to that).

Besides the above, one other reason I was wanting to rework my “blog” was because I wanted a bit more than just a linear blog. I was feeling that I couldn’t post “unfinished” or partial updates to projects as they would either lack context or get lost as I interleaved updates from other projects and as I jumped between them. As a result of the move I will soon be creating a project page to list links to project updates, and as a nice side affect I feel like it also gives me room to share personal, non-tech posts if I feel like writing them.

In any case it is all up now, and I’m looking forward to digging into some new projects and sharing the updates soon!

My First CFP

Recently I submitted a proposal to a conference and while it didn’t get accepted I wanted to share my proposal anyway, both as a reference to anyone that might be interested in hearing me talk about it but also as an example of a first timer’s CFP (Call For Proposal). Shout-out to Cara Hill for reviewing the proposal and giving content and grammar feedback.

Are Our Tools Broken? Mental Building Blocks and Metaphors in Programming

Bio

Samson has been found around computers since he was young but did not start programming in earnest until his mid-twenties when he discovered he was reading programming books in engineering classes. Since completing a Computer Science degree, Samson has spent the last 8 years working with many different companies as an employee, consultant and teacher. He strongly believes that people should always be the focus of technology and likes thinking about programming as a form of communication.

Abstract

Programming is difficult and most of the tools we use to program are not helping. From learning to teaching, we use and share mental models and metaphors as hand holds to make the heavy lifting a bit easier. So what are these metaphors? How do they differ between people/groups? And even more interesting, which ones might be holding us back? Join me in an examination of the mental building blocks we play with every day.

Details

This talk will focus on the communication devices used in programming; I will discuss the frequently used metaphors that we might not even think about, including those that gave rise to object-oriented programing and modern GUIs, and some of the less explored mental and visual metaphors. I will propose some new ideas I have been contemplating in this space (using more than just coloured text!). I will also discuss how our tools might be designed to help with reasoning about our computer systems, especially as they grow in complexity and are maintained by more and more people.

The target audience will be wide, from brand new programmers to seasoned developers. The talk will not only aim to provoke thought on how we communicate our ideas to each other, but also explore what kind of thinking our tools might be promoting with or without our direct knowledge or understanding. I would like the audience to come away from the talk thinking about programming in a way they may not have before. Whether that is thinking about code like prose or about how more of our senses could be engaged to hold more information in our heads as we develop new programs.

Pitch

I think this subject is pertinent given that developers are asked to understand a constant flow of information in order to program effectively. We need to know how to work with concepts like object-oriented and functional programming, static pages and live streams of data, large legacy applications and many small systems talking together. I think it is important to stop to reflect on how we communicate that information, not only to become better programmers but also to appreciate how young our profession really is and how many ideas are yet to be explored.

I have a Computer Science degree, have spent over 7 years working in the web development industry as both a contractor and employee, and have more recently taught programming in a web development bootcamp-style course on Ruby, Javascript and other web technologies. Having done all of this I feel like I have been exposed to many different learning, conceptualisation and communication styles and as a result have rediscovered and refined my own style of understanding and modelling our virtual world, many times over.

Notes & Feedback

Feedback from Carina C. Zona

  • Include the takeaways in the abstract too. It’s going to be what the audience reads, and they will make decisions based on how much those takeaways seem valuable for them.
  • The “details” and “pitch” sections are atypical. Are these private comments fields to the program committee?
  • Eliminate hedge language. “Might”, etc. Recast it in declarative language. A speaker is positioning themselves as an authority on what they’re talking about. Not necessarily the only authority. But one.
  • (This applies to “I think”, etc, too.)
  • The takeaways seem to all end at stirring thought/curiosity/etc. Can you take it a step further into action takeaways that they’ll get from the thinking?
  • Extend the declarative to the title too. Program committees and audiences are intrigued by a title and opening sentence that are a bit of controversial throwdown. It’s compelling, as long as the rest of the abstract evidences there’s credible case to make for it.
  • e.g. “Our Tools Are Broken.” Bam.