├── .env ├── .gitignore ├── ATTRIBUTIONS.md ├── CONTRIBUTING.md ├── LICENSE.md ├── app.json ├── bot.js ├── components ├── express_webserver.js ├── onboarding.js ├── plugin_glitch.js ├── routes │ ├── incoming_webhooks.js │ └── oauth.js ├── rtm_manager.js └── user_registration.js ├── docs └── glitch_directory.md ├── glitch_readme.md ├── package-lock.json ├── package.json ├── public ├── login_error.html ├── login_success.html ├── styles.css └── styles.css.map ├── readme.md ├── sass └── styles.scss ├── skills ├── channel_join.js ├── interactive_messages.js ├── sample_conversations.js ├── sample_events.js ├── sample_hears.js ├── sample_middleware.js └── sample_taskbot.js └── views ├── index.hbs ├── installation.hbs ├── layouts └── default.hbs ├── partials ├── footer.hbs ├── head.hbs ├── header.hbs └── tabs_head.hbs └── styles.css /.env: -------------------------------------------------------------------------------- 1 | # Environment Config 2 | 3 | # store your secrets and config variables in here 4 | # only invited collaborators will be able to see your .env values 5 | # reference these in your code with process.env.SECRET 6 | 7 | clientId= 8 | clientSecret= 9 | clientSigningSecret= 10 | studio_token= 11 | PORT= 12 | 13 | # note: .env is a shell file so there can’t be spaces around = 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | .env 3 | node_modules 4 | components/routes/_* 5 | .sass-cache/* 6 | -------------------------------------------------------------------------------- /ATTRIBUTIONS.md: -------------------------------------------------------------------------------- 1 | 2 | # key-tree-store 3 | 4 | Copyright (c) Henrik Joreteg 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | 12 | # set-immediate-shim 13 | 14 | Copyright (c) Sindre Sorhus (sindresorhus.com) 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | # json-schema 23 | 24 | The "New" BSD License: 25 | ********************** 26 | 27 | Copyright (c) 2005-2018, The JS Foundation 28 | All rights reserved. 29 | 30 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 31 | 32 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 33 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 34 | * Neither the name of the JS Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 35 | 36 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | # browser-request 40 | 41 | Copyright (c) 2014 Jason Smith Work , Jason Smith , maxogden 42 | 43 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 44 | 45 | http://www.apache.org/licenses/LICENSE-2.0 46 | 47 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 48 | 49 | 50 | # weak-map 51 | 52 | Copyright (c) 2011 Google Inc., Kris Kowal 53 | 54 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 55 | 56 | http://www.apache.org/licenses/LICENSE-2.0 57 | 58 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 59 | 60 | 61 | # scmp 62 | 63 | Copyright (c) 2014, Sean Lavine 64 | All rights reserved. 65 | 66 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 67 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 68 | * Neither the name of the scmp project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 69 | 70 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 71 | 72 | 73 | # spdx-exceptions 74 | 75 | spdx-exceptions.json (c) 2010-2015 Linux Foundation and its Contributors. 76 | 77 | spdx-exceptions.json is licensed under a Creative Commons Attribution 3.0 Unported License (CC BY 3.0) License. 78 | 79 | You should have received a copy of the license along with this work. If not, see https://creativecommons.org/licenses/by/3.0/legalcode. 80 | 81 | 82 | # botkit-studio-metrics 83 | 84 | Copyright (c) ben@howdy.ai 85 | 86 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 87 | 88 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 89 | 90 | 91 | # xmpp.js 92 | 93 | Copyright (c) 2017, xmpp.js 94 | 95 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 96 | 97 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 98 | 99 | 100 | # url-join 101 | 102 | Copyright (c) Rogier Schouten , Mike Deverell 103 | 104 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 105 | 106 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 107 | 108 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 109 | 110 | 111 | # ampersand-version 112 | 113 | Copyright (c) 2014 &yet, LLC and AmpersandJS contributors 114 | 115 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 116 | 117 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 118 | 119 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 120 | 121 | # array-next 122 | 123 | Copyright (c) Henrik Joreteg 124 | 125 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 126 | 127 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 128 | 129 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 130 | 131 | 132 | # botbuilder 133 | 134 | Copyright (c) 2016 Microsoft 135 | 136 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 137 | 138 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 139 | 140 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 141 | 142 | 143 | # botkit-studio-sdk 144 | 145 | Copyright (c) howdyai 146 | 147 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 148 | 149 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 150 | 151 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 152 | 153 | 154 | # ciscospark 155 | 156 | Copyright (c) 2016-2018 Cisco and/or its affiliates. All Rights Reserved. 157 | 158 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 159 | 160 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 161 | 162 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 163 | 164 | 165 | # concat-map 166 | 167 | Copyright (c) James Halliday 168 | 169 | Permission is hereby granted, free of charge, to any person obtaining a copy of 170 | this software and associated documentation files (the "Software"), to deal in 171 | the Software without restriction, including without limitation the rights to 172 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 173 | the Software, and to permit persons to whom the Software is furnished to do so, 174 | subject to the following conditions: 175 | 176 | The above copyright notice and this permission notice shall be included in all 177 | copies or substantial portions of the Software. 178 | 179 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 180 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 181 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 182 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 183 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 184 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 185 | 186 | 187 | # deprecate 188 | 189 | Copyright (c) Brian M. Carlson 190 | 191 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 192 | 193 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 194 | 195 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 196 | 197 | 198 | # envify 199 | 200 | Copyright (c) Hugh Kennedy (http://hughskennedy.com/) 201 | 202 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 203 | 204 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 205 | 206 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 207 | 208 | 209 | # es6-promisify 210 | 211 | Copyright (c) 2014 Mike Hall / Digital Design Labs 212 | 213 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 214 | 215 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 216 | 217 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 218 | 219 | # exit-hook 220 | 221 | "Copyright (c) Sindre Sorhus (sindresorhus.com) 222 | 223 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 224 | 225 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 226 | 227 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." 228 | 229 | 230 | # fast-json-stable-stringify 231 | 232 | Copyright (c) James Halliday 233 | 234 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 235 | 236 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 237 | 238 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 239 | 240 | 241 | # inquirer 242 | 243 | Copyright (c) 2012 Simon Boudrias 244 | 245 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 246 | 247 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 248 | 249 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 250 | 251 | # invert-kv 252 | 253 | Copyright (c) Sindre Sorhus (sindresorhus.com) 254 | 255 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 256 | 257 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 258 | 259 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 260 | 261 | 262 | 263 | # is-typedarray 264 | 265 | Copyright (c) Hugh Kennedy (http://hughsk.io/) 266 | 267 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 268 | 269 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 270 | 271 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 272 | 273 | 274 | # minimist 275 | 276 | Copyright (c) James Halliday 277 | 278 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 279 | 280 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 281 | 282 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 283 | 284 | 285 | # node-xmpp-client 286 | 287 | Copyright (c) 2016 node-xmpp 288 | 289 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 290 | 291 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 292 | 293 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 294 | 295 | # node-xmpp-core 296 | 297 | Copyright (c) 2016 node-xmpp 298 | 299 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 300 | 301 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 302 | 303 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 304 | 305 | 306 | 307 | # node-xmpp-tls-connect 308 | 309 | Copyright (c) 2016 node-xmpp 310 | 311 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 312 | 313 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 314 | 315 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 316 | 317 | 318 | # openurl 319 | 320 | Copyright (c) Axel Rauschmayer 321 | 322 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 323 | 324 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 325 | 326 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 327 | 328 | 329 | # pop-iterate 330 | 331 | Copyright (c) Kris Kowal 332 | 333 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 334 | 335 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 336 | 337 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 338 | 339 | # qbox 340 | 341 | Copyright (c) Arunoda Susiripala 342 | 343 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 344 | 345 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 346 | 347 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 348 | 349 | 350 | # readline2 351 | Copyright (c) 2014 Simon Boudrias 352 | 353 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 354 | 355 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 356 | 357 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 358 | 359 | 360 | # regenerator-runtime 361 | 362 | Copyright (c) 2014-present, Facebook, Inc. 363 | 364 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 365 | 366 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 367 | 368 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 369 | 370 | 371 | # rootpath 372 | 373 | Copyright (c) Fabrizio Moscon 374 | 375 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 376 | 377 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 378 | 379 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 380 | 381 | # wordwrap 382 | 383 | Copyright (c) James Halliday 384 | 385 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 386 | 387 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 388 | 389 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Instructions for Contributing Code 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 6 | 7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 12 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 13 | provided by the bot. You will only need to do this once across all repos using our CLA. 14 | 15 | ## Code of Conduct 16 | 17 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Botkit Starter Kit", 3 | "description": "A starting point for building custom Slack applications", 4 | "repository": "https://github.com/howdyai/botkit-starter-slack", 5 | "keywords": ["node", "bots", "slack","botkit"], 6 | "website": "https://botkit.ai/", 7 | "success_url":"/", 8 | "addons":[ 9 | { 10 | "plan": "mongolab", 11 | "as": "MONGO" 12 | } 13 | ], 14 | "env": { 15 | "clientId": { 16 | "description": "Client ID provided by Slack" 17 | }, 18 | "clientSecret": { 19 | "description": "Client Secret provided by Slack" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bot.js: -------------------------------------------------------------------------------- 1 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | ______ ______ ______ __ __ __ ______ 3 | /\ == \ /\ __ \ /\__ _\ /\ \/ / /\ \ /\__ _\ 4 | \ \ __< \ \ \/\ \ \/_/\ \/ \ \ _"-. \ \ \ \/_/\ \/ 5 | \ \_____\ \ \_____\ \ \_\ \ \_\ \_\ \ \_\ \ \_\ 6 | \/_____/ \/_____/ \/_/ \/_/\/_/ \/_/ \/_/ 7 | 8 | 9 | This is a sample Slack bot built with Botkit. 10 | 11 | This bot demonstrates many of the core features of Botkit: 12 | 13 | * Connect to Slack using the real time API 14 | * Receive messages based on "spoken" patterns 15 | * Reply to messages 16 | * Use the conversation system to ask questions 17 | * Use the built in storage system to store and retrieve information 18 | for a user. 19 | 20 | # RUN THE BOT: 21 | 22 | Create a new app via the Slack Developer site: 23 | 24 | -> http://api.slack.com 25 | 26 | Run your bot from the command line: 27 | 28 | clientId= clientSecret= PORT=<3000> node bot.js 29 | 30 | # USE THE BOT: 31 | 32 | Navigate to the built-in login page: 33 | 34 | https:///login 35 | 36 | This will authenticate you with Slack. 37 | 38 | If successful, your bot will come online and greet you. 39 | 40 | 41 | # EXTEND THE BOT: 42 | 43 | Botkit has many features for building cool and useful bots! 44 | 45 | Read all about it here: 46 | 47 | -> http://howdy.ai/botkit 48 | 49 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 50 | var env = require('node-env-file'); 51 | env(__dirname + '/.env'); 52 | 53 | 54 | if (!process.env.clientId || !process.env.clientSecret || !process.env.PORT) { 55 | usage_tip(); 56 | // process.exit(1); 57 | } 58 | 59 | var Botkit = require('botkit'); 60 | var debug = require('debug')('botkit:main'); 61 | 62 | var bot_options = { 63 | clientId: process.env.clientId, 64 | clientSecret: process.env.clientSecret, 65 | clientSigningSecret: process.env.clientSigningSecret, 66 | // debug: true, 67 | scopes: ['bot'], 68 | studio_token: process.env.studio_token, 69 | studio_command_uri: process.env.studio_command_uri 70 | }; 71 | 72 | // Use a mongo database if specified, otherwise store in a JSON file local to the app. 73 | // Mongo is automatically configured when deploying to Heroku 74 | if (process.env.MONGO_URI) { 75 | var mongoStorage = require('botkit-storage-mongo')({mongoUri: process.env.MONGO_URI}); 76 | bot_options.storage = mongoStorage; 77 | } else { 78 | bot_options.json_file_store = __dirname + '/.data/db/'; // store user data in a simple JSON format 79 | } 80 | 81 | // Create the Botkit controller, which controls all instances of the bot. 82 | var controller = Botkit.slackbot(bot_options); 83 | 84 | controller.startTicking(); 85 | 86 | // Set up an Express-powered webserver to expose oauth and webhook endpoints 87 | var webserver = require(__dirname + '/components/express_webserver.js')(controller); 88 | 89 | if (!process.env.clientId || !process.env.clientSecret) { 90 | 91 | // Load in some helpers that make running Botkit on Glitch.com better 92 | require(__dirname + '/components/plugin_glitch.js')(controller); 93 | 94 | webserver.get('/', function(req, res){ 95 | res.render('installation', { 96 | domain: req.get('host'), 97 | protocol: req.protocol, 98 | glitch_domain: process.env.PROJECT_DOMAIN, 99 | layout: 'layouts/default' 100 | }); 101 | }) 102 | 103 | var where_its_at = 'http://' + (process.env.PROJECT_DOMAIN ? process.env.PROJECT_DOMAIN+ '.glitch.me/' : 'localhost:' + process.env.PORT || 3000); 104 | console.log('WARNING: This application is not fully configured to work with Slack. Please see instructions at ' + where_its_at); 105 | }else { 106 | 107 | webserver.get('/', function(req, res){ 108 | res.render('index', { 109 | domain: req.get('host'), 110 | protocol: req.protocol, 111 | glitch_domain: process.env.PROJECT_DOMAIN, 112 | layout: 'layouts/default' 113 | }); 114 | }) 115 | // Set up a simple storage backend for keeping a record of customers 116 | // who sign up for the app via the oauth 117 | require(__dirname + '/components/user_registration.js')(controller); 118 | 119 | // Send an onboarding message when a new team joins 120 | require(__dirname + '/components/onboarding.js')(controller); 121 | 122 | // Load in some helpers that make running Botkit on Glitch.com better 123 | require(__dirname + '/components/plugin_glitch.js')(controller); 124 | 125 | var normalizedPath = require("path").join(__dirname, "skills"); 126 | require("fs").readdirSync(normalizedPath).forEach(function(file) { 127 | require("./skills/" + file)(controller); 128 | }); 129 | 130 | // This captures and evaluates any message sent to the bot as a DM 131 | // or sent to the bot in the form "@bot message" and passes it to 132 | // Botkit CMS to evaluate for trigger words and patterns. 133 | // If a trigger is matched, the conversation will automatically fire! 134 | // You can tie into the execution of the script using the functions 135 | // controller.studio.before, controller.studio.after and controller.studio.validate 136 | if (process.env.studio_token) { 137 | controller.on('direct_message,direct_mention,mention', function(bot, message) { 138 | controller.studio.runTrigger(bot, message.text, message.user, message.channel, message).then(function(convo) { 139 | if (!convo) { 140 | // no trigger was matched 141 | // If you want your bot to respond to every message, 142 | // define a 'fallback' script in Botkit CMS 143 | // and uncomment the line below. 144 | // controller.studio.run(bot, 'fallback', message.user, message.channel); 145 | } else { 146 | // set variables here that are needed for EVERY script 147 | // use controller.studio.before('script') to set variables specific to a script 148 | convo.setVar('current_time', new Date()); 149 | } 150 | }).catch(function(err) { 151 | bot.reply(message, 'I experienced an error with a request to Botkit CMS: ' + err); 152 | debug('Botkit CMS: ', err); 153 | }); 154 | }); 155 | } else { 156 | console.log('~~~~~~~~~~'); 157 | console.log('NOTE: Botkit CMS functionality has not been enabled'); 158 | console.log('Learn mode https://github.com/howdyai/botkit-cms'); 159 | } 160 | } 161 | 162 | 163 | 164 | 165 | 166 | function usage_tip() { 167 | console.log('~~~~~~~~~~'); 168 | console.log('Botkit Starter Kit'); 169 | console.log('Execute your bot application like this:'); 170 | console.log('clientId= clientSecret= PORT=3000 node bot.js'); 171 | console.log('Get Slack app credentials here: https://api.slack.com/apps') 172 | console.log('~~~~~~~~~~'); 173 | } 174 | -------------------------------------------------------------------------------- /components/express_webserver.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var bodyParser = require('body-parser'); 3 | var cookieParser = require('cookie-parser'); 4 | var querystring = require('querystring'); 5 | var debug = require('debug')('botkit:webserver'); 6 | var http = require('http'); 7 | var hbs = require('express-hbs'); 8 | 9 | module.exports = function(controller) { 10 | 11 | var webserver = express(); 12 | webserver.use(function(req, res, next) { 13 | req.rawBody = ''; 14 | 15 | req.on('data', function(chunk) { 16 | req.rawBody += chunk; 17 | }); 18 | 19 | next(); 20 | }); 21 | webserver.use(cookieParser()); 22 | webserver.use(bodyParser.json()); 23 | webserver.use(bodyParser.urlencoded({ extended: true })); 24 | 25 | // set up handlebars ready for tabs 26 | webserver.engine('hbs', hbs.express4({partialsDir: __dirname + '/../views/partials'})); 27 | webserver.set('view engine', 'hbs'); 28 | webserver.set('views', __dirname + '/../views/'); 29 | 30 | webserver.use(express.static('public')); 31 | 32 | var server = http.createServer(webserver); 33 | 34 | server.listen(process.env.PORT || 3000, null, function() { 35 | 36 | console.log('Express webserver configured and listening at http://localhost:' + process.env.PORT || 3000); 37 | 38 | }); 39 | 40 | // import all the pre-defined routes that are present in /components/routes 41 | var normalizedPath = require("path").join(__dirname, "routes"); 42 | require("fs").readdirSync(normalizedPath).forEach(function(file) { 43 | require("./routes/" + file)(webserver, controller); 44 | }); 45 | 46 | controller.webserver = webserver; 47 | controller.httpserver = server; 48 | 49 | return webserver; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /components/onboarding.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:onboarding'); 2 | 3 | module.exports = function(controller) { 4 | 5 | controller.on('onboard', function(bot) { 6 | debug('Starting an onboarding experience!'); 7 | bot.startPrivateConversation({user: bot.config.createdBy},function(err,convo) { 8 | if (err) { 9 | console.log(err); 10 | } else { 11 | convo.say('I am a bot that has just joined your team'); 12 | convo.say('You must now /invite me to a channel so that I can be of use!'); 13 | } 14 | }); 15 | }); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /components/plugin_glitch.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | module.exports = function(controller) { 3 | 4 | function keepalive() { 5 | 6 | request({ 7 | url: 'http://' + process.env.PROJECT_DOMAIN + '.glitch.me', 8 | }, function(err) { 9 | 10 | setTimeout(function() { 11 | keepalive(); 12 | }, 55000); 13 | 14 | }); 15 | 16 | } 17 | 18 | // if this is running on Glitch 19 | if (process.env.PROJECT_DOMAIN) { 20 | // make a web call to self every 55 seconds 21 | // in order to avoid the process being put to sleep. 22 | keepalive(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/routes/incoming_webhooks.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:incoming_webhooks'); 2 | 3 | module.exports = function(webserver, controller) { 4 | 5 | debug('Configured /slack/receive url'); 6 | webserver.post('/slack/receive', function(req, res) { 7 | 8 | // NOTE: we should enforce the token check here 9 | 10 | // respond to Slack that the webhook has been received. 11 | res.status(200); 12 | 13 | // Now, pass the webhook into be processed 14 | controller.handleWebhookPayload(req, res); 15 | 16 | }); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /components/routes/oauth.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:oauth'); 2 | 3 | module.exports = function(webserver, controller) { 4 | 5 | var handler = { 6 | login: function(req, res) { 7 | res.redirect(controller.getAuthorizeURL()); 8 | }, 9 | oauth: function(req, res) { 10 | var code = req.query.code; 11 | var state = req.query.state; 12 | 13 | // we need to use the Slack API, so spawn a generic bot with no token 14 | var slackapi = controller.spawn({}); 15 | 16 | var opts = { 17 | client_id: controller.config.clientId, 18 | client_secret: controller.config.clientSecret, 19 | code: code 20 | }; 21 | 22 | slackapi.api.oauth.access(opts, function(err, auth) { 23 | 24 | if (err) { 25 | debug('Error confirming oauth', err); 26 | return res.redirect('/login_error.html'); 27 | } 28 | 29 | // what scopes did we get approved for? 30 | var scopes = auth.scope.split(/\,/); 31 | 32 | // use the token we got from the oauth 33 | // to call auth.test to make sure the token is valid 34 | // but also so that we reliably have the team_id field! 35 | slackapi.api.auth.test({token: auth.access_token}, function(err, identity) { 36 | 37 | if (err) { 38 | debug('Error fetching user identity', err); 39 | return res.redirect('/login_error.html'); 40 | } 41 | 42 | // Now we've got all we need to connect to this user's team 43 | // spin up a bot instance, and start being useful! 44 | // We just need to make sure this information is stored somewhere 45 | // and handled with care! 46 | 47 | // In order to do this in the most flexible way, we fire 48 | // a botkit event here with the payload so it can be handled 49 | // by the developer without meddling with the actual oauth route. 50 | 51 | auth.identity = identity; 52 | controller.trigger('oauth:success', [auth]); 53 | 54 | res.cookie('team_id', auth.team_id); 55 | res.cookie('bot_user_id', auth.bot.bot_user_id); 56 | res.redirect('/login_success.html'); 57 | 58 | }); 59 | 60 | 61 | }); 62 | } 63 | } 64 | 65 | 66 | // Create a /login link 67 | // This link will send user's off to Slack to authorize the app 68 | // See: https://github.com/howdyai/botkit/blob/master/readme-slack.md#custom-auth-flows 69 | debug('Configured /login url'); 70 | webserver.get('/login', handler.login); 71 | 72 | // Create a /oauth link 73 | // This is the link that receives the postback from Slack's oauth system 74 | // So in Slack's config, under oauth redirect urls, 75 | // your value should be https:///oauth 76 | debug('Configured /oauth url'); 77 | webserver.get('/oauth', handler.oauth); 78 | 79 | return handler; 80 | } 81 | -------------------------------------------------------------------------------- /components/rtm_manager.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:rtm_manager'); 2 | 3 | module.exports = function(controller) { 4 | 5 | var managed_bots = {}; 6 | 7 | // Capture the rtm:start event and actually start the RTM... 8 | controller.on('rtm:start', function(config) { 9 | var bot = controller.spawn(config); 10 | manager.start(bot); 11 | }); 12 | 13 | // 14 | controller.on('rtm_close', function(bot) { 15 | manager.remove(bot); 16 | }); 17 | 18 | // The manager object exposes some useful tools for managing the RTM 19 | var manager = { 20 | start: function(bot) { 21 | 22 | if (managed_bots[bot.config.token]) { 23 | debug('Start RTM: already online'); 24 | } else { 25 | bot.startRTM(function(err, bot) { 26 | if (err) { 27 | debug('Error starting RTM:', err); 28 | } else { 29 | managed_bots[bot.config.token] = bot.rtm; 30 | debug('Start RTM: Success'); 31 | } 32 | }); 33 | } 34 | }, 35 | stop: function(bot) { 36 | if (managed_bots[bot.config.token]) { 37 | if (managed_bots[bot.config.token].rtm) { 38 | debug('Stop RTM: Stopping bot'); 39 | managed_bots[bot.config.token].closeRTM() 40 | } 41 | } 42 | }, 43 | remove: function(bot) { 44 | debug('Removing bot from manager'); 45 | delete managed_bots[bot.config.token]; 46 | }, 47 | reconnect: function() { 48 | 49 | debug('Reconnecting all existing bots...'); 50 | controller.storage.teams.all(function(err, list) { 51 | 52 | if (err) { 53 | throw new Error('Error: Could not load existing bots:', err); 54 | } else { 55 | for (var l = 0; l < list.length; l++) { 56 | manager.start(controller.spawn(list[l].bot)); 57 | } 58 | } 59 | 60 | }); 61 | 62 | } 63 | } 64 | 65 | 66 | return manager; 67 | 68 | } 69 | -------------------------------------------------------------------------------- /components/user_registration.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:user_registration'); 2 | 3 | module.exports = function(controller) { 4 | 5 | /* Handle event caused by a user logging in with oauth */ 6 | controller.on('oauth:success', function(payload) { 7 | 8 | debug('Got a successful login!', payload); 9 | if (!payload.identity.team_id) { 10 | debug('Error: received an oauth response without a team id', payload); 11 | } 12 | controller.storage.teams.get(payload.identity.team_id, function(err, team) { 13 | if (err) { 14 | debug('Error: could not load team from storage system:', payload.identity.team_id, err); 15 | } 16 | 17 | var new_team = false; 18 | if (!team) { 19 | team = { 20 | id: payload.identity.team_id, 21 | createdBy: payload.identity.user_id, 22 | url: payload.identity.url, 23 | name: payload.identity.team, 24 | }; 25 | var new_team= true; 26 | } 27 | 28 | team.bot = { 29 | token: payload.bot.bot_access_token, 30 | user_id: payload.bot.bot_user_id, 31 | createdBy: payload.identity.user_id, 32 | app_token: payload.access_token, 33 | }; 34 | 35 | var testbot = controller.spawn(team.bot); 36 | 37 | testbot.api.auth.test({}, function(err, bot_auth) { 38 | if (err) { 39 | debug('Error: could not authenticate bot user', err); 40 | } else { 41 | team.bot.name = bot_auth.user; 42 | 43 | // add in info that is expected by Botkit 44 | testbot.identity = bot_auth; 45 | 46 | testbot.identity.id = bot_auth.user_id; 47 | testbot.identity.name = bot_auth.user; 48 | 49 | testbot.team_info = team; 50 | 51 | // Replace this with your own database! 52 | 53 | controller.storage.teams.save(team, function(err, id) { 54 | if (err) { 55 | debug('Error: could not save team record:', err); 56 | } else { 57 | if (new_team) { 58 | controller.trigger('create_team', [testbot, team]); 59 | } else { 60 | controller.trigger('update_team', [testbot, team]); 61 | } 62 | } 63 | }); 64 | } 65 | }); 66 | }); 67 | }); 68 | 69 | 70 | controller.on('create_team', function(bot, team) { 71 | 72 | debug('Team created:', team); 73 | 74 | // Trigger an event that will establish an RTM connection for this bot 75 | controller.trigger('rtm:start', [bot.config]); 76 | 77 | // Trigger an event that will cause this team to receive onboarding messages 78 | controller.trigger('onboard', [bot, team]); 79 | 80 | }); 81 | 82 | 83 | controller.on('update_team', function(bot, team) { 84 | 85 | debug('Team updated:', team); 86 | // Trigger an event that will establish an RTM connection for this bot 87 | controller.trigger('rtm:start', [bot]); 88 | 89 | }); 90 | 91 | } 92 | -------------------------------------------------------------------------------- /docs/glitch_directory.md: -------------------------------------------------------------------------------- 1 | # Botkit Starter Kit for Slack Bots 2 | 3 | This repo contains everything you need to get started building a Slack bot with [Botkit](https://botkit.ai). 4 | 5 | Botkit is designed to ease the process of designing and running useful, creative bots that live inside messaging platforms. Bots are applications that can send and receive messages, and in many cases, appear alongside their human counterparts as users. 6 | 7 | Some bots talk like people, others silently work in the background, while others present interfaces much like modern mobile applications. Botkit gives developers the necessary tools for building bots of any kind! It provides an easy-to-understand interface for sending and receiving messages so that developers can focus on creating novel applications and experiences instead of dealing with API endpoints. 8 | 9 | Our goal with Botkit is to make bot building easy, fun, and accessible to anyone with the desire to create a future filled with talking machines! 10 | 11 | If you are looking to create a bot on other platforms using Glitch, check out the [Botkit project page](https://glitch.com/botkit). 12 | 13 | ### What's Included 14 | * [Botkit core](https://github.com/howdyai/botkit/blob/master/docs/readme.md#developing-with-botkit) - a complete programming system for building conversational software 15 | * [Pre-configured Express.js webserver](https://expressjs.com/) including: 16 | * A customizable "Install my Bot" homepage 17 | * Login and oauth endpoints that allow teams to install your bot 18 | * Webhook endpoints for communicating with platforms 19 | * Sample skill modules that demonstrate various features of Botkit 20 | 21 | ### Getting Started 22 | 23 | There are a myriad of methods you can use to set up an application on Slack, but we feel this is the most flexible path you can use to setup your bot on the Slack Events API. 24 | 25 | #### Set up your Slack Application 26 | 27 | Once you have remixed this project, the next thing you will want to do is set up a new Slack application via the [Slack developer portal](https://api.slack.com/). This is a multi-step process, but only takes a few minutes. 28 | 29 | * [Read this step-by-step guide](https://github.com/howdyai/botkit/blob/master/docs/slack-events-api.md) to make sure everything is set up. 30 | * We also have this [handy video walkthrough](https://youtu.be/us2zdf0vRz0) for setting up this project with Glitch. 31 | 32 | Update the `.env` file in the Glitch project with your newly acquired tokens. 33 | 34 | Once all your tokens have been entered, your `Show Live` button should become green. Click this button and you will see an option to add this bot to your team. 35 | 36 | Now comes the fun part of [making your bot!](https://github.com/howdyai/botkit/blob/master/docs/readme.md#basic-usage) 37 | 38 | # Developer & Support Community 39 | 40 | You can find full documentation for Botkit on our [GitHub page](https://github.com/howdyai/botkit/blob/master/readme.md). 41 | 42 | ### Need more help? 43 | * Glitch allows users to ask the community for help directly from the editor! For more information on raising your hand, [read this blog post.](https://medium.com/glitch/just-raise-your-hand-how-glitch-helps-aa6564cb1685) 44 | 45 | * Join our thriving community of Botkit developers and bot enthusiasts at large. Over 4500 members strong, [our open Slack group](http://community.botkit.ai) is _the place_ for people interested in the art and science of making bots. 46 | 47 | Come to ask questions, share your progress, and commune with your peers! 48 | 49 | * We also host a [regular meetup and annual conference called TALKABOT.](http://talkabot.ai) Come meet and learn from other bot developers! 50 | 51 | [Full video of our 2016 event is available on Youtube.](https://www.youtube.com/playlist?list=PLD3JNfKLDs7WsEHSal2cfwG0Fex7A6aok) 52 | 53 | 54 | 55 | # About Botkit 56 | 57 | Botkit is a product of [Howdy](https://howdy.ai) and made in Austin, TX with the help of a worldwide community of botheads. 58 | -------------------------------------------------------------------------------- /glitch_readme.md: -------------------------------------------------------------------------------- 1 | # Howdy, bot builder! 2 | ## When you see "Show Live" in the upper left corner, your new bot app is live. 3 | ## Click the sunglasses to view your app! 4 | 5 | ### Having trouble? 6 | * You should check [that your .env file](?path=.env:1:0) has all the correct tokens. 7 | 8 | * *Raise your hand!* - Glitch allows users to ask the community for help directly from the editor! For more information on raising your hand, [read this blog post.](https://medium.com/glitch/just-raise-your-hand-how-glitch-helps-aa6564cb1685) 9 | 10 | * Join our thriving community of Botkit developers and bot enthusiasts at large. Over 9000 members strong, [our open community group](http://community.botkit.ai) is _the place_ for people interested in the art and science of making bots. 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit-starter-slack", 3 | "version": "0.0.2", 4 | "description": "A starter kit for building a custom Slack bot with Botkit", 5 | "main": "bot.js", 6 | "scripts": { 7 | "start": "node bot.js" 8 | }, 9 | "dependencies": { 10 | "body-parser": "^1.15.2", 11 | "botkit": "^0.7.0", 12 | "botkit-storage-mongo": "^1.0.6", 13 | "cookie-parser": "^1.4.3", 14 | "debug": "^2.3.3", 15 | "express": "^4.14.0", 16 | "express-hbs": "^1.0.4", 17 | "node-env-file": "^0.1.8", 18 | "querystring": "^0.2.0", 19 | "request": "^2.79.0", 20 | "wordfilter": "^0.2.6" 21 | }, 22 | "devDependencies": {}, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/howdyai/botkit-starter-slack.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/howdyai/botkit-starter-slack/issues" 29 | }, 30 | "homepage": "https://github.com/howdyai/botkit-starter-slack", 31 | "keywords": [ 32 | "bots", 33 | "chatbots", 34 | "slack" 35 | ], 36 | "author": "ben@howdy.ai", 37 | "license": "MIT" 38 | } 39 | -------------------------------------------------------------------------------- /public/login_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Botkit Bot 5 | 6 | 7 | 8 |
9 |
10 |

