Skip to content

Instantly share code, notes, and snippets.

@grncdr
Last active August 29, 2015 14:09
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 grncdr/e44b465f6e76c0bace8e to your computer and use it in GitHub Desktop.
Save grncdr/e44b465f6e76c0bace8e to your computer and use it in GitHub Desktop.
Turn Contentful webhooks into Gengo jobs
var Bluebird = require('bluebird');
var createContentfulClient = require('contentful-management').createClient;
var createGengoClient = require('gengo');
var collectStream = Bluebird.promisify(require('collect-stream'));
var keys = Object.keys;
module.exports = checkForUntranslatedFields;
module.exports.schema = {
cmaAccessToken: {
type: 'string',
minLength: 32
},
gengoPublicKey: {
type: 'string',
minLength: 4
},
gengoPrivateKey: {
type: 'string',
minLength: 4
},
gengoSandbox: 'boolean',
gengoCallback: {
type: 'string',
default: 'http://hook.io/grncdr/gengo2contentful'
},
spaceIdOverride: 'string',
entryIdOverride: 'string'
};
function checkForUntranslatedFields (hook) {
var contentful = createContentfulClient({ accessToken: hook.params.cmaAccessToken });
var gengoJobsAPI = Bluebird.promisifyAll(
createGengoClient(hook.params.gengoPublicKey,
hook.params.gengoPrivateKey,
hook.params.gengoSandbox).jobs
);
getEntry(hook, contentful).then(function (entry) {
if (entry) {
return getGengoJobs(entry).then(gengoJobsAPI.createAsync);
} else {
return { message: 'ignored' };
}
}).then(function (result) {
hook.res.setHeader({ 'content-type': 'application/json' });
hook.res.end(JSON.stringify(result));
}).catch(function (err) {
hook.debug(err.stack);
hook.res.statusCode = 500;
hook.res.end(JSON.stringify({ message: err.message }));
}).done();
function getGengoJobs (entry) {
var spacePath = '/spaces/' + entry.sys.space.sys.id;
var localesPath = spacePath + '/locales';
var cTypePath = spacePath + '/content_types/' + entry.sys.contentType.sys.id + '/published';
return Bluebird.join(
contentful.request(localesPath).get('items'),
contentful.request(cTypePath)
).spread(function (locales, contentType) {
var callbackUrl = hook.params.gengoCallback;
callbackUrl += (callbackUrl.indexOf('?') < 0) ? '?' : '&';
callbackUrl += 'cmaAccessToken=' + hook.params.cmaAccessToken;
return createGengoPayload(locales, contentType, entry, callbackUrl);
});
}
}
function getEntry (hook, contentful) {
if (hook.params.spaceIdOverride && hook.params.entryIdOverride) {
hook.debug('get entry from query params: ' + entryPath);
return contentful.request('/' + [
'spaces',
hook.params.spaceIdOverride,
'entries',
hook.params.entryIdOverride,
'published'
].join('/'));
}
if (hook.req.headers['x-contentful-topic'] === "ContentManagement.Entry.publish") {
hook.debug('get entry from request body');
return collectStream(hook.req).then(JSON.parse);
}
}
function createGengoPayload (locales, contentType, entry, callbackUrl) {
var fieldsById = lookup(contentType.fields, 'id');
var fieldOrder = contentTypes.fields.map(function (f) { return f.id; });
var defaultLocale = locales.filter(isDefault).pop();
return keys(entry.fields).reduce(function (payload, fieldId) {
if (!fieldsById[fieldId].localized) {
return payload;
}
var field = entry.fields[fieldId];
var source = field[defaultLocale.code];
var fieldPostition = String(fieldOrder.indexOf(fieldId));
if (!source) {
return payload;
}
locales.filter(function (l) {
return l.contentManagementApi && !l.default && !field[l.code];
}).forEach(function (targetLocale) {
var jobId = [
entry.sys.space.sys.id,
entry.sys.id,
fieldId,
targetLocale.code
].join('!');
payload.as_group = true; // payload must be empty if there are no translations
payload[jobId] = {
custom_data: JSON.stringify({
type: 'Field',
space: entry.sys.space.sys.id,
entry: entry.sys.id,
id: fieldId,
}),
src_lc: defaultLocale.code,
tgt_lc: locale.code,
body_src: source,
position: fieldPosition,
callback_url: callbackUrl,
};
});
return payload;
});
}
function lookup (objects, prop) {
return objects.reduce(function (result, object) {
result[object[prop]] = object;
return result;
}, {});
}
function isDefault (locale) {
return locale.default;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment