Coder Social home page Coder Social logo

howdyai / botkit Goto Github PK

View Code? Open in Web Editor NEW
11.3K 317.0 2.3K 11.79 MB

Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.

License: MIT License

JavaScript 42.27% TypeScript 53.55% HTML 1.45% SCSS 2.50% Shell 0.21% Handlebars 0.03%
botkit botkit-studio microsoft-bot-framework bot-application slack facebook twilio cisco-spark bots sms

botkit's Introduction

Botkit

Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.

This repository contains the core Botkit library, as well as a series of plugins and extensions for connecting Botkit to messaging and chat platforms and other tools in the bot building ecosystem.

Botkit is part of the Microsoft Bot Framework and is released under the MIT Open Source license

Use Botkit

Packages included in this repo

Package Description NPM Status
botkit Botkit Core library NPM Badge
botbuilder-adapter-web A platform adapter for the web NPM Badge
botbuilder-adapter-slack A platform adapter for Slack NPM Badge
botbuilder-adapter-webex A platform adapter for Webex Teams NPM Badge
botbuilder-adapter-hangouts A platform adapter for Google NPM Badge
botbuilder-adapter-twilio-sms A platform adapter for Twilio SMS NPM Badge
botbuilder-adapter-facebook A platform adapter for Facebook Messenger NPM Badge
generator-botkit A Yeoman generator for creating a new Botkit project NPM Badge
botkit-plugin-cms A plugin that adds support for Botkit CMS NPM Badge

Build Botkit locally

This repo contains multiple inter-linked packages containing Botkit Core, platform adapter packages, and some additional plugins and extensions. To build these locally, follow the instructions below.

Install lerna and TypeScript globally:

npm install -g typescript
npm install -g lerna

Clone the entire Botkit project from Github.

git clone [email protected]:howdyai/botkit.git

Enter the new folder and install the dependent packages:

cd botkit
npm install

Use lerna to set up the local packages:

lerna bootstrap --hoist

Now, build all of the libraries:

lerna run build

To build updated versions of the class reference documents found in packages/docs, run:

lerna run build-docs

botkit's People

Contributors

adantoscano avatar agamrafaeli avatar anonrig avatar auberryberry avatar benbrown avatar ccruson avatar colestrode avatar dependabot[bot] avatar esoelzer avatar etiennellipse avatar fastbean-au avatar innorag avatar jonchurch avatar joshuaklassen avatar jsalwen avatar jsoref avatar krismuniz avatar mvaragnat avatar naktibalda avatar nishch avatar o-mutt avatar ouadie-lahdioui avatar panx981389 avatar peterswimm avatar qiongfangzhang avatar rafaelcosman avatar stevenic avatar sundeepgupta avatar xavdid avatar zetlen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

botkit's Issues

Add tags / releases

Hi there,

Noticed that recently many PRs and improvements have been pushed to master. It would be great (even awesome) to start tagging some releases and publishing to npm in order for us to rely on stable and fixes commit tags.

Thanks a lot

regex - \b and ^()?

