Skip to content

Instantly share code, notes, and snippets.

@kornysietsma
Last active February 11, 2019 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kornysietsma/63f68258d45080a35af3518d5e06cbbc to your computer and use it in GitHub Desktop.
Save kornysietsma/63f68258d45080a35af3518d5e06cbbc to your computer and use it in GitHub Desktop.
Slack actions and buttons in rust
extern crate actix;
extern crate actix_web;
extern crate bytes;
extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate json;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use actix_web::{
client, error, http, middleware, server, App, AsyncResponder, Error, Form, HttpMessage,
HttpRequest, HttpResponse, Json, Result,
};
use bytes::BytesMut;
use futures::{Future, Stream};
use json::JsonValue;
#[derive(Debug, Deserialize)]
struct SlackPayload {
payload: String,
}
fn index_slack(params: Form<SlackPayload>) -> Result<HttpResponse> {
println!("payload: {:?}", params.payload);
// I'm lazy - parsing using json-rust for now rather than creating the types needed for serde
let result = json::parse(&params.payload); // return Result
let response: HttpResponse = match result {
Ok(message) => {
match message["type"].as_str() {
Some("interactive_message") => {
// the button
HttpResponse::Ok().content_type("application/json").body(
object! {"response_type" => "in_channel",
"replace_original" => false,
"text" => "Ow!"
}
.dump(),
)
}
Some("message_action") => {
// the action
let response_url = message["response_url"].as_str().expect("No response url!");
client::ClientRequest::post(response_url) // <- Create request builder
.content_type("application/json")
.body(
object! {"response_type" => "in_channel", "replace_original" => false, "text" => "Pong!"}
.dump(),
)
.unwrap()
.send() // <- Send http request
.map_err(|_| ())
.and_then(|response| {
// <- server http response
println!("Slack responded with: {:?}", response);
Ok(())
}); // Fails!!! - needs a future here.
HttpResponse::Ok().finish()
}
_ => HttpResponse::BadRequest()
.body(format!("Unknown type: {}", message["type"].to_string())),
}
}
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
};
Ok(response)
}
fn main() {
::std::env::set_var("RUST_LOG", "actix_web=debug");
env_logger::init();
let sys = actix::System::new("json-example");
server::new(|| {
App::new()
// enable logger
.middleware(middleware::Logger::default())
.resource("/slack", |r| r.method(http::Method::POST).with(index_slack))
})
.bind("127.0.0.1:8080")
.unwrap()
.shutdown_timeout(1)
.start();
println!("Started http server: 127.0.0.1:8080");
let _ = sys.run();
}
use std::env;
use slack_hook::SlackTextContent::{self, Link, Text, User};
use slack_hook::{
Action, AttachmentBuilder, Field, PayloadBuilder, Slack, SlackLink, SlackText, SlackUserLink,
};
pub fn env_hook_url() -> String {
env::var("SLACK_HOOK_URL").expect("No SLACK_HOOK_URL found")
}
pub fn env_channel() -> String {
env::var("SLACK_CHANNEL").expect("no SLACK_CHANNEL found")
}
fn env_username() -> String {
env::var("SLACK_NAME").expect("no SLACK_NAME found")
}
fn main() {
let slack = Slack::new(&env_hook_url() as &str).unwrap();
let a = vec![
AttachmentBuilder::new("The one with the action <&>")
.text("Ping me!")
.callback_id("ping")
.color("#6800e8")
.fields(vec![Field::new(
"Ping please",
"(use the \"...\" button to show the action ",
None,
)])
.build()
.unwrap(),
AttachmentBuilder::new("The one with the button")
.text("Poke me!")
.callback_id("poke")
.color("#FF50A8")
.fields(vec![Field::new(
"Poke please",
"(with the button below)",
None,
)])
.actions(vec![Action::new(
"button",
"poke poke poke",
"buttonname",
None,
Some("value".to_owned()),
)])
.build()
.unwrap(),
];
let p = PayloadBuilder::new()
.text("This should have a button and an action!")
.channel(env_channel())
.username(env_username())
.icon_emoji(":bubblebobble:")
.attachments(a)
.build()
.unwrap();
let res = slack.send(&p);
match res {
Ok(()) => println!("ok"),
Err(x) => println!("ERR: {:?}", x),
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment