2016-05-03 11:04:46 +00:00
'use strict' ;
let log = require ( 'npmlog' ) ;
let db = require ( '../lib/db' ) ;
let tools = require ( '../lib/tools' ) ;
let feed = require ( '../lib/feed' ) ;
let campaigns = require ( '../lib/models/campaigns' ) ;
function feedLoop ( ) {
db . getConnection ( ( err , connection ) => {
2017-02-01 05:05:01 +00:00
const feed _timeout = 15 * 1000 ;
2016-05-03 11:04:46 +00:00
if ( err ) {
log . error ( 'Feed' , err . stack ) ;
2017-02-01 05:05:01 +00:00
return setTimeout ( feedLoop , feed _timeout ) ;
2016-05-03 11:04:46 +00:00
}
2016-05-04 16:11:41 +00:00
let query = 'SELECT `id`, `source_url`, `from`, `address`, `subject`, `list`, `segment`, `html` FROM `campaigns` WHERE `type`=2 AND `status`=6 AND (`last_check` IS NULL OR `last_check`< NOW() - INTERVAL 10 MINUTE) LIMIT 1' ;
2016-05-03 11:04:46 +00:00
connection . query ( query , ( err , rows ) => {
2016-05-04 08:27:46 +00:00
connection . release ( ) ;
2016-05-03 11:04:46 +00:00
if ( err ) {
log . error ( 'Feed' , err ) ;
2017-02-01 05:05:01 +00:00
return setTimeout ( feedLoop , feed _timeout ) ;
2016-05-03 11:04:46 +00:00
}
if ( ! rows || ! rows . length ) {
2017-02-01 05:05:01 +00:00
return setTimeout ( feedLoop , feed _timeout ) ;
2016-05-03 11:04:46 +00:00
}
let parent = tools . convertKeys ( rows [ 0 ] ) ;
2016-05-04 08:27:46 +00:00
updateRssInfo ( parent . id , true , false , ( ) => {
2017-02-01 05:05:01 +00:00
const rss _timeout = 1 * 1000 ;
2016-05-03 11:04:46 +00:00
log . verbose ( 'Feed' , 'Checking feed %s (%s)' , parent . sourceUrl , parent . id ) ;
feed . fetch ( parent . sourceUrl , ( err , entries ) => {
if ( err ) {
log . error ( 'Feed' , err ) ;
2016-05-04 08:27:46 +00:00
return updateRssInfo ( parent . id , false , 'Feed error: ' + err . message , ( ) => {
2017-02-01 05:05:01 +00:00
setTimeout ( feedLoop , rss _timeout ) ;
2016-05-04 08:27:46 +00:00
} ) ;
2016-05-03 11:04:46 +00:00
}
checkEntries ( parent , entries , ( err , result ) => {
2016-05-04 08:27:46 +00:00
let message ;
2016-05-03 11:04:46 +00:00
if ( err ) {
log . error ( 'Feed' , err ) ;
2016-05-04 08:27:46 +00:00
message = 'Feed error: ' + err . message ;
} else if ( result ) {
2016-05-03 11:04:46 +00:00
log . verbose ( 'Feed' , 'Added %s new campaigns for %s' , result , parent . id ) ;
2016-05-04 13:54:09 +00:00
message = 'Found ' + result + ' new campaign messages from feed' ;
2016-05-04 08:27:46 +00:00
} else {
message = 'Found nothing new from the feed' ;
2016-05-03 11:04:46 +00:00
}
2016-05-04 08:27:46 +00:00
return updateRssInfo ( parent . id , false , message , ( ) => {
2017-02-01 05:05:01 +00:00
setTimeout ( feedLoop , rss _timeout ) ;
2016-05-04 08:27:46 +00:00
} ) ;
2016-05-03 11:04:46 +00:00
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
2016-05-04 08:27:46 +00:00
function updateRssInfo ( id , updateCheck , status , callback ) {
db . getConnection ( ( err , connection ) => {
if ( err ) {
log . error ( 'Feed' , err . stack ) ;
return callback ( err ) ;
}
let query ;
let values ;
if ( updateCheck ) {
if ( status ) {
query = 'UPDATE `campaigns` SET `last_check`=NOW(), `check_status`=? WHERE id=? LIMIT 1' ;
values = [ status , id ] ;
} else {
query = 'UPDATE `campaigns` SET `last_check`=NOW() WHERE id=? LIMIT 1' ;
values = [ id ] ;
}
} else {
query = 'UPDATE `campaigns` SET `check_status`=? WHERE id=? LIMIT 1' ;
values = [ status , id ] ;
}
connection . query ( query , values , ( err , result ) => {
connection . release ( ) ;
if ( err ) {
log . error ( 'Feed' , err ) ;
return callback ( err ) ;
}
return callback ( null , result . affectedRows ) ;
} ) ;
} ) ;
}
2016-05-03 11:04:46 +00:00
function checkEntries ( parent , entries , callback ) {
let pos = 0 ;
let added = 0 ;
let checkNextEntry = ( ) => {
if ( pos >= entries . length ) {
return callback ( null , added ) ;
}
let entry = entries [ pos ++ ] ;
if ( ! entry || ! entry . guid ) {
return checkNextEntry ( ) ;
}
db . getConnection ( ( err , connection ) => {
if ( err ) {
log . error ( 'Feed' , err . stack ) ;
return setTimeout ( checkNextEntry , 15 * 1000 ) ;
}
// parent+guid is unique, so the query should fail for existing entries
let query = 'INSERT IGNORE INTO `rss` (`parent`, `guid`, `pubdate`) VALUES (?,?,?)' ;
connection . query ( query , [ parent . id , entry . guid , entry . date ] , ( err , result ) => {
connection . release ( ) ;
if ( err ) {
log . error ( 'Feed' , err ) ;
return setTimeout ( checkNextEntry , 15 * 1000 ) ;
}
if ( ! result . insertId ) {
return setImmediate ( checkNextEntry ) ;
}
let entryId = result . insertId ;
2016-05-04 16:11:41 +00:00
let html = ( parent . html || '' ) . toString ( ) . trim ( ) ;
if ( /\[RSS_ENTRY\]/i . test ( html ) ) {
html = html . replace ( /\[RSS_ENTRY\]/ , entry . content ) ;
} else {
html = entry . content + html ;
}
2016-05-03 11:04:46 +00:00
let campaign = {
type : 'entry' ,
name : entry . title || 'RSS entry ' + ( entry . guid . substr ( 0 , 67 ) ) ,
from : parent . from ,
address : parent . address ,
subject : entry . title || parent . subject ,
2016-05-05 14:02:22 +00:00
list : parent . segment ? parent . list + ':' + parent . segment : parent . list ,
2016-05-04 16:11:41 +00:00
html
2016-05-03 11:04:46 +00:00
} ;
campaigns . create ( campaign , {
parent : parent . id
} , ( err , campaignId ) => {
if ( err ) {
log . error ( 'Campaign' , err ) ;
return setTimeout ( checkNextEntry , 15 * 1000 ) ;
}
added ++ ;
db . getConnection ( ( err , connection ) => {
if ( err ) {
log . error ( 'Feed' , err . stack ) ;
return setTimeout ( checkNextEntry , 15 * 1000 ) ;
}
let query = 'UPDATE `rss` SET `campaign`=? WHERE id=? LIMIT 1' ;
connection . query ( query , [ campaignId , entryId ] , err => {
connection . release ( ) ;
if ( err ) {
log . error ( 'Feed' , err . stack ) ;
return setTimeout ( checkNextEntry , 15 * 1000 ) ;
}
return setImmediate ( checkNextEntry ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ;
checkNextEntry ( ) ;
}
module . exports = callback => {
feedLoop ( ) ;
setImmediate ( callback ) ;
} ;