├── .gitignore ├── .travis.yml ├── package.json ├── LICENSE ├── .eslintrc ├── test.js ├── README.markdown └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: '0.10' 4 | before_script: 5 | - npm install -g jshint 6 | script: 7 | - make ci 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apod", 3 | "version": "0.3.0", 4 | "description": "Wrapper around NASA's APOD API", 5 | "author": "Andrew Stewart (http://andrew.stwrt.ca)", 6 | 7 | "contributors": [ 8 | "Dan Flettre (https://twitter.com/flettre)" 9 | ], 10 | 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/stewart/apod.js" 14 | }, 15 | 16 | "license": "MIT", 17 | 18 | "dependencies": { 19 | "superagent": "^1.2.0", 20 | "superagent-proxy": "^1.0.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Andrew Stewart 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | 4 | rules: 5 | camelcase: [2, {properties: "never"}] 6 | comma-dangle: "always-multiline" 7 | comma-spacing: [2, {before: false, after: true}] 8 | comma-style: [2, "last"] 9 | handle-callback-err: [2, "^.*(e|E)rr" ] 10 | indent: [2, 2] 11 | key-spacing: [2, { beforeColon: false, afterColon: true }] 12 | max-depth: [1, 3] 13 | max-len: [1, 80, 4] 14 | max-nested-callbacks: [1, 3] 15 | no-cond-assign: 2 16 | no-constant-condition: 2 17 | no-dupe-args: 2 18 | no-dupe-keys: 2 19 | no-else-return: 2 20 | no-empty: 2 21 | no-lonely-if: 2 22 | no-multiple-empty-lines: 2 23 | no-nested-ternary: 2 24 | no-reserved-keys: 2 25 | no-self-compare: 2 26 | no-sync: 1 27 | no-throw-literal: 2 28 | no-underscore-dangle: 0 29 | quote-props: [2, "as-needed"] 30 | quotes: [2, "double", "avoid-escape"] 31 | radix: 2 32 | semi-spacing: [2, {before: false, after: true}] 33 | semi: [2, "always"] 34 | space-after-keywords: [2, "always"] 35 | space-before-blocks: [2, "always"] 36 | space-before-function-paren: [1, "never"] 37 | space-in-parens: [2, "never"] 38 | spaced-line-comment: [1, "always"] 39 | strict: [2, "global"] 40 | valid-jsdoc: 2 41 | yoda: [2, "never"] 42 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var apod = require("./index.js"); 4 | 5 | if (!process.env.API_KEY) { 6 | throw new Error("No API_KEY env var set"); 7 | } 8 | 9 | apod.apiKey = process.env.API_KEY; 10 | 11 | function works(thing) { 12 | return thing ? "works" : "doesn't work"; 13 | } 14 | 15 | apod(function(err, data) { 16 | if (err) { 17 | console.error(err); 18 | throw new Error("Error occured while testing apod()"); 19 | } 20 | 21 | console.log("apod() ->", works(data.url)); 22 | }); 23 | 24 | apod(new Date(1999, 11, 31), function(err, data) { 25 | if (err) { 26 | console.error(err); 27 | throw new Error("Error occured while testing apod(Date)"); 28 | } 29 | 30 | console.log("apod(Date) ->", works(data.url)); 31 | }); 32 | 33 | apod(1999, 11, 31, function(err, data) { 34 | if (err) { 35 | console.error(err); 36 | throw new Error("Error occured while testing apod(YYYY, MM, DD)"); 37 | } 38 | 39 | console.log("apod(YYYY, MM, DD) ->", works(data.url)); 40 | }); 41 | 42 | apod("December 31, 1999", function(err, data) { 43 | if (err) { 44 | console.error(err); 45 | throw new Error("Error occured while testing apod(String)"); 46 | } 47 | 48 | console.log("apod(String) ->", works(data.url)); 49 | }); 50 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # apod.js 2 | 3 | A small JS wrapper around [NASA's APOD API][api]. 4 | 5 | [api]: https://data.nasa.gov/developer/external/planetary/#apod 6 | 7 | To use this, you'll need an api.data.gov API key - you can request one here: https://data.nasa.gov/developer/external/planetary/#apply-for-an-api-key 8 | 9 | ## Installation 10 | 11 | $ npm install apod 12 | 13 | ## Usage 14 | 15 | ```javascript 16 | var apod = require("apod"); 17 | 18 | apod.apiKey = "YOUR_API_KEY"; 19 | 20 | function callback(err, data) { 21 | // do cool stuff with APOD data here 22 | } 23 | 24 | // get today's APOD 25 | apod(callback); 26 | 27 | // APOD for December 31, 1999 (JS has 0-indexed months) 28 | apod(new Date(1999, 11, 31), callback); 29 | 30 | // the same 31 | apod(1999, 11, 31, callback); 32 | 33 | // once more, with feeling 34 | apod("December 31, 1999" callback); 35 | 36 | // get a random APOD 37 | apod.random(callback); 38 | ``` 39 | 40 | Assuming success, all methods trigger the callback with an object like the following, direct from NASA's API: 41 | 42 | ```json 43 | { 44 | "concept_tags": true, 45 | "title": "The Millennium that Defined Earth", 46 | "url": "http://apod.nasa.gov/apod/image/9912/earthrise_apollo8.jpg", 47 | "explanation": "When the second millennium began, people generally knew that [...]", 48 | "concepts": {"0": "Galaxy", "1": "Milky Way", "2": "Earth", "3": "Solar System", "4": "Universe", "5": "Sun", "6": "Planet", "7": "Gravitation"}, 49 | "date": "1999-12-31" 50 | } 51 | ``` 52 | 53 | ## HTTPS Proxy 54 | 55 | Sending via an HTTP/HTTPS proxy is supported. 56 | Just set the environment variable `https_proxy` and it will be used when making requests to the API. 57 | Alternatively, set the `apod.proxy` string. 58 | 59 | Here's examples of both usage patterns: 60 | 61 | $ https_proxy="https://my.secure.proxy" node script.js 62 | 63 | ```javascript 64 | // script.js 65 | apod.proxy = "https://my.secure.proxy" 66 | ``` 67 | 68 | ## Version History 69 | 70 | Version | Notes 71 | ------- | ----- 72 | 0.2.0 | Update endpoint URL, remove concept_tags 73 | 0.2.0 | Add support for HTTPS proxy, refactors. 74 | 0.1.0 | Interface change, use new NASA APOD API 75 | 0.0.1 | Initial release 76 | 77 | ## License 78 | 79 | MIT. For more details, see the `LICENSE` file. 80 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var superagent = require("superagent"); 4 | 5 | var endpoint = "https://api.nasa.gov/planetary/apod", 6 | proxyConfigured = false; 7 | 8 | function quit(reason) { 9 | throw new Error(reason); 10 | } 11 | 12 | function getDate(arr) { 13 | if (!arr.length) { return new Date(); } 14 | switch (typeof arr[0]) { 15 | case "string": 16 | return new Date(arr[0]); 17 | 18 | case "number": 19 | // this sucks, the alternatives are worse 20 | return new Date(arr.join("-")); 21 | 22 | default: 23 | if (arr[0] instanceof Date) { 24 | return arr[0]; 25 | } 26 | 27 | quit("Unknown arguments provided to apod()"); 28 | } 29 | } 30 | 31 | // anytime between start of APOD and now 32 | function randomDate() { 33 | var start = new Date(1995, 5, 16), 34 | end = new Date(), 35 | current = start, 36 | dates = []; 37 | 38 | while (current < end) { 39 | dates.push([ 40 | current.getFullYear(), 41 | current.getMonth() + 1, 42 | current.getDate() 43 | ].join("-")); 44 | 45 | current.setDate(current.getDate() + 1); 46 | } 47 | 48 | return dates[Math.floor(Math.random() * dates.length)]; 49 | } 50 | 51 | var apod = module.exports = function apod() { 52 | var args = [].slice.call(arguments); 53 | 54 | var callback = args.pop(), 55 | date = getDate(args); 56 | 57 | if (!callback || typeof callback !== "function") { 58 | quit("No callback provided to apod()"); 59 | } 60 | 61 | if (!apod.apiKey) { 62 | quit("No API key set"); 63 | } 64 | 65 | date = [ 66 | date.getFullYear(), 67 | date.getMonth() + 1, // javascript 68 | date.getDate() 69 | ].join("-"); 70 | 71 | var proxy = process.env.https_proxy || apod.proxy; 72 | 73 | if (proxy && !proxyConfigured) { 74 | proxyConfigured = true; 75 | require("superagent-proxy")(superagent); 76 | } 77 | 78 | var params = { api_key: apod.apiKey, date: date }, 79 | req = superagent.get(endpoint).query(params); 80 | 81 | if (proxy) { 82 | req = req.proxy(proxy); 83 | } 84 | 85 | req.query() 86 | .end(function(err, res) { 87 | var body = res.body; 88 | 89 | if (err || !res.ok) { 90 | callback(body, null); 91 | return; 92 | } 93 | 94 | callback(null, body); 95 | }); 96 | }; 97 | 98 | apod.apiKey = null; 99 | apod.proxy = ""; 100 | 101 | apod.random = function(callback) { 102 | if (!callback || typeof callback !== "function") { 103 | quit("No callback provided to apod#random()"); 104 | } 105 | 106 | function handler(err, data) { 107 | if (err) { 108 | apod(randomDate(), handler); 109 | return; 110 | } 111 | 112 | callback(err, data); 113 | } 114 | 115 | apod(randomDate(), handler); 116 | }; 117 | --------------------------------------------------------------------------------