-
Notifications
You must be signed in to change notification settings - Fork 14
Add additional API features #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
f161514
b41c3ff
4ab3d6f
bfc0849
a46016a
ce07746
1c0adce
9e0d37c
3947622
bab3f61
fa62b4f
fd73350
f7079bc
8fbe3ac
ccf3c5d
c91b0c3
f3e6a46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,26 +7,78 @@ var qs = require('querystring') | |
var FormData = require('form-data') | ||
|
||
function NeoCities(user, pass, opts) { | ||
this.user = user | ||
this.pass = pass | ||
this.opts = opts || {} | ||
if (typeof pass == 'object' || pass == undefined) { | ||
this.key = user | ||
} | ||
this.opts = opts || (typeof pass == 'object' ? pass : {}) | ||
if (!this.opts.key && !this.key) { | ||
this.user = user | ||
this.pass = pass | ||
} | ||
else { | ||
this.opts.key = this.opts.key || true | ||
} | ||
this.url = url.parse(this.opts.url || 'https://neocities.org') | ||
this.siteurl = this.opts.siteurl ? url.parse(this.ops.siteurl) : null | ||
this.client = this.url.protocol == 'https:' ? https : http | ||
if (this.opts.key && !this.key) { | ||
this.get('key', null, function (res) { | ||
this.key = res.api_key | ||
if (typeof this.opts.key == 'function') this.opts.key(this) | ||
}, user, pass) | ||
} | ||
} | ||
|
||
NeoCities.prototype.get = function(method, args, callback) { | ||
var path = '/api/'+method | ||
|
||
if(args) | ||
path += '?'+qs.stringify(args) | ||
NeoCities.prototype.download = function(files, callback) { | ||
console.log(files) | ||
var i = 0 | ||
var that = this | ||
var returning = false | ||
|
||
if (!this.siteurl) { | ||
this.info(function (resp) { | ||
that.siteurl = url.parse(that.url.protocol + '//' + (resp.info.domain || resp.info.sitename + '.' + that.url.hostname)) | ||
dwnldFile() | ||
}) | ||
} | ||
else dwnldFile() | ||
|
||
function dwnldFile() { | ||
if (i < files.length) { | ||
if (files[i].path) { | ||
var file = fs.createWriteStream(files[i].path) | ||
file.on('finish', function() {file.close((dwnldFile))}) | ||
that.client.get(that.siteurl.href + files[i].name.replace(/^\/?/, '/'), | ||
function(data) {return data.pipe(file)}) | ||
} | ||
// else { | ||
// returning = true | ||
// that.client.request(that.siteurl.href + files[i].name.replace(/^\/?/, '/'), | ||
// . function (data) {returnData[files[i].name] = data}) | ||
// } | ||
i ++ | ||
} | ||
else if (typeof callback == 'function' && !returning) | ||
callback({status:'success'}) | ||
} | ||
} | ||
|
||
var request = this.client.request({ | ||
NeoCities.prototype.get = function(method, args, callback, user, pass) { | ||
var opts = { | ||
method: 'get', | ||
host: this.url.hostname, | ||
port: this.url.port, | ||
path: path, | ||
auth: this.user+':'+this.pass | ||
}, function(res) { | ||
path: '/api/' + method + (args ? '?' + qs.stringify(args) : '') | ||
} | ||
|
||
if (!this.key) { | ||
opts.auth = (user || this.user) + ':' + (pass || this.pass) | ||
} | ||
else { | ||
opts.headers = {Authorization: 'Bearer ' + this.key} | ||
} | ||
|
||
var request = this.client.request(opts, function(res) { | ||
var body = '' | ||
|
||
res.on('data', function (chunk) { | ||
|
@@ -43,63 +95,179 @@ NeoCities.prototype.get = function(method, args, callback) { | |
|
||
NeoCities.prototype.info = function(sitename, callback) { | ||
var args = null | ||
|
||
if(typeof sitename == 'function') | ||
callback = sitename | ||
else if(typeof sitename == 'string') | ||
args = {sitename: sitename} | ||
|
||
this.get('info', args, callback) | ||
} | ||
|
||
NeoCities.prototype.list = function(path, callback) { | ||
var args = null | ||
|
||
if (typeof path == 'function') | ||
callback = path | ||
else if (typeof path == 'string') | ||
args = {path: path} | ||
|
||
this.get('list', args, callback) | ||
} | ||
|
||
NeoCities.prototype.post = function(method, args, callback) { | ||
var form = new FormData() | ||
var i | ||
|
||
for(i=0;i<args.length;i++) | ||
|
||
for(var i = 0; i < args.length; i ++) | ||
form.append(args[i].name, args[i].value) | ||
|
||
var request = this.client.request({ | ||
var opts = { | ||
method: 'post', | ||
host: this.url.hostname, | ||
port: this.url.port, | ||
path: '/api/'+method, | ||
headers: form.getHeaders(), | ||
auth: this.user+':'+this.pass | ||
}, function(res) { | ||
path: '/api/' + method, | ||
headers: form.getHeaders() | ||
} | ||
|
||
if (!this.key) { | ||
opts.auth = this.user + ':' + this.pass | ||
} | ||
else { | ||
opts.headers.Authorization = 'Bearer ' + this.key | ||
} | ||
|
||
var request = this.client.request(opts, function(res) { | ||
var body = '' | ||
|
||
res.on('data', function (chunk) { | ||
body += chunk | ||
}) | ||
|
||
res.on('end', function() { | ||
var resObj = JSON.parse(body) | ||
callback(resObj) | ||
}) | ||
}) | ||
|
||
form.pipe(request) | ||
} | ||
|
||
NeoCities.prototype.delete = function(filenames, callback) { | ||
var args = [] | ||
var i | ||
|
||
for(i=0;i<filenames.length;i++) | ||
|
||
for(var i = 0; i < filenames.length; i ++) | ||
args.push({name: 'filenames[]', value: filenames[i]}) | ||
|
||
this.post('delete', args, callback) | ||
} | ||
|
||
NeoCities.prototype.upload = function(files, callback) { | ||
var args = [] | ||
var i | ||
|
||
for(i=0;i<files.length;i++) | ||
|
||
for(var i = 0; i < files.length; i ++) | ||
args.push({name: files[i].name, value: fs.createReadStream(files[i].path)}) | ||
|
||
this.post('upload', args, callback) | ||
} | ||
|
||
NeoCities.prototype.push = function(localPath, webPath, excludes, callback) { | ||
if (typeof webPath == 'function' || typeof webPath == 'object') { | ||
callback = excludes | ||
excludes = webPath | ||
webPath = '/' | ||
} | ||
if (typeof excludes == 'function') { | ||
callback = excludes | ||
excludes = [] | ||
} | ||
var activePaths = [] | ||
var that = this | ||
excludes = excludes.map(function(dir) {return path.resolve(localPath, dir)}) | ||
|
||
list(localPath) | ||
|
||
function list(dir) { | ||
activePaths.push(dir) | ||
fs.readdir(dir, parseFiles) | ||
|
||
function parseFiles(err, dirContents) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be cleaner and easier for others to understand if it had better logical separation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried to make this better, but I don't have to worry about the readability of my code very often so I have no clue how well I did. |
||
dirContents = dirContents.map(function(file) {return path.resolve(dir, file)}) | ||
var uploadArgs = dirContents.filter(function(file) { | ||
if (excludes.includes(path.relative(localPath, file)) || | ||
excludes.some(function(exclude) { | ||
return (exclude.constructor == RegExp && file.match(exclude)) || | ||
(typeof exclude == 'function' && exclude(file)) | ||
})) { | ||
return false | ||
} | ||
|
||
var fileData = fs.statSync(file) | ||
|
||
if (fileData.isDirectory()) { | ||
list(file) | ||
} | ||
else { | ||
return true | ||
} | ||
}).map(function(file) { | ||
return { | ||
path: file, name: webPath.replace(/[/\\]?$/, '/') + | ||
path.relative(path.resolve(localPath), file) | ||
} | ||
}) | ||
activePaths.splice(activePaths.indexOf(dir), 1) | ||
that.upload(uploadArgs, activePaths.length ? function() {} : callback) | ||
} | ||
} | ||
} | ||
|
||
NeoCities.prototype.pull = function(localPath, webPath, excludes, callback) { | ||
if (typeof webPath == 'function' || typeof webPath == 'object') { | ||
callback = excludes | ||
excludes = webPath | ||
webPath = '/' | ||
} | ||
if (typeof excludes == 'function') { | ||
callback = excludes | ||
excludes = [] | ||
} | ||
|
||
var that = this | ||
|
||
fs.exists(localPath, createIfFailed) | ||
|
||
function createIfFailed(pathExists) { | ||
if (!pathExists) { | ||
fs.mkdir(localPath, {}, startDownload) | ||
} | ||
else { | ||
startDownload() | ||
} | ||
} | ||
|
||
function startDownload() { | ||
that.list(filterDirs) | ||
|
||
function filterDirs(files) { | ||
if (files.result == 'success') { | ||
that.download(files.files.filter(function(file) { | ||
return !file.is_directory && | ||
(!path.relative(webPath, file.path).match(/^\.\.[/\\]/) || webPath == '/') && | ||
!excludes.includes(path.relative(webPath, file.path)) && | ||
!excludes.some(function(exclude) { | ||
return (exclude.prototype == RegExp && file.path.match(exclude)) || | ||
(typeof exclude == 'function' && exclude(file.path)) || | ||
(typeof exclude == 'string' && path.relative(exclude, path.relative(webPath, file.path)).match(/^\.\.[/\\]/)) | ||
}) | ||
}).map(function(file) { | ||
return { | ||
path: localPath.replace(/[/\\]?$/, '/') + path.relative(webPath, file.path), | ||
name: file.path | ||
} | ||
}), callback) | ||
} | ||
} | ||
} | ||
} | ||
|
||
module.exports = NeoCities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think its good practice to include commented code, its better to refer the commented block for discussion. Any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured out what that commented block was intended to do. It was the start of some code that allows files to be downloaded to a variable to return without saving them to the system. The use case would be if the file is needed for immediate use, but not for later. If you think that it would be good for this library to have that feature, I can finish adding it. Otherwise, it can just be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any comment on this feature?