Started adding support for RSS campaigns

This commit is contained in:
Andris Reinman 2016-05-03 00:04:43 +03:00
parent b0d36be790
commit 09103ac58b
8 changed files with 308 additions and 6 deletions

56
lib/feed.js Normal file
View file

@ -0,0 +1,56 @@
'use strict';
let FeedParser = require('feedparser');
let request = require('request');
module.exports.fetch = (url, callback) => {
let req = request(url);
let feedparser = new FeedParser();
let returned = false;
req.setHeader('user-agent', 'Mailtrain');
req.setHeader('accept', 'text/html,application/xhtml+xml');
req.on('error', err => {
if (returned) {
return;
}
returned = true;
callback(err);
});
req.on('response', res => {
if (returned) {
return;
}
if (res.statusCode !== 200) {
return req.emit('error', new Error('Bad status code'));
}
req.pipe(feedparser);
});
feedparser.on('error', err => {
if (returned) {
return;
}
returned = true;
callback(err);
});
feedparser.on('readable', () => {
// This is where the action is!
let meta = feedparser.meta;
let item;
while ((item = feedparser.read())) {
//console.log(require('util').inspect(item, false, 22));
console.log(item.title);
console.log(item.description || item.summary);
console.log('--------');
}
});
};
module.exports.fetch('https://andris9.wordpress.com/feed/', console.log);

View file

@ -200,6 +200,15 @@ module.exports.create = (campaign, callback) => {
campaign.segment = 0; campaign.segment = 0;
} }
switch ((campaign.type || '').toString().trim().toLowerCase()) {
case 'rss':
campaign.type = 2;
break;
case 'normal':
default:
campaign.type = 1;
}
campaign.template = Number(campaign.template) || 0; campaign.template = Number(campaign.template) || 0;
if (!name) { if (!name) {
@ -261,7 +270,9 @@ module.exports.create = (campaign, callback) => {
}); });
}; };
if (campaign.template) { if (campaign.type === 2) {
create();
} else if (campaign.template) {
templates.get(campaign.template, (err, template) => { templates.get(campaign.template, (err, template) => {
if (err) { if (err) {
return callback(err); return callback(err);

View file

@ -42,6 +42,7 @@
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"express": "^4.13.4", "express": "^4.13.4",
"express-session": "^1.13.0", "express-session": "^1.13.0",
"feedparser": "^1.1.4",
"geoip-ultralight": "^0.1.3", "geoip-ultralight": "^0.1.3",
"handlebars": "^4.0.5", "handlebars": "^4.0.5",
"hbs": "^4.0.0", "hbs": "^4.0.0",

View file

@ -83,7 +83,15 @@ router.get('/create', passport.csrfProtection, (req, res) => {
data.address = data.address || configItems.defaultAddress; data.address = data.address || configItems.defaultAddress;
data.subject = data.subject || configItems.defaultSubject; data.subject = data.subject || configItems.defaultSubject;
res.render('campaigns/create', data); let view;
switch (req.query.type) {
case 'rss':
view = 'campaigns/create-rss';
break;
default:
view = 'campaigns/create';
}
res.render(view, data);
}); });
}); });
}); });
@ -96,7 +104,7 @@ router.post('/create', passport.parseForm, passport.csrfProtection, (req, res) =
return res.redirect('/campaigns/create?' + tools.queryParams(req.body)); return res.redirect('/campaigns/create?' + tools.queryParams(req.body));
} }
req.flash('success', 'Campaign “' + req.body.name + '” created'); req.flash('success', 'Campaign “' + req.body.name + '” created');
res.redirect('/campaigns/edit/' + id + '?tab=template'); res.redirect('/campaigns/view/' + id);
}); });
}); });
@ -139,7 +147,17 @@ router.get('/edit/:id', passport.csrfProtection, (req, res, next) => {
campaign.showGeneral = req.query.tab === 'general' || !req.query.tab; campaign.showGeneral = req.query.tab === 'general' || !req.query.tab;
campaign.showTemplate = req.query.tab === 'template'; campaign.showTemplate = req.query.tab === 'template';
res.render('campaigns/edit', campaign); let view;
switch (campaign.type) {
case 2: //rss
view = 'campaigns/edit-rss';
break;
case 1:
default:
view = 'campaigns/edit';
}
res.render(view, campaign);
}); });
}); });
}); });
@ -209,7 +227,7 @@ router.post('/ajax', (req, res) => {
recordsFiltered: filteredTotal, recordsFiltered: filteredTotal,
data: data.map((row, i) => [ data: data.map((row, i) => [
(Number(req.body.start) || 0) + 1 + i, (Number(req.body.start) || 0) + 1 + i,
'<span class="glyphicon glyphicon-inbox" aria-hidden="true"></span> <a href="/campaigns/view/'+row.id+'">' + htmlescape(row.name || '') + '</a>', '<span class="glyphicon glyphicon-inbox" aria-hidden="true"></span> <a href="/campaigns/view/' + row.id + '">' + htmlescape(row.name || '') + '</a>',
htmlescape(striptags(row.description) || ''), htmlescape(striptags(row.description) || ''),
getStatusText(row), getStatusText(row),
'<span class="datestring" data-date="' + row.created.toISOString() + '" title="' + row.created.toISOString() + '">' + row.created.toISOString() + '</span>' '<span class="datestring" data-date="' + row.created.toISOString() + '" title="' + row.created.toISOString() + '">' + row.created.toISOString() + '</span>'

View file

@ -4,7 +4,15 @@
</ol> </ol>
<div class="pull-right"> <div class="pull-right">
<a class="btn btn-primary" href="/campaigns/create" role="button"><i class="glyphicon glyphicon-plus"></i> Create Campaign</a> <div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Create Campaign <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="/campaigns/create"><i class="glyphicon glyphicon-plus"></i> Normal Campaign</a></li>
<li><a href="/campaigns/create?type=rss"><i class="glyphicon glyphicon-signal"></i> RSS Campaign</a></li>
</ul>
</div>
</div> </div>
<h2>Campaigns</h2> <h2>Campaigns</h2>

View file

@ -0,0 +1,96 @@
<ol class="breadcrumb">
<li><a href="/">Home</a></li>
<li><a href="/campaigns">Campaigns</a></li>
<li class="active">Create RSS Campaign</li>
</ol>
<h2>Create RSS Campaign</h2>
<hr>
<div class="panel panel-default">
<div class="panel-body">
RSS campaign sets up a tracker against selected RSS feed address. Whenever a new entry is found from this feed it is sent to selected list as an email message.
</div>
</div>
<form class="form-horizontal" method="post" action="/campaigns/create">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="type" value="rss">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control input-lg" name="name" id="name" value="{{name}}" placeholder="Campaign Name" autofocus required>
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3" name="description" id="description">{{description}}</textarea>
<span class="help-block">HTML is allowed</span>
</div>
</div>
<div class="form-group">
<label for="list" class="col-sm-2 control-label">List</label>
<div class="col-sm-10">
<select class="form-control" id="list" name="list" required>
<option value=""> Select </option>
{{#each listItems}}
<option value="{{id}}" {{#if selected}} selected {{/if}}>
{{name}} <span class="text-muted"> &mdash; {{subscribers}} subscribers</span>
</option>
{{#if segments}}
<optgroup label="{{name}} segments">
{{#each segments}}
<option value="{{../id}}:{{id}}" {{#if selected}} selected {{/if}}>
{{../name}}: {{name}}
</option>
{{/each}}
</optgroup>
{{/if}}
{{/each}}
</select>
</div>
</div>
<div class="form-group">
<label for="template" class="col-sm-2 control-label">RSS Feed Url</label>
<div class="col-sm-10">
<input type="url" class="form-control" name="source-url" id="source-url" value="{{sourceUrl}}" placeholder="http://example.com/rss.php">
<span class="help-block">New entries from this RSS URL are sent out to list subscribers as email messages</span>
</div>
</div>
<hr />
<div class="form-group">
<label for="from" class="col-sm-2 control-label">Email "from name"</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="from" id="from" value="{{from}}" placeholder="This is the name your emails will come from" required>
</div>
</div>
<div class="form-group">
<label for="address" class="col-sm-2 control-label">Email "from" address</label>
<div class="col-sm-10">
<input type="email" class="form-control" name="address" id="address" value="{{address}}" placeholder="This is the address people will send replies to" required>
</div>
</div>
<div class="form-group">
<label for="subject" class="col-sm-2 control-label">Email "subject line"</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="subject" id="subject" value="{{subject}}" placeholder="Keep it relevant and non-spammy" required>
</div>
</div>
<hr />
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-plus"></i> Create RSS Campaign</button>
</div>
</div>
</form>

View file

@ -10,6 +10,7 @@
<form class="form-horizontal" method="post" action="/campaigns/create"> <form class="form-horizontal" method="post" action="/campaigns/create">
<input type="hidden" name="_csrf" value="{{csrfToken}}"> <input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="type" value="normal">
<div class="form-group"> <div class="form-group">
<label for="name" class="col-sm-2 control-label">Name</label> <label for="name" class="col-sm-2 control-label">Name</label>

View file

@ -0,0 +1,111 @@
<ol class="breadcrumb">
<li><a href="/">Home</a></li>
<li><a href="/campaigns">Campaigns</a></li>
<li><a href="/campaigns/view/{{id}}">{{name}}</a></li>
<li class="active">Edit RSS Campaign</li>
</ol>
<h2>Edit RSS Campaign <a class="btn btn-default btn-xs" href="/campaigns/view/{{id}}" role="button"><span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span> View campaign</a></h2>
<hr>
<div class="panel panel-default">
<div class="panel-body">
RSS campaign sets up a tracker against selected RSS feed address. Whenever a new entry is found from this feed it is sent to selected list as an email message.
</div>
</div>
<form method="post" class="delete-form" id="campaigns-delete" action="/campaigns/delete">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="id" value="{{id}}" />
</form>
<form class="form-horizontal" method="post" action="/campaigns/edit">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="id" value="{{id}}" />
<fieldset>
<legend>
General Settings
</legend>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control input-lg" name="name" id="name" value="{{name}}" placeholder="Campaign Name" autofocus required>
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3" name="description" id="description">{{description}}</textarea>
<span class="help-block">HTML is allowed</span>
</div>
</div>
<div class="form-group">
<label for="list" class="col-sm-2 control-label">List</label>
<div class="col-sm-10">
<select class="form-control" id="list" name="list" required>
<option value=""> Select </option>
{{#each listItems}}
<option value="{{id}}" {{#if selected}} selected {{/if}}>
{{name}} <span class="text-muted"> &mdash; {{subscribers}} subscribers</span>
</option>
{{#if segments}}
<optgroup label="{{name}} segments">
{{#each segments}}
<option value="{{../id}}:{{id}}" {{#if selected}} selected {{/if}}>
{{../name}}: {{name}}
</option>
{{/each}}
</optgroup>
{{/if}}
{{/each}}
</select>
</div>
</div>
<div class="form-group">
<label for="template" class="col-sm-2 control-label">RSS Feed Url</label>
<div class="col-sm-10">
<input type="url" class="form-control" name="source-url" id="source-url" value="{{sourceUrl}}" placeholder="http://example.com/rss.php">
<span class="help-block">New entries from this RSS URL are sent out to list subscribers as email messages</span>
</div>
</div>
<hr />
<div class="form-group">
<label for="from" class="col-sm-2 control-label">Email "from name"</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="from" id="from" value="{{from}}" placeholder="This is the name your emails will come from" required>
</div>
</div>
<div class="form-group">
<label for="address" class="col-sm-2 control-label">Email "from" address</label>
<div class="col-sm-10">
<input type="email" class="form-control" name="address" id="address" value="{{address}}" placeholder="This is the address people will send replies to" required>
</div>
</div>
<div class="form-group">
<label for="subject" class="col-sm-2 control-label">Email "subject line"</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="subject" id="subject" value="{{subject}}" placeholder="Keep it relevant and non-spammy" required>
</div>
</div>
</fieldset>
<hr />
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="pull-right">
<button type="submit" form="campaigns-delete" class="btn btn-danger"><i class="glyphicon glyphicon-remove"></i> Delete Campaign</button>
</div>
<button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-ok"></i> Update</button>
</div>
</div>
</form>