slack-rs-api
slack-rs-api copied to clipboard
Support new Buttons api
They've made it so you can added buttons to messages that come from Apps
https://api.slack.com/docs/message-buttons
Mostly means some changes to attachments
i tried emulating that with putting json as text into slack::chat::PostMessageRequest::attachments but i'm unsure how this is supposed to work with the legacy api
"Darn – that didn’t work. Only Slack Apps can add interactive elements to messages. Manage your apps here"
Yes as the docs state it requires you are an app not just a bot and it requires an interactive message, which can only be created under certain circumstances.
https://api.slack.com/interactive-messages
and you can't be an app without using the new oauth based api as far as i understand, correct?
https://api.slack.com/internal-integrations
Yea but they made it much easier to use for a simple internal app
@dten care to share how you're doing that? i couldnt figure it out with slack-rs
I didn't get very far, but here's an example. It doesn't actually use anything from slack-rs since it doesn't provide the types required yet. The bot associated with the app uses slack-rs but the slash commands I didn't complete :)
#![feature(plugin)]
#![feature(custom_derive)]
#![plugin(rocket_codegen)]
#![recursion_limit="128"]
extern crate rocket;
extern crate rocket_contrib;
extern crate serde;
#[macro_use]
extern crate serde_json;
use rocket::request::Form;
use rocket_contrib::{JSON, Value};
static TOKEN: &str = "YOUR TOKEN HERE";
#[allow(dead_code)]
#[derive(FromForm, Debug)]
struct SlashCommand {
token: String,
team_id: String,
team_domain: String,
channel_id: String,
channel_name: String,
user_id: String,
user_name: String,
command: String,
text: String,
response_url: String,
}
#[post("/coffee", data = "<slash_command>")]
fn coffee<'a>(slash_command: Form<SlashCommand>) -> Result<JSON<Value>, &'static str> {
if slash_command.get().token != TOKEN {
return Err("no")
}
println!("{:?}", slash_command.get());
Ok(JSON(json!(
{
"text": "*Cooffffeeeeee!!!!*\n Also, would you like to play a game?",
"as_user": false,
"username": "Sir Coffee Pot",
"icon_emoji": ":coffee:",
"attachments": [
{
"text": "Choose a game to play",
"fallback": "You are unable to choose a game",
"callback_id": "wopr_game",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "game",
"text": "Chess",
"type": "button",
"value": "chess"
},
{
"name": "game",
"text": "Falken's Maze",
"type": "button",
"value": "maze"
},
{
"name": "game",
"text": "Thermonuclear War",
"style": "danger",
"type": "button",
"value": "war",
"confirm": {
"title": "Are you sure?",
"text": "Wouldn't you prefer a good game of chess?",
"ok_text": "Yes",
"dismiss_text": "No"
}
}
]
}
]
}
)))
}
#[allow(dead_code)]
#[derive(FromForm, Debug)]
struct ActionData {
payload: String,
}
#[post("/action-endpoint", data = "<action_data>")]
fn action_endpoint(action_data: Form<ActionData>) -> Result<String, String> {
let v: Value = serde_json::from_str(&action_data.get().payload)
.map_err(|_| "bad data".to_string())?;
println!("{}", v);
match v.get("token") {
Some(&Value::String(ref token)) if token == TOKEN => {},
_ => return Err("no".to_string())
}
let decision = v.get("actions")
.and_then(|a| a.get(0))
.and_then(|a| a.get("value"));
match decision {
Some(&Value::String(ref v)) => Ok(format!("{} it is...", v)),
_ => Ok("pardon?".into()),
}
}
fn main() {
rocket::ignite()
.mount("/slackcommands", routes![coffee, action_endpoint])
.launch();
}