├── .gitignore ├── sample └── index.js ├── temperatureReport ├── package.json ├── test │ └── indexTest.js └── index.js ├── weatherReport ├── package.json ├── test │ └── indexTest.js └── index.js ├── README.md ├── dustAlert ├── package.json ├── test │ └── weekTest.js └── src │ └── week.js └── botChat └── src └── douzodouzo.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ -------------------------------------------------------------------------------- /sample/index.js: -------------------------------------------------------------------------------- 1 | 2 | exports.handler = function(event, context) { 3 | console.log(JSON.stringify({event: event, context: context}, null, 2)); 4 | context.succeed({event: event}); 5 | }; -------------------------------------------------------------------------------- /temperatureReport/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "weather.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "axios": "^0.7.0", 13 | "xml2js": "^0.4.15", 14 | "asyncawait": "^1.0.1", 15 | "aws-sdk": "^2.2.19", 16 | "lodash": "^3.10.1", 17 | "es6-promise": "^3.0.2" 18 | }, 19 | "devDependencies": { 20 | "espower-loader": "^1.0.0", 21 | "power-assert": "^1.2.0", 22 | "proxyquire": "^1.7.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /weatherReport/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "weather.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "axios": "^0.7.0", 13 | "xml2js": "^0.4.15", 14 | "asyncawait": "^1.0.1", 15 | "aws-sdk": "^2.2.19", 16 | "lodash": "^3.10.1", 17 | "es6-promise": "^3.0.2" 18 | }, 19 | "devDependencies": { 20 | "espower-loader": "^1.0.0", 21 | "power-assert": "^1.2.0", 22 | "proxyquire": "^1.7.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # slackBot 3 | 4 | this repo has some slack bot(running on AWS-Lambda and NodeJS) 5 | 6 | the functions are 7 | 8 | - botChat 9 | - simplest sample of "slack outgoing web-hook" with "AWS Lambda & API Gateway" 10 | - bots communicate each other. 11 | 12 | - dustAlert 13 | - sample of "slack incoming web-hook" with "scheduled AWS Lambda" 14 | - when dust day has come, alert it. 15 | 16 | - weatherReport 17 | - sample of "slack incoming web-hook" with "scheduled AWS Lambda" 18 | - when today will be rainy, alert it. 19 | 20 | - temperatureReport 21 | - sample of "slack incoming web-hook" with "scheduled AWS Lambda" 22 | - when today will be cold/hot(±5 than yesterday), alert it. -------------------------------------------------------------------------------- /dustAlert/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slackBot", 3 | "version": "1.0.0", 4 | "description": "nodeJsSamples =============", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/TechResidence/slackBot.git" 15 | }, 16 | "author": "uryyyyyyy", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/TechResidence/slackBot/issues" 20 | }, 21 | "homepage": "https://github.com/TechResidence/slackBot", 22 | "dependencies": { 23 | "aws-sdk": "^2.2.19" 24 | }, 25 | "devDependencies": { 26 | "mocha": "^2.3.4", 27 | "espower-loader": "^1.0.0", 28 | "power-assert": "^1.2.0", 29 | "proxyquire": "^1.7.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dustAlert/test/weekTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var week = require('../src/week'); 4 | var assert = require('power-assert'); 5 | 6 | describe('week', function(){ 7 | describe('calcText()', function(){ 8 | it('Tue', function(){ 9 | var date = new Date('Mon, 30 Nov 2015 22:00:00'); 10 | var str = week.calcText(date); 11 | assert(str === "明日 ハ 「可燃ゴミ」 ノ 日デス"); 12 | }); 13 | 14 | it('1st Wed', function(){ 15 | var date = new Date('Tue, 1 Dec 2015 22:00:00'); 16 | var str = week.calcText(date); 17 | assert(str === "明日 ハ 「不燃ゴミ」 ノ 日デス"); 18 | }); 19 | 20 | it('2nd Wed', function(){ 21 | var date = new Date('Tue, 8 Dec 2015 22:00:00'); 22 | var str = week.calcText(date); 23 | assert(str === null); 24 | }); 25 | 26 | it('Thu', function(){ 27 | var date = new Date('Thu, 2 Dec 2015 22:00:00'); 28 | var str = week.calcText(date); 29 | assert(str === "明日 ハ 「資源ゴミ」 ノ 日デス"); 30 | }); 31 | 32 | it('Fri', function(){ 33 | var date = new Date('Fri, 3 Dec 2015 22:00:00'); 34 | var str = week.calcText(date); 35 | assert(str === "明日 ハ 「可燃ゴミ」 ノ 日デス"); 36 | }); 37 | }); 38 | }); -------------------------------------------------------------------------------- /botChat/src/douzodouzo.js: -------------------------------------------------------------------------------- 1 | exports.handler = function(event, context) { 2 | console.log(event); 3 | if(event.text === "<@USLACKBOT>: じゃあ俺がやるよ"){ 4 | context.done(null, {text: "<@USLACKBOT>: なら俺がやるよ", 5 | "username": "slackbot", 6 | "icon_emoji": ":slackbot:" 7 | }); 8 | }else if(event.text === "<@USLACKBOT>: なら俺がやるよ"){ 9 | context.done(null, {text: "<@USLACKBOT>: いや、俺がやるよ", 10 | "username": "slackbot2", 11 | "icon_emoji": ":robot_face:" 12 | }); 13 | }else if(event.text === "<@USLACKBOT>: いや、俺がやるよ"){ 14 | context.done(null, {text: "<@USLACKBOT>: そんなそんな、私がやりますよ。", 15 | "username": "bot_ko", 16 | "icon_emoji": ":shibata_ko:" 17 | }); 18 | }else if(event.text === "<@USLACKBOT>: じゃあ"){ 19 | context.done(null, {text: "<@USLACKBOT>: どうぞどうぞ", 20 | "username": "slackbot", 21 | "icon_emoji": ":slackbot:" 22 | }); 23 | }else if(event.text === "<@USLACKBOT>: どうぞどうぞ"){ 24 | context.done(null, {text: "<@USLACKBOT>: どうぞどうぞ!", 25 | "username": "slackbot2", 26 | "icon_emoji": ":robot_face:" 27 | }); 28 | }else if(event.text === "<@USLACKBOT>: どうぞどうぞ!"){ 29 | context.done(null, {text: "<@USLACKBOT>: どうぞどうぞどうぞ", 30 | "username": "bot_ko", 31 | "icon_emoji": ":shibata_ko:" 32 | }); 33 | } 34 | }; -------------------------------------------------------------------------------- /weatherReport/test/indexTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require('es6-promise').polyfill(); 3 | 4 | var index = require('../index'); 5 | var assert = require('power-assert'); 6 | var async = require('asyncawait/async'); 7 | var await = require('asyncawait/await'); 8 | 9 | var onFailure = function(value) { 10 | console.log(value); 11 | }; 12 | 13 | describe('index', function() { 14 | describe('sendToSlack()', function () { 15 | it('simple', function () { 16 | var promise = index.sendToSlack("test"); 17 | return promise.then(function (value) { 18 | assert(value.status === 200); 19 | }).catch(onFailure); 20 | }); 21 | }); 22 | 23 | describe('getWeatherAPI()', function () { 24 | it('simple', function () { 25 | var promise = index.getWeatherAPI(); 26 | return promise.then(function (value) { 27 | assert(value.status === 200); 28 | }).catch(onFailure); 29 | }); 30 | }); 31 | 32 | describe('integrationTest', function () { 33 | it('simple', function () { 34 | var func = async (function () { 35 | var res = await(index.getWeatherAPI()); 36 | var obj = await(index.xmlToJson(res.data)); 37 | var forecasts = index.getForecast(obj); 38 | var rainFallChances = index.getTodaysRainFallChance(forecasts); 39 | if(index.willFallRain(rainFallChances)){ 40 | var text = index.format(rainFallChances, obj); 41 | return index.sendToSlack(text); 42 | }else{ 43 | return Promise.resolve("no rain"); 44 | } 45 | }); 46 | return func().then(function (value) { 47 | assert(value === "no rain"); 48 | }).catch(onFailure); 49 | }); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /temperatureReport/test/indexTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require('es6-promise').polyfill(); 3 | 4 | var index = require('../index'); 5 | var assert = require('power-assert'); 6 | var async = require('asyncawait/async'); 7 | var await = require('asyncawait/await'); 8 | 9 | var onFailure = function(value) { 10 | console.log(value); 11 | }; 12 | 13 | describe('index', function() { 14 | describe('sendToSlack()', function () { 15 | it('simple', function () { 16 | var promise = index.sendToSlack("test"); 17 | return promise.then(function (value) { 18 | assert(value.status === 200); 19 | }).catch(onFailure); 20 | }); 21 | }); 22 | 23 | describe('getWeatherAPI()', function () { 24 | it('simple', function () { 25 | var promise = index.getWeatherAPI(); 26 | return promise.then(function (value) { 27 | assert(value.status === 200); 28 | }).catch(onFailure); 29 | }); 30 | }); 31 | 32 | describe('integrationTest', function () { 33 | it('simple', function () { 34 | var func = async (function () { 35 | var res = await(index.getWeatherAPI()); 36 | var obj = await(index.xmlToJson(res.data)); 37 | var forecasts = index.getForecast(obj); 38 | var rainFallChances = index.getTodaysRainFallChance(forecasts); 39 | if(index.willFallRain(rainFallChances)){ 40 | var text = index.format(rainFallChances, obj); 41 | return index.sendToSlack(text); 42 | }else{ 43 | return Promise.resolve("no rain"); 44 | } 45 | }); 46 | return func().then(function (value) { 47 | assert(value === "no rain"); 48 | }).catch(onFailure); 49 | }); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /dustAlert/src/week.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var https = require('https'); 4 | 5 | var postJson = function(obj, succCB, failCB) { 6 | var options = { 7 | hostname: 'hooks.slack.com', 8 | port: 443, 9 | path: '/services/XXX', 10 | method: 'POST', 11 | headers: { 12 | 'Content-Type': 'application/json' 13 | } 14 | }; 15 | 16 | var data = JSON.stringify(obj); 17 | var req = https.request(options, function(res) { 18 | 19 | var body = ''; 20 | res.setEncoding('utf8'); 21 | 22 | res.on('data', function(chunk) { 23 | body += chunk; 24 | }); 25 | 26 | res.on('end', function() { 27 | succCB(body); 28 | }); 29 | 30 | }).on('error', function(e) { 31 | failCB(e); 32 | }); 33 | 34 | req.write(data); 35 | req.end(); 36 | }; 37 | 38 | var calcText = function(date){ 39 | console.log(date); 40 | var weekNum = date.getDay(); 41 | if(weekNum === 1){//Mon 42 | return "今日 ハ 「可燃ゴミ」 ノ 日デス" 43 | }else if(weekNum === 3){//Wed 44 | return "今日 ハ 「資源ゴミ」 ノ 日デス" 45 | }else if(weekNum === 4){//Thu 46 | return "今日 ハ 「可燃ゴミ」 ノ 日デス" 47 | } 48 | if(weekNum === 2){//Tue 49 | date.setDate( date.getDate() + 1 ); 50 | var dateNum = date.getDate(); 51 | if(1 <= dateNum && dateNum <= 7) {//Tue 52 | return "今日 ハ 月ニ 一度 ノ 「不燃ゴミ」 ノ 日デス\n▒▒▓█▇▅▂∩( ✧Д✧)∩ファイアー▂▅▇█▓▒▒" 53 | } 54 | } 55 | return null; 56 | }; 57 | 58 | exports.calcText = calcText; 59 | 60 | exports.handler = function(event, context) { 61 | var onSuccess = function(value) { 62 | console.log(value); 63 | context.done(null, 'onSuccess'); 64 | }; 65 | 66 | var onFailure = function(value) { 67 | console.log(value); 68 | context.error(null, 'onSuccess'); 69 | }; 70 | 71 | console.log('start'); 72 | var date = new Date(); 73 | 74 | var text = calcText(date); 75 | if(text){ 76 | postJson({ 77 | 'text': text, 78 | "icon_emoji": ":slackbot:", 79 | "username": "slackbot", 80 | "channel": "#bot" 81 | }, onSuccess, onFailure); 82 | }else{ 83 | context.done(null, 'a very merry unbirthday to you'); 84 | } 85 | }; -------------------------------------------------------------------------------- /temperatureReport/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require('es6-promise').polyfill(); 3 | 4 | var assert = require('assert'); 5 | var _ = require('lodash'); 6 | var axios = require('axios'); 7 | var parseString = require('xml2js').parseString; 8 | var async = require('asyncawait/async'); 9 | var await = require('asyncawait/await'); 10 | 11 | 12 | var xmlToJson = function(xml) { 13 | return new Promise(function(resolve, reject) { 14 | parseString(xml, function (err, result) { 15 | if(err){ 16 | reject(err); 17 | }else{ 18 | resolve(result); 19 | } 20 | }); 21 | }); 22 | }; 23 | exports.xmlToJson = xmlToJson; 24 | 25 | var getForecast = function(obj) { 26 | var tokyoArea = obj.weatherforecast.pref[0].area[3]; 27 | assert (tokyoArea.$.id === "東京地方"); 28 | return tokyoArea.info; 29 | }; 30 | exports.getForecast = getForecast; 31 | 32 | var getWeatherAPI = function() { 33 | var weatherUrl = 'http://www.drk7.jp/weather/xml/13.xml'; 34 | return axios({ 35 | method: 'get', 36 | url: weatherUrl 37 | }); 38 | }; 39 | exports.getWeatherAPI = getWeatherAPI; 40 | 41 | var sendToSlack = function(text) { 42 | var slackUrl = 'https://hooks.slack.com/services/XXX';//set your slack API 43 | return axios({ 44 | method: 'post', 45 | url: slackUrl, 46 | data: { 47 | text: text, 48 | "username": "slackbot", 49 | "icon_emoji": ":slackbot:", 50 | "channel": "#bot" 51 | }, 52 | headers: {'Content-Type': 'application/json'} 53 | }); 54 | }; 55 | exports.sendToSlack = sendToSlack; 56 | 57 | 58 | var func = async (function () { 59 | var res = await(getWeatherAPI()); 60 | console.log("res"); 61 | console.log(res); 62 | var obj = await(xmlToJson(res.data)); 63 | console.log("obj"); 64 | console.log(obj); 65 | var forecasts = getForecast(obj); 66 | console.log("forecasts"); 67 | console.log(forecasts); 68 | 69 | var yesterdayMaxTemp = forecasts[0].temperature[0].range[0]._; 70 | console.log(yesterdayMaxTemp); 71 | var todayMaxTemp = forecasts[1].temperature[0].range[0]._; 72 | console.log(todayMaxTemp); 73 | var diff = todayMaxTemp - yesterdayMaxTemp; 74 | console.log(diff); 75 | if(diff > 5){ 76 | return sendToSlack("今日は、昨日より " + diff + "度 高いので暑いです"); 77 | }else if(diff < -5){ 78 | return sendToSlack("今日は、昨日より " + Math.abs(diff) + "度 低いので寒いです"); 79 | }else{ 80 | return Promise.resolve("no diff"); 81 | } 82 | }); 83 | 84 | exports.handler = function(event, context) { 85 | var onSuccess = function(value) { 86 | console.log("onSuccess"); 87 | context.done(null, value); 88 | }; 89 | 90 | var onFailure = function(value) { 91 | console.log("fail"); 92 | console.log(value); 93 | context.fail(value); 94 | }; 95 | func().then(onSuccess).catch(onFailure); 96 | }; -------------------------------------------------------------------------------- /weatherReport/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require('es6-promise').polyfill(); 3 | 4 | var assert = require('assert'); 5 | var _ = require('lodash'); 6 | var axios = require('axios'); 7 | var parseString = require('xml2js').parseString; 8 | var async = require('asyncawait/async'); 9 | var await = require('asyncawait/await'); 10 | 11 | 12 | var xmlToJson = function(xml) { 13 | return new Promise(function(resolve, reject) { 14 | parseString(xml, function (err, result) { 15 | if(err){ 16 | reject(err); 17 | }else{ 18 | resolve(result); 19 | } 20 | }); 21 | }); 22 | }; 23 | exports.xmlToJson = xmlToJson; 24 | 25 | var getForecast = function(obj) { 26 | var tokyoArea = obj.weatherforecast.pref[0].area[3]; 27 | assert (tokyoArea.$.id === "東京地方"); 28 | return tokyoArea.info; 29 | }; 30 | exports.getForecast = getForecast; 31 | 32 | var getTodaysRainFallChance = function(forecasts) { 33 | var res = []; 34 | console.log(forecasts[1].rainfallchance[0].period); 35 | res[0] = forecasts[1].rainfallchance[0].period[1]; 36 | res[1] = forecasts[1].rainfallchance[0].period[2]; 37 | res[2] = forecasts[1].rainfallchance[0].period[3]; 38 | res[3] = forecasts[2].rainfallchance[0].period[0]; 39 | return res; 40 | }; 41 | exports.getTodaysRainFallChance = getTodaysRainFallChance; 42 | 43 | var willFallRain = function(periods) { 44 | var ss = _.filter(periods, function(v){ 45 | return Number(v._) >= 50; 46 | }); 47 | return ss.length > 0; 48 | }; 49 | exports.willFallRain = willFallRain; 50 | 51 | var format = function(periods, obj) { 52 | var ss = _.map(periods, function(v){ 53 | if(v.$.hour === "00-06"){ 54 | return "翌日の" + v.$.hour + "時は" + v._ + "%"; 55 | }else{ 56 | return v.$.hour + "時は" + v._ + "%"; 57 | } 58 | }); 59 | var s = _.reduce(ss, function(acc, v){ 60 | return acc + "\n" + v; 61 | }); 62 | 63 | var tokyoArea = obj.weatherforecast.pref[0].area[3]; 64 | var todayStr = tokyoArea.info[1].$.date; 65 | return "今日(" + todayStr + ")は「" + tokyoArea.$.id + "」で雨が降りそうです。降水確率は、\n" + s; 66 | }; 67 | exports.format = format; 68 | 69 | var getWeatherAPI = function() { 70 | var weatherUrl = 'http://www.drk7.jp/weather/xml/13.xml'; 71 | return axios({ 72 | method: 'get', 73 | url: weatherUrl 74 | }); 75 | }; 76 | exports.getWeatherAPI = getWeatherAPI; 77 | 78 | var sendToSlack = function(text) { 79 | var slackUrl = 'https://hooks.slack.com/services/XXX';//set your slack API 80 | return axios({ 81 | method: 'post', 82 | url: slackUrl, 83 | data: { 84 | text: text, 85 | "username": "slackbot", 86 | "icon_emoji": ":slackbot:", 87 | "channel": "#bot" 88 | }, 89 | headers: {'Content-Type': 'application/json'} 90 | }); 91 | }; 92 | exports.sendToSlack = sendToSlack; 93 | 94 | 95 | var func = async (function () { 96 | var res = await(getWeatherAPI()); 97 | console.log("res"); 98 | console.log(res); 99 | var obj = await(xmlToJson(res.data)); 100 | console.log("obj"); 101 | console.log(obj); 102 | var forecasts = getForecast(obj); 103 | console.log("forecasts"); 104 | console.log(forecasts); 105 | var rainFallChances = getTodaysRainFallChance(forecasts); 106 | console.log("rainFallChances"); 107 | console.log(rainFallChances); 108 | if(willFallRain(rainFallChances)){ 109 | var text = format(rainFallChances, obj); 110 | console.log("text"); 111 | console.log(text); 112 | return sendToSlack(text); 113 | }else{ 114 | return Promise.resolve("no rain"); 115 | } 116 | }); 117 | 118 | exports.handler = function(event, context) { 119 | var onSuccess = function(value) { 120 | console.log("onSuccess"); 121 | context.done(null, value); 122 | }; 123 | 124 | var onFailure = function(value) { 125 | console.log("fail"); 126 | console.log(value); 127 | context.fail(value); 128 | }; 129 | func().then(onSuccess).catch(onFailure); 130 | }; --------------------------------------------------------------------------------