dbmedialab/reader-critics

View on GitHub
src/app/queue/handlers/onPollArticleUpdate/onPollArticleUpdate.ts

Summary

Maintainability
A
0 mins
Test Coverage
//
// LESERKRITIKK v2 (aka Reader Critics)
// Copyright (C) 2017 DB Medialab/Aller Media AS, Oslo, Norway
// https://github.com/dbmedialab/reader-critics/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//

import * as Promise from 'bluebird';

import * as app from 'app/util/applib';

import {
    DoneCallback,
    Job,
} from 'kue';

import {
    Article,
    Website
} from 'base';

import {
    articleService,
    websiteService,
} from 'app/services';

import { ArticleURL } from 'base/ArticleURL';
import { ObjectID } from 'app/db';
import { PollUpdateData } from 'app/services/article/ArticleService';
import { notifyEnduserAboutUpdate } from './notifyEnduserAboutUpdate';

const log = app.createLog();

export function onPollArticleUpdate(job : Job, done : DoneCallback) : void {
    pollArticle(job.data as PollUpdateData)
    .then(() => {
        done();
        return null;
    })
    .catch(error => {
        if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
            log('Network problem while trying to fetch article (%s)', error.code);
        }
        else {
            app.yell(error);
        }
        return done(error);
    });
}

function pollArticle(pollData : PollUpdateData) : Promise <void> {
    let articleURL : ArticleURL;
    let website : Website;

    // 1 - Article URL and Website identification
    return Promise.resolve(ArticleURL.from(pollData.url)).then((a : ArticleURL) => {
        articleURL = a;
        log('Polling', pollData.url.toString());
        return websiteService.identify(articleURL);
    })
    // 2 - Download the most recent version of the article
    .then((w : Website) => {
        if (w === null) {
            return Promise.reject(new Error('Polling article but could not identify its website'));
        }

        website = w;
        return articleService.fetch(website, articleURL);
    })
    // 3 - Compare the polled data to the existing article
    .then((newArticle : Article) => {
        if (newArticle.version === pollData.version) {
            log('No update found for', pollData.url);
            return;
        }

        return Promise.all([
            articleService.get(articleURL, pollData.version, false),
            articleService.saveNewVersion(website, newArticle, new ObjectID(pollData.ID)),
        ])
        // 4 - Check existing feedbacks and notify their endusers (if possible)
        .spread((oldRevision : Article, newRevision : Article) => (
            notifyEnduserAboutUpdate(website, oldRevision, newRevision)
        ));
    });
}