Simple issue, I'd like to be able to specify the difference between hi and hire..two separate controller.hears() functions with different use cases. I've tried controller.hears('\bhi' ..... and controller.hears('^hi?' ..... with no luck. any reason why these operators wouldn't work?

Issues with node-gyp and xcodebuild

~/Code/bot-test
 โฏ npm install --save botkit

> [email protected] install /Users/kevinSuttle/Code/bot-test/node_modules/bufferutil
> node-gyp rebuild

  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
In file included from ../src/bufferutil.cc:16:
../../nan/nan.h:261:25: error: redefinition of '_NanEnsureLocal'
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
                        ^
../../nan/nan.h:256:25: note: previous definition is here
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
                        ^
../../nan/nan.h:661:13: error: no member named 'smalloc' in namespace 'node'
    , node::smalloc::FreeCallback callback
      ~~~~~~^
../../nan/nan.h:672:12: error: no matching function for call to 'New'
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
           ^~~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:31:40: note: candidate function not viable: no known
      conversion from 'uint32_t' (aka 'unsigned int') to 'enum encoding' for 3rd argument
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:43:40: note: candidate function not viable: 2nd argument
      ('const char *') would lose const qualifier
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:28:40: note: candidate function not viable: requires 2
      arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate, size_t length);
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:36:40: note: candidate function not viable: requires 5
      arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
In file included from ../src/bufferutil.cc:16:
../../nan/nan.h:676:12: error: no viable conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object>'
    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:210:7: note: candidate constructor (the implicit copy constructor)
      not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to 'const v8::Local<v8::Object> &' for 1st
      argument
class Local {
      ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:210:7: note: candidate constructor (the implicit move constructor)
      not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object> &&' for 1st argument
class Local {
      ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:214:13: note: candidate template ignored: could not match 'Local'
      against 'MaybeLocal'
  V8_INLINE Local(Local<S> that)
            ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:326:13: note: candidate template ignored: could not match 'S *'
      against 'v8::MaybeLocal<v8::Object>'
  V8_INLINE Local(S* that)
            ^
In file included from ../src/bufferutil.cc:16:
../../nan/nan.h:683:26: error: no member named 'Use' in namespace 'node::Buffer'
    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
           ~~~~~~~~~~~~~~^
In file included from ../src/bufferutil.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Primitive *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:414:12: note: in instantiation of function template specialization
      'v8::Local<v8::Primitive>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Boolean *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:424:12: note: in instantiation of function template specialization
      'v8::Local<v8::Boolean>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Function *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:1514:12: note: in instantiation of function template specialization
      'v8::Local<v8::Function>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/bufferutil.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Object *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:1632:12: note: in instantiation of function template specialization
      'v8::Local<v8::Object>::Local<v8::Value>' requested here
    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
9 errors generated.
make: *** [Release/obj.target/bufferutil/src/bufferutil.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:270:23)
gyp ERR! stack     at emitTwo (events.js:88:13)
gyp ERR! stack     at ChildProcess.emit (events.js:173:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:201:12)
gyp ERR! System Darwin 15.2.0
gyp ERR! command "/usr/local/Cellar/node/5.2.0/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/kevinSuttle/Code/bot-test/node_modules/bufferutil
gyp ERR! node -v v5.2.0
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok
npm WARN install:[email protected] [email protected] install: `node-gyp rebuild`
npm WARN install:[email protected] Exit status 1

> [email protected] install /Users/kevinSuttle/Code/bot-test/node_modules/utf-8-validate
> node-gyp rebuild

  CXX(target) Release/obj.target/validation/src/validation.o
In file included from ../src/validation.cc:15:
../../nan/nan.h:261:25: error: redefinition of '_NanEnsureLocal'
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
                        ^
../../nan/nan.h:256:25: note: previous definition is here
NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
                        ^
../../nan/nan.h:661:13: error: no member named 'smalloc' in namespace 'node'
    , node::smalloc::FreeCallback callback
      ~~~~~~^
../../nan/nan.h:672:12: error: no matching function for call to 'New'
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
           ^~~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:31:40: note: candidate function not viable: no known
      conversion from 'uint32_t' (aka 'unsigned int') to 'enum encoding' for 3rd argument
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:43:40: note: candidate function not viable: 2nd argument
      ('const char *') would lose const qualifier
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:28:40: note: candidate function not viable: requires 2
      arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate, size_t length);
                                       ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/node_buffer.h:36:40: note: candidate function not viable: requires 5
      arguments, but 3 were provided
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                       ^
In file included from ../src/validation.cc:15:
../../nan/nan.h:676:12: error: no viable conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object>'
    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:210:7: note: candidate constructor (the implicit copy constructor)
      not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to 'const v8::Local<v8::Object> &' for 1st
      argument
class Local {
      ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:210:7: note: candidate constructor (the implicit move constructor)
      not viable: no known conversion from 'v8::MaybeLocal<v8::Object>' to 'v8::Local<v8::Object> &&' for 1st argument
class Local {
      ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:214:13: note: candidate template ignored: could not match 'Local'
      against 'MaybeLocal'
  V8_INLINE Local(Local<S> that)
            ^
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:326:13: note: candidate template ignored: could not match 'S *'
      against 'v8::MaybeLocal<v8::Object>'
  V8_INLINE Local(S* that)
            ^
In file included from ../src/validation.cc:15:
../../nan/nan.h:683:26: error: no member named 'Use' in namespace 'node::Buffer'
    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
           ~~~~~~~~~~~~~~^
In file included from ../src/validation.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Primitive *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:414:12: note: in instantiation of function template specialization
      'v8::Local<v8::Primitive>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Boolean *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:424:12: note: in instantiation of function template specialization
      'v8::Local<v8::Boolean>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Function *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:1514:12: note: in instantiation of function template specialization
      'v8::Local<v8::Function>::Local<v8::Value>' requested here
    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
In file included from ../src/validation.cc:7:
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:221:5: error: assigning to 'v8::Object *volatile' from
      incompatible type 'v8::Value *'
    TYPE_CHECK(T, S);
    ^~~~~~~~~~~~~~~~
/Users/kevinSuttle/.node-gyp/5.2.0/include/node/v8.h:180:37: note: expanded from macro 'TYPE_CHECK'
    *(static_cast<T* volatile*>(0)) = static_cast<S*>(0);      \
                                    ^ ~~~~~~~~~~~~~~~~~~
../../nan/nan.h:1632:12: note: in instantiation of function template specialization
      'v8::Local<v8::Object>::Local<v8::Value>' requested here
    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
           ^
../../nan/nan.h:398:30: note: expanded from macro 'NanEscapeScope'
# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
                             ^
9 errors generated.
make: *** [Release/obj.target/validation/src/validation.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:270:23)
gyp ERR! stack     at emitTwo (events.js:88:13)
gyp ERR! stack     at ChildProcess.emit (events.js:173:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:201:12)
gyp ERR! System Darwin 15.2.0
gyp ERR! command "/usr/local/Cellar/node/5.2.0/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/kevinSuttle/Code/bot-test/node_modules/utf-8-validate
gyp ERR! node -v v5.2.0
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok
npm WARN install:[email protected] [email protected] install: `node-gyp rebuild`
npm WARN install:[email protected] Exit status 1
[email protected] /Users/kevinSuttle/Code/bot-test
โ””โ”€โ”€ [email protected]

npm WARN EPACKAGEJSON [email protected] No repository field.

I even reset and made the CLT explicitly point to Xcode.

โฏ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

โฏ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix

Fix file uploading

I can't get the file upload functionality working this is my latest attempt:

            var filepath = path.join(__dirname, '..', '/screenshots/'+ name + '.png');
            fs.readFile(filepath, function (err, data) {
                if (err) throw err;

                console.log(message.channel);

                bot.api.files.upload({
                    content: data,
                    channel: message.channel
                },function(err,res) {
                    if (err) {
                        bot.botkit.log("Failed to add screenshot :(",err);
                        bot.botkit.log(data);
                    }
                });

But I don't get anything back, the data is there I also tried replacing content: with file and I get an error from the api saying not file data. Any help is highly appreciated.

simple_storage.js: "Error: could not load data"

Here's my code

var Botkit = require("botkit");
var simpleStorage = require("./simpleStorage")

...

var controller = Botkit.slackbot({
  debug: false,
  storage: simpleStorage()
});

...

controller.hears(['hello','hi'],'direct_message,direct_mention,mention',
  function(bot, message) {
    bot.reply(message,"Hello!");

    controller.storage.teams.save({id: message.team, foo:"bar"}, function(err){console.log(err)});
    controller.storage.teams.get(message.team, function(err){console.log(err)})
  }
)

Put extra storages out of the botkit

Hi,

I'm happy to see the 0.0.5 release (not tagged?) with many other storages.
However, most of them need extra packages (monk, ...) that are not is the botkit package.json file.

So when installing, it does not work.
And if you had them all in the botkit package.json, it will install lots of useless packages.

What about keeping only the "jfs" as default (light) and move the others in other npm packages like botkit-storage-mongo, botkit-storage-redis and so on?

message_received event is not a catch-all

(I was writing this as I investigated the issue, so it became a bit long. Thanks for creating botkit!)

Problem

I wanted to hook onto 'message_received' but I noticed that my handler isn't firing at all.

  1. It seems to happen on an rtm message here, as I would expect
  2. it's correctly triggering the event here
  3. could it be this?
  4. this is the "default handler" that is registered by botkit

Actually yeah, it looks like the default handler at #4 will run first given the definition of trigger(), and then what I said in #3, this, prevents subsequent handlers from running if a handler returns false. It seems that there are a variety of situations in which the default handler may return false.

For reference, I'm simply typing a simple message such as "blah". Indeed, this would be considered an "ambient" message and the default handler would mark it as such and trigger "ambient" and return false, cutting off all subsequent "message_received" handlers.

This is confusing because the event is referred to as a catch-all:

This event is fired for any message of any kind that is received and can be used as a catch all

Though it's not much of a catch all when the default handler catches most cases and cuts off subsequent handlers.

Considerations

  1. Can we perhaps reconsider the role of the default handler, so that it allows other handlers to run?

  2. More generally, could we reconsider the idea that any random handler may prevent others from running?

    Personally it goes against the whole idea of event handlers for me, where you register one without having to worry about what other handlers might do. All it takes is one faulty handler to accidentally return false in some edge case to bring the whole thing down.

    Is this functionality the reason why we're not using something more standard like eventemitter?

    In my opinion, if we want some sort of pipeline/stream API where we can hook into separate phases/stages of the pipeline to transform the message/input successively and have the result affect subsequent stages, that could be interesting. However, in my opinion, that would be better served as a separate API instead of clobbering the simple event pattern that most people are already familiar with.

  3. There are two useful interpretations of "message_received" that I can think of:

    1. High-level: The equivalent of ["ambient", "direct_mention", "mention", "direct_message"].
    2. Low-level: The raw message as received via RTM

    In my opinion both would be useful. The first as a convenience (and to match the readme), and the second to benefit from the JSON parsing (and possible future work) that botkit already does with the raw messages, which would be lost if we were to simply directly access the controller.rtm.on("message"), if that even works.

Recommendation

My recommendation would be to make "message_received" an alias for ["ambient", "direct_mention", "mention", "direct_message"], and introduce something like "rtm_message" to the websocket events which would happen directly after the message is JSON parsed.

Default callback not invoked in multi-ask conversation

Hi, Maybe I am just not using this correctly but when I have a conversation in which the bot is asking several questions in succession as in the snippet below, the default callback is not invoked. I confirmed this by commenting out other asks and just leaving the one with the default and in that case the default callback in invoked (as is the case with the sample code 'Shall we proceed Say YES, NO or DONE to quit.')

        convo.ask('Any more to say?', [{
            pattern: bot.utterances.no,
            callback: function(response, convo) {
                convo.say('Moving on..');
                convo.next();
            }
        }, {
            pattern: bot.utterances.yes,
            callback: function(response, convo) {
                convo.say('Great! I will continue...');
                convo.next();
            }
        }, {
            default: true,
            callback: function(response, convo) {
                // just repeat the question 
                convo.say('Repeating..');
                convo.repeat();
                convo.next();
            }
        }]);

        convo.ask(username + ', what did you do last year?', [{
            pattern: '.*',
            callback: function(response, convo) {
                console.log(response);
                //convo.say(username + ', what are you doing today?')
                convo.next();
            }
        }]);```

Send message async

I am wondering how can I send back a message from an async call.
ejem

controller.hears(['balance'], 'direct_message', function(bot, message){
    var url = baseUrl + '/procesess';
    requestify.get(url, options).then(function(response) {
      var data = JSON.parse(response.body);
      bot.reply('Your new balance for account *' + account + '* is: *$1.300.000.00*'); //This doesn't get sent 
    }, function(err){
      console.log(err);
    });
});

How should we handle something like that?

controller.hears not matching regular expressions correctly

Using this code:

controller.hears('set volume (.*)','direct_message,direct_mention,mention', function(bot, message) {
    console.log(message);
});

I get this output:

{ type: 'message',
  channel: 'G0HNQCS23',
  user: 'U0A1H66FJ',
  text: 'set volume 50',
  ts: '1452007099.000065',
  team: 'T09JJJWKZ',
  event: 'direct_mention' }

There is no match property on message, just the text which I suppose does mean that the regex matched even if it didn't parse the brackets.

However if the regex is 'set volume (\d+)' matching the same text doesn't work (which I think it should).

Am I doing something wrong here?

Thanks!

BotKit crashes on Heroku due to port issue

We have a small BotKit app that runs fine on the desktop but not in Heroku, crashing with the message Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

Heroku logs:

app[web.1]: ** API CALL: https://slack.com/api/rtm.start
app[web.1]: ** No persistent storage method specified! Data may be lost when process shuts down.
app[web.1]: ** Setting up custom handlers for processing Slack messages
app[web.1]: ** BOT ID:  sandworm  ...attempting to connect to RTM!
heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
heroku[web.1]: Stopping process with SIGKILL
heroku[web.1]: State changed from starting to crashed
[web.1]: Process exited with status 137

This is our connection script:

var slackToken = process.env['TOKEN'];
var controller = Botkit.slackbot();
var bot = controller.spawn({
  token: slackToken
});

bot.startRTM(function(err,bot,payload) {
  if (err) {
    throw new Error('Could not connect to Slack');
  }
});

According to this StackOverflow post the problem is usually one of binding the app to the correct port as provided by Heroku, but we cannot find any way to do this with BotKit.

Get channel and user names by ID?

By reading messages on message API, i'm getting this object

{ type: 'message',
  channel: 'G0HBYU10R',
  user: 'U086E9068',
  text: 'hello !',
  ts: '1451320460.000007',
  team: 'T02C5T9ES',
  event: 'ambient' }

but i need to get additional data like channel name and user name, not only their ID's

is this possible with botkit?

Not connecting to slack RTM

When I run the bot It gets stuck on this message:

token=my-real-slack-token node bot.js
** No persistent storage method specified! Data may be lost when process shuts down.
** Setting up custom handlers for processing Slack messages
** API CALL: https://slack.com/api/rtm.start
** BOT ID:  catbot  ...attempting to connect to RTM!

Here's the code:

var Botkit = require('botkit')

if (!process.env.token) {
  console.log('Error: Specify token in environment')
  process.exit(1)
}

var controller = Botkit.slackbot({
 debug: false,
})

controller.spawn({
  token: process.env.token
}).startRTM(function(err) {
  if (err) {
    throw new Error(err)
  }
})

function rand(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

var listeners = 'direct_message, direct_mention, mention'
controller.hears(['rand'], listeners, function(bot, message) {
    bot.reply(message, rand(1,100))
})

Identifying a user

I want to get the friendly name of a user.

Tried: controller.storage.users.get(message.user,function(err,user) {}) which is in the bot.js file but user always come in as undefined.

Reading through source it appears that there is storage but no methods to lookup users...

Is this right?

Case sensitive "hears"

It'd be nice if there were a way to make .hears have a case sensitive option. That way our bot can be a proper grammar nazi. ๐Ÿ˜ˆ

"npm install" not working for me

As a total newbie to node.js/npm (I'm an iOS developer), ran into a substantial # of roadblocks installing botkit. I figured out I had to install all these npm packages to make it work, but would have been nice for that to be in the instructions.

After destroying a conversation

Upon destroying a conversation, creating a new conversation is buggy. This stacktrace can be used.

In order to reproduce:

  • start a conversation using bot.startConversation
  • ask several questions
  • on callback of convo.ask('question 1') call convo.stop()
  • try to create a new conversation
/Users/anonrig/Desktop/projects/botkit/node_modules/botkit/lib/Slackbot_worker.js:234
            if (cb) { cb(null); }
                      ^
TypeError: cb is not a function
    at /Users/anonrig/Desktop/projects/botkit/node_modules/botkit/lib/Slackbot_worker.js:234:23
    at afterWrite (_stream_writable.js:346:3)
    at onwrite (_stream_writable.js:337:7)
    at TLSSocket.WritableState.onwrite (_stream_writable.js:89:5)
    at WriteWrap.afterWrite (net.js:775:12)

What's kind of message?

I saw some Bot can post message like below format, I do not look like normal message.

screen shot 2015-12-28 at 4 51 16 pm

Can we do that with botkit?

Thanks

Unable to connect when behind a proxy

We are unable to connect when we need to use a proxy

The http_proxy environment variables are set but this doesn't make a difference

Should this work behind a proxy?

Add 'typing' indicator

Small enhancement suggestion.

I find my bot often kicking off actions that take more than a few seconds to complete & callback. Users seem to think he's bugged or broken somewhere if they don't see a reply immediately.

Currently, I use a typing indicator RTM event to keep users informed that the bot did, in fact, hear their message and is processing it, like this:
bot.reply(message, {"type": "typing"});

It'd be quite convenient to have that wrapped in a method like:
bot.typing(message);

If only for the sake of usability affordance.

bot.say does not work with # prefixed channel name

When you try to send a message to channel with # prefixed channel name nothing is happening.

bot.say({
    text: "Hello World!",
    channel: "#random"
});

Instead of # prefixed channel name, when you try with channel id everything works great.

bot.say({
    text: "Hello World!",
    channel: 'C0XXXXXXX'
});

Testing Botkit Blocks

I didn't see any examples or documentation on how to write tests for Botkit blocks. Please add!

SOLVED - Cant send formatted URL

Hey All,

I'm trying to send a reply message which should include a link (a couple actually).
The issue I'm having is that whenever i format the message response with the <url|link text> it looks like it is escaping the text before sending it through.

I've got something along the lines of:
bot.reply(message,'This is my sample message http://google.com|google');

Any suggestions on what I can check?

Bot listens to wrong parts of the message

Hi,

I am playing around with this library and it is pretty neat, but I ran into the following issue.

const LISTEN_TO = 'direct_message,direct_mention,mention';

controller.hears(['hello','hi'], LISTEN_TO, (bot, message) => {

    bot.api.reactions.add({
        timestamp: message.ts,
        channel: message.channel,
        name: 'robot_face',
    }, (err, res) =>{
        if (err) {
            bot.log("Failed to add emoji reaction :(", err);
        }
    });

    controller.storage.users.get(message.user, (err, user) => {
        if (user && user.name) {
            bot.reply(message, `Hello ${user.name}!!`);
        } else {
            bot.reply(message, "Hello.");
        }
    });

}); // hello, hi

The bot replies Hello. even if the message to it was something like @bot: while I do not hate you ... - the hi in while triggers the bot to reply Hello..

I don't think it should be that way. Is there a bugfix for this or a workaround?

Version: I am using "botkit": "latest", in my package.json file, and it installed version 0.0.4.

More logging

Could you add more logging and use the great https://github.com/visionmedia/debug to do so?

In this way you can for example add here logging with debug('botkit:event:trigger')(event, ":", data);

When I had some problems, it has been difficult to find out what is going on and I had to add a few custom botkit.debug in botkit code. On the other end, some of these botkit.debug made the logs very noisy.

Using the debug module you can selectively enabling the kind of debug you want setting the environment variable DEBUG. It is a "standard" used by a lot on npm modules including express, socket.io, etc.

On a side note, it is unclear why botkit.debugalways log to the console and botkit.log it is more flexible and let you even choose to redefine a handler. I used to use Winston everywhere for logging but lately with docker and so many log collection services (ex: papertrail), I started sending everything to the console and capture that output. I would recommend that is a way or another you make log and debug work in the same way.

Can botkit start messaging someone without being messaged first?

All the functionality I see is for botkit to REPLY to someone. Is there functionality to allow botkit to start messaging someone without being messaged first?

At a certain time of day, I would like to have my bot automatedly direct message everyone on my team, and THEN the bot should listen to and reply to their responses.

I can use Slack's webAPI to issue a chat.privatemessage to a user, but these messages will just go to the user's slackbot channel, and my bot won't hear messages in that slackbot channel....

Any thoughts on how to accomplish something like this? Thanks!

Testing storages in a more generic way.

A generic solution to testing and enforcing tests for separate storage units can be found.

Proposed solution is:

After initialization of the controller:

var controller = Botkit.slackbot({
  storage: my_storage_provider
})

Botkit.slackbot constructor can automatically test the storage tests and if test fails, we prompt a message to user and terminate the botkit process.

If --force is used, we skip the test and run the application without any testing.

TypeError: Cannot set property 'channel' of undefined

Trying to use this project with just the basic hello responder, I ran into this error twice.

/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/Slackbot_worker.js:359
      msg.channel = src.channel;
                  ^

TypeError: Cannot set property 'channel' of undefined
    at Object.bot.reply (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/Slackbot_worker.js:359:19)
    at Object.<anonymous> (/Users/nblack/Dropbox/acronym-bot/bot.js:25:9)
    at Object.<anonymous> (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/CoreBot.js:655:20)
    at Object.Botkit.botkit.trigger (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/CoreBot.js:684:41)
    at Object.<anonymous> (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/SlackBot.js:499:26)
    at Object.Botkit.botkit.trigger (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/CoreBot.js:684:41)
    at /Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/CoreBot.js:755:16
    at Object.bot.findConversation (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/Slackbot_worker.js:391:5)
    at Object.Botkit.botkit.receiveMessage (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/CoreBot.js:751:9)
    at WebSocket.<anonymous> (/Users/nblack/Dropbox/acronym-bot/node_modules/botkit/lib/Slackbot_worker.js:101:19)

The severe lack of tests for this botkit worries me. $1.5M should get you a lot more than 5 tests.

Conversations frequently end early when gap between replies is > 100ms

Bot conversations seem to end prematurely when dealing with multiple delayed responses. Here's an example using promises and synchronous timeouts to illustrate the point:

var Promise = require('bluebird');
//..
// Regular bot config, etc.
//..
controller.hears(['promise test'],['direct_message'], function (bot, message) {
  // Get timeout duration from message:
  // e.g. `promise test 3000` for 3 seconds
  var timeoutDuration = parseInt(message.text.split('promise test')[1].trim()) || 0;

  bot.startConversation(message, function (err, convo) {
    convo.say('Testing ' + timeoutDuration + 'ms API response time');

    // Simulated API request
    var apiRequest = function () {
      return new Promise(function (resolve) {
        console.log('1. Making request');
        // Fake response time
        setTimeout(function () {
          console.log('2. Sending back the response');
          resolve();
        }, timeoutDuration);
      });
    };

    apiRequest().then(function () {
      console.log('3. API response received');
      convo.say('API response received');
    });

    setTimeout(function () {
      console.log('4. Synchronous timeout reached');
      convo.say('Synchronous timeout reached');
    }, timeoutDuration);
  });
}

Expected behavior is the conversation will continue until all of the convo.say methods run. You can see the inconsistency with the conversation below:

screen shot 2015-12-18 at 3 38 09 pm

The console logs will always show up as expected, but when the subsequent replies lag > 100ms the conversation will end early more than half the time. This feels like a race condition.

Via Node logs, when the conversation ends early it ignores all but the first reply.

>   [Start]  8  Conversation with  [USER] in [CHANNEL]
1. Making requesting
2. Sending back the response
4. Synchronous timeout reached
3. API response received
>   [End]  8  Conversation with  [USER] in [CHANNEL]
[End]  8  Task for  [USER] in [CHANNEL]
[Start]  9  Task for  [USER] in [CHANNEL]
>   [Start]  9  Conversation with  [USER] in [CHANNEL]
1. Making requesting
>   [End]  9  Conversation with  [USER] in [CHANNEL]
[End]  9  Task for  [USER] in [CHANNEL]
2. Sending back the response
4. Synchronous timeout reached
3. API response received

Happy to be helpful with more info if needed.

How to deploy on Heroku?

First of all, thanks for this amazing tool! I find it really helpful.

I've deployed my bot on Heroku. However, every now and then logs show messages like this Stopping all processes with SIGTERM and my bot goes offline.

Is there any particular way to deploy this on Heroku?

Thank you!

"Getting Started" instructions are missing a step

The getting started instructions are missing a step instructing the user to run npm install to install all necessary dependencies.

Also, it should be made clear that those instructions assume the reader has cloned the repo from Github, not installed it via npm.

Can I repeat what a user says when there are multiple "listeners" in one controller?

var Botkit = require('botkit');

var controller = Botkit.slackbot({
  debug: false
});

// connect the bot to a stream of messages
 controller.spawn({
 token: "XXXX-XXXXXXXXXXXXXXXXXXXXX",
}).startRTM()

controller.hears(['Apple', 'Orange'],['direct_message,direct_mention,mention'],function(bot,message, that_thing_that_you_typed) {
    console.log("You said " + that_thing_that_you_typed)
});

Storage test should be moved into the tests/ folder

All of the tests should be in there all together.

However, this would require that all the dependencies for any possible storage method would have to be installed... which might be a lot of unnecessary junk.

I think storage module dependencies are a sticky issue in general. It may make sense to break them out into subordinate plugin modules to be installed and managed independently. Something to think about!

Can my bot reply without hears any thing?

This is the normal code:

controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', function(bot, message) {
  bot.reply(message, "Hello.");
})

How can I call bot.reply without controller.hears?

The tiniest of Issues: The capital "B" on first example on the site

This is a super small thing, but I got tripped up on it for a bit so others might run into it too.

In the "Get your Bot Online" section of the site. The first line of the example code is:

var Botkit = require('Botkit');

This is cool, so I was excited and just copy pasted that whole chunk of code and starting playing around. I got things working locally and decided to do a quick deploy to Heroku. Once I did that, I started seeing module not found errors in the Heroku logs.

It's that capital "B" in the require. I don't know the exact difference in the systems, but my local setup (OS X) is not case sensitive for node modules, but Heroku's sure are.

I changed the import to:

var Botkit = require('botkit');

and all was well. Might be helpful to include that change in the site.

Thanks for a rad library, having a lot of fun with it already ๐Ÿ’ฏ

Redis storage

Hi,

I wrote a simple Redis storage using redis hashes storage to handle data. Are you interested by it? Do you want me to make a PR here and add it somewhere in the repo, or create a dedicated repo and link it in the README?

Best

Update dependencies

Well it's that time of open source projects. Again. ๐Ÿ‘Ž

"ws" can be updated from ^0.8.1 to ^1.0.0 (Installed: none, Latest: 1.0.0)
"tape" can be updated from ^4.2.2 to ^4.4.0 (Installed: none, Latest: 4.4.0)

I've added this issue to discuss on the projects' changelogs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.