Slacking is a lightweight C++11 header only library for communicating with the Slack Web API.
Slacking aims to be easy and intuitive to use. Slacking requires to have an API token.
- C++11 compatible compiler. Tested with Clang (3.5, 3.6, 3.7) and GCC (4.9, 5).
- Curl (which you probably already have).
Note: Slacking uses the awesome C++ Requests (CPR) and Nlohmann Json which are already included in the project. CPR has been rewritten to be a header only library. Hence, you don't have to install anything!
Just copy the include/slacking
folder in your project and add #include "slacking.hpp"
. That's all.
Initialize a slack instance:
auto& slack = slack::create("xxx-xxx-xxx-xxx"); // "xxx-xxx-xxx-xxx" is your Slack API token
slack.chat.channel = "#general"; // set a default channel
Sending a message in Slack is intuitive, the chat.postMessage syntax is easily recognizable:
slack.chat.postMessage("Hello there!"); // will send the message "Hello there!" in the channel #general with the registered token
If you need maximum control, you can use the generic functions slack::post
or slack::get
.
Everything available in Web Slack API is possible from here.
slack::post (
"chat.postMessage",
{
{"text" , "Slacking is awesome!" },
{"channel" , "#mychannel" },
{"username" , "peach" },
{"icon_emoji", ":princess:" }
} // note that "token" is not needed here and is a "registered" parameter
); // it is automatically inserted when using slack::post()
If you prefer to mimic the Json approach given in the API, you can also use this syntax:
auto json = R"({
"text": "But Our Princess is in Another Castle!",
"channel" : "#general",
"username": "peach",
"icon_emoji": ":princess:"
})"_json;
slack::post("chat.postMessage", json);
Check out the examples for more illustrations.
You can make richly-formated messages with attachments.
slack.chat.channel_username_iconemoji("#ticker-channel", "Support Bot", ":hamster:");
auto json_attachments = R"([
{
"fallback": "New ticket from Bjarne Stroustrup - Ticket #2017: Still looking for reflection",
"pretext": "New ticket from Bjarne Stroustrup",
"title": "Ticket #2017: Still looking for reflection",
"title_link": "https://www.youtube.com/watch?v=ND-TuW0KIgg",
"text": "Help me adding reflection!",
"color": "#7CD197",
"image_url": "https://img.youtube.com/vi/ND-TuW0KIgg/2.jpg"
}
])"_json;
slack.chat.attachments = json_attachments;
auto response = slack.chat.postMessage(); // get a slack::Json object
std::cout << response << std::endl;
The output is a JSON response sent back by Slack:
{"channel":"C1AUF9AN4","message":{"attachments":[{"color":"7CD197","fallback":"New ticket from Bjarne Stroustrup - Ticket #2017: Still looking for reflection","id":1,"image_bytes":4820,"image_height":90,"image_url":"https://img.youtube.com/vi/ND-TuW0KIgg/2.jpg","image_width":120,"pretext":"New ticket from Bjarne Stroustrup","text":"Help me adding reflection!","title":"Ticket #2017: Still looking for reflection","title_link":"https://www.youtube.com/watch?v=ND-TuW0KIgg"}],"bot_id":"B20LJ4Y12","icons":{"emoji":":hamster:","image_64":"https://slack.global.ssl.fastly.net/d4bf/img/emoji_2015_2/apple/1f439.png"},"subtype":"bot_message","text":" ","ts":"1464251666.000063","type":"message","username":"Support Bot"},"ok":true,"ts":"1464251666.000063"}
Since Slack::Json is a nlohmann::json, you have all the features of the latter one (conversions, STL like access, ...). For instance, response["ok"]
will give true
.
Slacking will throw a runtime error exception if the curl request does not succeed, if the response from Slack is not correct, or if response["ok"]
received is not true
. You are free to handle these exceptions the way you like.
The library on master
branch should always be functional.
You can use the slack::post
or slack::get
methods to fully exploit the Slack Web API methods. You can refer to examples/06-custom_post_get.cpp.cpp.
Following C++ helpers free functions and member methods are available in Slacking for convenience :
- api.test (see examples/01-basic.cpp)
- chat.postMessage (see examples/00-showcase.cpp, examples/01-basic.cpp, examples/02-basic.cpp, examples/03-attachments.cpp)
- users.list, users.info (see examples/04-users.cpp)
- channels.list, channels.info (see examples/05-channels.cpp)
Try out the "magic" functions for grabbing ready-to-use structures.
This is an ongoing work so more convenient helpers functions and structures might come in the near future...
If you need any features feel free to ask and contribute.
Here are two approaches to keep alive the Slacking session in your program so you can use it anytime, anywhere.
####Use Meyers singleton
Slacking provides free convenient functions : slack::create(const std::string& token)
and slack::instance()
.
Initialize the Slacking instance with:
auto slack& = slack::create("xxx-xxx-xxx-xxx");
And when you are in another scope and you have lost the slack
reference, you can grab it again with :
auto slack& = slack::instance();
It might not be the recommended way but since we generally want to handle only one Slack instance (one token), it is highly convenient. You can refer to the example usage and examples/01-basic.cpp.
####Pass by reference (or by pointer)
An other approach is to pass the Slacking instance by reference, store it, and call the appropriate methods when needed.
void foo(slack::Slacking& slack) {
slack.chat.postMessage("I am slacking!", "#random");
}
int main() {
slack::Slacking slack_instance{"xxx-xxx-xxx-xxx"};
foo(slack_instance);
}
You can use a std::reference_wrapper as shown in examples/02-basic.cpp. This strategy is useful if you have to manage several Slacking instances.
mkdir build && cd build
cmake .. && make
examples/[whatever]
In your project, if you want a verbose output like when running the examples, add the following compilation flag:
-DSLACKING_VERBOSE_OUTPUT=1
.