From 21f12043073cc378695abc0e6b4f1d6727aa7d59 Mon Sep 17 00:00:00 2001 From: "K.K. POON" Date: Fri, 29 Jan 2016 09:14:55 +0800 Subject: [PATCH] first commit --- .gitignore | 1 + .travis.yml | 6 +++ Gruntfile.js | 40 +++++++++++++++ README.md | 37 ++++++++++++++ index.coffee | 12 +++++ npm-debug.log | 105 +++++++++++++++++++++++++++++++++++++++ package.json | 39 +++++++++++++++ script/bootstrap | 18 +++++++ script/test | 6 +++ src/weather.coffee | 65 ++++++++++++++++++++++++ test/weather-test.coffee | 19 +++++++ 11 files changed, 348 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Gruntfile.js create mode 100644 README.md create mode 100644 index.coffee create mode 100644 npm-debug.log create mode 100644 package.json create mode 100755 script/bootstrap create mode 100755 script/test create mode 100644 src/weather.coffee create mode 100644 test/weather-test.coffee diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3c29566 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.11" + - "0.10" +notifications: + email: false \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..c79f93f --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,40 @@ +'use strict'; + +module.exports = function(grunt) { + + grunt.loadNpmTasks('grunt-mocha-test'); + grunt.loadNpmTasks('grunt-release'); + + grunt.initConfig({ + mochaTest: { + test: { + options: { + reporter: 'spec', + require: 'coffee-script' + }, + src: ['test/**/*.coffee'] + } + }, + release: { + options: { + tagName: 'v<%= version %>', + commitMessage: 'Prepared to release <%= version %>.' + } + }, + watch: { + files: ['Gruntfile.js', 'test/**/*.coffee'], + tasks: ['test'] + } + }); + + grunt.event.on('watch', function(action, filepath, target) { + grunt.log.writeln(target + ': ' + filepath + ' has ' + action); + }); + + // load all grunt tasks + require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); + + grunt.registerTask('test', ['mochaTest']); + grunt.registerTask('test:watch', ['watch']); + grunt.registerTask('default', ['test']); +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd2d7e5 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# hubot-weather-underground + +a hubot weather reporter + +See [`src/weather.coffee`](src/weather.coffee) for full documentation. + +## Installation + +In hubot project repo, run: + +`npm install hubot-weather-underground --save` + +Then add **hubot-weather-underground** to your `external-scripts.json`: + +```json +["hubot-weather-underground"] +``` + +## Set the environment variable + +`HUBOT_WEATHER_WUNDERGROUND_KEY=YOUR_WUNDERGROUND_KEY` + +## Sample Interaction + +``` +user1>> hubot weather of Hong Kong +hubot>> The current weather condition of Hong Kong is Light Rain Showers: +At Fri, 29 Jan 2016 09:13:02 +0800, Temperature is 16.4°C (feels like 16.4°C), Humidity: 94%, Pressure: 1018hPa, Wind: Calm, UV: 1.0 +user1>> hubot what is Sha Tin exactly called? +hubot>> Here are the possibilities: +Sha Tin, China +Sha Tin Racecourse, China +Sha Tin Sports Ground, China +Sha Tin Tau, Hong Kong +Sha Tin Wai, Hong Kong +Sha Tin, Hong Kong +``` diff --git a/index.coffee b/index.coffee new file mode 100644 index 0000000..d00a198 --- /dev/null +++ b/index.coffee @@ -0,0 +1,12 @@ +fs = require 'fs' +path = require 'path' + +module.exports = (robot, scripts) -> + scriptsPath = path.resolve(__dirname, 'src') + fs.exists scriptsPath, (exists) -> + if exists + for script in fs.readdirSync(scriptsPath) + if scripts? and '*' not in scripts + robot.loadFile(scriptsPath, script) if script in scripts + else + robot.loadFile(scriptsPath, script) diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..4408ddf --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,105 @@ +0 info it worked if it ends with ok +1 verbose cli [ '/Users/kkpoon/.nvm/versions/node/v4.2.6/bin/node', +1 verbose cli '/Users/kkpoon/.nvm/versions/node/v4.2.6/bin/npm', +1 verbose cli 'publish' ] +2 info using npm@2.14.12 +3 info using node@v4.2.6 +4 verbose publish [ '.' ] +5 silly cache add args [ '.', null ] +6 verbose cache add spec . +7 silly cache add parsed spec Result { +7 silly cache add raw: '.', +7 silly cache add scope: null, +7 silly cache add name: null, +7 silly cache add rawSpec: '.', +7 silly cache add spec: '/Users/kkpoon/Development/clustertech/hubot/hubot-weather', +7 silly cache add type: 'directory' } +8 verbose addLocalDirectory /Users/kkpoon/.npm/hubot-weather/0.1.0/package.tgz not in flight; packing +9 verbose tar pack [ '/Users/kkpoon/.npm/hubot-weather/0.1.0/package.tgz', +9 verbose tar pack '/Users/kkpoon/Development/clustertech/hubot/hubot-weather' ] +10 verbose tarball /Users/kkpoon/.npm/hubot-weather/0.1.0/package.tgz +11 verbose folder /Users/kkpoon/Development/clustertech/hubot/hubot-weather +12 info prepublish hubot-weather@0.1.0 +13 verbose addLocalTarball adding from inside cache /Users/kkpoon/.npm/hubot-weather/0.1.0/package.tgz +14 silly cache afterAdd hubot-weather@0.1.0 +15 verbose afterAdd /Users/kkpoon/.npm/hubot-weather/0.1.0/package/package.json not in flight; writing +16 verbose afterAdd /Users/kkpoon/.npm/hubot-weather/0.1.0/package/package.json written +17 silly publish { name: 'hubot-weather', +17 silly publish description: 'a hubot weather reporter', +17 silly publish version: '0.1.0', +17 silly publish author: { name: 'K.K. POON', email: 'noopkk@gmail.com' }, +17 silly publish license: 'MIT', +17 silly publish keywords: [ 'hubot', 'hubot-scripts', 'weather' ], +17 silly publish repository: +17 silly publish { type: 'git', +17 silly publish url: 'git://github.com/kkpoon/hubot-weather.git' }, +17 silly publish bugs: { url: 'https://github.com/kkpoon/hubot-weather/issues' }, +17 silly publish dependencies: { 'coffee-script': '~1.6' }, +17 silly publish devDependencies: +17 silly publish { mocha: '*', +17 silly publish chai: '*', +17 silly publish 'sinon-chai': '*', +17 silly publish sinon: '*', +17 silly publish 'grunt-mocha-test': '~0.7.0', +17 silly publish 'grunt-release': '~0.6.0', +17 silly publish matchdep: '~0.1.2', +17 silly publish 'grunt-contrib-watch': '~0.5.3' }, +17 silly publish main: 'index.coffee', +17 silly publish scripts: { test: 'grunt test' }, +17 silly publish readme: '# hubot-weather\n\na hubot weather reporter\n\nSee [`src/weather.coffee`](src/weather.coffee) for full documentation.\n\n## Installation\n\nIn hubot project repo, run:\n\n`npm install hubot-weather --save`\n\nThen add **hubot-weather** to your `external-scripts.json`:\n\n```json\n["hubot-weather"]\n```\n\n## Set the environment variable\n\n`HUBOT_WEATHER_WUNDERGROUND_KEY=YOUR_WUNDERGROUND_KEY`\n\n## Sample Interaction\n\n```\nuser1>> hubot hello\nhubot>> hello!\n```\n', +17 silly publish readmeFilename: 'README.md', +17 silly publish gitHead: '866fcbced941fdbc13b64b9a351e90e8953944b4', +17 silly publish homepage: 'https://github.com/kkpoon/hubot-weather#readme', +17 silly publish _id: 'hubot-weather@0.1.0', +17 silly publish _shasum: '487d1840f8872ebdb53072fe4436fe4380e9e21e', +17 silly publish _from: '.' } +18 verbose getPublishConfig undefined +19 silly mapToRegistry name hubot-weather +20 silly mapToRegistry using default registry +21 silly mapToRegistry registry https://registry.npmjs.org/ +22 silly mapToRegistry uri https://registry.npmjs.org/hubot-weather +23 verbose publish registryBase https://registry.npmjs.org/ +24 silly publish uploading /Users/kkpoon/.npm/hubot-weather/0.1.0/package.tgz +25 verbose request uri https://registry.npmjs.org/hubot-weather +26 verbose request sending authorization for write operation +27 info attempt registry request try #1 at 9:18:30 AM +28 verbose request using bearer token for auth +29 verbose request id d00e2423b37885d5 +30 http request PUT https://registry.npmjs.org/hubot-weather +31 http 403 https://registry.npmjs.org/hubot-weather +32 verbose headers { 'content-type': 'application/json', +32 verbose headers 'cache-control': 'max-age=300', +32 verbose headers 'content-length': '105', +32 verbose headers 'accept-ranges': 'bytes', +32 verbose headers date: 'Fri, 29 Jan 2016 01:18:31 GMT', +32 verbose headers via: '1.1 varnish', +32 verbose headers connection: 'keep-alive', +32 verbose headers 'x-served-by': 'cache-hkg6822-HKG', +32 verbose headers 'x-cache': 'MISS', +32 verbose headers 'x-cache-hits': '0', +32 verbose headers 'x-timer': 'S1454030310.945159,VS0,VE698' } +33 verbose request invalidating /Users/kkpoon/.npm/registry.npmjs.org/hubot-weather on PUT +34 error publish Failed PUT 403 +35 verbose stack Error: You do not have permission to publish 'hubot-weather'. Are you logged in as the correct user? : hubot-weather +35 verbose stack at makeError (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:264:12) +35 verbose stack at CachingRegistryClient. (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:252:14) +35 verbose stack at Request._callback (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:172:14) +35 verbose stack at Request.self.callback (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/request/request.js:198:22) +35 verbose stack at emitTwo (events.js:87:13) +35 verbose stack at Request.emit (events.js:172:7) +35 verbose stack at Request. (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/request/request.js:1082:10) +35 verbose stack at emitOne (events.js:82:20) +35 verbose stack at Request.emit (events.js:169:7) +35 verbose stack at IncomingMessage. (/Users/kkpoon/.nvm/versions/node/v4.2.6/lib/node_modules/npm/node_modules/request/request.js:1009:12) +36 verbose statusCode 403 +37 verbose pkgid hubot-weather +38 verbose cwd /Users/kkpoon/Development/clustertech/hubot/hubot-weather +39 error Darwin 15.3.0 +40 error argv "/Users/kkpoon/.nvm/versions/node/v4.2.6/bin/node" "/Users/kkpoon/.nvm/versions/node/v4.2.6/bin/npm" "publish" +41 error node v4.2.6 +42 error npm v2.14.12 +43 error code E403 +44 error You do not have permission to publish 'hubot-weather'. Are you logged in as the correct user? : hubot-weather +45 error If you need help, you may report this error at: +45 error +46 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..e6e95fd --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "hubot-weather-underground", + "description": "a hubot weather reporter", + "version": "0.1.0", + "author": "K.K. POON ", + "license": "MIT", + + "keywords": ["hubot","hubot-scripts","weather","wunderground"], + + "repository": { + "type": "git", + "url": "git://github.com/kkpoon/hubot-weather-underground.git" + }, + + "bugs": { + "url": "https://github.com/kkpoon/hubot-weather-underground/issues" + }, + + "dependencies": { + "coffee-script": "~1.6" + }, + + "devDependencies": { + "mocha": "*", + "chai": "*", + "sinon-chai": "*", + "sinon": "*", + "grunt-mocha-test": "~0.7.0", + "grunt-release": "~0.6.0", + "matchdep": "~0.1.2", + "grunt-contrib-watch": "~0.5.3" + }, + + "main": "index.coffee", + + "scripts": { + "test": "grunt test" + } +} diff --git a/script/bootstrap b/script/bootstrap new file mode 100755 index 0000000..4c5c66e --- /dev/null +++ b/script/bootstrap @@ -0,0 +1,18 @@ +#!/bin/bash + +# Make sure everything is development forever +export NODE_ENV=development + +# Load environment specific environment variables +if [ -f .env ]; then + source .env +fi + +if [ -f .env.${NODE_ENV} ]; then + source .env.${NODE_ENV} +fi + +npm install + +# Make sure coffee and mocha are on the path +export PATH="node_modules/.bin:$PATH" \ No newline at end of file diff --git a/script/test b/script/test new file mode 100755 index 0000000..e142362 --- /dev/null +++ b/script/test @@ -0,0 +1,6 @@ +#!/bin/bash + +# bootstrap environment +source script/bootstrap + +mocha --compilers coffee:coffee-script \ No newline at end of file diff --git a/src/weather.coffee b/src/weather.coffee new file mode 100644 index 0000000..dc11c5f --- /dev/null +++ b/src/weather.coffee @@ -0,0 +1,65 @@ +# Description +# a hubot weather reporter +# +# Configuration: +# HUBOT_WEATHER_WUNDERGROUND_KEY +# +# Commands: +# hubot weather of PLACE +# hubot what is PLACE exactly called? +# +# Author: +# K.K. POON + +WUNDERGROUND_KEY = process.env.HUBOT_WEATHER_WUNDERGROUND_KEY + +WUNDERGROUND_URL = "http://api.wunderground.com/api/#{WUNDERGROUND_KEY}" + +module.exports = (robot) -> + robot.respond /weather of (.*)/i, (msg) -> + place = msg.match[1] + + msg.http("#{WUNDERGROUND_URL}/conditions/q/#{place}.json") + .get() (err, res, body) -> + if err + msg.send err + robot.emit 'error', err + return + + try + data = JSON.parse(body) + obs = data.current_observation + msg.send "The current weather condition of " + + "#{obs.display_location.city} is #{obs.weather}:\n" + + "At #{obs.observation_time_rfc822}, " + + "Temperature is #{obs.temp_c}°C " + + "(feels like #{obs.feelslike_c}°C), " + + "Humidity #{obs.relative_humidity}, " + + "Pressure #{obs.pressure_mb}hPa, " + + "Wind #{obs.wind_string}, " + + "UV #{obs.UV}" + + catch err + msg.send err + robot.emit 'error', err + + + robot.respond /what is (.*) (exactly|exact) (called|named|call|name)[\?]?/i, (msg) -> + place = msg.match[1] + + msg.http("http://autocomplete.wunderground.com/aq?query=#{place}") + .get() (err, res, body) -> + if err + msg.send err + robot.emit 'error', err + return + + try + data = JSON.parse(body) + results = data.RESULTS + msg.send "Here are the possibilities:\n" + + ("- " + r.name for r in results).join "\n" + + catch err + msg.send err + robot.emit 'error', err diff --git a/test/weather-test.coffee b/test/weather-test.coffee new file mode 100644 index 0000000..c3186ef --- /dev/null +++ b/test/weather-test.coffee @@ -0,0 +1,19 @@ +chai = require 'chai' +sinon = require 'sinon' +chai.use require 'sinon-chai' + +expect = chai.expect + +describe 'weather', -> + beforeEach -> + @robot = + respond: sinon.spy() + hear: sinon.spy() + + require('../src/weather')(@robot) + + it 'registers a respond listener', -> + expect(@robot.respond).to.have.been.calledWith(/hello/) + + it 'registers a hear listener', -> + expect(@robot.hear).to.have.been.calledWith(/orly/)