slack-rs-api icon indicating copy to clipboard operation
slack-rs-api copied to clipboard

Support new Buttons api

Open dten opened this issue 8 years ago • 6 comments

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

dten avatar Jun 27 '16 11:06 dten

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"

aep avatar Dec 09 '17 15:12 aep

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

dten avatar Dec 09 '17 16:12 dten

and you can't be an app without using the new oauth based api as far as i understand, correct?

aep avatar Dec 09 '17 16:12 aep

https://api.slack.com/internal-integrations

Yea but they made it much easier to use for a simple internal app

dten avatar Dec 09 '17 22:12 dten

@dten care to share how you're doing that? i couldnt figure it out with slack-rs

aep avatar Dec 10 '17 10:12 aep

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();
}

dten avatar Dec 10 '17 14:12 dten