├── .gitignore ├── .travis.yml ├── test ├── blank_appkey.js ├── invalid_response.js ├── bogus_appkey.js └── valid_response.js ├── package.json ├── LICENSE ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | env: CXX=g++-4.8 4 | addons: 5 | apt: 6 | sources: 7 | - ubuntu-toolchain-r-test 8 | packages: 9 | - g++-4.8 10 | node_js: 11 | - "6" 12 | - "4" 13 | - "0.12" 14 | - "0.10" 15 | -------------------------------------------------------------------------------- /test/blank_appkey.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test, 2 | wolfram = require('../') 3 | 4 | test('blank application key', function(t) { 5 | var client = wolfram.createClient() 6 | 7 | client.query("integrate 2x", function(err, result) { 8 | t.type(err, "string", "error should be a string describing the message") 9 | t.equals(result, null, "result should be null") 10 | t.end() 11 | }) 12 | }) -------------------------------------------------------------------------------- /test/invalid_response.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test, 2 | wolfram = require('../') 3 | 4 | test('invalid response', function(t) { 5 | var client = wolfram.createClient(process.env.WOLFRAM_APPID) 6 | 7 | client.query("adh89u8n0eudhdah", function(err, result) { 8 | t.notOk(err, "err should be null") 9 | t.type(result, "object") 10 | t.equal(result.length, 0) 11 | t.end() 12 | }) 13 | }) -------------------------------------------------------------------------------- /test/bogus_appkey.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test, 2 | wolfram = require('../') 3 | 4 | test('bogus application id', function(t) { 5 | var client = wolfram.createClient("bogus-trololoo") 6 | 7 | client.query("integrate 2x", function(err, result) { 8 | t.type(err, "string", "error should be a string describing the message") 9 | t.notOk(result, "result should be null") 10 | t.end() 11 | }) 12 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Sami Kukkonen ", 3 | "name": "wolfram", 4 | "description": "Wolfram Alpha API", 5 | "keywords": "wolfram alpha api wolframalpha", 6 | "version": "0.3.4", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/strax/wolfram.git" 10 | }, 11 | "scripts": { 12 | "test": "tap test/*.js" 13 | }, 14 | "main": "index.js", 15 | "engines": { 16 | "node": ">=0.8.0" 17 | }, 18 | "dependencies": { 19 | "request": "^2.0", 20 | "libxmljs": "^0.18.0" 21 | }, 22 | "devDependencies": { 23 | "tap": "~> 0.4.0" 24 | }, 25 | "license": "MIT" 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2017 Sami Kukkonen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all 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 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /test/valid_response.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test, 2 | wolfram = require('../') 3 | 4 | test('valid response', function(t) { 5 | var client = wolfram.createClient(process.env.WOLFRAM_APPID) 6 | 7 | t.test("integrate 2x", function(t) { 8 | client.query("integrate 2x", function(err, result) { 9 | t.notOk(err, "err should be null") 10 | t.type(result, "object") 11 | t.ok(result.length) 12 | t.equal(result.length, 2, "result length should be 2") 13 | t.equal(result[0].primary, true, "first pod should be primary") 14 | t.equal(result[0].subpods[0].value, ' integral 2 x dx = x^2 + constant', 'result should be constant') 15 | t.ok(result[0].subpods[0].image, "result should have an image representation") 16 | t.ok(result[0].title, "result should have a title of Indefinite integral") 17 | t.end() 18 | }) 19 | }) 20 | 21 | t.test("1+1", function(t) { 22 | client.query("1+1", function(err, result) { 23 | t.notOk(err, "err should be null") 24 | t.type(result, "object") 25 | t.ok(result.length) 26 | t.equal(result.length, 6) 27 | t.equal(result[1].primary, true) 28 | t.equal(result[1].subpods[0].value, '2') 29 | t.end() 30 | }) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wolfram [![Build Status](https://travis-ci.org/strax/node-wolfram.svg?branch=master)](https://travis-ci.org/strax/node-wolfram) 2 | ================================================= 3 | 4 | Wolfram is a simple Wolfram|Alpha API wrapper for Node.js with support for both plaintext and image results. 5 | 6 | How to use 7 | ---------- 8 | 9 | Register for a Wolfram|Alpha application ID. The Wolfram|Alpha® API is available for free for non-commercial experimental use with a low monthly cap on queries. For more information, visit [http://products.wolframalpha.com/developers/](http://products.wolframalpha.com/developers/). Wolfram is a registered trademark of the Wolfram Group of Companies. 10 | 11 | Install the module with npm: 12 | `$ npm install wolfram` 13 | 14 | Example usage: 15 | 16 | ```javascript 17 | var wolfram = require('wolfram').createClient("[CENSORED]") 18 | 19 | wolfram.query("integrate 2x", function(err, result) { 20 | if(err) throw err 21 | console.log("Result: %j", result) 22 | }) 23 | ``` 24 | 25 | Running tests 26 | ------------- 27 | 28 | Navigate to the project folder and run `npm install` to install the project's dependencies. 29 | 30 | Run the following command, substituting `your-app-id` with your Wolfram|Alpha application ID. 31 | 32 | `$ WOLFRAM_APPID=your-app-id npm test` 33 | 34 | License 35 | ------- 36 | 37 | [MIT](https://github.com/strax/node-wolfram/blob/master/LICENSE) 38 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var xml = require('libxmljs'), 2 | request = require('request') 3 | 4 | var Client = exports.Client = function Client(appKey) { 5 | this.appKey = appKey 6 | } 7 | 8 | Client.prototype.query = function(input, cb) { 9 | if(!this.appKey) { 10 | return cb("Application key not set", null) 11 | } 12 | 13 | var uri = 'http://api.wolframalpha.com/v2/query?input=' + encodeURIComponent(input) + '&primary=true&appid=' + this.appKey 14 | 15 | request(uri, function(error, response, body) { 16 | if(!error && response.statusCode == 200) { 17 | var doc = xml.parseXml(body), root = doc.root() 18 | 19 | if(root.attr('error').value() != 'false') { 20 | var message = root.get('//error/msg').text() 21 | return cb(message, null) 22 | } else { 23 | var pods = root.find('pod').map(function(pod) { 24 | var title = pod.attr('title').value(); 25 | var subpods = pod.find('subpod').map(function(node) { 26 | return { 27 | title: node.attr('title').value(), 28 | value: node.get('plaintext').text(), 29 | image: node.get('img').attr('src').value() 30 | } 31 | }) 32 | var primary = (pod.attr('primary') && pod.attr('primary').value()) == 'true' 33 | return { title : title, subpods: subpods, primary: primary } 34 | }) 35 | return cb(null, pods) 36 | } 37 | } else { 38 | return cb(error, null) 39 | } 40 | }) 41 | } 42 | 43 | exports.createClient = function(appKey) { 44 | return new Client(appKey) 45 | } 46 | --------------------------------------------------------------------------------