Skip to content

Instantly share code, notes, and snippets.

@mash
Last active August 29, 2015 14:15
Show Gist options
  • Save mash/4466fac3808daf8de8a7 to your computer and use it in GitHub Desktop.
Save mash/4466fac3808daf8de8a7 to your computer and use it in GitHub Desktop.
var l = require("nlogger").logger(module),
config = require('./config'),
ifttt = require("./models/ifttt"),
Client = require("../../irkit-client/"),
irkit = new Client({
apikey : config.apikey
}),
async = require("async")
;
// ifttt servers actually request us like following:
// 2015-02-15 05:28:45.796 deserialized: mt.supportedMethods ([0])
// 2015-02-15 05:28:46.203 deserialized: metaWeblog.getRecentPosts ([0,"o.masakazu@gmail.com","password",1])
// 2015-02-15 05:28:46.415 deserialized: metaWeblog.getRecentPosts ([0,"o.masakazu@gmail.com","password",1])
// 2015-02-15 05:28:46.816 deserialized: mt.supportedMethods ([0])
// 2015-02-15 05:28:47.217 deserialized: metaWeblog.getRecentPosts ([0,"o.masakazu@gmail.com","password",1])
// 2015-02-15 05:28:47.417 deserialized: metaWeblog.getRecentPosts ([0,"o.masakazu@gmail.com","password",1])
ifttt.setDelegate({
getRecentPosts: function(username, password, callback) {
// always success
callback();
},
newPost: function(username, password, post, callback) {
// ignore username and password
var clientkey = post.title;
var signal;
try {
signal = JSON.parse(post.description);
} catch (e) {
l.info("JSON.parse failed: ", e, post.description);
callback(400);
return;
};
var deviceids = post.categories;
async.map(deviceids,
function(deviceid, cb) {
irkit.messages.create(clientkey, signal, deviceid, cb);
},
function(err, results) {
callback(err);
});
}
});
module.exports = ifttt;
var http = require("http"),
Deserializer = require("xmlrpc/lib/deserializer"),
Serializer = require("xmlrpc/lib/serializer"),
l = require("nlogger").logger(module),
HTTPStatus = require("http-status")
;
// thanks to https://github.com/femto113/node-ifttt-webhook
var server = http.createServer(function (request, response) {
var deserializer = new Deserializer();
deserializer.deserializeMethodCall(request, function(error, methodName, params) {
var xml = null,
username,
password,
post;
if (!error) {
l.info("deserialized: "+methodName+" ("+JSON.stringify(params)+")");
switch (methodName) {
case 'mt.supportedMethods': // codex.wordpress.org/XML-RPC_MovableType_API#mt.supportedMethods
// this is used by IFTTT to verify the site is actually a wordpress blog ;-)
server.writeSuccess(response, ['metaWeblog.getRecentPosts', 'metaWeblog.newPost']);
break;
case 'metaWeblog.getRecentPosts': // codex.wordpress.org/XML-RPC_MetaWeblog_API#metaWeblog.getRecentPosts
{
// this is the authentication request from IFTTT
// send a blank blog response
// this also makes sure that the channel is never triggered
params.shift();
username = params.shift();
password = params.shift();
server.delegate.getRecentPosts(username, password, function(err) {
if (err) {
l.info(err);
if (typeof err === "number") {
server.writeError(response, err, HTTPStatus[err]);
}
else {
server.writeError(response, 401, "Unauthorized");
}
}
else {
server.writeSuccess(response, []);
}
});
}
break;
case 'metaWeblog.newPost': // codex.wordpress.org/XML-RPC_WordPress_API/Posts#wp.newPost
{
// This is the actual webhook. Parameters are provided via fields in IFTTT's GUI. By convention
// we put the target URL in the Tags field (passed as mt_keywords). e.g. params
// [0, "user", "password", {"title":"...","description":"...","categories":[...],mt_keywords":[webhook url]}]
params.shift(); // blogid?
username = params.shift();
password = params.shift();
post = params.shift();
server.delegate.newPost(username, password, post, function(err) {
if (err) {
l.info(err);
if (typeof err === "number") {
server.writeError(response, err, HTTPStatus[err]);
}
else {
server.writeError(response, 500, "Internal Server Error");
}
}
else {
// a "postid", presumably ignored by IFTTT
server.writeSuccess(response, Date.now().toString(32));
}
});
}
break;
default:
server.writeError(response, 400, "Invalid Request. Method Not Found");
break;
}
}
});
});
server.writeSuccess = function (response, object) {
var xml = Serializer.serializeMethodResponse(object);
this.writeXML(response, xml);
};
server.writeError = function (response, faultCode, faultString) {
var xml = Serializer.serializeFault({
faultCode: faultCode,
faultString: faultString
});
this.writeXML(response, xml);
};
server.writeXML = function (response, xml) {
response.writeHead(200, {
'Content-Type': 'text/xml', 'Content-Length': xml.length
});
response.end(xml);
};
server.setDelegate = function (delegate) {
if (typeof delegate.getRecentPosts !== "function") {
throw("delegate.getRecentPosts function required");
}
if (typeof delegate.newPost !== "function") {
throw("delegate.newPost function required");
}
server.delegate = delegate;
};
module.exports = server;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment