1 | 'use strict';
|
2 |
|
3 | var https = require('https');
|
4 | var http = require('http');
|
5 | var jsonStatus = require('./statusmsgs.json');
|
6 | var url = require('url');
|
7 |
|
8 | module.exports = Plotly;
|
9 |
|
10 | function Plotly(username,apiKey) {
|
11 | if (!(this instanceof Plotly)) return new Plotly(username,apiKey);
|
12 |
|
13 | var opts = {};
|
14 |
|
15 | if (typeof username === 'object') {
|
16 | opts = username;
|
17 | this.username = opts.username;
|
18 | this.apiKey = opts.apiKey;
|
19 | this.host = opts.host || 'plot.ly';
|
20 | this.port = opts.port || 443;
|
21 | } else {
|
22 | this.username = username;
|
23 | this.apiKey = apiKey;
|
24 | this.host = 'plot.ly';
|
25 | this.port = 443;
|
26 | }
|
27 | this.streamHost = '';
|
28 | this.version='0.0.2';
|
29 | this.platform='nodejs';
|
30 | this.origin='plot';
|
31 | }
|
32 |
|
33 | Plotly.prototype.plot = function(data, graphOptions, callback) {
|
34 | var self = this;
|
35 | if (!callback) { callback = function() {}; }
|
36 |
|
37 |
|
38 | if (!Array.isArray(data)) data = [data];
|
39 |
|
40 | var urlencoded = '';
|
41 | var pack = {
|
42 | 'platform': self.platform,
|
43 | 'version': self.version,
|
44 | 'args': JSON.stringify(data),
|
45 | 'kwargs': JSON.stringify(graphOptions),
|
46 | 'un': self.username,
|
47 | 'key': self.apiKey,
|
48 | 'origin': self.origin
|
49 | };
|
50 |
|
51 | for (var key in pack) {
|
52 | urlencoded += key + '=' + pack[key] + '&';
|
53 | }
|
54 |
|
55 |
|
56 | urlencoded = urlencoded.substring(0, urlencoded.length - 1);
|
57 |
|
58 | var options = {
|
59 | host: self.host,
|
60 | port: self.port,
|
61 | path: '/clientresp',
|
62 | method: 'POST',
|
63 | headers: {
|
64 | 'Content-Type': 'application/x-www-form-urlencoded',
|
65 | 'Content-Length': urlencoded.length
|
66 | },
|
67 | withCredentials: false
|
68 | };
|
69 |
|
70 | var req = https.request(options, function (res) {
|
71 | parseRes(res, function (err, body) {
|
72 | body = JSON.parse(body);
|
73 |
|
74 | if ( body['stream-status'] != undefined) {
|
75 | self.streamHost = url.parse(body['stream-host']).hostname;
|
76 | }
|
77 |
|
78 | if ( body.error.length > 0 ) {
|
79 | var error = new Error(body.error);
|
80 | error.body = body;
|
81 | error.statusCode = res.statusCode;
|
82 | callback(error);
|
83 | } else {
|
84 | callback(null, {
|
85 | streamstatus : body['stream-status'],
|
86 | url: body.url,
|
87 | message: body.message,
|
88 | warning: body.warning,
|
89 | filename: body.filename,
|
90 | error: body.error
|
91 | });
|
92 | }
|
93 | });
|
94 | });
|
95 |
|
96 | req.on('error', function(err) {
|
97 | callback(err);
|
98 | });
|
99 |
|
100 | req.write(urlencoded);
|
101 | req.end();
|
102 | };
|
103 |
|
104 | Plotly.prototype.stream = function(token, callback) {
|
105 | var self = this;
|
106 | var opts = {};
|
107 |
|
108 | if (typeof token === 'object') {
|
109 | opts = token;
|
110 | token = opts.token;
|
111 | var host = opts.streamHost || self.streamHost;
|
112 | var port = opts.port || 80;
|
113 | }
|
114 |
|
115 | var options = {
|
116 | host: host || self.streamHost || 'stream.plot.ly',
|
117 | port: port || 80,
|
118 | path: '/',
|
119 | method: 'POST',
|
120 | agent: false,
|
121 | headers: { 'plotly-streamtoken' : token }
|
122 | };
|
123 |
|
124 | if (!callback) { callback = function() {}; }
|
125 |
|
126 | var stream = http.request(options, function (res) {
|
127 | var message = jsonStatus[res.statusCode];
|
128 |
|
129 | if (res.statusCode !== 200) {
|
130 | var error = new Error(message);
|
131 | error.statusCode = res.statusCode;
|
132 | callback(error);
|
133 | } else {
|
134 | callback(null, {msg : message, statusCode: res.statusCode});
|
135 | }
|
136 | });
|
137 |
|
138 | if (stream.setTimeout) stream.setTimeout(Math.pow(2, 32) * 1000);
|
139 |
|
140 | return stream;
|
141 | };
|
142 |
|
143 |
|
144 | Plotly.prototype.getFigure = function (fileOwner, fileId, callback) {
|
145 | var self = this;
|
146 |
|
147 | if (!callback) { callback = function() {}; }
|
148 |
|
149 | var headers = {
|
150 | 'plotly-username': this.username,
|
151 | 'plotly-apikey': this.apiKey,
|
152 | 'plotly-version': this.version,
|
153 | 'plotly-platform': this.platform
|
154 | };
|
155 |
|
156 | var resource = '/apigetfile/'+fileOwner+'/'+fileId;
|
157 |
|
158 | var options = {
|
159 | host: self.host,
|
160 | path: resource,
|
161 | port: self.port,
|
162 | headers: headers,
|
163 | method: 'GET'
|
164 | };
|
165 |
|
166 | var req = https.get(options, function (res) {
|
167 | parseRes(res, function (err, body) {
|
168 | if (JSON.parse(body).error) {
|
169 | err = JSON.parse(body).error;
|
170 | callback(err);
|
171 | } else {
|
172 | var figure = JSON.parse(body).payload.figure;
|
173 | callback(null, figure);
|
174 | }
|
175 | });
|
176 | });
|
177 |
|
178 | req.end();
|
179 | };
|
180 |
|
181 | Plotly.prototype.getImage = function (figure, opts, callback) {
|
182 | callback = callback || function () {};
|
183 | if (!figure) return new Error('no figure provided!');
|
184 |
|
185 | var self = this;
|
186 | var payload = JSON.stringify({
|
187 | figure: figure,
|
188 | format: opts.format || 'png',
|
189 | width: opts.width || 700,
|
190 | height: opts.height || 500
|
191 | });
|
192 |
|
193 | var headers = {
|
194 | 'plotly-username': self.username,
|
195 | 'plotly-apikey': self.apiKey,
|
196 | 'plotly-version': self.version,
|
197 | 'plotly-platform': self.platform,
|
198 | 'Content-Type': 'application/x-www-form-urlencoded',
|
199 | 'Content-Length': payload.length
|
200 | };
|
201 |
|
202 | var options = {
|
203 | hostname: self.host,
|
204 | path : '/apigenimage/',
|
205 | port: self.port,
|
206 | headers: headers,
|
207 | method: 'POST',
|
208 | agent: false
|
209 | };
|
210 |
|
211 | function handleResponse(res) {
|
212 | parseRes(res, function (err, body) {
|
213 | if (res.statusCode !== 200) {
|
214 | var error = new Error('Bad response status code ' + res.statusCode);
|
215 | error.msg = body;
|
216 | return callback(error, null);
|
217 | }
|
218 | var imageData = JSON.parse(body).payload;
|
219 | callback(null, imageData);
|
220 | });
|
221 | }
|
222 |
|
223 | var req = https.request(options, handleResponse);
|
224 | req.write(payload);
|
225 | req.end();
|
226 | };
|
227 |
|
228 |
|
229 | function parseRes (res, cb) {
|
230 | var body = '';
|
231 | if ('setEncoding' in res) res.setEncoding('utf-8');
|
232 |
|
233 | res.on('data', function (data) {
|
234 | body += data;
|
235 | if (body.length > 1e10) {
|
236 |
|
237 | res.connection.destroy();
|
238 | res.writeHead(413, {'Content-Type': 'text/plain'});
|
239 | res.end('req body too large');
|
240 | return cb(new Error('body overflow'));
|
241 | }
|
242 | });
|
243 |
|
244 | res.on('end', function () {
|
245 | cb(null, body);
|
246 | });
|
247 |
|
248 | }
|