├── .gitignore ├── LICENSE ├── README.md ├── alchemyapi.js ├── app.js ├── emaxfpo.jpg ├── package.json ├── tests.js └── views ├── example.dust └── layout.dust /.gitignore: -------------------------------------------------------------------------------- 1 | api_key.txt 2 | node_modules 3 | .*.swp 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # alchemyapi_node # 2 | 3 | A software development kit (sdk) for AlchemyAPI using Node.js - **_Please note that this legacy AlchemyAPI SDK is no longer supported by IBM. Please use the Watson SDKs https://github.com/watson-developer-cloud?utf8=✓&query=sdk_** 4 | 5 | 6 | ## AlchemyAPI ## 7 | 8 | AlchemyAPI offers artificial intelligence as a service. We teach computers to learn how to read and see, and apply our technology to text analysis and image recognition through a cloud-based API. Our customers use AlchemyAPI to transform their unstructured content such as blog posts, news articles, social media posts and images into much more useful structured data. 9 | 10 | AlchemyAPI is a tech startup located in downtown Denver, Colorado. As the world’s most popular text analysis service, AlchemyAPI serves over 3.5 billion monthly API requests to over 35,000 developers. To enable our services, we use artificial intelligence, machine learning, neural networks, natural language processing and massive-scale web crawling. Our technology powers use cases in a variety of industry verticals, including social media monitoring, business intelligence, content recommendations, financial trading and targeted advertising. 11 | 12 | More information at: http://www.alchemyapi.com 13 | 14 | 15 | 16 | ## API Key ## 17 | 18 | To use AlchemyAPI, you'll need to obtain an API key and attach that key to all requests. If you do not already have a key, please visit: http://www.alchemyapi.com/api/register.html 19 | 20 | 21 | 22 | ## Getting Started with the Node.js SDK ## 23 | 24 | To get started and run the example, simply: 25 | 26 | git clone https://github.com/AlchemyAPI/alchemyapi_node.git 27 | cd alchemyapi_node 28 | npm install 29 | node alchemyapi.js YOUR_KEY_HERE 30 | node app.js 31 | 32 | 33 | Just replace YOUR_KEY_HERE with your key, and you should be good to go. 34 | 35 | The example will be available at: http://localhost:3000 36 | 37 | 38 | ## A Note about Client Side Javascript ## 39 | 40 | This is intended to be used on the server side using Node. While it's possible to utilize AlchemyAPI completely in the browser, it is not recommended. First, this would expose your API key to the world, and this key is a secret. Second, most browsers will block calls to a different domain for security reasons. It's possible to get around this with jsonp, but it's recommended that you proxy any requests to AlchemyAPI through your own server. 41 | 42 | -------------------------------------------------------------------------------- /alchemyapi.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2014 AlchemyAPI 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | 18 | var http = require('http'); 19 | var fs = require('fs'); 20 | 21 | 22 | //Make the class available 23 | exports = module.exports = AlchemyAPI; 24 | 25 | 26 | 27 | /** 28 | * Checks if file is called directly, and then writes the API key to api_key.txt if it's included in the args 29 | * 30 | * Note: if you don't have an API key, register for one at: http://www.alchemyapi.com/api/register.html 31 | * 32 | * INPUT: 33 | * Your API Key (sent as a command line argument) 34 | * 35 | * OUTPUT: 36 | * none 37 | */ 38 | if (require.main === module) { 39 | //file was called directly from command line to set the key 40 | if (process.argv[2]) { 41 | console.log('Args: ' + process.argv[2]); 42 | fs.writeFile(__dirname + '/api_key.txt',process.argv[2], function(err) { 43 | if (err) { 44 | console.log('Error, unable to write key file: ' + err); 45 | process.exit(1); 46 | } else { 47 | console.log('AlchemyAPI key: ' + process.argv[2] + ' successfully written to api_key.txt'); 48 | console.log('You are now ready to start using AlchemyAPI. For an example, run: node app.js'); 49 | process.exit(0); 50 | } 51 | }); 52 | } else { 53 | console.log('Are you trying to set the key? Make sure to use: node alchemyapi.js YOUR_KEY_HERE'); 54 | process.exit(1); 55 | } 56 | } 57 | 58 | 59 | 60 | function AlchemyAPI() { 61 | 62 | //Load the key from api_key.txt 63 | try { 64 | key = fs.readFileSync(__dirname + '/api_key.txt').toString().trim(); 65 | } 66 | catch(err) { 67 | //Create the file 68 | fs.openSync(__dirname + '/api_key.txt', 'w'); 69 | console.log('API key not detected in api_key.txt, please run: node alchemyapi.js YOUR_KEY_HERE'); 70 | console.log('If you do not have a key, register for one at: http://www.alchemyapi.com/api/register.html'); 71 | process.exit(1); 72 | } 73 | 74 | //Make sure the key formating looks good 75 | if (key.length != 40) { 76 | console.log('The API key in api_key.txt does not appear to be valid. Make sure to run: node alchemyapi.js YOUR_KEY_HERE'); 77 | console.log('If you do not have a key, register for one at: http://www.alchemyapi.com/api/register.html'); 78 | process.exit(1); 79 | } 80 | 81 | //Set the key 82 | this.apikey = key; 83 | 84 | 85 | /** 86 | * HTTP Request wrapper that is called by the endpoint functions. This function is not intended to be called through an external interface. 87 | * It makes the call, then converts the returned JSON string into a Javascript object. 88 | * 89 | * INPUT: 90 | * url -> the full URI encoded url 91 | * params -> the call parameters, both required and optional 92 | * sfile -> a file to stream if this is a file upload (optional) 93 | * callback -> the callback function 94 | * 95 | * OUTPUT: 96 | * The response, already converted from JSON to a Javascript object. 97 | */ 98 | /* 99 | this.analyze = function (endpoint, params, sfile, callback) { 100 | // This is an upload if there is a file for streaming 101 | if (typeof sfile === "string") { 102 | return this.analyze_upload(endpoint, params, sfile, callback); 103 | } else { 104 | callback = sfile; 105 | } 106 | 107 | //Insert the base url 108 | var url = AlchemyAPI.BASE_URL + endpoint; 109 | 110 | //Add the API key and set the output mode to JSON 111 | params['apikey'] = this.apikey; 112 | params['outputMode'] = 'json'; 113 | if ("image" in params) { 114 | params['imagePostMode'] = 'not-raw'; 115 | } 116 | 117 | //Fire off the request 118 | request.post(url, {form:params}, function(error, response, body) { 119 | if (error) throw new Error(error); 120 | if (response.statusCode == 200) { 121 | callback(JSON.parse(body)); 122 | } else { 123 | callback({ status:'ERROR', statusInfo:'invalid server response' }); 124 | } 125 | }); 126 | } 127 | */ 128 | 129 | /** 130 | * HTTP Uploader 131 | * It makes the call, then converts the returned JSON string into a Javascript object. 132 | * 133 | * INPUT: 134 | * url -> the full URI encoded url 135 | * params -> the call parameters, both required and optional 136 | * sfile -> a file to stream if this is a file upload (optional) 137 | * callback -> the callback function 138 | * 139 | * OUTPUT: 140 | * The response, already converted from JSON to a Javascript object. 141 | */ 142 | this.analyze = function (endpoint, params, sfile, callback) { 143 | var urlKVPairs = []; 144 | var reqParams = ""; 145 | var reqBody = ""; 146 | var upload = false; 147 | 148 | //Add the API key and set the output mode to JSON 149 | params['apikey'] = this.apikey; 150 | params['outputMode'] = 'json'; 151 | 152 | // This is an upload if there is a file for streaming 153 | if (typeof sfile === "string") { 154 | params['imagePostMode'] = 'raw'; 155 | upload = true; 156 | } else { // not an upload, sfile param must be the callback 157 | callback = sfile; 158 | } 159 | 160 | //Build the API options into the URL (for upload) or body 161 | Object.keys(params).forEach(function(key) { 162 | urlKVPairs.push(key + '=' + encodeURIComponent(params[key])); 163 | }); 164 | if (upload) { 165 | reqParams = "?" + urlKVPairs.join('&'); 166 | } else { 167 | reqBody = urlKVPairs.join('&'); 168 | } 169 | 170 | //Build the HTTP request options 171 | var opts = { 172 | method: "POST", 173 | hostname: AlchemyAPI.HOST, 174 | path: AlchemyAPI.BASE_URL + endpoint + reqParams, 175 | }; 176 | if (upload) { 177 | opts['headers'] = {'Content-Length': fs.statSync(sfile).size}; 178 | } else { 179 | opts['headers'] = {'Content-Length': reqBody.length}; 180 | } 181 | 182 | var postReq = http.request(opts, function (res) { 183 | var response = ""; 184 | res.setEncoding('utf8'); 185 | res.on('data', function (chunk) { response += chunk; }); 186 | res.on('end', function () { callback(JSON.parse(response)); }); 187 | res.on('error', function (err) { 188 | callback({ status:'ERROR', statusInfo: err }); 189 | }); 190 | }); 191 | 192 | // Execute the call to the API 193 | if (upload) { 194 | fs.createReadStream(sfile).pipe(postReq); 195 | } else { 196 | postReq.write(reqBody); 197 | postReq.end(); 198 | } 199 | }; 200 | 201 | }; // end AlchemyAPI 202 | 203 | 204 | //Add the static variables 205 | AlchemyAPI.HOST = 'access.alchemyapi.com'; 206 | AlchemyAPI.BASE_URL = '/calls'; 207 | 208 | //Setup the endpoints 209 | AlchemyAPI.ENDPOINTS = {}; 210 | AlchemyAPI.ENDPOINTS['sentiment'] = {}; 211 | AlchemyAPI.ENDPOINTS['sentiment']['url'] = '/url/URLGetTextSentiment'; 212 | AlchemyAPI.ENDPOINTS['sentiment']['text'] = '/text/TextGetTextSentiment'; 213 | AlchemyAPI.ENDPOINTS['sentiment']['html'] = '/html/HTMLGetTextSentiment'; 214 | AlchemyAPI.ENDPOINTS['sentiment_targeted'] = {}; 215 | AlchemyAPI.ENDPOINTS['sentiment_targeted']['url'] = '/url/URLGetTargetedSentiment'; 216 | AlchemyAPI.ENDPOINTS['sentiment_targeted']['text'] = '/text/TextGetTargetedSentiment'; 217 | AlchemyAPI.ENDPOINTS['sentiment_targeted']['html'] = '/html/HTMLGetTargetedSentiment'; 218 | AlchemyAPI.ENDPOINTS['author'] = {}; 219 | AlchemyAPI.ENDPOINTS['author']['url'] = '/url/URLGetAuthor'; 220 | AlchemyAPI.ENDPOINTS['author']['html'] = '/html/HTMLGetAuthor'; 221 | AlchemyAPI.ENDPOINTS['keywords'] = {}; 222 | AlchemyAPI.ENDPOINTS['keywords']['url'] = '/url/URLGetRankedKeywords'; 223 | AlchemyAPI.ENDPOINTS['keywords']['text'] = '/text/TextGetRankedKeywords'; 224 | AlchemyAPI.ENDPOINTS['keywords']['html'] = '/html/HTMLGetRankedKeywords'; 225 | AlchemyAPI.ENDPOINTS['concepts'] = {}; 226 | AlchemyAPI.ENDPOINTS['concepts']['url'] = '/url/URLGetRankedConcepts'; 227 | AlchemyAPI.ENDPOINTS['concepts']['text'] = '/text/TextGetRankedConcepts'; 228 | AlchemyAPI.ENDPOINTS['concepts']['html'] = '/html/HTMLGetRankedConcepts'; 229 | AlchemyAPI.ENDPOINTS['entities'] = {}; 230 | AlchemyAPI.ENDPOINTS['entities']['url'] = '/url/URLGetRankedNamedEntities'; 231 | AlchemyAPI.ENDPOINTS['entities']['text'] = '/text/TextGetRankedNamedEntities'; 232 | AlchemyAPI.ENDPOINTS['entities']['html'] = '/html/HTMLGetRankedNamedEntities'; 233 | AlchemyAPI.ENDPOINTS['category'] = {}; 234 | AlchemyAPI.ENDPOINTS['category']['url'] = '/url/URLGetCategory'; 235 | AlchemyAPI.ENDPOINTS['category']['text'] = '/text/TextGetCategory'; 236 | AlchemyAPI.ENDPOINTS['category']['html'] = '/html/HTMLGetCategory'; 237 | AlchemyAPI.ENDPOINTS['relations'] = {}; 238 | AlchemyAPI.ENDPOINTS['relations']['url'] = '/url/URLGetRelations'; 239 | AlchemyAPI.ENDPOINTS['relations']['text'] = '/text/TextGetRelations'; 240 | AlchemyAPI.ENDPOINTS['relations']['html'] = '/html/HTMLGetRelations'; 241 | AlchemyAPI.ENDPOINTS['language'] = {}; 242 | AlchemyAPI.ENDPOINTS['language']['url'] = '/url/URLGetLanguage'; 243 | AlchemyAPI.ENDPOINTS['language']['text'] = '/text/TextGetLanguage'; 244 | AlchemyAPI.ENDPOINTS['language']['html'] = '/html/HTMLGetLanguage'; 245 | AlchemyAPI.ENDPOINTS['text'] = {}; 246 | AlchemyAPI.ENDPOINTS['text']['url'] = '/url/URLGetText'; 247 | AlchemyAPI.ENDPOINTS['text']['html'] = '/html/HTMLGetText'; 248 | AlchemyAPI.ENDPOINTS['text_raw'] = {}; 249 | AlchemyAPI.ENDPOINTS['text_raw']['url'] = '/url/URLGetRawText'; 250 | AlchemyAPI.ENDPOINTS['text_raw']['html'] = '/html/HTMLGetRawText'; 251 | AlchemyAPI.ENDPOINTS['title'] = {}; 252 | AlchemyAPI.ENDPOINTS['title']['url'] = '/url/URLGetTitle'; 253 | AlchemyAPI.ENDPOINTS['title']['html'] = '/html/HTMLGetTitle'; 254 | AlchemyAPI.ENDPOINTS['feeds'] = {}; 255 | AlchemyAPI.ENDPOINTS['feeds']['url'] = '/url/URLGetFeedLinks'; 256 | AlchemyAPI.ENDPOINTS['feeds']['html'] = '/html/HTMLGetFeedLinks'; 257 | AlchemyAPI.ENDPOINTS['microformats'] = {}; 258 | AlchemyAPI.ENDPOINTS['microformats']['url'] = '/url/URLGetMicroformatData'; 259 | AlchemyAPI.ENDPOINTS['microformats']['html'] = '/html/HTMLGetMicroformatData'; 260 | AlchemyAPI.ENDPOINTS['taxonomy'] = {}; 261 | AlchemyAPI.ENDPOINTS['taxonomy']['url'] = '/url/URLGetRankedTaxonomy'; 262 | AlchemyAPI.ENDPOINTS['taxonomy']['text'] = '/text/TextGetRankedTaxonomy'; 263 | AlchemyAPI.ENDPOINTS['taxonomy']['html'] = '/html/HTMLGetRankedTaxonomy'; 264 | AlchemyAPI.ENDPOINTS['combined'] = {}; 265 | AlchemyAPI.ENDPOINTS['combined']['url'] = '/url/URLGetCombinedData'; 266 | AlchemyAPI.ENDPOINTS['image'] = {}; 267 | AlchemyAPI.ENDPOINTS['image']['url'] = '/url/URLGetImage'; 268 | AlchemyAPI.ENDPOINTS['image_keywords'] = {}; 269 | AlchemyAPI.ENDPOINTS['image_keywords']['url'] = '/url/URLGetRankedImageKeywords'; 270 | AlchemyAPI.ENDPOINTS['image_keywords']['image'] = '/image/ImageGetRankedImageKeywords'; 271 | 272 | 273 | 274 | /** 275 | * Extracts the entities for text, a URL or HTML. 276 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/entity-extraction/ 277 | * For the docs, please refer to: http://www.alchemyapi.com/api/entity-extraction/ 278 | * 279 | * INPUT: 280 | * flavor -> which version of the call, i.e. text, url or html. 281 | * data -> the data to analyze, either the text, the url or html code. 282 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 283 | * callback -> the callback function for this async function 284 | * 285 | * Available Options: 286 | * disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) 287 | * linkedData -> include linked data on disambiguated entities. 0: disabled, 1: enabled (default) 288 | * coreference -> resolve coreferences (i.e. the pronouns that correspond to named entities). 0: disabled, 1: enabled (default) 289 | * quotations -> extract quotations by entities. 0: disabled (default), 1: enabled. 290 | * sentiment -> analyze sentiment for each entity. 0: disabled (default), 1: enabled. Requires 1 additional API transction if enabled. 291 | * showSourceText -> 0: disabled (default), 1: enabled 292 | * maxRetrieve -> the maximum number of entities to retrieve (default: 50) 293 | * 294 | * OUTPUT: 295 | * The response, already converted from JSON to a Javascript object. 296 | */ 297 | AlchemyAPI.prototype.entities = function(flavor, data, options, callback) { 298 | options = options || {} 299 | 300 | if (!(flavor in AlchemyAPI.ENDPOINTS['entities'])) { 301 | callback({ status:'ERROR', statusInfo:'Entity extraction is not available for ' + flavor }); 302 | } else { 303 | //Add the data to the options and analyze 304 | options[flavor] = data; 305 | this.analyze(AlchemyAPI.ENDPOINTS['entities'][flavor], options, callback); 306 | } 307 | }; 308 | 309 | 310 | /** 311 | * Extracts the keywords from text, a URL or HTML. 312 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/keyword-extraction/ 313 | * For the docs, please refer to: http://www.alchemyapi.com/api/keyword-extraction/ 314 | * 315 | * INPUT: 316 | * flavor -> which version of the call, i.e. text, url or html. 317 | * data -> the data to analyze, either the text, the url or html code. 318 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 319 | * callback -> the callback function for this async function 320 | * 321 | * Available Options: 322 | * keywordExtractMode -> normal (default), strict 323 | * sentiment -> analyze sentiment for each keyword. 0: disabled (default), 1: enabled. Requires 1 additional API transaction if enabled. 324 | * showSourceText -> 0: disabled (default), 1: enabled. 325 | * maxRetrieve -> the max number of keywords returned (default: 50) 326 | * 327 | * OUTPUT: 328 | * The response, already converted from JSON to a Javascript object. 329 | */ 330 | AlchemyAPI.prototype.keywords = function(flavor, data, options, callback) { 331 | options = options || {} 332 | 333 | if (!(flavor in AlchemyAPI.ENDPOINTS['keywords'])) { 334 | callback({ status:'ERROR', statusInfo:'Keyword extraction is not available for ' + flavor }); 335 | } else { 336 | //Add the data to the options and analyze 337 | options[flavor] = data; 338 | this.analyze(AlchemyAPI.ENDPOINTS['keywords'][flavor], options, callback); 339 | } 340 | }; 341 | 342 | 343 | /** 344 | * Tags the concepts for text, a URL or HTML. 345 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/concept-tagging/ 346 | * For the docs, please refer to: http://www.alchemyapi.com/api/concept-tagging/ 347 | * 348 | * INPUT: 349 | * flavor -> which version of the call, i.e. text, url or html. 350 | * data -> the data to analyze, either the text, the url or html code. 351 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 352 | * callback -> the callback function for this async function 353 | * 354 | * Available Options: 355 | * maxRetrieve -> the maximum number of concepts to retrieve (default: 8) 356 | * linkedData -> include linked data, 0: disabled, 1: enabled (default) 357 | * showSourceText -> 0:disabled (default), 1: enabled 358 | * 359 | * OUTPUT: 360 | * The response, already converted from JSON to a Javascript object. 361 | */ 362 | AlchemyAPI.prototype.concepts = function(flavor, data, options, callback) { 363 | options = options || {} 364 | 365 | if (!(flavor in AlchemyAPI.ENDPOINTS['concepts'])) { 366 | callback({ status:'ERROR', statusInfo:'Concept tagging is not available for ' + flavor }); 367 | } else { 368 | //Add the data to the options and analyze 369 | options[flavor] = data; 370 | this.analyze(AlchemyAPI.ENDPOINTS['concepts'][flavor], options, callback); 371 | } 372 | }; 373 | 374 | 375 | /** 376 | * Calculates the sentiment for text, a URL or HTML. 377 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ 378 | * For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ 379 | * 380 | * INPUT: 381 | * flavor -> which version of the call, i.e. text, url or html. 382 | * data -> the data to analyze, either the text, the url or html code. 383 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 384 | * callback -> the callback function for this async function 385 | * 386 | * Available Options: 387 | * showSourceText -> 0: disabled (default), 1: enabled 388 | * 389 | * OUTPUT: 390 | * The response, already converted from JSON to a Javascript object. 391 | */ 392 | AlchemyAPI.prototype.sentiment = function(flavor, data, options, callback) { 393 | options = options || {} 394 | 395 | if (!(flavor in AlchemyAPI.ENDPOINTS['sentiment'])) { 396 | callback({ status:'ERROR', statusInfo:'Sentiment analysis is not available for ' + flavor }); 397 | } else { 398 | //Add the data to the options and analyze 399 | options[flavor] = data; 400 | this.analyze(AlchemyAPI.ENDPOINTS['sentiment'][flavor], options, callback); 401 | } 402 | }; 403 | 404 | 405 | /** 406 | * Calculates the targeted sentiment for text, a URL or HTML. 407 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ 408 | * For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ 409 | * 410 | * INPUT: 411 | * flavor -> which version of the call, i.e. text, url or html. 412 | * data -> the data to analyze, either the text, the url or html code. 413 | * target -> the word or phrase to run sentiment analysis on. 414 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 415 | * callback -> the callback function for this async function 416 | * 417 | * Available Options: 418 | * showSourceText -> 0: disabled, 1: enabled 419 | * 420 | * OUTPUT: 421 | * The response, already converted from JSON to a Javascript object. 422 | */ 423 | AlchemyAPI.prototype.sentiment_targeted = function(flavor, data, target, options, callback) { 424 | options = options || {} 425 | 426 | if (!(flavor in AlchemyAPI.ENDPOINTS['sentiment_targeted'])) { 427 | callback({ status:'ERROR', statusInfo:'Sentiment analysis is not available for ' + flavor }); 428 | } else if (!target) { 429 | callback({ status:'ERROR', statusInfo:'target must not be null' }); 430 | } else { 431 | //Add the data to the options and analyze 432 | options[flavor] = data; 433 | options['target'] = target; 434 | this.analyze(AlchemyAPI.ENDPOINTS['sentiment_targeted'][flavor], options, callback); 435 | } 436 | }; 437 | 438 | 439 | /** 440 | * Extracts the cleaned text (removes ads, navigation, etc.) for a URL or HTML. 441 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ 442 | * For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ 443 | * 444 | * INPUT: 445 | * flavor -> which version of the call, i.e. url or html. 446 | * data -> the data to analyze, either the url or html code. 447 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 448 | * callback -> the callback function for this async function 449 | * 450 | * Available Options: 451 | * useMetadata -> utilize meta description data, 0: disabled, 1: enabled (default) 452 | * extractLinks -> include links, 0: disabled (default), 1: enabled. 453 | * 454 | * OUTPUT: 455 | * The response, already converted from JSON to a Javascript object. 456 | */ 457 | AlchemyAPI.prototype.text = function(flavor, data, options, callback) { 458 | options = options || {} 459 | 460 | if (!(flavor in AlchemyAPI.ENDPOINTS['text'])) { 461 | callback({ status:'ERROR', statusInfo:'Text extraction is not available for ' + flavor }); 462 | } else { 463 | //Add the data to the options and analyze 464 | options[flavor] = data; 465 | this.analyze(AlchemyAPI.ENDPOINTS['text'][flavor], options, callback); 466 | } 467 | }; 468 | 469 | 470 | /** 471 | * Extracts the raw text (includes ads, navigation, etc.) for a URL or HTML. 472 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ 473 | * For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ 474 | * 475 | * INPUT: 476 | * flavor -> which version of the call, i.e. url or html. 477 | * data -> the data to analyze, either the url or html code. 478 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 479 | * callback -> the callback function for this async function 480 | * 481 | * Available Options: 482 | * none 483 | * 484 | * OUTPUT: 485 | * The response, already converted from JSON to a Javascript object. 486 | */ 487 | AlchemyAPI.prototype.text_raw = function(flavor, data, options, callback) { 488 | options = options || {} 489 | 490 | if (!(flavor in AlchemyAPI.ENDPOINTS['text_raw'])) { 491 | callback({ status:'ERROR', statusInfo:'Text extraction is not available for ' + flavor }); 492 | } else { 493 | //Add the data to the options and analyze 494 | options[flavor] = data; 495 | this.analyze(AlchemyAPI.ENDPOINTS['text_raw'][flavor], options, callback); 496 | } 497 | }; 498 | 499 | 500 | /** 501 | * Extracts the author from a URL or HTML. 502 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/author-extraction/ 503 | * For the docs, please refer to: http://www.alchemyapi.com/api/author-extraction/ 504 | * 505 | * INPUT: 506 | * flavor -> which version of the call, i.e. url or html. 507 | * data -> the data to analyze, either the the url or html code. 508 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 509 | * callback -> the callback function for this async function 510 | * 511 | * Availble Options: 512 | * none 513 | * 514 | * OUTPUT: 515 | * The response, already converted from JSON to a Javascript object. 516 | */ 517 | AlchemyAPI.prototype.author = function(flavor, data, options, callback) { 518 | options = options || {} 519 | 520 | if (!(flavor in AlchemyAPI.ENDPOINTS['author'])) { 521 | callback({ status:'ERROR', statusInfo:'Author extraction is not available for ' + flavor }); 522 | } else { 523 | //Add the data to the options and analyze 524 | options[flavor] = data; 525 | this.analyze(AlchemyAPI.ENDPOINTS['author'][flavor], options, callback); 526 | } 527 | }; 528 | 529 | 530 | /** 531 | * Detects the language for text, a URL or HTML. 532 | * For an overview, please refer to: http://www.alchemyapi.com/api/language-detection/ 533 | * For the docs, please refer to: http://www.alchemyapi.com/products/features/language-detection/ 534 | * 535 | * INPUT: 536 | * flavor -> which version of the call, i.e. text, url or html. 537 | * data -> the data to analyze, either the text, the url or html code. 538 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 539 | * callback -> the callback function for this async function 540 | * 541 | * Available Options: 542 | * none 543 | * 544 | * OUTPUT: 545 | * The response, already converted from JSON to a Javascript object. 546 | */ 547 | AlchemyAPI.prototype.language = function(flavor, data, options, callback) { 548 | options = options || {} 549 | 550 | if (!(flavor in AlchemyAPI.ENDPOINTS['language'])) { 551 | callback({ status:'ERROR', statusInfo:'Language detection is not available for ' + flavor }); 552 | } else { 553 | //Add the data to the options and analyze 554 | options[flavor] = data; 555 | this.analyze(AlchemyAPI.ENDPOINTS['language'][flavor], options, callback); 556 | } 557 | }; 558 | 559 | 560 | /** 561 | * Extracts the title for a URL or HTML. 562 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ 563 | * For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ 564 | * 565 | * INPUT: 566 | * flavor -> which version of the call, i.e. url or html. 567 | * data -> the data to analyze, either the url or html code. 568 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 569 | * callback -> the callback function for this async function 570 | * 571 | * Available Options: 572 | * useMetadata -> utilize title info embedded in meta data, 0: disabled, 1: enabled (default) 573 | * 574 | * OUTPUT: 575 | * The response, already converted from JSON to a Javascript object. 576 | */ 577 | AlchemyAPI.prototype.title = function(flavor, data, options, callback) { 578 | options = options || {} 579 | 580 | if (!(flavor in AlchemyAPI.ENDPOINTS['title'])) { 581 | callback({ status:'ERROR', statusInfo:'Title extraction is not available for ' + flavor }); 582 | } else { 583 | //Add the data to the options and analyze 584 | options[flavor] = data; 585 | this.analyze(AlchemyAPI.ENDPOINTS['title'][flavor], options, callback); 586 | } 587 | }; 588 | 589 | 590 | /** 591 | * Extracts the relations for text, a URL or HTML. 592 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/relation-extraction/ 593 | * For the docs, please refer to: http://www.alchemyapi.com/api/relation-extraction/ 594 | * 595 | * INPUT: 596 | * flavor -> which version of the call, i.e. text, url or html. 597 | * data -> the data to analyze, either the text, the url or html code. 598 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 599 | * callback -> the callback function for this async function 600 | * 601 | * Available Options: 602 | * sentiment -> 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. 603 | * keywords -> extract keywords from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. 604 | * entities -> extract entities from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. 605 | * requireEntities -> only extract relations that have entities. 0: disabled (default), 1: enabled. 606 | * sentimentExcludeEntities -> exclude full entity name in sentiment analysis. 0: disabled, 1: enabled (default) 607 | * disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) 608 | * linkedData -> include linked data with disambiguated entities. 0: disabled, 1: enabled (default). 609 | * coreference -> resolve entity coreferences. 0: disabled, 1: enabled (default) 610 | * showSourceText -> 0: disabled (default), 1: enabled. 611 | * maxRetrieve -> the maximum number of relations to extract (default: 50, max: 100) 612 | * 613 | * OUTPUT: 614 | * The response, already converted from JSON to a Javascript object. 615 | */ 616 | AlchemyAPI.prototype.relations = function(flavor, data, options, callback) { 617 | options = options || {} 618 | 619 | if (!(flavor in AlchemyAPI.ENDPOINTS['relations'])) { 620 | callback({ status:'ERROR', statusInfo:'Relation extraction is not available for ' + flavor }); 621 | } else { 622 | //Add the data to the options and analyze 623 | options[flavor] = data; 624 | this.analyze(AlchemyAPI.ENDPOINTS['relations'][flavor], options, callback); 625 | } 626 | }; 627 | 628 | 629 | /** 630 | * Categorizes the text for text, a URL or HTML. 631 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/text-categorization/ 632 | * For the docs, please refer to: http://www.alchemyapi.com/api/text-categorization/ 633 | * 634 | * INPUT: 635 | * flavor -> which version of the call, i.e. text, url or html. 636 | * data -> the data to analyze, either the text, the url or html code. 637 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 638 | * callback -> the callback function for this async function 639 | * 640 | * Available Options: 641 | * showSourceText -> 0: disabled (default), 1: enabled 642 | * 643 | * OUTPUT: 644 | * The response, already converted from JSON to a Javascript object. 645 | */ 646 | AlchemyAPI.prototype.category = function(flavor, data, options, callback) { 647 | options = options || {} 648 | 649 | if (!(flavor in AlchemyAPI.ENDPOINTS['category'])) { 650 | callback({ status:'ERROR', statusInfo:'Text categorization is not available for ' + flavor }); 651 | } else { 652 | //Add the data to the options and analyze 653 | options[flavor] = data; 654 | this.analyze(AlchemyAPI.ENDPOINTS['category'][flavor], options, callback); 655 | } 656 | }; 657 | 658 | 659 | /** 660 | * Detects the RSS/ATOM feeds for a URL or HTML. 661 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/feed-detection/ 662 | * For the docs, please refer to: http://www.alchemyapi.com/api/feed-detection/ 663 | * 664 | * INPUT: 665 | * flavor -> which version of the call, i.e. url or html. 666 | * data -> the data to analyze, either the the url or html code. 667 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 668 | * callback -> the callback function for this async function 669 | * 670 | * Available Options: 671 | * none 672 | * 673 | * OUTPUT: 674 | * The response, already converted from JSON to a Javascript object. 675 | */ 676 | AlchemyAPI.prototype.feeds = function(flavor, data, options, callback) { 677 | options = options || {} 678 | 679 | if (!(flavor in AlchemyAPI.ENDPOINTS['feeds'])) { 680 | callback({ status:'ERROR', statusInfo:'Feed detection is not available for ' + flavor }); 681 | } else { 682 | //Add the data to the options and analyze 683 | options[flavor] = data; 684 | this.analyze(AlchemyAPI.ENDPOINTS['feeds'][flavor], options, callback); 685 | } 686 | }; 687 | 688 | 689 | /** 690 | * Parses the microformats for a URL or HTML. 691 | * For an overview, please refer to: http://www.alchemyapi.com/products/features/microformats-parsing/ 692 | * For the docs, please refer to: http://www.alchemyapi.com/api/microformats-parsing/ 693 | * 694 | * INPUT: 695 | * flavor -> which version of the call, i.e. url or html. 696 | * data -> the data to analyze, either the the url or html code. 697 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 698 | * callback -> the callback function for this async function 699 | * 700 | * Available Options: 701 | * none 702 | * 703 | * OUTPUT: 704 | * The response, already converted from JSON to a Javascript object. 705 | */ 706 | AlchemyAPI.prototype.microformats = function(flavor, data, options, callback) { 707 | options = options || {} 708 | 709 | if (!(flavor in AlchemyAPI.ENDPOINTS['microformats'])) { 710 | callback({ status:'ERROR', statusInfo:'Microformats parsing is not available for ' + flavor }); 711 | } else { 712 | //Add the data to the options and analyze 713 | options[flavor] = data; 714 | this.analyze(AlchemyAPI.ENDPOINTS['microformats'][flavor], options, callback); 715 | } 716 | }; 717 | 718 | 719 | /** 720 | * Categorized through the taxonomy call for text, HTML, or a URL. 721 | * 722 | * INPUT: 723 | * flavor -> which version of the call (currently, only 'url' is supported) 724 | * data -> the data to analyze, either the the url or html code. 725 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 726 | * callback -> the callback function for this async function 727 | * 728 | * Available Options: 729 | * showSourceText -> 0: disabled (default), 1: enabled. 730 | * 731 | * OUTPUT: 732 | * The response, already converted from JSON to a Javascript object. 733 | */ 734 | AlchemyAPI.prototype.taxonomy = function(flavor, data, options, callback) { 735 | options = options || {} 736 | 737 | //Add the data to the options and analyze 738 | options[flavor] = data; 739 | this.analyze(AlchemyAPI.ENDPOINTS['taxonomy'][flavor], options, callback); 740 | }; 741 | 742 | 743 | /** 744 | * Extracts the combined call for a URL. 745 | * 746 | * INPUT: 747 | * flavor -> which version of the call (currently, only 'url' is supported) 748 | * data -> the data to analyze, either the the url or html code. 749 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 750 | * callback -> the callback function for this async function 751 | * 752 | * Available Options: 753 | * extract -> VALUE,VALUE,VALUE,... (possible VALUEs: page-image,entity,keyword,title,author,taxonomy,concept,relation,doc-sentiment) 754 | * extractMode -> (only applies when 'page-image' VALUE passed to 'extract' option) 755 | * trust-metadata: less CPU-intensive, less accurate 756 | * always-infer: more CPU-intensive, more accurate 757 | * disambiguate -> whether to disambiguate detected entities, 0: disabled, 1: enabled (default) 758 | * linkedData -> whether to include Linked Data content links with disambiguated entities, 0: disabled, 1: enabled (default). disambiguate must be enabled to use this. 759 | * coreference -> whether to he/she/etc coreferences into detected entities, 0: disabled, 1: enabled (default) 760 | * quotations -> whether to enable quotations extraction, 0: disabled (default), 1: enabled 761 | * sentiment -> whether to enable entity-level sentiment analysis, 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. 762 | * showSourceText -> 0: disabled (default), 1: enabled. 763 | * maxRetrieve -> maximum number of named entities to extract (default: 50) 764 | * 765 | * OUTPUT: 766 | * The response, already converted from JSON to a Javascript object. 767 | */ 768 | AlchemyAPI.prototype.combined = function(flavor, data, options, callback) { 769 | options = options || {} 770 | 771 | //Add the data to the options and analyze 772 | options[flavor] = data; 773 | this.analyze(AlchemyAPI.ENDPOINTS['combined'][flavor], options, callback); 774 | }; 775 | 776 | 777 | /** 778 | * Extracts images from a URL. 779 | * 780 | * INPUT: 781 | * flavor -> which version of the call (currently, only 'url' is supported) 782 | * data -> the data to analyze, either the the url or html code. 783 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 784 | * callback -> the callback function for this async function 785 | * 786 | * Available Options: 787 | * extractMode -> trust-metadata: less CPU-intensive and less accurate, always-infer: more CPU-intensive and more accurate 788 | * 789 | * OUTPUT: 790 | * The response, already converted from JSON to a Javascript object. 791 | */ 792 | AlchemyAPI.prototype.image = function(flavor, data, options, callback) { 793 | options = options || {} 794 | 795 | //Add the data to the options and analyze 796 | options[flavor] = data; 797 | this.analyze(AlchemyAPI.ENDPOINTS['image'][flavor], options, callback); 798 | }; 799 | 800 | 801 | /** 802 | * Tags image with keywords 803 | * 804 | * INPUT: 805 | * flavor -> which version of the call (currently, only 'url' or 'image' is supported) 806 | * data -> the URL to the data to analyze. 807 | * options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. 808 | * callback -> the callback function for this async function 809 | * 810 | * Available Options: 811 | * extractMode -> trust-metadata: less CPU-intensive and less accurate, always-infer: more CPU-intensive and more accurate 812 | * imagePostMode -> not-raw: pass an unencoded image file with "image=URI_ENCODED_DATA"; raw: pass an unencoded image file using POST ('image' flavor only). 813 | * 814 | * OUTPUT: 815 | * The response of keywords, already converted from JSON to a Javascript object. 816 | */ 817 | AlchemyAPI.prototype.image_keywords = 818 | function(flavor, data, options, callback) { 819 | options = options || {} 820 | 821 | //Add the data to the options and analyze 822 | if (flavor === "image") { // if it's an image, we'll pass the image to upload 823 | this.analyze(AlchemyAPI.ENDPOINTS['image_keywords'][flavor], 824 | options, data, callback); 825 | } else { 826 | options[flavor] = data; 827 | this.analyze(AlchemyAPI.ENDPOINTS['image_keywords'][flavor], 828 | options, callback); 829 | } 830 | }; 831 | 832 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2014 AlchemyAPI 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | 18 | var express = require('express'); 19 | var consolidate = require('consolidate'); 20 | 21 | var app = express(); 22 | var server = require('http').createServer(app); 23 | 24 | //Create the AlchemyAPI object 25 | var AlchemyAPI = require('./alchemyapi'); 26 | var alchemyapi = new AlchemyAPI(); 27 | 28 | // all environments 29 | app.engine('dust',consolidate.dust); 30 | app.set('views',__dirname + '/views'); 31 | app.set('view engine', 'dust'); 32 | app.set('port', process.env.PORT || 3000); 33 | app.use(express.favicon()); 34 | app.use(express.logger('dev')); 35 | app.use(express.bodyParser()); 36 | app.use(express.methodOverride()); 37 | 38 | // development only 39 | if ('development' == app.get('env')) { 40 | app.use(express.errorHandler()); 41 | } 42 | 43 | app.get('/', example); 44 | 45 | 46 | 47 | var port = process.env.PORT || 3000; 48 | server.listen(port, function(){ 49 | console.log('Express server listening on port ' + port); 50 | console.log('To view the example, point your favorite browser to: localhost:3000'); 51 | }); 52 | 53 | 54 | 55 | var demo_text = 'Yesterday dumb Bob destroyed my fancy iPhone in beautiful Denver, Colorado. I guess I will have to head over to the Apple Store and buy a new one.'; 56 | var demo_url = 'http://www.npr.org/2013/11/26/247336038/dont-stuff-the-turkey-and-other-tips-from-americas-test-kitchen'; 57 | var demo_html = 'Node.js Demo | AlchemyAPI

