Slide 1

Slide 1 text

What’s so hard about wri/ng a Slack Client in Rust?

Slide 2

Slide 2 text

@ma

Slide 3

Slide 3 text

Mo/va/on

Slide 4

Slide 4 text

120 Million monthly users
 3 Billion requests / month
 lots of data
 lots of services 
 1200 employees
 all using Slack

Slide 5

Slide 5 text

Write bots! (Chatops) Collect metrics! (Messages per day…) Clone Alien-Dinosaurs! Have fun!

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

2 Million!!!!11! Jan 2016

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

To create a
 Slack bot we need a
 Slack client (d’oh)

Slide 12

Slide 12 text

slack-rs-api
 example Holy Batman… Pass client and token
 with every request? ಠ_ಠ

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

What could be improved? •Documenta/on:
 Some/mes the only way to make things working
 is to look at the source code •Not idioma/c:
 Code doesn’t feel ergonomic/rus/c •No tests •…

Slide 15

Slide 15 text

wat if I create one?

Slide 16

Slide 16 text

Goals

Slide 17

Slide 17 text

Goals Great ergonomics. Easy to use! Pure, idioma/c Rust code. Fully documented and tested. Solid error handling. Convert from JSON to seman/c types. Full Slack API implementa/on.

Slide 18

Slide 18 text

Topics 1. Idioma/c Rust: Builder pa

Slide 19

Slide 19 text

Idioma/c Rust
 Using the Builder pa

Slide 20

Slide 20 text

h

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Error handling

Slide 24

Slide 24 text

error_chain

Slide 25

Slide 25 text

error_chain

Slide 26

Slide 26 text

error_chain

Slide 27

Slide 27 text

error_chain

Slide 28

Slide 28 text

Tes/ng yup_hyper_mock

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Code genera/on

Slide 31

Slide 31 text

Group: "dnd" Method: "dnd.endSnooze" Method: "dnd.setSnooze" Method: "dnd.endDnd" Method: "dnd.info" Method: "dnd.teamInfo" Group: "search" Method: "search.messages" Method: "search.files" Method: "search.all" Group: "api" Method: "api.test" Group: "auth" Method: "auth.test" Method: "auth.revoke" Group: "users" Method: "users.info" Method: "users.setPresence" Method: "users.setPhoto" Method: "users.profile.set" Method: "users.deletePhoto" Method: "users.profile.get" Method: "users.setAc/ve" Method: "users.list" Method: "users.iden/ty" Method: "users.getPresence" Group: "reac/ons" Method: "reac/ons.add" Method: "reac/ons.list" Method: "reac/ons.remove" Method: "reac/ons.get" Group: "oauth" Method: "oauth.access" Group: "stars" Method: "stars.add" Method: "stars.list" Method: "stars.remove" Group: "files" Method: "files.upload" Method: "files.list" Method: "files.sharedPublicURL" Method: "files.revokePublicURL" Method: "files.comments.delete" Method: "files.delete" Method: "files.comments.edit" Method: "files.info" Method: "files.comments.add" Group: "bots" Method: "bots.info" Group: "im" Method: "im.replies" Method: "im.mark" Method: "im.history" Method: "im.open" Method: "im.close" Method: "im.list" Group: "pins" Method: "pins.list" Method: "pins.add" Method: "pins.remove" Group: "mpim" Method: "mpim.history" Method: "mpim.mark" Method: "mpim.list" Method: "mpim.close" Method: "mpim.open" Method: "mpim.replies" Group: "channels" Method: "channels.mark" Method: "channels.list" Method: "channels.kick" Method: "channels.rename" Method: "channels.create" Method: "channels.setPurpose" Method: "channels.history" Method: "channels.unarchive" Method: "channels.join" Method: "channels.archive" Method: "channels.replies" Method: "channels.info" Method: "channels.setTopic" Method: "channels.leave" Method: "channels.invite" Group: "emoji" Method: "emoji.list" Group: "groups" Method: "groups.setTopic" Method: "groups.history" Method: "groups.unarchive" Method: "groups.leave" Method: "groups.create" Method: "groups.createChild" Method: "groups.archive" Method: "groups.kick" Method: "groups.setPurpose" Method: "groups.list" Method: "groups.invite" Method: "groups.open" Method: "groups.mark" Method: "groups.close" Method: "groups.replies" Method: "groups.rename" Method: "groups.info" Group: "usergroups" Method: "usergroups.create" Method: "usergroups.list" Method: "usergroups.users.u Method: "usergroups.disable Method: "usergroups.update Method: "usergroups.users.li Method: "usergroups.enable Group: "reminders" Method: "reminders.add" Method: "reminders.info" Method: "reminders.list" Method: "reminders.delete" Method: "reminders.complet Group: "rtm" Method: "rtm.start" Group: "team" Method: "team.accessLogs" Method: "team.billableInfo" Method: "team.integra/onLo Method: "team.info" Method: "team.profile.get" Group: "chat" Method: "chat.postMessage" Method: "chat.update" Method: "chat.meMessage" Method: "chat.delete"

Slide 32

Slide 32 text

Slack build.rs Main Rust crate codegen build.rs Helper Rust crate Slack API ref Ruby rake h

Slide 33

Slide 33 text

let mut slack = Client::new("token"); let response = slack.im_history("channel_name")
 .with_latest(123.1)
 .send(); Slack client usage

Slide 34

Slide 34 text

let mut slack = Client::new("token"); let response = slack.send( history::HistoryOptions { channel: "hello", inclusive: Some(true), ..Default::default() }; Slack client usage
 (alterna/ve)

Slide 35

Slide 35 text

Some(ImHistory { ok: true, latest: None, messages: vec![Message { msg_type: MessageType::Message, ts: 1358546515.000008, user: Some("U2147483896".to_string()), text: Some("Hello".to_string()), is_starred: false, wibblr: false, reactions: vec![], }, // ... Message { msg_type: MessageType::Im, ts: 1358546515.000007, user: None, text: None, is_starred: false, wibblr: true, reactions: vec![], }], has_more: false, }) Result

Slide 36

Slide 36 text

Lessons learned Doing anything right is hard
 Doing anything right takes /me
 
 Simple things are difficult

Slide 37

Slide 37 text

Outlook

Slide 38

Slide 38 text

Outlook • Support Real/me Slack API • Convert all Slack types to Rust (Slack::Emoji, Timestamp,…) • Iterators for pagina/on • Proper into conversions • Just read Pascal’s Blog.
 h