-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
156 lines (141 loc) · 4.25 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// @todo: cancel upload if a new upload is requested (debounce, but better)
// @todo: prevent upload if file is empty. tumblr will fail silently
'use strict';
const https = require('https');
const path = require('path');
const ini = require('iniparser');
const appRoots = [
process.cwd(),
path.dirname(require.main.filename),
require('app-root-path')
];
/**
* Set tumblr account to accept future uploads
* @param {object|array} c Credentials to use, object or array in this order: tumblr_id, user_form_key, anon_id, pfe, pfp, pfs, pfu
*/
function Blog(c) {
const blog = this;
if (c && c.length === 7) {
c = {
tumblr_id: c[0],
user_form_key: c[1],
anon_id: c[2],
pfe: c[3],
pfp: c[4],
pfs: c[5],
pfu: c[6]
};
}
if (!c || !c.tumblr_id || !c.user_form_key || !c.anon_id || !c.pfe || !c.pfp || !c.pfs || !c.pfu) {
throw new Error('Credentials missing or incomplete!');
}
blog.pwd = c;
}
/**
* Upload the specified template using the previously-specified credentials
* @param {string} htmlTemplate Tumblr template to upload
* @param {Function} callback Function to call after the upload is done or has failed
* @return {ClientRequest} Node ClientRequest method, can be .abort()'ed
*/
Blog.prototype.upload = function (htmlTemplate, callback) {
if (typeof htmlTemplate !== 'string') {
throw new TypeError('The parameter `htmlTemplate` should be a string.');
}
const blog = this;
const pwd = blog.pwd;
const options = {
host: 'www.tumblr.com',
port: 443,
path: '/customize_api/blog/' + pwd.tumblr_id,
method: 'POST',
headers: {
'x-requested-with': 'XMLHttpRequest',
'x-for-issues': 'https://github.com/fregante/tumblr-upload',
'pragma': 'no-cache',
'content-type': 'application/json',
'accept': 'application/json, text/j avascript, */*; q=0.01',
'cache-control': 'no-cache',
'Cookie': 'logged_in=1; pfp=' + pwd.pfp + '; pfs=' + pwd.pfs + '; pfe=' + pwd.pfe + '; pfu=' + pwd.pfu + '; anon_id=' + pwd.anon_id + ';',
'referer': 'https://www.tumblr.com/customize/' + pwd.tumblr_id + '?redirect_to=/blog/' + pwd.tumblr_id
}
};
const httpBody = JSON.stringify({
custom_theme: htmlTemplate,
id: pwd.tumblr_id,
user_form_key: pwd.user_form_key
});
// do request
const request = https.request(options, res => {
if (!callback || !callback.call) {
return;
}
let response = '';
res.on('data', chunk => {
response += chunk;
});
res.on('end', () => {
if (/Authentication required|permission/i.test(response)) {
callback(new Error('Authentication failed'));
} else {
try {
// verify that it's a valid json response
JSON.parse(response);
callback(false);
} catch (err) {
callback(new Error('Failed parsing of response: ' + response));
}
}
});
});
if (callback && callback.call) {
request.on('error', e => {
callback(new Error(e.message));
});
}
request.write(httpBody);
request.end();
return blog;
};
/**
* Upload specified template and use the settings in tumblr-upload.ini file
* @see Blog.prototype.upload
*/
function uploadWithIniConfig(htmlTemplate, tumblr_id, callback) {
let c;
const paths = [];
if (typeof htmlTemplate !== 'string') {
throw new TypeError('The parameter `htmlTemplate` should be a string.');
}
if (typeof tumblr_id !== 'string') {
throw new TypeError('The parameter `tumblr_id` should be a string.');
}
// try to load config file from all the possible paths
appRoots.some(appRoot => {
try {
const filename = appRoot + '/tumblr-upload.ini';
paths.push(path.dirname(filename));
c = ini.parseSync(filename);
return true;
} catch (err) {
return false;
}
});
// were the credentials found?
if (!c) {
throw new Error('Credentials missing! I looked for tumblr-upload.ini in:\n' + paths.join('\n'));
}
// pick the right blog
c = c[tumblr_id];
if (!c) {
throw new Error('Blog `' + tumblr_id + '` doesn\'t exist in the config file ' + paths.pop());
}
c.tumblr_id = tumblr_id;
// cheaply verify credentials
if (!c.user_form_key || !c.anon_id || !c.pfe || !c.pfp || !c.pfs || !c.pfu) {
throw new Error('Credentials incomplete: ' + JSON.stringify(c));
}
// upload template
return new Blog(c).upload(htmlTemplate, callback);
}
module.exports = uploadWithIniConfig;
module.exports.Blog = Blog;