Skip to content

Instantly share code, notes, and snippets.

@ryokdy
Last active August 20, 2019 01:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryokdy/cad4af0bb8cbc80c9661 to your computer and use it in GitHub Desktop.
Save ryokdy/cad4af0bb8cbc80c9661 to your computer and use it in GitHub Desktop.
kintone-lambda
var im = require('imagemagick');
var fs = require('fs');
var https = require('https');
var url = require('url');
var querystring = require('querystring');
var path = require('path');
var async = require('async');
const kintoneHost = '<SUBDOMAIN>.cybozu.com';
const appId = <APP_ID>;
const apiToken = '<YOUR_API_KEY>';
var getOptions = function(path, method) {
return {
hostname: kintoneHost,
port: 443,
path: path,
method: method,
secureProtocol: 'TLSv1_method',
headers: {
'X-Cybozu-API-Token': apiToken
}
};
};
var postProcessResource = function(resource, fn) {
var ret = null;
if (resource) {
if (fn) {
ret = fn(resource);
}
try {
fs.unlinkSync(resource);
} catch (err) {
// Ignore
}
}
return ret;
};
var getRecords = function(callback) {
console.log('start getRecords');
var params = {
"app": appId,
"query": 'processed not in ("processed")'
};
var query = querystring.stringify(params);
var options = getOptions('/k/v1/records.json?' + query, 'GET');
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
if (res.statusCode === 200) {
callback(null, JSON.parse(chunk).records);
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(e.message);
});
req.end();
};
var putRecord = function(id, fileKey, callback) {
console.log('start putRecord');
var params = {
"app": appId,
"id": id,
"record": {
pdf: {
value: [{
fileKey: fileKey
}]
},
processed: {
value: ['processed']
}
}
};
var json = JSON.stringify(params);
var options = getOptions('/k/v1/record.json', 'PUT');
options.headers['Content-Type'] = 'application/json';
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
if (res.statusCode === 200) {
callback(null, JSON.parse(chunk));
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(e.message);
});
req.write(json);
req.end();
};
var getFile = function(file, callback) {
console.log('start getFile');
var options = getOptions('/k/v1/file.json?fileKey=' + file.fileKey, 'GET');
var fileName = '/tmp/' + file.fileKey + path.extname(file.name);
postProcessResource(fileName);
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function(chunk) {
if (res.statusCode === 200) {
console.log(chunk.length + ' chunked');
fs.appendFileSync(fileName, chunk, 'binary');
}
});
res.on('end', function() {
if (res.statusCode === 200) {
callback(null, fileName);
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(e.message);
});
req.end();
};
var postFile = function(outputFile, callback) {
console.log('start postFile');
var options = getOptions('/k/v1/file.json', 'POST');
var boundary = 'afdasfd77a6s234ak3hs7';
options.headers['Content-Type'] = 'multipart/form-data; boundary="' + boundary + '"';
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
if (res.statusCode === 200) {
callback(null, JSON.parse(chunk));
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(e.message);
});
req.write(
'--' + boundary + '\r\n' + 'Content-Type: application/octet-stream\r\n' + 'Content-Disposition: form-data; name="file"; filename="images.pdf"\r\n' + 'Content-Transfer-Encoding: binary\r\n\r\n'
);
stream = fs.createReadStream(outputFile, {
bufferSize: 4 * 1024
});
stream.on('data', function(chunk) {
req.write(chunk);
});
stream.on('end', function() {
req.end('\r\n--' + boundary + '--');
});
};
var convert = function(inputFiles, callback) {
var args = [];
console.log('start converting');
for (var i = 0; i < inputFiles.length; i++) {
if (args.length > 0) {
args.push('-adjoin');
}
args.push(inputFiles[i]);
}
var outputFile = '/tmp/' + (new Date()).getTime() + '-images.pdf';
args.push(outputFile);
console.log(args);
im.convert(args, function(err, output) {
if (err) {
console.log('Convert operation failed:', err);
callback(err);
} else {
console.log('Convert operation completed successfully');
inputFiles.forEach(function(inputFile) {
postProcessResource(inputFile);
});
callback(null, outputFile);
}
});
};
var handleRecord = function(record, callback) {
var handlers = [];
for (var i = 0; i < record.images.value.length; i++) {
var ext = path.extname(record.images.value[i].name).toLowerCase();
if (ext == '.jpg' || ext == '.png' || ext == '.jpeg' || ext == '.gif') {
handlers.push(getFile.bind(this, record.images.value[i]));
}
}
if (handlers.length === 0) {
callback(null, true);
return;
}
async.series(handlers, function(err, files) {
if (err || !files) {
callback(err);
return;
}
convert(files, function(err, outputFile) {
if (err) {
callback(err);
return;
}
postFile(outputFile, function(err, file) {
if (err || !file) {
callback(err);
return;
}
putRecord(record.$id.value, file.fileKey, function(err, res) {
if (err) {
callback(err);
return;
}
callback(null, true);
});
});
});
});
};
exports.handler = function(event, context) {
var operation = event.operation;
getRecords(function(err, records) {
if (err) {
context.fail(err);
} else {
var recs = records.map(function(r) {
return handleRecord.bind(this, r);
});
async.waterfall(recs, function(err) {
console.log('done');
if (err) {
context.fail(err);
} else {
context.succeed(records.length);
}
});
}
});
return;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment