Skip to content

Commit

Permalink
Added webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
gomfunkel committed Jan 17, 2011
1 parent 1cc1a65 commit 3ccf1a5
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 7 deletions.
36 changes: 30 additions & 6 deletions README.md
@@ -1,11 +1,17 @@
node-mailchimp
==============

A node.js wrapper for the MailChimp API.
A node.js wrapper for the MailChimp API.

All functions of the MailChimp API (Version 1.3) and the MailChimp Export API
(Version 1.0) as described on [http://www.mailchimp.com/api/](http://www.mailchimp.com/api/)
are exposed to your node.js application.
node-mailchimp exposes the following features of the MailChimp API to your
node.js application:

* MailChimp API (Version 1.3)
* MailChimp Export API (Version 1.0)
* MailChimp Webhooks

Further information on the MailChimp API and its features is available at
[http://www.mailchimp.com/api/](http://www.mailchimp.com/api/)

Installation
------------
Expand All @@ -23,7 +29,7 @@ Usage
-----

More or less proper documentation can be found in the source code. Available
API functions and their documentation can be found on
API functions and their documentation can be found at
[http://www.mailchimp.com/api/](http://www.mailchimp.com/api/). You can also
find further information on how to obtain an API key and much more on the
MailChimp API pages.
Expand Down Expand Up @@ -72,12 +78,30 @@ MailChimp Export API:
else
console.log(data); // Do something with your data!
});

MailChimp Webhooks:

var MailChimpWebhook = require('mailchimp').MailChimpWebhook;

var webhook = new MailChimpWebhook();

webhook.on('error', function (message) {
console.log('Error: '+message);
});

webhook.on('subscribe', function (data, meta) {
console.log(data.email+' subscribed to your newsletter!'); // Do something with your data!
});

webhook.on('unsubscribe', function (data, meta) {
console.log(data.email+' unsubscribed from your newsletter!'); // Do something with your data!
});

ToDo / Ideas
------------

* Implement API versions 1.1 and 1.2
* Implement WebHooks
* Webhooks over HTTPS

License
-------
Expand Down
118 changes: 118 additions & 0 deletions lib/mailchimp/MailChimpWebhook.js
@@ -0,0 +1,118 @@
var http = require('http'),
util = require('util'),
url = require('url'),
querystring = require('querystring'),
EventEmitter = require('events').EventEmitter;

/**
* A server that listens for POST requests from MailChimp which are issued on
* special events as specified on their Webhook page. Please refer to that page
* on how to set everything up.
*
* @see http://www.mailchimp.com/api/webhooks/
*
* If the server receives a valid request from MailChimp the received data is
* wrapped in a nice object and an event is emitted which you can listen for
* in your application and then take further action.
*
* Available options are:
* - port Port the server is going to listen on. Defaults to 8100.
* - secret Secret key as suggested on the Webhook page which is then simply
* added as a pathname to the Webhook URL in your MailChimp account
* and checked for here. Nothing too fancy but a small enhancement to
* security. Leave empty (default setting) if you don't want to use a
* secret key. Example: If you set the secret to 'ChimpSecret' you
* would enter the Webhook URL http://www.yourdomain.com/ChimpSecret
* in the MailChimp Webhook settings.
*
* @param options Configuration options
* @return Instance of {@link MailChimpWebhook}
*/
function MailChimpWebhook (options) {

var self = this;

if (!options)
var options = {};

EventEmitter.call(this);

this.httpPort = options.port || 8100;
this.secret = options.secret || '';

this.allowedTypes = [
'subscribe',
'unsubscribe',
'profile',
'upemail',
'cleaned'
];

http.createServer(function (request, response) {

var requestBody = '';
var requestUrl = url.parse(request.url);

if (self.secret != '' && requestUrl.pathname !== '/'+self.secret) {
self.emit('error', 'Received a request with an invalid secret key.');
response.writeHead(500, { 'Content-Type' : 'text/plain' });
response.end();
return;
}

// Say "hi" to the webhook validator, the only request not sent via POST
if (request.headers['user-agent'] === 'MailChimp.com WebHook Validator') {
response.writeHead(200, { 'Content-Type' : 'text/plain' });
response.end();
return;
}

if (request.method != 'POST') {
self.emit('error', 'Received something other than a POST request.');
response.writeHead(500, { 'Content-Type' : 'text/plain' });
response.end();
return;
}

request.on('data', function (chunk) {
requestBody += chunk;
});

request.on('end', function () {

var payload = querystring.parse(requestBody);
var meta = { type : payload.type, fired_at : payload.fired_at };
var data = payload.data;

if (meta.type && self.allowedTypes.has(meta.type)) {
self.emit(payload.type, data, meta);
response.writeHead(200, { 'Content-Type' : 'text/plain' });
response.end();
} else {
self.emit('error', 'Received a request with an unknown type of payload.');
response.writeHead(500, { 'Content-Type' : 'text/plain' });
response.end();
}

});

}).listen(this.httpPort);

}

util.inherits(MailChimpWebhook, EventEmitter);
module.exports = MailChimpWebhook;

/**
* Extends the Array object with a method that checks if the array has an
* element with the value specified by the parameter needle.
*
* @param needle Element to search the array for
* @return true if needle was found, otherwise false
*/
Array.prototype.has = function (needle) {
for (var i = 0; i < this.length; i++) {
if (this[i] === needle) return true;
}
return false
}
3 changes: 2 additions & 1 deletion lib/mailchimp/index.js
@@ -1,2 +1,3 @@
exports.MailChimpAPI = require('./MailChimpAPI.js');
exports.MailChimpExportAPI = require('./MailChimpExportAPI.js');
exports.MailChimpExportAPI = require('./MailChimpExportAPI.js');
exports.MailChimpWebhook = require('./MailChimpWebhook.js');

0 comments on commit 3ccf1a5

Please sign in to comment.