Did you know that AlchemyAPI works on HTML?

Well, you do now.

'; 58 | 59 | 60 | function example(req, res) { 61 | var output = {}; 62 | 63 | //Start the analysis chain 64 | entities(req, res, output); 65 | } 66 | 67 | 68 | function entities(req, res, output) { 69 | alchemyapi.entities('text', demo_text,{ 'sentiment':1 }, function(response) { 70 | output['entities'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response['entities'] }; 71 | keywords(req, res, output); 72 | }); 73 | } 74 | 75 | 76 | function keywords(req, res, output) { 77 | alchemyapi.keywords('text', demo_text, { 'sentiment':1 }, function(response) { 78 | output['keywords'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response['keywords'] }; 79 | concepts(req, res, output); 80 | }); 81 | } 82 | 83 | 84 | function concepts(req, res, output) { 85 | alchemyapi.concepts('text', demo_text, { 'showSourceText':1 }, function(response) { 86 | output['concepts'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response['concepts'] }; 87 | sentiment(req, res, output); 88 | }); 89 | } 90 | 91 | 92 | function sentiment(req, res, output) { 93 | alchemyapi.sentiment('html', demo_html, {}, function(response) { 94 | output['sentiment'] = { html:demo_html, response:JSON.stringify(response,null,4), results:response['docSentiment'] }; 95 | text(req, res, output); 96 | }); 97 | } 98 | 99 | 100 | function text(req, res, output) { 101 | alchemyapi.text('url', demo_url, {}, function(response) { 102 | output['text'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 103 | author(req, res, output); 104 | }); 105 | } 106 | 107 | 108 | function author(req, res, output) { 109 | alchemyapi.author('url', demo_url, {}, function(response) { 110 | output['author'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 111 | language(req, res, output); 112 | }); 113 | } 114 | 115 | 116 | function language(req, res, output) { 117 | alchemyapi.language('text', demo_text, {}, function(response) { 118 | output['language'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response }; 119 | title(req, res, output); 120 | }); 121 | } 122 | 123 | 124 | function title(req, res, output) { 125 | alchemyapi.title('url', demo_url, {}, function(response) { 126 | output['title'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 127 | relations(req, res, output); 128 | }); 129 | } 130 | 131 | 132 | function relations(req, res, output) { 133 | alchemyapi.relations('text', demo_text, {}, function(response) { 134 | output['relations'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response['relations'] }; 135 | category(req, res, output); 136 | }); 137 | } 138 | 139 | 140 | function category(req, res, output) { 141 | alchemyapi.category('text', demo_text, {}, function(response) { 142 | output['category'] = { text:demo_text, response:JSON.stringify(response,null,4), results:response }; 143 | feeds(req, res, output); 144 | }); 145 | } 146 | 147 | 148 | function feeds(req, res, output) { 149 | alchemyapi.feeds('url', demo_url, {}, function(response) { 150 | output['feeds'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response['feeds'] }; 151 | microformats(req, res, output); 152 | }); 153 | } 154 | 155 | 156 | function microformats(req, res, output) { 157 | alchemyapi.microformats('url', demo_url, {}, function(response) { 158 | output['microformats'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response['microformats'] }; 159 | taxonomy(req, res, output); 160 | }); 161 | } 162 | 163 | 164 | function taxonomy(req, res, output) { 165 | alchemyapi.taxonomy('url', demo_url, {}, function(response) { 166 | output['taxonomy'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 167 | combined(req, res, output); 168 | }); 169 | } 170 | 171 | function combined(req, res, output) { 172 | alchemyapi.combined('url', demo_url, {}, function(response) { 173 | output['combined'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 174 | image(req, res, output); 175 | }); 176 | } 177 | 178 | function image(req, res, output) { 179 | alchemyapi.image('url', demo_url, {}, function(response) { 180 | output['image'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 181 | image_keywords(req, res, output); 182 | }); 183 | } 184 | 185 | function image_keywords(req, res, output) { 186 | alchemyapi.image_keywords('url', demo_url, {}, function(response) { 187 | output['image_keywords'] = { url:demo_url, response:JSON.stringify(response,null,4), results:response }; 188 | res.render('example',output); 189 | }); 190 | } 191 | 192 | -------------------------------------------------------------------------------- /emaxfpo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlchemyAPI/alchemyapi_node/7db0f2116a68b87f5d13e315b819c4fdf2e27ebb/emaxfpo.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alchemyapi_node", 3 | "version": "0.10.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node app.js" 7 | }, 8 | "main": "./alchemyapi.js", 9 | "dependencies": { 10 | "express": "3.4.0", 11 | "request": "~2.27.0", 12 | "consolidate": "~0.9.1", 13 | "dustjs-linkedin": "~2.0.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2014 AlchemyAPI 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | 18 | var AlchemyAPI = require('./alchemyapi'); 19 | var alchemyapi = new AlchemyAPI(); 20 | var assert = require('assert'); 21 | 22 | 23 | var test_text = 'Bob broke my heart, and then made up this silly sentence to test the Node.js SDK'; 24 | var test_html = 'The best SDK Test | AlchemyAPI

