diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0a17ab610 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Logs +logs +*.log +npm-debug.log* + +nbproject +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +.idea/* + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history +/nbproject/private/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..613b22fd7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "weather"] + path = weather + url = https://github.com/cmfatih/weather.git diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 000000000..5fa5cacbc --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +botkit \ No newline at end of file diff --git a/.idea/botkit.iml b/.idea/botkit.iml new file mode 100644 index 000000000..e96c0571f --- /dev/null +++ b/.idea/botkit.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..97626ba45 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 000000000..d4bebd32e --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/botkit_node_modules.xml b/.idea/libraries/botkit_node_modules.xml new file mode 100644 index 000000000..9c430a8f5 --- /dev/null +++ b/.idea/libraries/botkit_node_modules.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..72abef0a7 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..ab24e7918 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..d22a7cd69 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $PROJECT_DIR$ + true + + bdd + + DIRECTORY + + false + + + + + + + + + + + 1456306378216 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..579c256d0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "5.4.0" + \ No newline at end of file diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE new file mode 100644 index 000000000..6748cca7c --- /dev/null +++ b/ISSUE_TEMPLATE @@ -0,0 +1,7 @@ +### Expected behavior + + +### Actual behavior + + +### Steps to reproduce the behavior diff --git a/Procfile b/Procfile new file mode 100644 index 000000000..87537474d --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +worker: node bot.js \ No newline at end of file diff --git a/bot.js b/bot.js index 00eb7b9bd..c977afd58 100755 --- a/bot.js +++ b/bot.js @@ -64,7 +64,8 @@ This bot demonstrates many of the core features of Botkit: -> http://howdy.ai/botkit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - +var weather = require('weather-js'); +var TinyURL = require('tinyurl'); if (!process.env.token) { console.log('Error: Specify token in environment'); @@ -74,6 +75,13 @@ if (!process.env.token) { var MathHelper = require('./botmath.js'); var Botkit = require('./lib/Botkit.js'); var os = require('os'); +var botmath = require('./botmath.js'); +var fibo = require('./fibonacci.js'); +var http = require('http'); +var request = require('request'); + + + var controller = Botkit.slackbot({ debug: true, @@ -134,6 +142,84 @@ controller.hears(['what is my name','who am i'],'direct_message,direct_mention,m }); +controller.hears(['google (.*)','googleta (.*)'],'direct_message,direct_mention,mention,message_received',function(bot, message) { + + var matches = message.text.match(/(google|googleta) (.*)/i); + + var sentence = matches[2]; + + console.log(sentence); + + controller.storage.users.get(message.user,function(err, user) { + + if(err) console.log(err); + + var link = String(botmath.googlefunc(sentence)); + + var randomfunc = botmath.randomanswer(); + + TinyURL.shorten(link, function(res) { + bot.reply(message, randomfunc + ' ' + res); + }); + }); +}); + +controller.hears(['who made me'],'direct_message,direct_mention,mention',function(bot, message) { + + controller.storage.users.get(message.user,function(err, user) { + if (user && user.name) { + bot.reply(message,user.name + ' made me'); + } else { + bot.reply(message,'I don\'t know yet!'); + } + }); +}); + +controller.on('user_channel_join',function(bot, message) { + var poembase = [ + "Roses are red, my cat eat dogs for breakfast", + "Gangters are like pets", + "Roses are red Violets are blue Rhyming is hard Like I am for you", + "Roses are okay Violets are fine You be the 6 And I'll be the 9", + "Roses are red Violets are violet Here is my number Why don't you dial it?", + ]; + var selecteditem = parseInt(poembase.length * Math.random(), 10); + var thispoem = poembase[selecteditem]; + + bot.reply(message, 'My poem is here: ' + thispoem); +}); + +controller.hears(['how is the weather in (.*)'],'direct_message,direct_mention,mention',function(bot, message) { + + var matches = message.text.match(/how is the weather in (.*)/i); + var city = matches[1]; + + controller.storage.users.get(message.user,function(err, user) { + if (city) { + + weather.find({search: ''+city+'', degreeType: 'C'}, function(err, result) { + if(err) console.log(err); + + /* + console.log("LOCATION " + JSON.stringify(result[0].location.name, null, 2)); + */ + + var cityname = JSON.stringify(result[0].location.name, null, 2); + var temperature = JSON.stringify(result[0].current.temperature, null, 2); + var weather = JSON.stringify(result[0].current.skytext, null, 2); + + bot.reply(message,'The weather in ' + cityname + ' ,' +' Temperature: ' + temperature + 'C ,' + " Weather: " + weather); + + }); + + } if(!city) { + bot.reply(message,'Please give city.'); + } + + }); +}); + + controller.hears(['shutdown'],'direct_message,direct_mention,mention',function(bot, message) { bot.startConversation(message,function(err, convo) { @@ -168,35 +254,78 @@ controller.hears(['uptime','identify yourself','who are you','what is your name' bot.reply(message,':robot_face: I am a bot named <@' + bot.identity.name + '>. I have been running for ' + uptime + ' on ' + hostname + '.'); }); +controller.hears(['prime'],'direct_message,direct_mention,mention',function(bot, message) { + + controller.storage.users.get(message.user,function(err, user) { + bot.reply(message,'2, 3, 5, 7, 11, 13, 17, 19, 23, 29'); + + }); +}); + +controller.hears(['prime (.*)'],'direct_message,direct_mention,mention',function(bot, message) { + + var numbers = message.text.match(/prime (.*)/i); + var number = numbers[1]; + + var test = number / number; + var sectest = number / 2; + + + controller.storage.users.get(message.user,function(err, user) { + + if(test == 1 && sectest % 1 != 0) { + bot.reply(message,number +' is prime number'); + } else if (number == 2) { + bot.reply(message,number +' is prime number'); + } else { + bot.reply(message,number +' is not prime number'); + + var count = 0; + var primenumbers = []; + var jako + var jako2 + + while(count < 10) + { + number--; + + jako = number / number; + jako2 = number / 2; + + if(jako == 1 && jako2 % 1 !== 0 || number == 2 || number == -2 || number == 0) + { + + primenumbers.push(number); + count++; + + } + + } + bot.reply(message,'next 10 prime numbers are: ' + primenumbers); + } + }); +}); 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, 'First five fibonacci numbers: 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); - + + var fibonacci = fibo.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(', ')); + var nextFibs = fibo.calculateNextFiveFibonacci(fibonacci); + bot.reply(message,"That is a Fibonacci number! Here are the next 5: " + nextFibs); } }); -function calculateFibonacciUpto(goal) { - var fibonacci = [1, 1]; - - while (fibonacci[fibonacci.length-1] < goal) { - fibonacci.push(fibonacci[fibonacci.length-2] + fibonacci[fibonacci.length-1]); - } - - return fibonacci; -} function formatUptime(uptime) { var unit = 'second'; @@ -214,8 +343,10 @@ function formatUptime(uptime) { uptime = uptime + ' ' + unit; return uptime; -} +}; + +/* 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'); @@ -250,4 +381,83 @@ controller.hears('prime (.*)',['direct_message', 'direct_mention', 'mention'],fu return bot.reply(message, "your parameter: " + parameter + " is not Prime number"); } }); +*/ + +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)); + } + +}); + +controller.hears(['speedrun (.*)'],'direct_message,direct_mention,mention',function(bot, message) { + + var matches = message.text.match(/speedrun (.*)/i); + var name = matches[1]; + + const apiUrl = 'http://www.speedrun.com/api_records.php?series='; + var url = apiUrl.concat(name); + + request(url, function (error, response, body) { + if (!error && response.statusCode == 200) { + var parsed = JSON.parse(body); + var gameArray = []; + + for(var x in parsed){ + gameArray.push(parsed[x]); + } + + bot.reply(message,'Here are some speedruns that I found!'); + + for (var item in parsed) { + bot.reply(message,'Game: ' + item); + for (var subItem in parsed[item]) { + var reply = JSON.stringify(parsed[item][subItem], null, 4); + bot.reply(message,reply); + } + } + } + if(error) { + console.log(error); + } + }) +}); + +controller.hears(['xkcd new'],'direct_message,direct_mention,mention',function(bot, message) { + + const url = 'https://xkcd.com/info.0.json'; + + request(url, function (error, response, body) { + if (!error && response.statusCode == 200) { + var parsed = JSON.parse(body); + bot.reply(message,'Here is the latest XKCD comic: ' + parsed['img']); + } + if(error) { + console.log(error); + } + }) +}); + +controller.hears(['xkcd random'],'direct_message,direct_mention,mention',function(bot, message) { + + const host = 'https://xkcd.com/'; + const end = '/info.0.json'; + var num = Math.floor(Math.random() * 1648); + var url = host + num + end; + request(url, function (error, response, body) { + if (!error && response.statusCode == 200) { + var parsed = JSON.parse(body); + console.log('PARSED: ' + parsed); + bot.reply(message,'Here is a random XKCD comic: ' + parsed['img']); + } + if(error) { + console.log(error); + } + }) +}); + diff --git a/botmath.js b/botmath.js index 20c4242a3..cdaadcb38 100644 --- a/botmath.js +++ b/botmath.js @@ -10,3 +10,38 @@ var isPrime = function (n) { module.exports.isPrime = isPrime; +var sum = function (num1, num2) { + return parseFloat(num1) + parseFloat(num2); +} + +module.exports.sum = sum; + +var googlefunc = function (searchstring) { + + var tosearch = searchstring.replace(/ /g, '+'); + + var link = 'http://lmgtfy.com/?q='+ tosearch; + console.log('Link' + link); + + return link; +} + +module.exports.googlefunc = googlefunc; + +var randomanswer = function () { + var listofresults = [ + 'I found a anwser for you. Check this out:', + 'Hmmm, Have you tried this:', + 'Hey That sound odd could it be this: ', + 'Check the first results here: ', + 'That sounds intrestings! Check this out: ', + 'Maybe you should ask help from here: ', + 'Sorry to hear that you have troubles:( Maybe this would help? ' + ]; + var answers = listofresults[Math.floor(Math.random() * listofresults.length)]; + console.log('result ' + answers); + + return answers; +} + +module.exports.randomanswer = randomanswer; diff --git a/fibonacci.js b/fibonacci.js new file mode 100644 index 000000000..0bfda90d9 --- /dev/null +++ b/fibonacci.js @@ -0,0 +1,30 @@ +/** + * Created by mikko on 23.2.2016. + */ +/** + * Created by mikko on 23.2.2016. + */ + +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; +}; +var calculateNextFiveFibonacci =function (arr) { + var fib = arr; + var count = 0; + while ( count < 5) { + fib.push(fib[fib.length-2] + fib[fib.length-1]); + count++; + } + fib = fib.slice(fib.length-5,fib.length).join(', '); + return fib; +}; + +module.exports.calculateFibonacciUpto = calculateFibonacciUpto; +module.exports.calculateNextFiveFibonacci = calculateNextFiveFibonacci; + diff --git a/package.json b/package.json index 69a5959a8..1ce6b7998 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,14 @@ "description": "Building blocks for Building Bots", "main": "lib/Botkit.js", "dependencies": { + "weather-js": "", + "tinyurl": "", "body-parser": "^1.14.2", "debug": "2.2.0", "eventemitter2": "0.4.14", "express": "^4.13.3", "jfs": "^0.2.6", + "mocha": "^2.4.5", "mustache": "^2.2.1", "request": "^2.67.0", "ws": "^1.0.0" @@ -21,6 +24,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/readme.md b/readme.md index 60fa8dc18..1e13ca50d 100755 --- a/readme.md +++ b/readme.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/teroanttila/botkit.svg?branch=master)](https://travis-ci.org/teroanttila/botkit.svg?branch=master) + # [Botkit](http://howdy.ai/botkit) - Best course ever! Botkit designed to ease the process of designing and running useful, creative or diff --git a/tests/botmathTest.js b/tests/botmathTest.js new file mode 100644 index 000000000..908258c99 --- /dev/null +++ b/tests/botmathTest.js @@ -0,0 +1,16 @@ +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'))); + }); + }); +}); diff --git a/tests/fibonacciTest.js b/tests/fibonacciTest.js new file mode 100644 index 000000000..36dffac09 --- /dev/null +++ b/tests/fibonacciTest.js @@ -0,0 +1,26 @@ +/** + * Created by mikko on 23.2.2016. + */ +var assert = require('assert'); +var fibonacci = require('../fibonacci.js'); + +describe('fibonacci', function() { + describe('calculateFibonacciUpto', function () { + it('should return array of fibonacci numbers up to a goal', function () { + assert.deepEqual([1,1,2,3,5,8], fibonacci.calculateFibonacciUpto(8)); + assert.deepEqual([1,1,2,3,5,8,13], fibonacci.calculateFibonacciUpto(13)); + assert.deepEqual([1,1], fibonacci.calculateFibonacciUpto(1)); + assert.deepEqual([1,1,2,3,5,8,13,21,34,55], fibonacci.calculateFibonacciUpto(55)); + }) + + }); + describe('calculateNextFiveFibonacci', function () { + it('should return the next 5 fibonacci numbers', function () { + //assert.deepEqual('13, 21, 34, 55, 89', fibonacci.calculateNextFiveFibonacci([1,1,2,3,5,8])); + assert.deepEqual('13, 21, 34, 55, 89', fibonacci.calculateNextFiveFibonacci(fibonacci.calculateFibonacciUpto(8))); + assert.deepEqual('233, 377, 610, 987, 1597', fibonacci.calculateNextFiveFibonacci(fibonacci.calculateFibonacciUpto(144))); + assert.deepEqual('2584, 4181, 6765, 10946, 17711', fibonacci.calculateNextFiveFibonacci(fibonacci.calculateFibonacciUpto(1597))); + }) + + }) +}); diff --git a/tests/test.js b/tests/test.js new file mode 100644 index 000000000..b2d23698f --- /dev/null +++ b/tests/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/weather b/weather new file mode 160000 index 000000000..cc33373de --- /dev/null +++ b/weather @@ -0,0 +1 @@ +Subproject commit cc33373de4fc850b050efe844c6e5d6089aa44c0