1/*! For license information please see f455e843.841157ef.js.LICENSE.txt */ 2"use strict";(self.webpackChunkquickchart_docs=self.webpackChunkquickchart_docs||[]).push([[6383],{7456:(e,t,a)=>{a.d(t,{Z:()=>l});var n=a(7294);const r="hr_bs4e",s="authorFlexContainer_BZ_D",i="authorImgContainer_OfUf",c="authorBio_ireB";function l(){return n.createElement(n.Fragment,null,n.createElement("hr",{className:r}),n.createElement("div",null,n.createElement("div",{className:s},n.createElement("div",{className:i},n.createElement("img",{src:"data:image/jpeg;base64,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",alt:"Ian Webster",width:150,height:150,loading:"lazy"})),n.createElement("div",{className:c},n.createElement("h2",null,"About the author"),n.createElement("p",null,"Ian Webster is a software engineer and former Googler based in San Mateo, California. He has helped Google, NASA, and governments around the world improve their data pipelines and visualizations. In 2018, Ian created QuickChart, a collection of open-source APIs that support data visualization efforts."),n.createElement("p",null,n.createElement("a",{href:"mailto:[email protected]"},"Email")," \xb7"," ",n.createElement("a",{href:"https://www.linkedin.com/in/ianww/"},"LinkedIn")," \xb7"," ",n.createElement("a",{href:"https://twitter.com/iwebst"},"Twitter"))))))}},8134:(e,t,a)=>{a.d(t,{Z:()=>l});var n=a(7294);const r="container_Nt4w",s="noBorder_zfZj",i="caption_czJ5",c="dropShadow_MaDw";function l(e){let{src:t,href:a,alt:l,caption:o,maxWidth:h,noBorder:A,noLazyLoad:d,dropShadow:p}=e;return n.createElement("div",{className:`${r} ${A?s:""} ${p?c:""}`},n.createElement("a",{href:a||t,target:"_blank",rel:"noopener noreferrer"},n.createElement("img",{loading:d?"eager":"lazy",src:t,alt:l||o,width:h})),n.createElement("div",{className:i},o))}},6498:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>h,contentTitle:()=>l,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>A});a(7294);var n=a(5893),r=a(1151),s=a(7456),i=a(8134);const c={slug:"/send-charts-with-slack-bot/",title:"Send charts with a Slack bot",tags:["slack","javascript"],sidebar_position:10,sidebar_label:"Send charts on Slack"},l="How to send dynamic charts with a Slack bot",o={unversionedId:"guides/sen
2d-charts-with-slack-bot",id:"guides/send-charts-with-slack-bot",title:"Send charts with a Slack bot",description:"Slack bots are limited by the Slack API to specific formats: text, images, and special controls. Critically, they cannot send Javascript or other dynamic formats. In order to send a chart or graph to your Slack channel, you must first render it as an image.",source:"@site/documentation/guides/send-charts-with-slack-bot.md",sourceDirName:"guides",slug:"/send-charts-with-slack-bot/",permalink:"/documentation/send-charts-with-slack-bot/",draft:!1,editUrl:"https://github.com/typpo/quickchart-docs/edit/master/documentation/guides/send-charts-with-slack-bot.md",tags:[{label:"slack",permalink:"/documentation/tags/slack"},{label:"javascript",permalink:"/documentation/tags/javascript"}],version:"current",sidebarPosition:10,frontMatter:{slug:"/send-charts-with-slack-bot/",title:"Send charts with a Slack bot",tags:["slack","javascript"],sidebar_position:10,sidebar_label:"Send charts on Slack"},sidebar:"docsSidebar",previous:{title:"Email charts with Mailgun",permalink:"/documentation/send-email-charts-with-mailgun/"},next:{title:"Send charts on Discord",permalink:"/documentation/send-charts-discord-bot/"}},h={},A=[{value:"Creating a chart image",id:"creating-a-chart-image",level:2},{value:"Sending the chart image to Slack",id:"sending-the-chart-image-to-slack",level:2}];function d(e){const t=Object.assign({h1:"h1",p:"p",strong:"strong",a:"a",ol:"ol",li:"li",h2:"h2",table:"table",thead:"thead",tr:"tr",th:"th",tbody:"tbody",td:"td",pre:"pre",code:"code",ul:"ul"},(0,r.ah)(),e.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"how-to-send-dynamic-charts-with-a-slack-bot",children:"How to send dynamic charts with a Slack bot"}),"\n","\n","\n",(0,n.jsxs)(t.p,{children:["Slack bots are limited by the Slack API to specific formats: text, images, and special controls. Critically, they cannot send Javascript or other dynamic formats. ",(0,n.jsx)(t.strong,{children:"In order to send a chart or graph to your Slack channel, you must first render it as an image."})]}),"\n",(0,n.jsx)(i.Z,{alt:"A chart on Slack",noLazyLoad:!0,noBorder:!0,src:"https://i.imgur.com/ab9fOuA.png"}),"\n",(0,n.jsxs)(t.p,{children:["In this tutorial we'll use the free and open-source ",(0,n.jsx)(t.a,{href:"https://quickchart.io",children:"QuickChart API"})," to generate chart images. To send these charts to Slack, you must:"]}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Construct the chart image"}),"\n",(0,n.jsx)(t.li,{children:"Include it in your Slack bot's message"}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"This tutorial is written assuming you are using Javascript, but the approach is general enough to work for any language."}),"\n",(0,n.jsx)(t.h2,{id:"creating-a-chart-image",children:"Creating a chart image"}),"\n",(0,n.jsxs)(t.p,{children:["If you're already showing these charts on a web frontend, your work here might already be done because QuickChart is built on top of ",(0,n.jsx)(t.a,{href:"https://www.chartjs.org",children:"Chart.js"}),". You can just use your existing Chart.js config. Otherwise, we have to construct a Chart.js config object."]}),"\n",(0,n.jsx)(t.p,{children:"For example, imagine we have the following data:"}),"\n",(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{children:"Retweets"}),(0,n.jsx)(t.th,{children:"Likes"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"12"}),(0,n.jsx)(t.td,{children:"80"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"5"}),(0,n.jsx)(t.td,{children:"42"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"40"}),(0,n.jsx)(t.td,{children:"215"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"5"}),(0,n.jsx)(t.td,{children:"30"})]})]})]}),"\n",(0,n.jsx)(t.p,{children:"First create an object using the Chart.js format:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-js",originalType:"code",children:"const chart = {\n type: 'bar',\n data: {\n labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],\n datasets: [\n {\n label: 'Retweets',\n data: [12, 5, 40, 5],\n },\n {\n label: 'Likes',\n data: [80, 42, 215, 30],\n },\n ],\n },\n};\n"})}),"\n",(0,n.jsx)(t.p,{children:"This object says that we have two data series, Retweets and Likes, and they each have values. The labels for the X axis are Weeks 1-4."}),"\n",(0,n.jsx)(t.p,{children:"Next, we turn the JSON chart specification into a string:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-js",originalType:"code",children:"const encodedChart = encodeURIComponent(JSON.stringify(chart));\n"})}),"\n",(0,n.jsx)(t.p,{children:"And put it into our URL:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-js",originalType:"code",children:"const chartUrl = `https://quickchart.io
2/chart?c=${encodedChart}`;\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This gives a URL that encodes the ",(0,n.jsx)(t.code,{children:"chart"})," object. Let's render that URL in an image tag:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-html",originalType:"code",children:'<img src="https://quickchart.io/chart?c=..." />\n'})}),"\n",(0,n.jsx)(t.p,{children:"We get the image below:"}),"\n",(0,n.jsx)(i.Z,{alt:"Rendered chart image, ready to go on Slack",noBorder:!0,maxWidth:500,src:"https://quickchart.io/chart?bkg=white&c=%7B%0A%20%20type%3A%20%27bar%27%2C%0A%20%20data%3A%20%7B%0A%20%20%20%20labels%3A%20%5B%27Week%201%27%2C%20%27Week%202%27%2C%20%27Week%203%27%2C%20%27Week%204%27%5D%2C%0A%20%20%20%20datasets%3A%20%5B%7B%0A%20%20%20%20%20%20label%3A%20%27Retweets%27%2C%0A%20%20%20%20%20%20data%3A%20%5B12%2C%205%2C%2040%2C%205%5D%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20label%3A%20%27Likes%27%2C%0A%20%20%20%20%20%20data%3A%20%5B80%2C%2042%2C%20215%2C%2030%5D%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D"}),"\n",(0,n.jsx)(t.p,{children:"To learn more about static chart rendering:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Customize your chart using the ",(0,n.jsx)(t.a,{href:"https://www.chartjs.org/docs/2.9.4/charts/bar.html",children:"Chart.js library"})]}),"\n",(0,n.jsxs)(t.li,{children:["Adjust chart rendering using the ",(0,n.jsx)(t.a,{href:"https://quickchart.io/documentation",children:"QuickChart documentation"})]}),"\n",(0,n.jsxs)(t.li,{children:["Use the ",(0,n.jsx)(t.a,{href:"https://quickchart.io/sandbox/",children:"live chart editor"})," to get your chart looking exactly the way you want."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"sending-the-chart-image-to-slack",children:"Sending the chart image to Slack"}),"\n",(0,n.jsx)(t.p,{children:"Now that we've generated a chart image, let's send it to Slack."}),"\n",(0,n.jsx)(t.p,{children:"You have a couple options here:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.a,{href:"https://api.slack.com/methods/files.upload",children:"Upload"})," the file to Slack"]}),"\n",(0,n.jsx)(t.li,{children:'Include the URL in a normal message and have Slack show or "unfurl" it'}),"\n",(0,n.jsxs)(t.li,{children:["Use the ",(0,n.jsx)(t.a,{href:"https://api.slack.com/reference/block-kit/blocks#image",children:"Image Block"})]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"We'll go with the third choice because it is the most practical. We construct a block like so, using the image URL from above."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-json",originalType:"code",children:'[\n {\n "type": "image",\n "title": {\n "type": "plain_text",\n "text": "Latest data"\n },\n "block_id": "quickchart-image",\n "image_url": "https://quickchart.io/chart?bkg=white&c=%7B%0A%20%20type%3A%20%27bar%27%2C%0A%20%20data%3A%20%7B%0A%20%20%20%20labels%3A%20%5B%27Week%201%27%2C%20%27Week%202%27%2C%20%27Week%203%27%2C%20%27Week%204%27%5D%2C%0A%20%20%20%20datasets%3A%20%5B%7B%0A%20%20%20%20%20%20label%3A%20%27Retweets%27%2C%0A%20%20%20%20%20%20data%3A%20%5B12%2C%205%2C%2040%2C%205%5D%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20label%3A%20%27Likes%27%2C%0A%20%20%20%20%20%20data%3A%20%5B80%2C%2042%2C%20215%2C%2030%5D%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D",\n "alt_text": "Chart showing latest data"\n }\n]\n'})}),"\n",(0,n.jsxs)(t.p,{children:["You can try this directly in Slack's ",(0,n.jsx)(t.a,{href:"https://api.slack.com/tools/block-kit-builder?mode=message&blocks=%5B%7B%22type%22%3A%22image%22%2C%22title%22%3A%7B%22type%22%3A%22plain_text%22%2C%22text%22%3A%22Latest%20data%22%7D%2C%22block_id%22%3A%22quickchart-image%22%2C%22image_url%22%3A%22https%3A%2F%2Fquickchart.io%2Fchart%3Fbkg%3Dwhite%26c%3D%257B%250A%2520%2520type%253A%2520%2527bar%2527%252C%250A%2520%2520data%253A%2520%257B%250A%2520%2520%2520%2520labels%253A%2520%255B%2527Week%25201%2527%252C%2520%2527Week%25202%2527%252C%2520%2527Week%25203%2527%252C%2520%2527Week%25204%2527%255D%252C%250A%2520%2520%2520%2520datasets%253A%2520%255B%257B%250A%2520%2520%2520%2520%2520%2520label%253A%2520%2527Retweets%2527%252C%250A%2520%2520%2520%2520%2520%2520data%253A%2520%255B12%252C%25205%252C%252040%252C%25205%255D%250A%2520%2520%2520%2520%257D%252C%2520%257B%250A%2520%2520%2520%2520%2520%2520label%253A%2520%2527Likes%2527%252C%250A%2520%2520%2520%2520%2520%2520data%253A%2520%255B80%252C%252042%252C%25202
215%252C%252030%255D%250A%2520%2520%2520%2520%257D%255D%250A%2520%2520%257D%250A%257D%22%2C%22alt_text%22%3A%22Chart%20showing%20latest%20data%22%7D%5D",children:"Block Kit Builder"}),". Have a look at the Slack documentation and play around with the different settings:"]}),"\n",(0,n.jsx)(i.Z,{alt:"Slack block kit builder",noBorder:!0,src:"https://i.imgur.com/NK6s8Lnl.png"}),"\n",(0,n.jsxs)(t.p,{children:["In order to send the image blocks from your bot, use Slack's ",(0,n.jsx)(t.a,{href:"https://api.slack.com/methods/chat.postMessage",children:"chat.postMessage"})," API endpoint."]}),"\n",(0,n.jsx)(t.p,{children:"Starting with the basics, let's use this boilerplate for our communication with the Slack API. If you're using a helper library you probably already have a way to send messages, but here is the boilerplate I always use:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-js",originalType:"code",children:"const request = require('request');\n\n// Put your bot token here.\nconst SLACK_BOT_USER_TOKEN = 'xyz123';\n\nfunction sendMessage(data) {\n request(\n {\n url: 'https://slack.com/api/chat.postMessage',\n method: 'POST',\n json: data,\n headers: {\n 'Content-Type': 'application/json; charset=utf-8',\n Authorization: `Bearer ${SLACK_BOT_USER_TOKEN}`,\n },\n },\n function (error, response, body) {\n if (error || response.statusCode !== 200) {\n console.error('Error sending slack response:', error);\n } else if (!response.body.ok) {\n console.error('Slack responded with error:', response.body);\n } else {\n // All good!\n }\n },\n );\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Now, we'll put it all together and send the message with chart image URL:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-js",originalType:"code",children:"sendMessage({\n text: 'Chart data update',\n blocks: [\n {\n type: 'image',\n title: {\n type: 'plain_text',\n text: 'Latest data',\n },\n block_id: 'quickchart-image',\n image_url:\n 'https://quickchart.io/chart?bkg=white&c=%7B%0A%20%20type%3A%20%27bar%27%2C%0A%20%20data%3A%20%7B%0A%20%20%20%20labels%3A%20%5B%27Week%201%27%2C%20%27Week%202%27%2C%20%27Week%203%27%2C%20%27Week%204%27%5D%2C%0A%20%20%20%20datasets%3A%20%5B%7B%0A%20%20%20%20%20%20label%3A%20%27Retweets%27%2C%0A%20%20%20%20%20%20data%3A%20%5B12%2C%205%2C%2040%2C%205%5D%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20label%3A%20%27Likes%27%2C%0A%20%20%20%20%20%20data%3A%20%5B80%2C%2042%2C%20215%2C%2030%5D%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D',\n alt_text: 'Chart showing latest data',\n },\n ],\n});\n"})}),"\n",(0,n.jsx)(t.p,{children:"That's it! Our message is sent and the graph appears in Slack."}),"\n",(0,n.jsx)(i.Z,{alt:"Graph from a Slack bot",noBorder:!0,src:"https://i.imgur.com/ab9fOuA.png"}),"\n",(0,n.jsxs)(t.p,{children:["Need more help? Ask questions in our ",(0,n.jsx)(t.a,{href:"https://community.quickchart.io/",children:"community"}),"."]}),"\n",(0,n.jsx)(s.Z,{})]})}const p=function(e){void 0===e&&(e={});const{wrapper:t}=Object.assign({},(0,r.ah)(),e.components);return t?(0,n.jsx)(t,Object.assign({},e,{children:(0,n.jsx)(d,e)})):d(e)}},5251:(e,t,a)=>{a(7418);var n=a(7294),r=60103;if(t.Fragment=60107,"function"==typeof Symbol&&Symbol.for){var s=Symbol.for;r=s("react.element"),t.Fragment=s("react.fragment")}var i=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c=Object.prototype.hasOwnProperty,l={key:!0,ref:!0,__self:!0,__source:!0};function o(e,t,a){var n,s={},o=null,h=null;for(n in void 0!==a&&(o=""+a),void 0!==t.key&&(o=""+t.key),void 0!==t.ref&&(h=t.ref),t)c.call(t,n)&&!l.hasOwnProperty(n)&&(s[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===s[n]&&(s[n]=t[n]);return{$$typeof:r,type:e,key:o,ref:h,props:s,_owner:i.current}}t.jsx=o,t.jsxs=o},5893:(e,t,a)=>{e.exports=a(5251)},1151:(e,t,a)=>{a.d(t,{Zo:()=>c,ah:()=>s});var n=a(7294);const r=n.createContext({});function s(e){const t=n.useContext(r);return n.useMemo((()=>"function"==typeof e?e(t):{...t,...e}),[t,e])}const i={};function c({components:e,children:t,disableParentContext:a}){let c=s(e);return a&&(c=e||i),n.createElement(r.Provider,{value:c},t)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.