Hello World!

My favorite language is Javascript

'; 25 | var test_url = 'http://www.nytimes.com/2013/07/13/us/politics/a-day-of-friction-notable-even-for-a-fractious-congress.html?_r=0'; 26 | var test_image = './emaxfpo.jpg'; 27 | 28 | 29 | 30 | //start the test sequence 31 | entities(); 32 | 33 | 34 | //Entities 35 | function entities() { 36 | console.log('Checking entities . . . '); 37 | alchemyapi.entities('random', test_text, null, function(response) { 38 | assert.equal(response['status'],'ERROR'); //invalid flavor 39 | 40 | alchemyapi.entities('text', test_text, null, function(response) { 41 | assert.equal(response['status'],'OK'); 42 | 43 | alchemyapi.entities('html', test_html, null, function(response) { 44 | assert.equal(response['status'],'OK'); 45 | 46 | alchemyapi.entities('url', test_url, null, function(response) { 47 | assert.equal(response['status'],'OK'); 48 | console.log('Entity tests complete!\n'); 49 | keywords(); 50 | }); 51 | }); 52 | }); 53 | }); 54 | } 55 | 56 | 57 | //Keywords 58 | function keywords() { 59 | console.log('Checking keywords . . . '); 60 | alchemyapi.keywords('random', test_text, null, function(response) { 61 | assert.equal(response['status'],'ERROR'); //invalid flavor 62 | 63 | alchemyapi.keywords('text', test_text, null, function(response) { 64 | assert.equal(response['status'],'OK'); 65 | 66 | alchemyapi.keywords('html', test_html, null, function(response) { 67 | assert.equal(response['status'],'OK'); 68 | 69 | alchemyapi.keywords('url', test_url, null, function(response) { 70 | assert.equal(response['status'],'OK'); 71 | console.log('Keyword tests complete!\n'); 72 | concepts(); 73 | }); 74 | }); 75 | }); 76 | }); 77 | } 78 | 79 | 80 | //Concepts 81 | function concepts() { 82 | console.log('Checking concepts . . . '); 83 | alchemyapi.concepts('random', test_text, null, function(response) { 84 | assert.equal(response['status'],'ERROR'); //invalid flavor 85 | 86 | alchemyapi.concepts('text', test_text, null, function(response) { 87 | assert.equal(response['status'],'OK'); 88 | 89 | alchemyapi.concepts('html', test_html, null, function(response) { 90 | assert.equal(response['status'],'OK'); 91 | 92 | alchemyapi.concepts('url', test_url, null, function(response) { 93 | assert.equal(response['status'],'OK'); 94 | console.log('Concept tests complete!\n'); 95 | sentiment(); 96 | }); 97 | }); 98 | }); 99 | }); 100 | } 101 | 102 | 103 | 104 | //Sentiment 105 | function sentiment() { 106 | console.log('Checking sentiment . . . '); 107 | alchemyapi.sentiment('random', test_text, null, function(response) { 108 | assert.equal(response['status'],'ERROR'); //invalid flavor 109 | 110 | alchemyapi.sentiment('text', test_text, null, function(response) { 111 | assert.equal(response['status'],'OK'); 112 | 113 | alchemyapi.sentiment('html', test_html, null, function(response) { 114 | assert.equal(response['status'],'OK'); 115 | 116 | alchemyapi.sentiment('url', test_url, null, function(response) { 117 | assert.equal(response['status'],'OK'); 118 | console.log('Sentiment tests complete!\n'); 119 | sentiment_targeted(); 120 | }); 121 | }); 122 | }); 123 | }); 124 | } 125 | 126 | 127 | //Targeted Sentiment 128 | function sentiment_targeted() { 129 | console.log('Checking targeted sentiment . . . '); 130 | alchemyapi.sentiment_targeted('text', test_text, null, null, function(response) { 131 | assert.equal(response['status'],'ERROR'); //did not supply the target 132 | 133 | alchemyapi.sentiment_targeted('random', test_text, 'heart', null, function(response) { 134 | assert.equal(response['status'],'ERROR'); //invalid flavor 135 | 136 | alchemyapi.sentiment_targeted('text', test_text, 'heart', null, function(response) { 137 | assert.equal(response['status'],'OK'); 138 | 139 | alchemyapi.sentiment_targeted('html', test_html, 'language', null, function(response) { 140 | assert.equal(response['status'],'OK'); 141 | 142 | alchemyapi.sentiment_targeted('url', test_url, 'Congress', null, function(response) { 143 | assert.equal(response['status'],'OK'); 144 | console.log('Targeted sentiment tests complete!\n'); 145 | text(); 146 | }); 147 | }); 148 | }); 149 | }); 150 | }); 151 | } 152 | 153 | 154 | //Text 155 | function text() { 156 | console.log('Checking text . . . '); 157 | alchemyapi.text('text', test_text, null, function(response) { 158 | assert.equal(response['status'],'ERROR'); //only works for html and urls 159 | 160 | alchemyapi.text('html', test_html, null, function(response) { 161 | assert.equal(response['status'],'OK'); 162 | 163 | alchemyapi.text('url', test_url, null, function(response) { 164 | assert.equal(response['status'],'OK'); 165 | console.log('Text tests complete!\n'); 166 | text_raw(); 167 | }); 168 | }); 169 | }); 170 | } 171 | 172 | 173 | //Text Raw 174 | function text_raw() { 175 | console.log('Checking raw text . . . '); 176 | alchemyapi.text_raw('text', test_text, null, function(response) { 177 | assert.equal(response['status'],'ERROR'); //only works for html and urls 178 | 179 | alchemyapi.text_raw('html', test_html, null, function(response) { 180 | assert.equal(response['status'],'OK'); 181 | 182 | alchemyapi.text_raw('url', test_url, null, function(response) { 183 | assert.equal(response['status'],'OK'); 184 | console.log('Raw Text tests complete!\n'); 185 | author(); 186 | }); 187 | }); 188 | }); 189 | } 190 | 191 | 192 | //Author 193 | function author() { 194 | console.log('Checking author . . . '); 195 | alchemyapi.author('text', test_text, null, function(response) { 196 | assert.equal(response['status'],'ERROR'); //only works for html and urls 197 | 198 | alchemyapi.author('html', test_html, null, function(response) { 199 | assert.equal(response['status'],'ERROR'); //there is no author in the test HTML content 200 | 201 | alchemyapi.author('url', test_url, null, function(response) { 202 | assert.equal(response['status'],'OK'); 203 | console.log('Author tests complete!\n'); 204 | language(); 205 | }); 206 | }); 207 | }); 208 | } 209 | 210 | 211 | //Language 212 | function language() { 213 | console.log('Checking language . . . '); 214 | alchemyapi.language('random', test_text, null, function(response) { 215 | assert.equal(response['status'],'ERROR'); //invalid flavor 216 | 217 | alchemyapi.language('text', test_text, null, function(response) { 218 | assert.equal(response['status'],'OK'); 219 | 220 | alchemyapi.language('html', test_html, null, function(response) { 221 | assert.equal(response['status'],'OK'); 222 | 223 | alchemyapi.language('url', test_url, null, function(response) { 224 | assert.equal(response['status'],'OK'); 225 | console.log('Language tests complete!\n'); 226 | title(); 227 | }); 228 | }); 229 | }); 230 | }); 231 | } 232 | 233 | 234 | //Title 235 | function title() { 236 | console.log('Checking title . . . '); 237 | alchemyapi.title('text', test_text, null, function(response) { 238 | assert.equal(response['status'],'ERROR'); //only works for html and urls 239 | 240 | alchemyapi.title('html', test_html, null, function(response) { 241 | assert.equal(response['status'],'OK'); 242 | 243 | alchemyapi.title('url', test_url, null, function(response) { 244 | assert.equal(response['status'],'OK'); 245 | console.log('Title tests complete!\n'); 246 | relations(); 247 | }); 248 | }); 249 | }); 250 | } 251 | 252 | 253 | //Relations 254 | function relations() { 255 | console.log('Checking relations . . . '); 256 | alchemyapi.relations('random', test_text, null, function(response) { 257 | assert.equal(response['status'],'ERROR'); //invalid flavor 258 | 259 | alchemyapi.relations('text', test_text, null, function(response) { 260 | assert.equal(response['status'],'OK'); 261 | 262 | alchemyapi.relations('html', test_html, null, function(response) { 263 | assert.equal(response['status'],'OK'); 264 | 265 | alchemyapi.relations('url', test_url, null, function(response) { 266 | assert.equal(response['status'],'OK'); 267 | console.log('Relation tests complete!\n'); 268 | category(); 269 | }); 270 | }); 271 | }); 272 | }); 273 | } 274 | 275 | 276 | //Category 277 | function category() { 278 | console.log('Checking category . . . '); 279 | alchemyapi.category('random', test_text, null, function(response) { 280 | assert.equal(response['status'],'ERROR'); //invalid flavor 281 | 282 | alchemyapi.category('text', test_text, null, function(response) { 283 | assert.equal(response['status'],'OK'); 284 | 285 | alchemyapi.category('html', test_html, {url:'test'}, function(response) { 286 | assert.equal(response['status'],'OK'); 287 | 288 | alchemyapi.category('url', test_url, null, function(response) { 289 | assert.equal(response['status'],'OK'); 290 | console.log('Category tests complete!\n'); 291 | feeds(); 292 | }); 293 | }); 294 | }); 295 | }); 296 | } 297 | 298 | 299 | //Feeds 300 | function feeds() { 301 | console.log('Checking feeds . . . '); 302 | alchemyapi.feeds('text', test_text, null, function(response) { 303 | assert.equal(response['status'],'ERROR'); //only works for html and urls 304 | 305 | alchemyapi.feeds('html', test_html, {url:'test'}, function(response) { 306 | assert.equal(response['status'],'OK'); 307 | 308 | alchemyapi.feeds('url', test_url, null, function(response) { 309 | assert.equal(response['status'],'OK'); 310 | console.log('Feeds tests complete!\n'); 311 | microformats(); 312 | }); 313 | }); 314 | }); 315 | } 316 | 317 | 318 | //Microformats 319 | function microformats() { 320 | console.log('Checking microformats . . . '); 321 | alchemyapi.microformats('text', test_text, null, function(response) { 322 | assert.equal(response['status'],'ERROR'); //only works for html and urls 323 | 324 | alchemyapi.microformats('html', test_html, {url:'test'}, function(response) { 325 | assert.equal(response['status'],'OK'); 326 | 327 | alchemyapi.microformats('url', test_url, null, function(response) { 328 | assert.equal(response['status'],'OK'); 329 | console.log('Microformat tests complete!\n'); 330 | taxonomy(); 331 | }); 332 | }); 333 | }); 334 | } 335 | 336 | 337 | //Taxonomy 338 | function taxonomy() { 339 | console.log('Checking taxonomy . . . '); 340 | alchemyapi.taxonomy('text', test_text, null, function(response) { 341 | assert.equal(response['status'],'OK'); //only works for html and urls 342 | 343 | alchemyapi.taxonomy('html', test_html, {url:'test'}, function(response) { 344 | assert.equal(response['status'],'OK'); 345 | 346 | alchemyapi.taxonomy('url', test_url, null, function(response) { 347 | assert.equal(response['status'],'OK'); 348 | console.log('Taxonomy tests complete!\n'); 349 | image(); 350 | }); 351 | }); 352 | }); 353 | } 354 | 355 | 356 | //Image 357 | function image() { 358 | console.log('Checking image . . . '); 359 | alchemyapi.image('url', test_url, null, function(response) { 360 | assert.equal(response['status'],'OK'); 361 | console.log('Image tests complete!\n'); 362 | url_image_keywords(); 363 | }); 364 | } 365 | 366 | 367 | //Image Keywords 368 | function url_image_keywords() { 369 | console.log('Checking url image keywords . . . '); 370 | alchemyapi.image_keywords('url', test_url, null, function(response) { 371 | assert.equal(response['status'],'OK'); 372 | console.log('Image keywords tests complete!\n'); 373 | image_keywords(); 374 | }); 375 | } 376 | 377 | //Image Keywords with post 378 | function image_keywords() { 379 | console.log('Checking image keywords . . . '); 380 | alchemyapi.image_keywords('image', test_image, null, function(response) { 381 | assert.equal(response['status'],'OK'); 382 | console.log('Image keywords tests complete!\n'); 383 | combined(); 384 | }); 385 | } 386 | 387 | 388 | //Combined 389 | function combined() { 390 | console.log('Checking combined . . . '); 391 | alchemyapi.combined('url', test_url, null, function(response) { 392 | assert.equal(response['status'],'OK'); 393 | console.log('Combined tests complete!\n'); 394 | 395 | console.log('\n\n**** All tests are complete! ****\n'); 396 | }); 397 | } 398 | 399 | -------------------------------------------------------------------------------- /views/example.dust: -------------------------------------------------------------------------------- 1 | {>layout/} 2 | 3 | { 5 | 8 | 9 |