Oops! Something went awry during your login.

11 | 12 |

Login again

13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /public/login_success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Botkit Bot 5 | 6 | 7 | 8 | 34 | 35 | 36 | 37 | 38 |
39 |
40 |

Success! Your new bot is waiting!

41 |
42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /public/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; } 3 | 4 | body, 5 | html { 6 | margin: 0; 7 | padding: 0; 8 | font-size: 18px; 9 | font-family: sans-serif; 10 | background-color: #FFF; } 11 | 12 | .wrapper { 13 | max-width: 1000px; 14 | margin: 0 auto; } 15 | 16 | .box { 17 | border: 2px solid #CCC; 18 | padding: 1rem calc(1rem - 2px); 19 | margin-bottom: 1rem; } 20 | .box h1, .box h2, .box h3 { 21 | margin-top: 0; } 22 | 23 | footer { 24 | text-align: center; } 25 | 26 | .hero { 27 | text-align: center; 28 | padding: 2rem; } 29 | .hero h1 { 30 | font-size: 4rem; } 31 | 32 | a { 33 | color: #a795ef; } 34 | 35 | .copyurl { 36 | width: 100%; 37 | font-size: 1.5rem; } 38 | 39 | div.input label { 40 | font-weight: bold; 41 | font-size: smaller; } 42 | 43 | .addon { 44 | display: flex; 45 | border: 1px solid #999; 46 | border-radius: 6px; 47 | padding: 5px; 48 | background: #F0F0F0; } 49 | .addon textarea, .addon input { 50 | flex-grow: 1; 51 | border: 0; 52 | background: transparent; } 53 | .addon button { 54 | flex-grow: 0; 55 | background: transparent; 56 | border: 1px solid #999; 57 | border-radius: 6px; 58 | font-weight: bold; } 59 | .addon button.textarea { 60 | align-self: flex-start; 61 | padding: 0.5rem; } 62 | .addon button:hover { 63 | background: #FFF; 64 | color: #a795ef; } 65 | 66 | div.hr { 67 | border: 1px dashed #ccc; 68 | width: 10%; 69 | margin: 4rem auto; 70 | height: 1px; } 71 | 72 | a.button { 73 | border: 2px solid #a795ef; 74 | font-weight: bold; 75 | margin: 0; 76 | border-radius: 3px; 77 | display: inline-block; 78 | padding: 0.5rem 2rem; 79 | text-align: center; 80 | text-decoration: none; 81 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2); 82 | background-color: #FFF; 83 | transition: box-shadow 0.1s linear; } 84 | a.button:hover { 85 | box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1); } 86 | 87 | /*# sourceMappingURL=styles.css.map */ 88 | -------------------------------------------------------------------------------- /public/styles.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAEA,CAAE;EACE,UAAU,EAAE,UAAU;;AAG1B;IACK;EACD,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EACV,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,UAAU;EACvB,gBAAgB,EAAE,IAAI;;AAI1B,QAAS;EACL,SAAS,EAAE,MAAM;EACjB,MAAM,EAAE,MAAM;;AAGlB,IAAK;EACH,MAAM,EAAE,cAAc;EACtB,OAAO,EAAE,qBAAqB;EAC9B,aAAa,EAAE,IAAI;EAEnB,yBAAY;IACV,UAAU,EAAE,CAAC;;AAIjB,MAAO;EACH,UAAU,EAAE,MAAM;;AAGtB,KAAM;EACF,UAAU,EAAE,MAAM;EAClB,OAAO,EAAE,IAAI;EAEb,QAAG;IACC,SAAS,EAAE,IAAI;;AAIvB,CAAE;EACE,KAAK,EA7CO,OAAO;;AAgDvB,QAAS;EACP,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,MAAM;;AAKjB,eAAM;EACJ,WAAW,EAAE,IAAI;EACjB,SAAS,EAAE,OAAO;;AAKtB,MAAO;EACL,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,cAAc;EACtB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,GAAG;EACZ,UAAU,EAAE,OAAO;EACnB,6BAAgB;IACd,SAAS,EAAE,CAAC;IACZ,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,WAAW;EAGzB,aAAO;IACL,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,WAAW;IACvB,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,GAAG;IAClB,WAAW,EAAE,IAAI;IAEjB,sBAAW;MACT,UAAU,EAAE,UAAU;MACtB,OAAO,EAAE,MAAM;IAGjB,mBAAQ;MACN,UAAU,EAAE,IAAI;MAChB,KAAK,EAxFK,OAAO;;AA8FvB,MAAO;EACL,MAAM,EAAE,eAAe;EACvB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,SAAS;EACjB,MAAM,EAAE,GAAG;;AAGb,QAAS;EACL,MAAM,EAAE,iBAAwB;EAChC,WAAW,EAAE,IAAI;EAEjB,MAAM,EAAE,CAAC;EACT,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,WAAW;EACpB,UAAU,EAAE,MAAM;EAClB,eAAe,EAAE,IAAI;EAErB,UAAU,EAAE,8BAA2B;EACvC,gBAAgB,EAAE,IAAI;EACtB,UAAU,EAAE,sBAAsB;EAElC,cAAQ;IAEJ,UAAU,EAAE,8BAA2B", 4 | "sources": ["../sass/styles.scss"], 5 | "names": [], 6 | "file": "styles.css" 7 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # This repo is deprecated! 2 | 3 | To get a fresh Botkit starter kit, use the Yeoman generator or [remix a starter kit on Glitch](https://glitch.com/botkit) 4 | 5 | ``` 6 | npm install -g yo generator-botkit 7 | yo botkit 8 | ``` 9 | 10 | 11 | # Botkit Starter Kit for Slack Bots 12 | 13 | This repo contains everything you need to get started building a Slack bot with [Botkit](https://botkit.ai). 14 | 15 | Botkit is designed to ease the process of designing and running useful, creative bots that live inside messaging platforms. Bots are applications that can send and receive messages, and in many cases, appear alongside their human counterparts as users. 16 | 17 | Some bots talk like people, others silently work in the background, while others present interfaces much like modern mobile applications. Botkit gives developers the necessary tools for building bots of any kind! It provides an easy-to-understand interface for sending and receiving messages so that developers can focus on creating novel applications and experiences instead of dealing with API endpoints. 18 | 19 | Our goal with Botkit is to make bot building easy, fun, and accessible to anyone with the desire to create a future filled with talking machines! 20 | 21 | If you are looking to create a bot on other platforms using Glitch, check out the [Botkit project page](https://glitch.com/botkit). 22 | 23 | ### What's Included 24 | * [Botkit core](https://botkit.ai/docs/core.html) - a complete programming system for building conversational software 25 | * [Pre-configured Express.js webserver](https://expressjs.com/) including: 26 | * A customizable "Install my Bot" homepage 27 | * Login and oauth endpoints that allow teams to install your bot 28 | * Webhook endpoints for communicating with platforms 29 | * Sample skill modules that demonstrate various features of Botkit 30 | 31 | ### Getting Started 32 | 33 | There are a myriad of methods you can use to set up an application on Slack, here are some of your options: 34 | 35 | #### Install Botkit 36 | 37 | [Remix this project on Glitch](https://glitch.com/~botkit-slack) 38 | 39 | [Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/howdyai/botkit-starter-slack/master) 40 | 41 | Clone this repository using Git: 42 | 43 | `git clone https://github.com/howdyai/botkit-starter-slack.git` 44 | 45 | Install dependencies, including [Botkit](https://github.com/howdyai/botkit): 46 | 47 | ``` 48 | cd botkit-starter-slack 49 | npm install 50 | ``` 51 | 52 | #### Set up your Slack Application 53 | Once you have setup your Botkit development enviroment, the next thing you will want to do is set up a new Slack application via the [Slack developer portal](https://api.slack.com/). This is a multi-step process, but only takes a few minutes. 54 | 55 | * [Read this step-by-step guide](https://botkit.ai/docs/provisioning/slack-events-api.html) to make sure everything is set up. 56 | 57 | * We also have this [handy video walkthrough](https://youtu.be/us2zdf0vRz0) for setting up this project with Glitch. 58 | 59 | Update the `.env` file with your newly acquired tokens. 60 | 61 | Launch your bot application by typing: 62 | 63 | `node .` 64 | 65 | Now, visit your new bot's login page: http://localhost:3000/login 66 | 67 | Now comes the fun part of [making your bot!](https://botkit.ai/docs/#build-your-bot) 68 | 69 | 70 | ### Extend This Starter kit 71 | 72 | This starter kit is designed to provide developers a robust starting point for building a custom bot. Included in the code are a set of sample bot "skills" that illustrate various aspects of the Botkit SDK features. Once you are familiar with how Botkit works, you may safely delete all of the files in the `skills/` subfolder. 73 | 74 | Developers will build custom features as modules that live in the `skills/` folder. The main bot application will automatically include any files placed there. 75 | 76 | A skill module should be in the format: 77 | 78 | ``` 79 | module.exports = function(controller) { 80 | 81 | // add event handlers to controller 82 | // such as hears handlers that match triggers defined in code 83 | // or controller.studio.before, validate, and after which tie into triggers 84 | // defined in the Botkit CMS UI. 85 | 86 | } 87 | ``` 88 | 89 | ### Customize Storage 90 | 91 | By default, the starter kit uses a simple file-system based storage mechanism to record information about the teams and users that interact with the bot. While this is fine for development, or use by a single team, most developers will want to customize the code to use a real database system. 92 | 93 | There are [Botkit plugins for all the major database systems](https://botkit.ai/readme-middlewares.html#storage-modules) which can be enabled with just a few lines of code. 94 | 95 | We have enabled our [Mongo middleware]() for starters in this project. To use your own Mongo database, just fill out `MONGO_URI` in your `.env` file with the appropriate information. For tips on reading and writing to storage, [check out these medium posts](https://botkit.groovehq.com/knowledge_base/categories/build-a-bot) 96 | 97 | # Developer & Support Community 98 | 99 | You can find full documentation for Botkit on [our website](https://botkit.ai/docs). 100 | 101 | ### Need more help? 102 | * Glitch allows users to ask the community for help directly from the editor! For more information on raising your hand, [read this blog post.](https://medium.com/glitch/just-raise-your-hand-how-glitch-helps-aa6564cb1685) 103 | 104 | * Join our thriving community of Botkit developers and bot enthusiasts at large. Over 4500 members strong, [our open Slack group](http://community.botkit.ai) is _the place_ for people interested in the art and science of making bots. 105 | 106 | Come to ask questions, share your progress, and commune with your peers! 107 | 108 | * We also host a [regular meetup and annual conference called TALKABOT.](http://talkabot.ai) Come meet and learn from other bot developers! 109 | 110 | [Full video of our 2016 event is available on Youtube.](https://www.youtube.com/playlist?list=PLD3JNfKLDs7WsEHSal2cfwG0Fex7A6aok) 111 | 112 | 113 | 114 | # About Botkit 115 | 116 | Botkit is a product of [Howdy](https://howdy.ai) and made in Austin, TX with the help of a worldwide community of botheads. 117 | -------------------------------------------------------------------------------- /sass/styles.scss: -------------------------------------------------------------------------------- 1 | $botkit_purple: #a795ef; 2 | 3 | * { 4 | box-sizing: border-box; 5 | } 6 | 7 | body, 8 | html { 9 | margin: 0; 10 | padding: 0; 11 | font-size: 18px; 12 | font-family: sans-serif; 13 | background-color: #FFF; 14 | 15 | } 16 | 17 | .wrapper { 18 | max-width: 1000px; 19 | margin: 0 auto; 20 | } 21 | 22 | .box { 23 | border: 2px solid #CCC; 24 | padding: 1rem calc(1rem - 2px); 25 | margin-bottom: 1rem; 26 | 27 | h1, h2, h3 { 28 | margin-top: 0; 29 | } 30 | } 31 | 32 | footer { 33 | text-align: center; 34 | } 35 | 36 | .hero { 37 | text-align: center; 38 | padding: 2rem; 39 | 40 | h1 { 41 | font-size: 4rem; 42 | } 43 | } 44 | 45 | a { 46 | color: $botkit_purple; 47 | } 48 | 49 | .copyurl { 50 | width: 100%; 51 | font-size: 1.5rem; 52 | } 53 | 54 | div.input { 55 | 56 | label { 57 | font-weight: bold; 58 | font-size: smaller; 59 | } 60 | 61 | } 62 | 63 | .addon { 64 | display: flex; 65 | border: 1px solid #999; 66 | border-radius: 6px; 67 | padding: 5px; 68 | background: #F0F0F0; 69 | textarea, input { 70 | flex-grow: 1; 71 | border: 0; 72 | background: transparent; 73 | } 74 | 75 | button { 76 | flex-grow: 0; 77 | background: transparent; 78 | border: 1px solid #999; 79 | border-radius: 6px; 80 | font-weight: bold; 81 | 82 | &.textarea { 83 | align-self: flex-start; 84 | padding: 0.5rem; 85 | } 86 | 87 | &:hover { 88 | background: #FFF; 89 | color: $botkit_purple; 90 | } 91 | } 92 | 93 | } 94 | 95 | div.hr { 96 | border: 1px dashed #ccc; 97 | width: 10%; 98 | margin: 4rem auto; 99 | height: 1px; 100 | } 101 | 102 | a.button { 103 | border: 2px solid $botkit_purple; 104 | font-weight: bold; 105 | // font-size: 4rem; 106 | margin: 0; 107 | border-radius: 3px; 108 | display: inline-block; 109 | padding: 0.5rem 2rem; 110 | text-align: center; 111 | text-decoration: none; 112 | // color: #FFF; 113 | box-shadow: 5px 5px 5px rgba(0,0,0,0.2); 114 | background-color: #FFF; 115 | transition: box-shadow 0.1s linear; 116 | 117 | &:hover { 118 | // background-color: rgba($botkit_purple, 0.1); 119 | box-shadow: 1px 1px 5px rgba(0,0,0,0.1); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /skills/channel_join.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('botkit:channel_join'); 2 | 3 | module.exports = function(controller) { 4 | 5 | controller.on('bot_channel_join', function(bot, message) { 6 | 7 | bot.reply(message,'I have arrived! I am a friendly helper bot.'); 8 | 9 | }); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /skills/interactive_messages.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | // create special handlers for certain actions in buttons 4 | // if the button action is 'say', act as if user said that thing 5 | controller.middleware.receive.use(function(bot, message, next) { 6 | if (message.type == 'interactive_message_callback') { 7 | if (message.actions[0].name.match(/^say$/)) { 8 | var reply = message.original_message; 9 | 10 | for (var a = 0; a < reply.attachments.length; a++) { 11 | reply.attachments[a].actions = null; 12 | } 13 | 14 | var person = '<@' + message.user + '>'; 15 | if (message.channel[0] == 'D') { 16 | person = 'You'; 17 | } 18 | 19 | reply.attachments.push( 20 | { 21 | text: person + ' said, ' + message.actions[0].value, 22 | } 23 | ); 24 | 25 | bot.replyInteractive(message, reply); 26 | 27 | } 28 | } 29 | 30 | next(); 31 | 32 | }); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /skills/sample_conversations.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | WHAT IS THIS? 4 | 5 | This module demonstrates simple uses of Botkit's conversation system. 6 | 7 | In this example, Botkit hears a keyword, then asks a question. Different paths 8 | through the conversation are chosen based on the user's response. 9 | 10 | */ 11 | 12 | module.exports = function(controller) { 13 | 14 | controller.hears(['color'], 'direct_message,direct_mention', function(bot, message) { 15 | 16 | bot.startConversation(message, function(err, convo) { 17 | convo.say('This is an example of using convo.ask with a single callback.'); 18 | 19 | convo.ask('What is your favorite color?', function(response, convo) { 20 | 21 | convo.say('Cool, I like ' + response.text + ' too!'); 22 | convo.next(); 23 | 24 | }); 25 | }); 26 | 27 | }); 28 | 29 | 30 | controller.hears(['question'], 'direct_message,direct_mention', function(bot, message) { 31 | 32 | bot.createConversation(message, function(err, convo) { 33 | 34 | // create a path for when a user says YES 35 | convo.addMessage({ 36 | text: 'How wonderful.', 37 | },'yes_thread'); 38 | 39 | // create a path for when a user says NO 40 | // mark the conversation as unsuccessful at the end 41 | convo.addMessage({ 42 | text: 'Cheese! It is not for everyone.', 43 | action: 'stop', // this marks the converation as unsuccessful 44 | },'no_thread'); 45 | 46 | // create a path where neither option was matched 47 | // this message has an action field, which directs botkit to go back to the `default` thread after sending this message. 48 | convo.addMessage({ 49 | text: 'Sorry I did not understand. Say `yes` or `no`', 50 | action: 'default', 51 | },'bad_response'); 52 | 53 | // Create a yes/no question in the default thread... 54 | convo.ask('Do you like cheese?', [ 55 | { 56 | pattern: bot.utterances.yes, 57 | callback: function(response, convo) { 58 | convo.gotoThread('yes_thread'); 59 | }, 60 | }, 61 | { 62 | pattern: bot.utterances.no, 63 | callback: function(response, convo) { 64 | convo.gotoThread('no_thread'); 65 | }, 66 | }, 67 | { 68 | default: true, 69 | callback: function(response, convo) { 70 | convo.gotoThread('bad_response'); 71 | }, 72 | } 73 | ]); 74 | 75 | convo.activate(); 76 | 77 | // capture the results of the conversation and see what happened... 78 | convo.on('end', function(convo) { 79 | 80 | if (convo.successful()) { 81 | // this still works to send individual replies... 82 | bot.reply(message, 'Let us eat some!'); 83 | 84 | // and now deliver cheese via tcp/ip... 85 | } 86 | 87 | }); 88 | }); 89 | 90 | }); 91 | 92 | }; 93 | -------------------------------------------------------------------------------- /skills/sample_events.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | controller.on('user_channel_join,user_group_join', function(bot, message) { 4 | 5 | bot.reply(message, 'Welcome, <@' + message.user + '>'); 6 | 7 | }); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /skills/sample_hears.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | WHAT IS THIS? 4 | 5 | This module demonstrates simple uses of Botkit's `hears` handler functions. 6 | 7 | In these examples, Botkit is configured to listen for certain phrases, and then 8 | respond immediately with a single line response. 9 | 10 | */ 11 | 12 | var wordfilter = require('wordfilter'); 13 | 14 | module.exports = function(controller) { 15 | 16 | /* Collect some very simple runtime stats for use in the uptime/debug command */ 17 | var stats = { 18 | triggers: 0, 19 | convos: 0, 20 | } 21 | 22 | controller.on('heard_trigger', function() { 23 | stats.triggers++; 24 | }); 25 | 26 | controller.on('conversationStarted', function() { 27 | stats.convos++; 28 | }); 29 | 30 | 31 | controller.hears(['^uptime','^debug'], 'direct_message,direct_mention', function(bot, message) { 32 | 33 | bot.createConversation(message, function(err, convo) { 34 | if (!err) { 35 | convo.setVar('uptime', formatUptime(process.uptime())); 36 | convo.setVar('convos', stats.convos); 37 | convo.setVar('triggers', stats.triggers); 38 | 39 | convo.say('My main process has been online for {{vars.uptime}}. Since booting, I have heard {{vars.triggers}} triggers, and conducted {{vars.convos}} conversations.'); 40 | convo.activate(); 41 | } 42 | }); 43 | 44 | }); 45 | 46 | controller.hears(['^say (.*)','^say'], 'direct_message,direct_mention', function(bot, message) { 47 | if (message.match[1]) { 48 | 49 | if (!wordfilter.blacklisted(message.match[1])) { 50 | bot.reply(message, message.match[1]); 51 | } else { 52 | bot.reply(message, '_sigh_'); 53 | } 54 | } else { 55 | bot.reply(message, 'I will repeat whatever you say.') 56 | } 57 | }); 58 | 59 | 60 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 61 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 62 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 63 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 64 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 65 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 66 | /* Utility function to format uptime */ 67 | function formatUptime(uptime) { 68 | var unit = 'second'; 69 | if (uptime > 60) { 70 | uptime = uptime / 60; 71 | unit = 'minute'; 72 | } 73 | if (uptime > 60) { 74 | uptime = uptime / 60; 75 | unit = 'hour'; 76 | } 77 | if (uptime != 1) { 78 | unit = unit + 's'; 79 | } 80 | 81 | uptime = parseInt(uptime) + ' ' + unit; 82 | return uptime; 83 | } 84 | 85 | }; 86 | -------------------------------------------------------------------------------- /skills/sample_middleware.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | // controller.middleware.receive.use(function(bot, message, next) { 4 | // 5 | // // do something... 6 | // console.log('RCVD:', message); 7 | // next(); 8 | // 9 | // }); 10 | // 11 | // 12 | // controller.middleware.send.use(function(bot, message, next) { 13 | // 14 | // // do something... 15 | // console.log('SEND:', message); 16 | // next(); 17 | // 18 | // }); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /skills/sample_taskbot.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is a sample bot that provides a simple todo list function 4 | and demonstrates the Botkit storage system. 5 | 6 | Botkit comes with a generic storage system that can be used to 7 | store arbitrary information about a user or channel. Storage 8 | can be backed by a built in JSON file system, or one of many 9 | popular database systems. 10 | 11 | See: 12 | 13 | botkit-storage-mongo 14 | botkit-storage-firebase 15 | botkit-storage-redis 16 | botkit-storage-dynamodb 17 | botkit-storage-mysql 18 | 19 | */ 20 | 21 | module.exports = function(controller) { 22 | 23 | // listen for someone saying 'tasks' to the bot 24 | // reply with a list of current tasks loaded from the storage system 25 | // based on this user's id 26 | controller.hears(['tasks','todo'], 'direct_message', function(bot, message) { 27 | 28 | // load user from storage... 29 | controller.storage.users.get(message.user, function(err, user) { 30 | 31 | // user object can contain arbitary keys. we will store tasks in .tasks 32 | if (!user || !user.tasks || user.tasks.length == 0) { 33 | bot.reply(message, 'There are no tasks on your list. Say `add _task_` to add something.'); 34 | } else { 35 | 36 | var text = 'Here are your current tasks: \n' + 37 | generateTaskList(user) + 38 | 'Reply with `done _number_` to mark a task completed.'; 39 | 40 | bot.reply(message, text); 41 | 42 | } 43 | 44 | }); 45 | 46 | }); 47 | 48 | // listen for a user saying "add ", and then add it to the user's list 49 | // store the new list in the storage system 50 | controller.hears(['add (.*)'],'direct_message,direct_mention,mention', function(bot, message) { 51 | 52 | var newtask = message.match[1]; 53 | controller.storage.users.get(message.user, function(err, user) { 54 | 55 | if (!user) { 56 | user = {}; 57 | user.id = message.user; 58 | user.tasks = []; 59 | } 60 | 61 | user.tasks.push(newtask); 62 | 63 | controller.storage.users.save(user, function(err,saved) { 64 | 65 | if (err) { 66 | bot.reply(message, 'I experienced an error adding your task: ' + err); 67 | } else { 68 | bot.api.reactions.add({ 69 | name: 'thumbsup', 70 | channel: message.channel, 71 | timestamp: message.ts 72 | }); 73 | } 74 | 75 | }); 76 | }); 77 | 78 | }); 79 | 80 | // listen for a user saying "done " and mark that item as done. 81 | controller.hears(['done (.*)'],'direct_message', function(bot, message) { 82 | 83 | var number = message.match[1]; 84 | 85 | if (isNaN(number)) { 86 | bot.reply(message, 'Please specify a number.'); 87 | } else { 88 | 89 | // adjust for 0-based array index 90 | number = parseInt(number) - 1; 91 | 92 | controller.storage.users.get(message.user, function(err, user) { 93 | 94 | if (!user) { 95 | user = {}; 96 | user.id = message.user; 97 | user.tasks = []; 98 | } 99 | 100 | if (number < 0 || number >= user.tasks.length) { 101 | bot.reply(message, 'Sorry, your input is out of range. Right now there are ' + user.tasks.length + ' items on your list.'); 102 | } else { 103 | 104 | var item = user.tasks.splice(number,1); 105 | 106 | // reply with a strikethrough message... 107 | bot.reply(message, '~' + item + '~'); 108 | 109 | if (user.tasks.length > 0) { 110 | bot.reply(message, 'Here are our remaining tasks:\n' + generateTaskList(user)); 111 | } else { 112 | bot.reply(message, 'Your list is now empty!'); 113 | } 114 | } 115 | }); 116 | } 117 | 118 | }); 119 | 120 | // simple function to generate the text of the task list so that 121 | // it can be used in various places 122 | function generateTaskList(user) { 123 | 124 | var text = ''; 125 | 126 | for (var t = 0; t < user.tasks.length; t++) { 127 | text = text + '> `' + (t + 1) + '`) ' + user.tasks[t] + '\n'; 128 | } 129 | 130 | return text; 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /views/index.hbs: -------------------------------------------------------------------------------- 1 |
2 | 3 |

I am a bot.

4 | 5 | Add to Slack 6 |
7 | -------------------------------------------------------------------------------- /views/installation.hbs: -------------------------------------------------------------------------------- 1 |
2 |

Botkit Starter Kit

3 |
4 | 5 |
6 |

7 | ✅ Your Botkit app is correctly deployed and running! 8 | Connect it to Slack to complete the setup. 9 |

10 | 11 | 12 |
13 | 14 |
15 |

Create a Slack Application

16 | 17 |

18 | To bring this bot online, create a new Slack application on the Slack developer site. 19 | You will get a client id and client secret. 20 | Make sure to copy and paste those values below for safe keeping. 21 |

22 | Open Slack developer site 23 | 24 |

25 | 26 | 27 |

28 | 29 |

30 | 31 | 32 |

33 | 34 |
35 | 36 |
37 | 38 |

Configure Features

39 | 40 |

41 | Botkit uses 4 features of Slack's API: Bot Users, Interactive Components, Event Subscriptions, and OAuth. 42 | You will need to configure each. 43 |

44 | 45 |

1. Bot User

46 | 47 |

48 | Click on the Slack application's "Bot Users" tab. Enter a Display name and a default username. 49 | Also enable the option labeled "Always Show My Bot as Online." 50 | Make sure to save your changes. 51 |

52 | 53 |

54 | This option will create a username and identity for your bot so that it can join channels 55 | and appear as a robotic team member. 56 |

57 | 58 |
59 | 60 |

2. Interactive Components

61 | 62 |

63 | Click on the Slack application's "Interactive Components" tab. 64 | Enter this URL in the "Request URL" field, and then save your changes. 65 |

66 | 67 |

68 | This option will allow your bot to send and receive interactive messages 69 | with buttons, menus and dialog boxes. 70 |

71 | 72 |
73 | 74 |
75 | 76 | 77 |
78 |
79 | 80 |
81 | 82 |

3. Event Subscriptions

83 | 84 |

85 | Click on the Slack application's "Event Subscriptions" tab. 86 | Click to enable events, then specify this URL in the "Request URL" field. 87 |

88 | 89 |
90 | 91 |
92 | 93 | 94 |
95 |
96 | 97 | 98 |

99 | After setting the URL, scroll down to the "Subscribe to Bot Events" section. 100 | Here, you will select 4 different messaging events:

101 | 102 |
    103 |
  1. message.channels
  2. 104 |
  3. message.groups
  4. 105 |
  5. message.im
  6. 106 |
  7. message.mpim
  8. 107 |
108 | 109 |

110 | You may also want to enable other events, but these 4 are required for your bot send and receive basic messages. 111 |

112 | 113 |
114 | 115 |

4. OAuth & Permissions

116 | 117 |

118 | Click on the Slack application's "OAuth & Permissions" tab. 119 | Scroll down to "Redirect URLs" and click "Add a new Redirect URL." 120 | Enter this URL, and click "Save URLs" 121 | 122 |

123 | 124 |
125 | 126 | 127 |
128 |
129 | 130 |
131 | 132 |

You are now finished with the Slack developer site! You can close that tab.

133 | 134 | 135 |
136 | 137 |
138 | 139 |

Edit the .env File

140 | 141 |

142 | The final step that will bring your bot online is to add the client id and client secret collected 143 | in step 1 to this projects .env file. 144 | Be careful not to change the other lines in this file! 145 |

146 | 147 |
148 | 149 |
150 | 151 | 152 |
153 |
154 | 155 | {{#glitch_domain}} 156 |

Edit your .env file

157 | {{/glitch_domain}} 158 |
159 | 160 |
161 |

Ready to Connect!

162 | 163 |

164 | Once you have values in your .env file, and Slack has been configured correctly, your bot is ready to connect. 165 | Restart this application and reload this page - you'll see an "Add to Slack" button that will install your new bot! 166 |

167 | 168 |
169 | 170 | 171 | 172 | 189 | -------------------------------------------------------------------------------- /views/layouts/default.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{> head}} 5 | 6 | {{>header}} 7 |
8 | {{{body}}} 9 |
10 | {{> footer}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /views/partials/footer.hbs: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /views/partials/head.hbs: -------------------------------------------------------------------------------- 1 | 2 | Botkit Starter Kit 3 | 4 | 5 | -------------------------------------------------------------------------------- /views/partials/header.hbs: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /views/partials/tabs_head.hbs: -------------------------------------------------------------------------------- 1 | 2 | Botkit Sample Tab for Microsoft Teams 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /views/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit-starter-slack/7f656c44f0f080a739aed8278ce5106fd8c28109/views/styles.css --------------------------------------------------------------------------------