/*global window, rJS */ /*jslint nomen: true, indent: 2, maxerr: 3*/ (function (window, rJS) { "use strict"; var gadget_klass = rJS(window), rusha = new Rusha(); gadget_klass .ready(function (g) { g.props = {}; g.props.jio_storage_dict = {}; g.props.storage_signature_dict = {}; return g.getDeclaredGadget('jio_gadget') .push(function (jio_gadget) { g.props.jio_gadget = jio_gadget; }); }) .ready(function (g) { return g.getDeclaredGadget('login_gadget') .push(function (login_gadget) { g.props.login_gadget = login_gadget; }); }) .ready(function (g) { return g.getDeclaredGadget('log_gadget') .push(function (log_gadget) { g.props.log_gadget = log_gadget; }); }) .declareAcquiredMethod("getSetting", "getSetting") .declareAcquiredMethod("setSetting", "setSetting") .declareMethod("startSync", function (options) { var gadget = this, monitor_cred_dict = {}; function formatDate(d){ function addZero(n){ return n < 10 ? '0' + n : '' + n; } return d.getFullYear() + "-" + addZero(d.getMonth()+1) + "-" + addZero(d.getDate()) + " " + addZero(d.getHours()) + ":" + addZero(d.getMinutes()) + ":" + addZero(d.getSeconds()); } function getErrorLog(error_list) { // Build error msg from failed sync var i, tmp_url, error_message = ""; for (i = 0; i < error_list.length; i += 1) { if (error_list[i].storage_dict.hasOwnProperty('sub_storage')) { if (error_list[i].storage_dict.sub_storage.hasOwnProperty('sub_storage')) { tmp_url = error_list[i].storage_dict.sub_storage.sub_storage.url; } else { tmp_url = error_list[i].storage_dict.sub_storage.url; } } else { tmp_url = error_list[i].storage_dict.url; } error_message += "> " + error_list[i].storage_dict.hosting + " > " + error_list[i].storage_dict.title + "\n"; error_message += "Cannot download file(s) at " + tmp_url + ".\n\n"; } return error_message; } function getJioGadget(gadget, storage_dict, query) { var hash, url; if (storage_dict.sub_storage.hasOwnProperty('sub_storage')) { url = storage_dict.sub_storage.sub_storage.url; } else { url = storage_dict.sub_storage.url; } hash = rusha.digestFromString(url); return new RSVP.Queue() .push(function () { var storage_signature = rusha.digestFromString( JSON.stringify(storage_dict) ); if (gadget.props.jio_storage_dict.hasOwnProperty(hash)) { if (!gadget.props.storage_signature_dict.hasOwnProperty(hash)) { gadget.props.storage_signature_dict[hash] = ''; } if (gadget.props.storage_signature_dict[hash] !== storage_signature) { // recreate jio_gadget as storage config changed gadget.props.storage_signature_dict[hash] = storage_signature; jio_declared_gadget.createJio(storage_dict, true, query); } return gadget.props.jio_storage_dict[hash]; } else { return gadget.declareGadget("gadget_monitoring_jio.html", { scope: 'jio_' + hash } ) .push(function (jio_declared_gadget) { gadget.props.storage_signature_dict[hash] = storage_signature; jio_declared_gadget.createJio(storage_dict, true, query); gadget.props.jio_storage_dict[hash] = jio_declared_gadget; return jio_declared_gadget; }); } }); } function syncStorage(gadget, storage_dict, query) { return getJioGadget(gadget, storage_dict, query) .push(function (jio_declared_gadget) { //jio_declared_gadget.createJio(storage_dict, true, query); return jio_declared_gadget.repair(); }) .push(undefined, function (error) { console.log(error); gadget.props.error_list.push({ storage_dict: storage_dict, query: query }); }); } function updateStatus(gadget, storage_dict, status) { var promise_list = [], jio_gadget, url, i; return getJioGadget(gadget, storage_dict) .push(function (jio_declared_gadget) { jio_gadget = jio_declared_gadget; return jio_gadget.allDocs({include_docs: true}); }) .push(undefined, function (error) { console.log(error); return { data: { total_rows: 0 } }; }) .push(function (jio_docs) { var tmp; for (i = 0; i < jio_docs.data.total_rows; i += 1) { if (jio_docs.data.rows[i].id.startsWith('_replicate_')) { continue; } tmp = jio_docs.data.rows[i].doc; if (storage_dict.storage_type === "rss") { if (tmp.category === "WARNING") { continue; } tmp.category = "WARNING"; } else if (storage_dict.storage_type === "webdav") { if (tmp.status === "WARNING") { continue; } tmp.status = "WARNING"; } promise_list.push(jio_gadget.put( jio_docs.data.rows[i].id, tmp )); } return RSVP.all(promise_list); }) .push(undefined, function (error) { console.log("ERROR: update status to WARNING"); console.log(error); }); } function getMonitoringStorageList (feed_url_list) { var base_url, base_url_hash, key, i, j, feed_config, dav_config, monitor_storage_list = [], storage_type_list = [], dav_storage = { type: "query", sub_storage: { type: "drivetojiomapping", sub_storage: { type: "dav" } } }, feed_storage = { type: "query", sub_storage: { type: "feed", feed_type: 'rss' } }; storage_type_list = [ /*{path: 'jio_public/', query: {}},*/ {path: '', query: {}, private_access: true}, ]; for (i = 0; i < feed_url_list.length; i += 1) { feed_config = JSON.parse(JSON.stringify(feed_storage)); feed_config.sub_storage.url = feed_url_list[i].htmlurl; // put Monitor instance name, usefull to track error feed_config.title = feed_url_list[i].title; feed_config.hosting = feed_url_list[i].opml_title; feed_config.storage_type = "rss"; monitor_storage_list.push({ storage: feed_config, query: {} }); base_url = feed_url_list[i].url; // XXX - compatibility if (base_url.endsWith('jio_public/')) { base_url = base_url.replace('jio_public/', 'jio_private/'); // Hard coded!! } base_url_hash = rusha.digestFromString(base_url); for (j = 0; j < storage_type_list.length; j += 1) { dav_config = JSON.parse(JSON.stringify(dav_storage)); dav_config.sub_storage.sub_storage.url = base_url + storage_type_list[j].path; if (storage_type_list[j].private_access) { if (monitor_cred_dict.hasOwnProperty(base_url_hash)) { dav_config.sub_storage.sub_storage.basic_login = monitor_cred_dict[base_url_hash].hash; } else { console.log("NotFound: skipping " + dav_config.sub_storage.sub_storage.url + " ..."); continue; } } // put Monitor instance name, usefull to track error dav_config.title = feed_url_list[i].title; dav_config.hosting = feed_url_list[i].opml_title; dav_config.storage_type = "webdav"; monitor_storage_list.push({ storage: dav_config, query: storage_type_list[j].query }); } } return monitor_storage_list; } function syncAllStorage() { var monitor_storage_list = [], last_sync_time; return new RSVP.Queue() .push(function () { return gadget.setSetting('sync_start_time', new Date().getTime()); }) .push(function () { $(".notifyjs-wrapper").remove(); return $.notify( "Synchronizing Data...", { position:"bottom right", autoHide: false, className: "info" } ); }) .push(function () { // Get all configured credentials return gadget.props.login_gadget.getUrlDict(); }) .push(undefined, function () { return {}; }) .push(function(url_dict) { monitor_cred_dict = url_dict; return gadget.props.jio_gadget.getUrlFeedDescription(options.query); }) .push(undefined, function () { return []; }) .push(function (url_list) { if (url_list.length <= 0) { // For backward compatibility, sync OMPL if there are empty! return new RSVP.Queue() .push(function () { return gadget.props.jio_gadget.syncMonitoringOpmlData(); }) .push(function () { return gadget.props.jio_gadget.getUrlFeedDescription(options.query); }) .push(undefined, function () { return []; }); } else { return url_list; } }) .push(function (url_list) { var i, promise_list = []; monitor_storage_list = getMonitoringStorageList(url_list); gadget.props.error_list = []; for (i = 0; i < monitor_storage_list.length; i += 1) { promise_list.push(syncStorage( gadget, monitor_storage_list[i].storage, monitor_storage_list[i].query)); } console.log("Sync monitoring data..."); return RSVP.all(promise_list); }) .push(undefined, function (error) { console.log(error); return; }) .push(function () { // Check if there was errors and retry them if possible var error_size = gadget.props.error_list.length, error_list = gadget.props.error_list.slice(0), promise_list = [], i; if (error_size > 0) { // Reset list of errors gadget.props.error_list = []; $(".notifyjs-wrapper").remove(); promise_list.push($.notify( "Retry Previous Failure(s)...", { position:"bottom right", autoHide: false, className: "info" } )); for (i = 0; i < error_size; i += 1) { promise_list.push(syncStorage( gadget, error_list[i].storage_dict, error_list[i].query )); } } return RSVP.all(promise_list); }) .push(undefined, function (error) { console.log(error); return; }) .push(function () { last_sync_time = new Date().getTime(); return gadget.setSetting('latest_sync_time', last_sync_time); }) .push(function () { var time = 3000, classname = "info", error_amount = gadget.props.error_list.length, message = "Synchronisation finished.", log_message = '', log_title = "OK: " + message; if ( error_amount > 0) { classname = "warning"; time = 5000; log_message = getErrorLog(gadget.props.error_list); log_title = "Synchronisation finished with " + error_amount + "error(s)."; message = log_title + "\nYou can retry with manual sync."; } $(".notifyjs-wrapper").remove(); return RSVP.all([$.notify( message, { position:"bottom right", autoHide: true, className: classname, autoHideDelay: time } ), gadget.props.log_gadget.log({ message: log_message, type: classname, title: log_title, method: 'Monitoring Sync' })]); }) .push(function () { var promise_list = [], i; // Update all failures monitoring status to Warning for (i = 0; i < gadget.props.error_list.length; i += 1) { promise_list.push(updateStatus( gadget, gadget.props.error_list[i].storage_dict, 'WARNING' )); } return RSVP.all(promise_list); }) .push(function () { return $.notify( "Last Sync: " + formatDate(new Date(last_sync_time)), { position:"bottom right", autoHide: true, className: "success", autoHideDelay: 30000 } ); }); } function syncDataTimer() { if (gadget.props.timer) { clearTimeout(gadget.props.timer); } gadget.props.timer = setTimeout(function(){ return new RSVP.Queue() .push(function () { return gadget.getSetting('sync_start_time'); }) .push(function (start_timestamp) { var current_time = new Date().getTime(); if (start_timestamp !== undefined && current_time - gadget.props.timer_interval <= start_timestamp) { // There was a recent sync don't start a new sync before the time_interval! return; } return syncAllStorage(); }) .push(undefined, function (error) { console.log(error); return; }) .push(function () { return gadget.getSetting('sync_data_interval'); }) .push(function (timer_interval) { if (timer_interval === undefined) { timer_interval = gadget.props.default_sync_interval; } gadget.props.timer_interval = timer_interval; return syncDataTimer(); }); }, gadget.props.timer_interval); return gadget.props.timer; } if (options === undefined) { options = {}; } if (options.query === undefined) { options.query = { include_docs: true }; } if (options.now) { return syncAllStorage(); } // Default sync interval to 5 minutes gadget.props.default_sync_interval = 300000; return new RSVP.Queue() .push(function () { return gadget.getSetting('sync_data_interval'); }) .push(function (timer_interval) { if (timer_interval === undefined) { // quickly sync because this is the first run! gadget.props.timer_interval = 10000; gadget.props.has_sync_interval = false; } else { gadget.props.timer_interval = timer_interval; } return gadget.getSetting('latest_sync_time'); }) .push(function (latest_sync_time) { var current_time = new Date().getTime(), time_diff; if (latest_sync_time !== undefined) { time_diff = current_time - latest_sync_time; if ((time_diff - 10000) >= gadget.props.timer_interval) { // sync in after 10 second gadget.props.timer_interval = 10000; } else { gadget.props.timer_interval = gadget.props.timer_interval - time_diff; } } if (!gadget.props.has_sync_interval) { return gadget.setSetting('sync_data_interval', gadget.props.default_sync_interval); } }) .push(function () { return syncDataTimer(); }); }); }(window, rJS));