Entity Extraction

10 |

For more information on entity extraction: http://www.alchemyapi.com/products/features/entity-extraction/
11 | For the docs: http://www.alchemyapi.com/api/entity-extraction/

12 | 13 |

Processed Text

14 |

{entities.text}

15 | 16 |

Response Object

17 | 18 | 19 |

Entities

20 | {#entities.results} 21 |

Text: {text}
22 | Type: {type}
23 | Relevance: {relevance}
24 | Sentiment: {sentiment.type} {#sentiment.score}({sentiment.score}){/sentiment.score}

25 | {/entities.results} 26 | 27 |
28 | 29 | 30 |

Keyword Extraction

31 |

For more information on keyword extraction: http://www.alchemyapi.com/products/features/keyword-extraction/
32 | For the docs: http://www.alchemyapi.com/api/keyword-extraction/

33 | 34 |

Processed Text

35 |

{keywords.text}

36 | 37 |

Response Object

38 | 39 | 40 |

Keywords

41 | {#keywords.results} 42 |

Text: {text}
43 | Relevance: {relevance}
44 | Sentiment: {sentiment.type} {#sentiment.score}({sentiment.score}){/sentiment.score}

45 | {/keywords.results} 46 | 47 |
48 | 49 | 50 |

Concept Tagging

51 |

For more information on concept tagging: http://www.alchemyapi.com/products/features/concept-tagging/
52 | For the docs: http://www.alchemyapi.com/api/concept-tagging/

53 | 54 |

Processed Text

55 |

{concepts.text}

56 | 57 |

Response Object

58 | 59 | 60 |

Concepts

61 | {#concepts.results} 62 |

Text: {text}
63 | Relevance: {relevance}

64 | {/concepts.results} 65 | 66 |
67 | 68 | 69 |

Sentiment Analysis

70 |

For more information on sentiment analysis: http://www.alchemyapi.com/products/features/sentiment-analysis/
71 | For the docs: http://www.alchemyapi.com/api/sentiment-analysis/

72 | 73 |

Processed HTML

74 |

{sentiment.html}

75 | 76 |

Response Object

77 | 78 | 79 |

Document Sentiment

80 |

Type: {sentiment.results.type}
81 | {#sentiment.results.score}Score: {sentiment.results.score}{/sentiment.results.score}

82 | 83 |
84 | 85 |

Text Extraction

86 |

For more information on text extraction: http://www.alchemyapi.com/products/features/text-extraction/
87 | For the docs: http://www.alchemyapi.com/api/text-extraction/

88 | 89 |

Processed URL

90 |

{text.url}

91 | 92 |

Response Object

93 | 94 | 95 |

Text

96 |

Text:
97 | {text.results.text}

98 | 99 |
100 | 101 |

Author Extraction

102 |

For more information on author extraction: http://www.alchemyapi.com/products/features/author-extraction/
103 | For the docs: http://www.alchemyapi.com/api/author-extraction/

104 | 105 |

Processed URL

106 |

{author.url}

107 | 108 |

Response Object

109 | 110 | 111 |

Author

112 |

Author: {author.results.author}

113 | 114 |
115 | 116 |

Language Detection

117 |

For more information on language detection: http://www.alchemyapi.com/products/features/language-detection/
118 | For the docs: http://www.alchemyapi.com/api/language-detection/

119 | 120 |

Processed Text

121 |

{language.text}

122 | 123 |

Response Object

124 | 125 | 126 |

Language

127 |

Language: {language.results.language}
128 | ISO-639-1: {language.results.iso-639-1}
129 | Native Speakers: {language.results.native-speakers}

130 | 131 |
132 | 133 |

Title Extraction

134 |

For the docs: http://www.alchemyapi.com/api/text/urls.html#title

135 | 136 |

Processed URL

137 |

{title.url}

138 | 139 |

Response Object

140 | 141 | 142 |

Title

143 |

Title: {title.results.title}

144 | 145 |
146 | 147 |

Relation Extraction

148 |

For more information on relation extraction: http://www.alchemyapi.com/products/features/relation-extraction/
149 | For the docs: http://www.alchemyapi.com/api/relation-extraction/

150 | 151 |

Processed Text

152 |

{relations.text}

153 | 154 |

Response Object

155 | 156 | 157 |

Relations

158 |

159 | {#relations.results} 160 |

161 | {#subject} 162 | Subject: {text}
163 | {/subject} 164 | 165 | {#action} 166 | Action: {text}
167 | {/action} 168 | 169 | {#object} 170 | Object: {text} 171 | {/object} 172 |

173 | {/relations.results} 174 |

175 |
176 | 177 |

Text Categorization

178 |

For more information on text categorization: http://www.alchemyapi.com/products/features/text-categorization/
179 | For the docs: http://www.alchemyapi.com/api/text-categorization/

180 | 181 |

Processed Text

182 |

{category.text}

183 | 184 |

Response Object

185 | 186 | 187 |

Text Category

188 |

Category: {category.results.category}
189 | Score: {category.results.score}

190 | 191 |
192 | 193 |

Feed Detection

194 |

For more information on feed detection: http://www.alchemyapi.com/products/features/feed-detection/
195 | For the docs: http://www.alchemyapi.com/api/feed-detection/

196 | 197 |

Processed URL

198 |

{feeds.url}

199 | 200 |

Response Object

201 | 202 | 203 |

Feeds

204 |

205 | {#feeds.results} 206 | Feed: {feed}
207 | {/feeds.results} 208 |

209 | 210 |
211 | 212 |

Microformats Parsing

213 |

For more information on microformats parsing: http://www.alchemyapi.com/products/features/microformats-parsing/
214 | For the docs: http://www.alchemyapi.com/api/microformats-parsing/

215 | 216 |

Processed URL

217 |

{microformats.url}

218 | 219 |

Response Object

220 | 221 | 222 |

Microformats

223 |

224 | {#microformats.results} 225 | Field: {field}
226 | Data: {data}

227 | {/microformats.results} 228 |

229 | 230 |
231 | 232 |

Taxonomy Parsing

233 |

234 | For the docs: http://www.alchemyapi.com/api/

235 | 236 |

Processed URL

237 |

{taxonomy.url}

238 | 239 |

Response Object

240 | 241 | 242 |

Taxonomy

243 | 244 | {#taxonomy.results.taxonomy} 245 |

Label: {label}
246 | Score: {score}
247 | Confident: {confident}

248 | {/taxonomy.results.taxonomy} 249 | 250 |
251 | 252 |

Image Parsing

253 |

254 | For the docs: http://www.alchemyapi.com/api/

255 | 256 |

Processed URL

257 |

{image.url}

258 | 259 |

Response Object

260 | 261 | 262 |

Image

263 | 264 |

Image: {image.results.image}
265 | 266 |


267 | 268 |

Image Keywords Tagging

269 |

270 | For the docs: http://www.alchemyapi.com/api/

271 | 272 |

Processed URL

273 |

{image_keywords.url}

274 | 275 |

Response Object

276 | 277 | 278 |

Keywords

279 | 280 | {#image_keywords.results.imageKeywords} 281 |

Keyword

282 |

Text: {text}
283 | Score: {score}
284 | {/image_keywords.results.imageKeywords} 285 | 286 |


287 | 288 |

Combined Parsing

289 |

290 | For the docs: http://www.alchemyapi.com/api/

291 | 292 |

Processed URL

293 |

{combined.url}

294 | 295 |

Response Object

296 | 297 | 298 |

Combined

299 | 300 |

Category: {combined.results.category.category}
301 | Score: {combined.results.category.score}

302 | 303 | {#combined.results.entities} 304 |

Entity

305 |

Text: {text}
306 | Type: {type}
307 | Relevance: {relevance}
308 | Sentiment: {sentiment.type} {#sentiment.score}({sentiment.score}){/sentiment.score}

309 | {/combined.results.entities} 310 | 311 | {#combined.results.concepts} 312 |

Concept

313 |

Text: {text}
314 | Relevance: {relevance}

315 | {/combined.results.concepts} 316 | 317 | {#combined.results.keywords} 318 |

Keyword

319 |

Text: {text}
320 | Relevance: {relevance}
321 | Sentiment: {sentiment.type} {#sentiment.score}({sentiment.score}){/sentiment.score}

322 | {/combined.results.keywords} 323 | 324 |
325 | 326 | 327 | 328 | {/content} 329 | -------------------------------------------------------------------------------- /views/layout.dust: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {+title}Node.js Example | AlchemyAPI{/title} 5 | 6 | 7 | 8 | {+head_stylesheets/} 9 | {+head_javascripts/} 10 | 11 | 12 | 13 | 14 | {+content/} 15 | 16 | {+footer/} 17 | 18 | 19 | 20 | {+footer_javascripts/} 21 | 22 | 23 | --------------------------------------------------------------------------------