diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..07e6e472c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..6160d8270 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - "4.1" + - "4.0" + - "0.12" + - "0.11" + - "0.10" + - "iojs" \ No newline at end of file diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..fe3ec6882 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,9 @@ +### What happened + +### Environment + +### Expected behaviour + +### Steps to reproduce the bag + +### Priority \ No newline at end of file diff --git a/ISSUE_TEMPLATE.txt b/ISSUE_TEMPLATE.txt new file mode 100644 index 000000000..ddd75f650 --- /dev/null +++ b/ISSUE_TEMPLATE.txt @@ -0,0 +1,7 @@ +What happened? + +What OS? + +Steps to reproduce? + +Priority diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..e69de29bb diff --git a/Procfile b/Procfile new file mode 100644 index 000000000..7cc11c45e --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +worker: node bot.js + diff --git a/bot.js b/bot.js old mode 100755 new mode 100644 index 00eb7b9bd..9f52de991 --- a/bot.js +++ b/bot.js @@ -1,201 +1,172 @@ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ______ ______ ______ __ __ __ ______ - /\ == \ /\ __ \ /\__ _\ /\ \/ / /\ \ /\__ _\ - \ \ __< \ \ \/\ \ \/_/\ \/ \ \ _"-. \ \ \ \/_/\ \/ - \ \_____\ \ \_____\ \ \_\ \ \_\ \_\ \ \_\ \ \_\ - \/_____/ \/_____/ \/_/ \/_/\/_/ \/_/ \/_/ - - -This is a sample Slack bot built with Botkit. - -This bot demonstrates many of the core features of Botkit: - -* Connect to Slack using the real time API -* Receive messages based on "spoken" patterns -* Reply to messages -* Use the conversation system to ask questions -* Use the built in storage system to store and retrieve information - for a user. - -# RUN THE BOT: - - Get a Bot token from Slack: - - -> http://my.slack.com/services/new/bot - - Run your bot from the command line: - - set token= - - node bot.js - -# USE THE BOT: - - Find your bot inside Slack to send it a direct message. - - Say: "Hello" - - The bot will reply "Hello!" - - Say: "who are you?" - - The bot will tell you its name, where it running, and for how long. - - Say: "Call me " - - Tell the bot your nickname. Now you are friends. - - Say: "who am I?" - - The bot will tell you your nickname, if it knows one for you. - - Say: "shutdown" - - The bot will ask if you are sure, and then shut itself down. - - Make sure to invite your bot into other channels using /invite @! - -# EXTEND THE BOT: - - Botkit is has many features for building cool and useful bots! - - Read all about it here: - - -> http://howdy.ai/botkit - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - - + ______ ______ ______ __ __ __ ______ + /\ == \ /\ __ \ /\__ _\ /\ \/ / /\ \ /\__ _\ + \ \ __< \ \ \/\ \ \/_/\ \/ \ \ _"-. \ \ \ \/_/\ \/ + \ \_____\ \ \_____\ \ \_\ \ \_\ \_\ \ \_\ \ \_\ + \/_____/ \/_____/ \/_/ \/_/\/_/ \/_/ \/_/ + This is a sample Slack bot built with Botkit. + This bot demonstrates many of the core features of Botkit: + * Connect to Slack using the real time API + * Receive messages based on "spoken" patterns + * Reply to messages + * Use the conversation system to ask questions + * Use the built in storage system to store and retrieve information + for a user. + # RUN THE BOT: + Get a Bot token from Slack: + -> http://my.slack.com/services/new/bot + Run your bot from the command line: + set token= + node bot.js + # USE THE BOT: + Find your bot inside Slack to send it a direct message. + Say: "Hello" + The bot will reply "Hello!" + Say: "who are you?" + The bot will tell you its name, where it running, and for how long. + Say: "Call me " + Tell the bot your nickname. Now you are friends. + Say: "who am I?" + The bot will tell you your nickname, if it knows one for you. + Say: "shutdown" + The bot will ask if you are sure, and then shut itself down. + Make sure to invite your bot into other channels using /invite @! + # EXTEND THE BOT: + Botkit is has many features for building cool and useful bots! + Read all about it here: + -> http://howdy.ai/botkit + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (!process.env.token) { console.log('Error: Specify token in environment'); process.exit(1); } - +var weather = require('weather-js'); var MathHelper = require('./botmath.js'); var Botkit = require('./lib/Botkit.js'); var os = require('os'); +<<<<<<< HEAD + +======= +>>>>>>> 53f857728fbc05b8033e000c1e6f1ee5b215104b +var botmath = require('./botmath.js'); var controller = Botkit.slackbot({ debug: true, }); - var bot = controller.spawn({ token: process.env.token }).startRTM(); - - -controller.hears(['hello','hi'],'direct_message,direct_mention,mention',function(bot, message) { - +controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', function (bot, message) { bot.api.reactions.add({ timestamp: message.ts, channel: message.channel, name: 'robot_face', - },function(err, res) { + }, function (err, res) { if (err) { - bot.botkit.log('Failed to add emoji reaction :(',err); + bot.botkit.log('Failed to add emoji reaction :(', err); } }); - - - controller.storage.users.get(message.user,function(err, user) { + controller.storage.users.get(message.user, function (err, user) { if (user && user.name) { - bot.reply(message,'Hello ' + user.name + '!!'); + bot.reply(message, 'Hello ' + user.name + '!!'); } else { - bot.reply(message,'Hello.'); + bot.reply(message, 'Hello.'); } }); }); - -controller.hears(['call me (.*)'],'direct_message,direct_mention,mention',function(bot, message) { +controller.hears(['call me (.*)'], 'direct_message,direct_mention,mention', function (bot, message) { var matches = message.text.match(/call me (.*)/i); var name = matches[1]; - controller.storage.users.get(message.user,function(err, user) { + controller.storage.users.get(message.user, function (err, user) { if (!user) { user = { id: message.user, }; } user.name = name; - controller.storage.users.save(user,function(err, id) { - bot.reply(message,'Got it. I will call you ' + user.name + ' from now on.'); + controller.storage.users.save(user, function (err, id) { + bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.'); }); }); }); - -controller.hears(['what is my name','who am i'],'direct_message,direct_mention,mention',function(bot, message) { - - controller.storage.users.get(message.user,function(err, user) { +controller.hears(['what is my name', 'who am i'], 'direct_message,direct_mention,mention', function (bot, message) { + controller.storage.users.get(message.user, function (err, user) { if (user && user.name) { - bot.reply(message,'Your name is ' + user.name); + bot.reply(message, 'Your name is ' + user.name); } else { - bot.reply(message,'I don\'t know yet!'); + bot.reply(message, 'I don\'t know yet!'); } }); }); - - -controller.hears(['shutdown'],'direct_message,direct_mention,mention',function(bot, message) { - - bot.startConversation(message,function(err, convo) { - convo.ask('Are you sure you want me to shutdown?',[ +controller.hears(['shutdown'], 'direct_message,direct_mention,mention', function (bot, message) { + bot.startConversation(message, function (err, convo) { + convo.ask('Are you sure you want me to shutdown?', [ { pattern: bot.utterances.yes, - callback: function(response, convo) { + callback: function (response, convo) { convo.say('Bye!'); convo.next(); - setTimeout(function() { + setTimeout(function () { process.exit(); - },3000); + }, 3000); } }, - { - pattern: bot.utterances.no, - default: true, - callback: function(response, convo) { - convo.say('*Phew!*'); - convo.next(); + { + pattern: bot.utterances.no, + default: true, + callback: function (response, convo) { + convo.say('*Phew!*'); + convo.next(); + } } - } ]); }); }); - -controller.hears(['uptime','identify yourself','who are you','what is your name'],'direct_message,direct_mention,mention',function(bot, message) { - +controller.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'], 'direct_message,direct_mention,mention', function (bot, message) { var hostname = os.hostname(); var uptime = formatUptime(process.uptime()); - - bot.reply(message,':robot_face: I am a bot named <@' + bot.identity.name + '>. I have been running for ' + uptime + ' on ' + hostname + '.'); - + bot.reply(message, ':robot_face: I am a bot named <@' + bot.identity.name + '>. I have been running for ' + uptime + ' on ' + hostname + '.'); }); - -controller.hears(['fibonacci'], 'direct_message,direct_mention,mention', function(bot, message) { +controller.hears(['fibonacci'], 'direct_message,direct_mention,mention', function (bot, message) { if (message.text === 'fibonacci') { - bot.reply(message, '1, 1, 2, 3, 5, 8, 13, 21, 34, 55'); + bot.reply(message, '1, 1, 2, 3, 5'); } }); -controller.hears(['fibonacci ([0-9]+)'], 'direct_message,direct_mention,mention', function(bot, message) { - var parameter = parseInt(message.match[1]); - - var fibonacci = calculateFibonacciUpto(parameter); - - if (fibonacci[fibonacci.length-1] !== parameter) { - bot.reply(message, 'That is not a Fibonacci number!'); - } - else { - bot.reply(message, fibonacci.slice(fibonacci.length-10,fibonacci.length).join(', ')); +controller.hears(['fibonacci (.*)'], 'direct_message,mention', function (bot, message) { + var num = message.match[1]; + if (isFibonacci(num) == 1) { + var i = 0; + var s = ""; + for (i = 0; i < 5; i++) { + num = findnextFibonacci(num); + s = s + ', ' + num; + } + bot.reply(message, 'your number is a fibonacci number, the following 5 fibonacci numbers are' + s); + } else { + bot.reply(message, 'your number is not a fibonacci number'); } -}); -function calculateFibonacciUpto(goal) { - var fibonacci = [1, 1]; - - while (fibonacci[fibonacci.length-1] < goal) { - fibonacci.push(fibonacci[fibonacci.length-2] + fibonacci[fibonacci.length-1]); + + +}); +function isFibonacci(number) { + var prev = 0; + var curr = 1; + while (prev <= number) { + if (prev == number) { + return 1; + } + curr = prev + curr; + prev = curr - prev; } - - return fibonacci; + +} +function findnextFibonacci(lowerLimit) { + + for (lowerLimit++; !isFibonacci(lowerLimit); lowerLimit++) + ; + return lowerLimit; } function formatUptime(uptime) { @@ -211,43 +182,69 @@ function formatUptime(uptime) { if (uptime != 1) { unit = unit + 's'; } - uptime = uptime + ' ' + unit; return uptime; } +<<<<<<< HEAD -controller.hears('prime',['direct_message', 'direct_mention', 'mention'],function(bot,message) { +======= +>>>>>>> 53f857728fbc05b8033e000c1e6f1ee5b215104b +controller.hears('prime', ['direct_message', 'direct_mention', 'mention'], function (bot, message) { if (message.text === "prime") { return bot.reply(message, '2, 3, 5, 7, 11, 13, 17, 19, 23, 29'); } }); -controller.hears('prime (.*)',['direct_message', 'direct_mention', 'mention'],function(bot,message) { - +controller.hears('prime (.*)', ['direct_message', 'direct_mention', 'mention'], function (bot, message) { var parameter = parseInt(message.match[1]); - if (MathHelper.isPrime(parameter)) { var primes = new Array(); - var number = parameter + 1; - + var number = parameter - 1; while (primes.length < 10) { - if (MathHelper.isPrime(number)) { primes.push(number); } - - number++; + number--; } - var reply = ""; for (var i = 0; i < primes.length; i++) { reply += primes[i] + " "; } - return bot.reply(message, reply); - } - else { + } else { return bot.reply(message, "your parameter: " + parameter + " is not Prime number"); } }); +controller.hears(['How is the weather in (.*)'], 'direct_message,mention', function (bot, message) { + var city = message.match[1]; + weather.find({search: city, degreeType: 'C'}, function (err, result) { + return bot.reply(message, 'The weather in ' + result[0]["location"]["name"] + " is " + result[0]["current"]["temperature"] + "C and it is " + result[0]["current"]["skytext"]); + + + if (err) + console.log(err); + + console.log(JSON.stringify(result, null, 2)); + + + }); +}); +<<<<<<< HEAD + +======= +>>>>>>> 53f857728fbc05b8033e000c1e6f1ee5b215104b + +controller.hears('what is (.*) \\+ (.*)',['direct_message', 'direct_mention', 'mention'],function(bot,message) { + + var num1 = message.match[1]; + var num2 = message.match[2]; + + if (num1 != null && num2 != null) { + return bot.reply(message, num1 + ' + ' + num2 + ' = ' + botmath.sum(num1, num2)); + } +}); +<<<<<<< HEAD + +======= +>>>>>>> 53f857728fbc05b8033e000c1e6f1ee5b215104b diff --git a/botmath.js b/botmath.js index 20c4242a3..07649dffb 100644 --- a/botmath.js +++ b/botmath.js @@ -1,3 +1,7 @@ +<<<<<<< HEAD +======= + +>>>>>>> 3f79b876dffff0bb273821454b62dcf4e2aecec2 var isPrime = function (n) { if (isNaN(n) || !isFinite(n) || n%1 || n<2) return false; if (n%2==0) return (n==2); @@ -10,3 +14,57 @@ var isPrime = function (n) { module.exports.isPrime = isPrime; +<<<<<<< HEAD + +======= +>>>>>>> 3f79b876dffff0bb273821454b62dcf4e2aecec2 +var sum = function (num1, num2) { + return parseFloat(num1) + parseFloat(num2); +} + +module.exports.sum = sum; + +<<<<<<< HEAD +======= +var calculateFibonacciUpto = function(goal) { + var fibonacci = [1, 1]; + while (fibonacci[fibonacci.length-1] < goal) { + fibonacci.push(fibonacci[fibonacci.length-2] + fibonacci[fibonacci.length-1]); + } + return fibonacci; +} + +module.exports.calculateFibonacciUpto = calculateFibonacciUpto; + +>>>>>>> 3f79b876dffff0bb273821454b62dcf4e2aecec2 +var isFibonacci = function (number) { + var prev = 0; + var curr = 1; + while (prev <= number) { + if (prev == number) { + return 1; + } + curr = prev + curr; + prev = curr - prev; + }} + +module.exports.isFibonacci = isFibonacci; +<<<<<<< HEAD + +var findnextFibonacci = function (lowerLimit) { + for (lowerLimit++; !isFibonacci(lowerLimit); lowerLimit++){ + return lowerLimit; + } +} + +module.exports.findnextFibonacci = findnextFibonacci; + +======= + +var findnextFibonacci = function (lowerLimit) { + for (lowerLimit++; !isFibonacci(lowerLimit); lowerLimit++); + return lowerLimit; +} + +module.exports.findnextFibonacci = findnextFibonacci; +>>>>>>> 3f79b876dffff0bb273821454b62dcf4e2aecec2 diff --git a/foo/calculateFibonacciUptoTest.js b/foo/calculateFibonacciUptoTest.js new file mode 100644 index 000000000..c9e01713c --- /dev/null +++ b/foo/calculateFibonacciUptoTest.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var bothmath = require('../botmath.js'); + +describe('botmath', function() { + describe('calculateFibonacciUpto', function () { + it('should find all Fibonacci numbers up to a given number', function () { + assert.equal([1,1], bothmath.calculateFibonacciUpto(0)); + assert.equal([1,1], bothmath.calculateFibonacciUpto(-1)); + assert.equal([0, 1, 1, 2, 3, 5, 8, 13, 21, 34], bothmath.calculateFibonacciUpto(34)); + }) + it('should return NaN if the value is not numeric', function () { + assert.ok(isNaN(bothmath.isPrime('fibonacci'))); + }); + }); +}); \ No newline at end of file diff --git a/foo/isPrimeTest.js b/foo/isPrimeTest.js new file mode 100644 index 000000000..c0cb5a4b7 --- /dev/null +++ b/foo/isPrimeTest.js @@ -0,0 +1,16 @@ +var assert = require('assert'); +var bothmath = require('../botmath.js'); + +describe('botmath', function() { + describe('isPrime', function () { + it('should check if a number is a prime number', function () { + assert.equal(true, bothmath.isPrime(1)); + assert.equal(false, bothmath.isPrime(4)); + assert.equal(false, bothmath.isPrime(-5)); + assert.equal(false, bothmath.isPrime(147876876876)); + }) + it('should return NaN if the value is not numeric', function () { + assert.ok(isNaN(bothmath.isPrime('prime'))); + }); + }); +}); \ No newline at end of file diff --git a/foo/test.js b/foo/test.js new file mode 100644 index 000000000..b2d23698f --- /dev/null +++ b/foo/test.js @@ -0,0 +1,9 @@ +var assert = require('assert'); +describe('Array', function() { + describe('#indexOf()', function () { + it('should return -1 when the value is not present', function () { + assert.equal(-1, [1,2,3].indexOf(5)); + assert.equal(-1, [1,2,3].indexOf(0)); + }); + }); +}); diff --git a/package.json b/package.json index 69a5959a8..0aa8a3211 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,10 @@ "eventemitter2": "0.4.14", "express": "^4.13.3", "jfs": "^0.2.6", + "mocha": "^2.4.5", "mustache": "^2.2.1", "request": "^2.67.0", + "weather-js": "^1.0.2", "ws": "^1.0.0" }, "devDependencies": { @@ -21,6 +23,9 @@ "tape": "^4.4.0", "winston": "^2.1.1" }, + "scripts": { + "test": "mocha tests/*.js" + }, "repository": { "type": "git", "url": "https://github.com/juhovan/botkit.git" diff --git a/tests/botmathTest.js b/tests/botmathTest.js new file mode 100644 index 000000000..ffeec7579 --- /dev/null +++ b/tests/botmathTest.js @@ -0,0 +1,80 @@ +var assert = require('assert'); +var bothmath = require('../botmath.js'); + +describe('botmath', function() { + describe('sum', function () { + it('should return sum of 2 values', function () { + assert.equal(-2, bothmath.sum(-2, 0)); + assert.equal(1, bothmath.sum(-1, 2)); + assert.equal(6.5, bothmath.sum(3.5, 3)); + assert.equal(1337, bothmath.sum(1338.2, -1.2)); + }) + it('should return NaN if both values are not numeric', function () { + assert.ok(isNaN(bothmath.sum(1335, 'a'))); + }); + }); +<<<<<<< HEAD + }); + + +}); + +describe('botmath', function() { + describe('isPrime', function() { + it('should return true if the number is Prime', function() { + assert.equal(false, bothmath.isPrime(-2)); + assert.equal(true, bothmath.isPrime(5)); + assert.equal(false, bothmath.isPrime(6)); + }); + + it('should return NaN if number is not numeric', function () { + assert.ok(!isNaN(bothmath.isPrime('a'))); + assert.ok(!isNaN(bothmath.isPrime(14))); + }); + }); +}); + +describe('botmath', function() { + describe('isFibonacci', function () { + it('should return 1 if number is fibonacci', function () { + assert.equal(1, bothmath.isFibonacci(144)); + assert.equal(1, bothmath.isFibonacci(13)); + }) + it('should return NaN if value is string', function () { + assert.ok(isNaN(bothmath.isFibonacci('a'))); + assert.ok(isNaN(bothmath.isFibonacci(14))); + assert.ok(isNaN(bothmath.isFibonacci(-1))); + }); + }); +======= +>>>>>>> 3f79b876dffff0bb273821454b62dcf4e2aecec2 +}); + + +describe('bothmath', function() { + describe('isPrime', function () { + it('should return true if a number is a prime number', function () { + assert.equal(true, bothmath.isPrime(5)); + assert.equal(false, bothmath.isPrime(4)); + assert.equal(false, bothmath.isPrime(-5)); + assert.equal(false, bothmath.isPrime(147876876876)); + }) + it('should return NaN if the value is not numeric', function () { + assert.ok(!isNaN(bothmath.isPrime('a'))); + }); + }); +}); + +describe('botmath', function() { + describe('isFibonacci', function () { + it('should return 1 if number is fibonacci', function () { + assert.equal(1, bothmath.isFibonacci(144)); + assert.equal(1, bothmath.isFibonacci(13)); + }) + it('should return NaN if value is string', function () { + assert.ok(isNaN(bothmath.isFibonacci('a'))); + assert.ok(isNaN(bothmath.isFibonacci(14))); + assert.ok(isNaN(bothmath.isFibonacci(-1))); + }); + }); +}); \ No newline at end of file