<commit_before>const refreshDropdown   = require('@binary-com/binary-style').selectDropdown;
const moment            = require('moment');
const TradingAnalysis   = require('./analysis');
const commonTrading     = require('./common');
const Contract          = require('./contract');
const Defaults          = require('./defaults');
const Durations         = require('./duration');
const GetTicks          = require('./get_ticks');
const Lookback          = require('./lookback');
const Notifications     = require('./notifications');
const Price             = require('./price');
const Reset             = require('./reset');
const StartDates        = require('./starttime').StartDates;
const Symbols           = require('./symbols');
const Tick              = require('./tick');
const BinarySocket      = require('../../base/socket');
const getMinPayout      = require('../../common/currency').getMinPayout;
const isCryptocurrency  = require('../../common/currency').isCryptocurrency;
const elementInnerHtml  = require('../../../_common/common_functions').elementInnerHtml;
const getElementById    = require('../../../_common/common_functions').getElementById;
const getVisibleElement = require('../../../_common/common_functions').getVisibleElement;
const localize          = require('../../../_common/localize').localize;
const State             = require('../../../_common/storage').State;
const getPropertyValue  = require('../../../_common/utility').getPropertyValue;

const Process = (() => {
    /*
     * This function process the active symbols to get markets
     * and underlying list
     */
    const processActiveSymbols = () => {
        BinarySocket.send({ active_symbols: 'brief' }).then((response) => {
            // populate the Symbols object
            Symbols.details(response);

            const market = commonTrading.getDefaultMarket();

            // store the market
            Defaults.set('market', market);

            commonTrading.displayMarkets();
            processMarket();
        });
    };

    /*
     * Function to call when market has changed
     */
    const processMarket = () => {
        // we can get market from sessionStorage as allowed market
        // is already set when this is called
        let market = Defaults.get('market');
        let symbol = Defaults.get('underlying');

        // change to default market if query string contains an invalid market
        if (!market || !Symbols.underlyings()[market]) {
            market = commonTrading.getDefaultMarket();
            Defaults.set('market', market);
        }
        if ((!symbol || !Symbols.underlyings()[market][symbol])) {
            symbol = undefined;
        }

        processMarketUnderlying();
    };

    /*
     * Function to call when underlying has changed
     */
    const processMarketUnderlying = () => {
        const underlying_element = document.getElementById('underlying');
        const underlying = underlying_element.value;

        Defaults.set('underlying', underlying);

        commonTrading.showFormOverlay();

        // get ticks for current underlying
        GetTicks.request(underlying);

        Tick.clean();

        commonTrading.updateWarmChart();

        BinarySocket.clearTimeouts();

        getContracts(underlying);

        commonTrading.displayTooltip();
    };

    const getContracts = (underlying) => {
        BinarySocket.send({ contracts_for: underlying }).then((response) => {
            Notifications.hide('CONNECTION_ERROR');
            processContract(response);
        });
    };

    /*
     * Function to display contract form for current underlying
     */
    const processContract = (contracts) => {
        if (getPropertyValue(contracts, ['error', 'code']) === 'InvalidSymbol') {
            Price.processForgetProposals();
            getElementById('contract_confirmation_container').style.display      = 'block';
            getElementById('contracts_list').style.display = 'none';
            getElementById('confirmation_message').hide();

            const confirmation_error = getElementById('confirmation_error');
            confirmation_error.show();
            elementInnerHtml(confirmation_error, `${contracts.error.message} <a href="javascript:;" onclick="sessionStorage.removeItem('underlying'); window.location.reload();">${localize('Please reload the page')}</a>`);
            return;
        }

        State.set('is_chart_allowed', !(contracts.contracts_for && contracts.contracts_for.feed_license && contracts.contracts_for.feed_license === 'chartonly'));

        getElementById('trading_socket_container').classList.add('show');

        const init_logo = getElementById('trading_init_progress');
        if (init_logo && init_logo.style.display !== 'none') {
            init_logo.style.display = 'none';
            Defaults.update();
        }

        Contract.setContracts(contracts);

        const contract_categories = Contract.contractForms();
        let formname;
        if (Defaults.get('formname') && contract_categories && contract_categories[Defaults.get('formname')]) {
            formname = Defaults.get('formname');
        } else {
            const tree = commonTrading.getContractCategoryTree(contract_categories);
            if (tree[0]) {
                if (typeof tree[0] === 'object') {
                    formname = tree[0][1][0];
                } else {
                    formname = tree[0];
                }
            }
        }

        const available_contracts = getPropertyValue(contracts, ['contracts_for', 'available']);

        commonTrading.displayContractForms('contract_form_name_nav', contract_categories, formname);

        processContractForm(available_contracts, formname);

        TradingAnalysis.request();

        commonTrading.hideFormOverlay();
    };

    const processContractForm = (available_contracts = State.getResponse('contracts_for.available'), formname_to_set = getElementById('contract').value || Defaults.get('formname')) => {
        setFormName(formname_to_set);

        // get updated formname
        Contract.details(Defaults.get('formname'));

        StartDates.display();

        displayPrediction();
        refreshDropdown('#prediction');
        displaySelectedTick();
        refreshDropdown('#selected_tick');
        Lookback.display();

        let r1;
        if (State.get('is_start_dates_displayed') && Defaults.get('date_start') && Defaults.get('date_start') !== 'now') {
            r1 = Durations.onStartDateChange(Defaults.get('date_start'));
            if (!r1 || Defaults.get('expiry_type') === 'endtime') Durations.display();
        } else {
            Durations.display();
        }

        // needs to be called after durations are populated
        displayEquals();

        const currency  = Defaults.get('currency') || getVisibleElement('currency').value;
        const is_crypto = isCryptocurrency(currency);
        const amount    = is_crypto ? 'amount_crypto' : 'amount';
        if (Defaults.get(amount)) {
            $('#amount').val(Defaults.get(amount));
        } else {
            const default_value = getMinPayout(currency);
            Defaults.set(amount, default_value);
            getElementById('amount').value = default_value;
        }
        if (Defaults.get('amount_type')) {
            commonTrading.selectOption(Defaults.get('amount_type'), getElementById('amount_type'));
        } else {
            Defaults.set('amount_type', getElementById('amount_type').value);
        }

        if (Contract.form() === 'callputspread') {
            commonTrading.selectOption('payout', getElementById('amount_type'));
            refreshDropdown('#amount_type');
            // hide stake option
            getElementById('stake_option').setVisibility(0);
            $('[data-value="stake"]').hide();
        } else {
            getElementById('stake_option').setVisibility(1);
            refreshDropdown('#amount_type');
        }

        if (Defaults.get('currency')) {
            commonTrading.selectOption(Defaults.get('currency'), getVisibleElement('currency'));
        }

        const expiry_type        = Defaults.get('expiry_type') || 'duration';
        const make_price_request = onExpiryTypeChange(expiry_type);

        if (make_price_request >= 0) {
            Price.processPriceRequest();
        }
    };

    const displayPrediction = () => {
        const prediction_row = getElementById('prediction_row');
        if (Contract.form() === 'digits' && sessionStorage.getItem('formname') !== 'evenodd') {
            prediction_row.show();
            const prediction = getElementById('prediction');
            if (Defaults.get('prediction')) {
                commonTrading.selectOption(Defaults.get('prediction'), prediction);
            } else {
                Defaults.set('prediction', prediction.value);
            }
        } else {
            prediction_row.hide();
            Defaults.remove('prediction');
        }
    };

    const displaySelectedTick = () => {
        const selected_tick_row       = getElementById('selected_tick_row');
        const highlowticks_expiry_row = getElementById('highlowticks_expiry_row');
        if (sessionStorage.getItem('formname') === 'highlowticks') {
            selected_tick_row.show();
            highlowticks_expiry_row.show();
            const selected_tick = getElementById('selected_tick');
            if (Defaults.get('selected_tick')) {
                commonTrading.selectOption(Defaults.get('selected_tick'), selected_tick);
            } else {
                Defaults.set('selected_tick', selected_tick.value);
            }
            Reset.hideResetTime();
        } else {
            selected_tick_row.hide();
            highlowticks_expiry_row.hide();
            Defaults.remove('selected_tick');
        }
    };

    const hasCallPutEqual = (contracts = getPropertyValue(Contract.contracts(), ['contracts_for', 'available']) || []) =>
        contracts.find(contract => contract.contract_category === 'callputequal');

    const displayEquals = () => {
        const formname  = Defaults.get('formname');
        const el_equals = document.getElementById('callputequal');
        const durations = getPropertyValue(Contract.durations(), [commonTrading.durationType(Defaults.get('duration_units'))]) || [];
        if (/^(callputequal|risefall)$/.test(formname) && 'callputequal' in durations && hasCallPutEqual()) {
            if (+Defaults.get('is_equal')) {
                el_equals.checked = true;
            }
            el_equals.parentElement.setVisibility(1);
        } else {
            el_equals.parentElement.setVisibility(0);
        }
    };

    const setFormName = (formname) => {
        let formname_to_set    = formname;
        const has_callputequal = hasCallPutEqual();
        if (/^(callputequal)$/.test(formname_to_set) && (!has_callputequal || !+Defaults.get('is_equal'))) {
            formname_to_set = 'risefall';
        } else if (/^(risefall)$/.test(formname_to_set) && has_callputequal && +Defaults.get('is_equal')) {
            formname_to_set = 'callputequal';
        }
        Defaults.set('formname', formname_to_set);
        getElementById('contract').setAttribute('value', formname_to_set);
    };

    const forgetTradingStreams = () => {
        Price.processForgetProposals();
        Price.processForgetProposalOpenContract();
        processForgetTicks();
    };

    /*
     * cancel the current tick stream
     * this need to be invoked before makin
     */
    const processForgetTicks = () => {
        BinarySocket.send({ forget_all: 'ticks' });
    };

    const onExpiryTypeChange = (value) => {
        const $expiry_type    = $('#expiry_type');
        const validated_value = value && $expiry_type.find(`option[value=${value}]`).length ? value : 'duration';
        $expiry_type.val(validated_value);

        let make_price_request = 0;
        if (validated_value === 'endtime') {
            Durations.displayEndTime();
            if (Defaults.get('expiry_date')) {
                // if time changed, proposal will be sent there if not we should send it here
                make_price_request = Durations.selectEndDate(moment(Defaults.get('expiry_date'))) ? -1 : 1;
            }
            Defaults.remove('duration_units', 'duration_amount');
        } else {
            StartDates.enable();
            Durations.display();
            if (Defaults.get('duration_units')) {
                onDurationUnitChange(Defaults.get('duration_units'));
            }
            const duration_amount = Defaults.get('duration_amount');
            if (duration_amount && duration_amount > $('#duration_minimum').text()) {
                $('#duration_amount').val(duration_amount);
            }
            make_price_request = 1;
            Defaults.remove('expiry_date', 'expiry_time', 'end_date');
            Durations.validateMinDurationAmount();
        }

        return make_price_request;
    };

    const onDurationUnitChange = (value) => {
        const $duration_units = $('#duration_units');
        if (!value || !$duration_units.find(`option[value=${value}]`).length) {
            return 0;
        }

        $duration_units.val(value);
        Defaults.set('duration_units', value);

        Durations.selectUnit(value);
        Durations.populate();

        return 1;
    };

    return {
        processActiveSymbols,
        processMarket,
        processContract,
        processContractForm,
        forgetTradingStreams,
        onExpiryTypeChange,
        onDurationUnitChange,
    };
})();

module.exports = Process;
<commit_msg>hide reset time if not reset<commit_after>const refreshDropdown   = require('@binary-com/binary-style').selectDropdown;
const moment            = require('moment');
const TradingAnalysis   = require('./analysis');
const commonTrading     = require('./common');
const Contract          = require('./contract');
const Defaults          = require('./defaults');
const Durations         = require('./duration');
const GetTicks          = require('./get_ticks');
const Lookback          = require('./lookback');
const Notifications     = require('./notifications');
const Price             = require('./price');
const Reset             = require('./reset');
const StartDates        = require('./starttime').StartDates;
const Symbols           = require('./symbols');
const Tick              = require('./tick');
const BinarySocket      = require('../../base/socket');
const getMinPayout      = require('../../common/currency').getMinPayout;
const isCryptocurrency  = require('../../common/currency').isCryptocurrency;
const elementInnerHtml  = require('../../../_common/common_functions').elementInnerHtml;
const getElementById    = require('../../../_common/common_functions').getElementById;
const getVisibleElement = require('../../../_common/common_functions').getVisibleElement;
const localize          = require('../../../_common/localize').localize;
const State             = require('../../../_common/storage').State;
const getPropertyValue  = require('../../../_common/utility').getPropertyValue;

const Process = (() => {
    /*
     * This function process the active symbols to get markets
     * and underlying list
     */
    const processActiveSymbols = () => {
        BinarySocket.send({ active_symbols: 'brief' }).then((response) => {
            // populate the Symbols object
            Symbols.details(response);

            const market = commonTrading.getDefaultMarket();

            // store the market
            Defaults.set('market', market);

            commonTrading.displayMarkets();
            processMarket();
        });
    };

    /*
     * Function to call when market has changed
     */
    const processMarket = () => {
        // we can get market from sessionStorage as allowed market
        // is already set when this is called
        let market = Defaults.get('market');
        let symbol = Defaults.get('underlying');

        // change to default market if query string contains an invalid market
        if (!market || !Symbols.underlyings()[market]) {
            market = commonTrading.getDefaultMarket();
            Defaults.set('market', market);
        }
        if ((!symbol || !Symbols.underlyings()[market][symbol])) {
            symbol = undefined;
        }

        processMarketUnderlying();
    };

    /*
     * Function to call when underlying has changed
     */
    const processMarketUnderlying = () => {
        const underlying_element = document.getElementById('underlying');
        const underlying = underlying_element.value;

        Defaults.set('underlying', underlying);

        commonTrading.showFormOverlay();

        // get ticks for current underlying
        GetTicks.request(underlying);

        Tick.clean();

        commonTrading.updateWarmChart();

        BinarySocket.clearTimeouts();

        getContracts(underlying);

        commonTrading.displayTooltip();
    };

    const getContracts = (underlying) => {
        BinarySocket.send({ contracts_for: underlying }).then((response) => {
            Notifications.hide('CONNECTION_ERROR');
            processContract(response);
        });
    };

    /*
     * Function to display contract form for current underlying
     */
    const processContract = (contracts) => {
        if (getPropertyValue(contracts, ['error', 'code']) === 'InvalidSymbol') {
            Price.processForgetProposals();
            getElementById('contract_confirmation_container').style.display      = 'block';
            getElementById('contracts_list').style.display = 'none';
            getElementById('confirmation_message').hide();

            const confirmation_error = getElementById('confirmation_error');
            confirmation_error.show();
            elementInnerHtml(confirmation_error, `${contracts.error.message} <a href="javascript:;" onclick="sessionStorage.removeItem('underlying'); window.location.reload();">${localize('Please reload the page')}</a>`);
            return;
        }

        State.set('is_chart_allowed', !(contracts.contracts_for && contracts.contracts_for.feed_license && contracts.contracts_for.feed_license === 'chartonly'));

        getElementById('trading_socket_container').classList.add('show');

        const init_logo = getElementById('trading_init_progress');
        if (init_logo && init_logo.style.display !== 'none') {
            init_logo.style.display = 'none';
            Defaults.update();
        }

        Contract.setContracts(contracts);

        const contract_categories = Contract.contractForms();
        let formname;
        if (Defaults.get('formname') && contract_categories && contract_categories[Defaults.get('formname')]) {
            formname = Defaults.get('formname');
        } else {
            const tree = commonTrading.getContractCategoryTree(contract_categories);
            if (tree[0]) {
                if (typeof tree[0] === 'object') {
                    formname = tree[0][1][0];
                } else {
                    formname = tree[0];
                }
            }
        }

        const available_contracts = getPropertyValue(contracts, ['contracts_for', 'available']);

        commonTrading.displayContractForms('contract_form_name_nav', contract_categories, formname);

        processContractForm(available_contracts, formname);

        TradingAnalysis.request();

        commonTrading.hideFormOverlay();
    };

    const processContractForm = (available_contracts = State.getResponse('contracts_for.available'), formname_to_set = getElementById('contract').value || Defaults.get('formname')) => {
        setFormName(formname_to_set);

        // get updated formname
        Contract.details(Defaults.get('formname'));

        StartDates.display();

        displayPrediction();
        refreshDropdown('#prediction');
        displaySelectedTick();
        refreshDropdown('#selected_tick');
        Lookback.display();

        if (!Reset.isReset(Defaults.get('formname'))) {
            Reset.hideResetTime();
        }

        let r1;
        if (State.get('is_start_dates_displayed') && Defaults.get('date_start') && Defaults.get('date_start') !== 'now') {
            r1 = Durations.onStartDateChange(Defaults.get('date_start'));
            if (!r1 || Defaults.get('expiry_type') === 'endtime') Durations.display();
        } else {
            Durations.display();
        }

        // needs to be called after durations are populated
        displayEquals();

        const currency  = Defaults.get('currency') || getVisibleElement('currency').value;
        const is_crypto = isCryptocurrency(currency);
        const amount    = is_crypto ? 'amount_crypto' : 'amount';
        if (Defaults.get(amount)) {
            $('#amount').val(Defaults.get(amount));
        } else {
            const default_value = getMinPayout(currency);
            Defaults.set(amount, default_value);
            getElementById('amount').value = default_value;
        }
        if (Defaults.get('amount_type')) {
            commonTrading.selectOption(Defaults.get('amount_type'), getElementById('amount_type'));
        } else {
            Defaults.set('amount_type', getElementById('amount_type').value);
        }

        if (Contract.form() === 'callputspread') {
            commonTrading.selectOption('payout', getElementById('amount_type'));
            refreshDropdown('#amount_type');
            // hide stake option
            getElementById('stake_option').setVisibility(0);
            $('[data-value="stake"]').hide();
        } else {
            getElementById('stake_option').setVisibility(1);
            refreshDropdown('#amount_type');
        }

        if (Defaults.get('currency')) {
            commonTrading.selectOption(Defaults.get('currency'), getVisibleElement('currency'));
        }

        const expiry_type        = Defaults.get('expiry_type') || 'duration';
        const make_price_request = onExpiryTypeChange(expiry_type);

        if (make_price_request >= 0) {
            Price.processPriceRequest();
        }
    };

    const displayPrediction = () => {
        const prediction_row = getElementById('prediction_row');
        if (Contract.form() === 'digits' && sessionStorage.getItem('formname') !== 'evenodd') {
            prediction_row.show();
            const prediction = getElementById('prediction');
            if (Defaults.get('prediction')) {
                commonTrading.selectOption(Defaults.get('prediction'), prediction);
            } else {
                Defaults.set('prediction', prediction.value);
            }
        } else {
            prediction_row.hide();
            Defaults.remove('prediction');
        }
    };

    const displaySelectedTick = () => {
        const selected_tick_row       = getElementById('selected_tick_row');
        const highlowticks_expiry_row = getElementById('highlowticks_expiry_row');
        if (sessionStorage.getItem('formname') === 'highlowticks') {
            selected_tick_row.show();
            highlowticks_expiry_row.show();
            const selected_tick = getElementById('selected_tick');
            if (Defaults.get('selected_tick')) {
                commonTrading.selectOption(Defaults.get('selected_tick'), selected_tick);
            } else {
                Defaults.set('selected_tick', selected_tick.value);
            }
        } else {
            selected_tick_row.hide();
            highlowticks_expiry_row.hide();
            Defaults.remove('selected_tick');
        }
    };

    const hasCallPutEqual = (contracts = getPropertyValue(Contract.contracts(), ['contracts_for', 'available']) || []) =>
        contracts.find(contract => contract.contract_category === 'callputequal');

    const displayEquals = () => {
        const formname  = Defaults.get('formname');
        const el_equals = document.getElementById('callputequal');
        const durations = getPropertyValue(Contract.durations(), [commonTrading.durationType(Defaults.get('duration_units'))]) || [];
        if (/^(callputequal|risefall)$/.test(formname) && 'callputequal' in durations && hasCallPutEqual()) {
            if (+Defaults.get('is_equal')) {
                el_equals.checked = true;
            }
            el_equals.parentElement.setVisibility(1);
        } else {
            el_equals.parentElement.setVisibility(0);
        }
    };

    const setFormName = (formname) => {
        let formname_to_set    = formname;
        const has_callputequal = hasCallPutEqual();
        if (/^(callputequal)$/.test(formname_to_set) && (!has_callputequal || !+Defaults.get('is_equal'))) {
            formname_to_set = 'risefall';
        } else if (/^(risefall)$/.test(formname_to_set) && has_callputequal && +Defaults.get('is_equal')) {
            formname_to_set = 'callputequal';
        }
        Defaults.set('formname', formname_to_set);
        getElementById('contract').setAttribute('value', formname_to_set);
    };

    const forgetTradingStreams = () => {
        Price.processForgetProposals();
        Price.processForgetProposalOpenContract();
        processForgetTicks();
    };

    /*
     * cancel the current tick stream
     * this need to be invoked before makin
     */
    const processForgetTicks = () => {
        BinarySocket.send({ forget_all: 'ticks' });
    };

    const onExpiryTypeChange = (value) => {
        const $expiry_type    = $('#expiry_type');
        const validated_value = value && $expiry_type.find(`option[value=${value}]`).length ? value : 'duration';
        $expiry_type.val(validated_value);

        let make_price_request = 0;
        if (validated_value === 'endtime') {
            Durations.displayEndTime();
            if (Defaults.get('expiry_date')) {
                // if time changed, proposal will be sent there if not we should send it here
                make_price_request = Durations.selectEndDate(moment(Defaults.get('expiry_date'))) ? -1 : 1;
            }
            Defaults.remove('duration_units', 'duration_amount');
        } else {
            StartDates.enable();
            Durations.display();
            if (Defaults.get('duration_units')) {
                onDurationUnitChange(Defaults.get('duration_units'));
            }
            const duration_amount = Defaults.get('duration_amount');
            if (duration_amount && duration_amount > $('#duration_minimum').text()) {
                $('#duration_amount').val(duration_amount);
            }
            make_price_request = 1;
            Defaults.remove('expiry_date', 'expiry_time', 'end_date');
            Durations.validateMinDurationAmount();
        }

        return make_price_request;
    };

    const onDurationUnitChange = (value) => {
        const $duration_units = $('#duration_units');
        if (!value || !$duration_units.find(`option[value=${value}]`).length) {
            return 0;
        }

        $duration_units.val(value);
        Defaults.set('duration_units', value);

        Durations.selectUnit(value);
        Durations.populate();

        return 1;
    };

    return {
        processActiveSymbols,
        processMarket,
        processContract,
        processContractForm,
        forgetTradingStreams,
        onExpiryTypeChange,
        onDurationUnitChange,
    };
})();

module.exports = Process;
<|endoftext|>


<commit_before>const db = require("./db");
db.importFromDisk('lazerwalker', 'example')
  .then((result) => console.log("Loaded example file"))
  .catch((e) => console.log("Error: " + e))<commit_msg>Properly exit after populating test DB<commit_after>const db = require("./db");
db.importFromDisk('lazerwalker', 'example')
  .then((result) => {
    console.log("Loaded example file");
    process.exit();
  }).catch((e) => {
    console.log("Error: " + e);
    process.exit(1)
  })<|endoftext|>


<commit_before>/*
 angular-tablesort v1.0.0
 (c) 2013 Mattias Holmlund, http://mattiash.github.io/angular-tablesort
 License: MIT
*/

var tableSortModule = angular.module( 'tableSort', [] );

tableSortModule.directive('tsWrapper', function( $log, $parse ) {
    return {
        scope: true,
        controller: function($scope) {
            $scope.sortExpression = [];
            $scope.headings = [];

            var parse_sortexpr = function( expr ) {
                return [$parse( expr ), null, false];
            };

            this.setSortField = function( sortexpr, element ) {
                var i;
                var expr = parse_sortexpr( sortexpr );
                if( $scope.sortExpression.length === 1
                    && $scope.sortExpression[0][0] === expr[0] ) {
                    if( $scope.sortExpression[0][2] ) {
                        element.removeClass( "tablesort-desc" );
                        element.addClass( "tablesort-asc" );
                        $scope.sortExpression[0][2] = false;
                    }
                    else {
                        element.removeClass( "tablesort-asc" );
                        element.addClass( "tablesort-desc" );
                        $scope.sortExpression[0][2] = true;
                    }
                }
                else {
                    for( i=0; i<$scope.headings.length; i=i+1 ) {
                        $scope.headings[i]
                            .removeClass( "tablesort-desc" )
                            .removeClass( "tablesort-asc" );
                    }
                    element.addClass( "tablesort-asc" );
                    $scope.sortExpression = [expr];
                }
            };

            this.addSortField = function( sortexpr, element ) {
                var i;
                var toggle_order = false;
                var expr = parse_sortexpr( sortexpr );
                for( i=0; i<$scope.sortExpression.length; i=i+1 ) {
                    if( $scope.sortExpression[i][0] === expr[0] ) {
                        if( $scope.sortExpression[i][2] ) {
                            element.removeClass( "tablesort-desc" );
                            element.addClass( "tablesort-asc" );
                            $scope.sortExpression[i][2] = false;
                        }
                        else {
                            element.removeClass( "tablesort-asc" );
                            element.addClass( "tablesort-desc" );
                            $scope.sortExpression[i][2] = true;
                        }
                        toggle_order = true;
                    }
                }
                if( !toggle_order ) {
                    element.addClass( "tablesort-asc" );
                    $scope.sortExpression.push( expr );
                }
            };

            this.registerHeading = function( headingelement ) {
                $scope.headings.push( headingelement );
            };

            $scope.sortFun = function( a, b ) {
                var i, aval, bval, descending;
                for( i=0; i<$scope.sortExpression.length; i=i+1 ){
                    aval = $scope.sortExpression[i][0](a);
                    bval = $scope.sortExpression[i][0](b);
                    filterFun = b[$scope.sortExpression[i][1]];
                    if( filterFun ) {
                        aval = filterFun( aval );
                        bval = filterFun( bval );
                    }
                    descending = $scope.sortExpression[i][2];
                    if( aval > bval ) {
                        return descending ? -1 : 1;
                    }
                    else if( aval < bval ) {
                        return descending ? 1 : -1;
                    }
                }
                return 0;
            };
        }
    };
} );

tableSortModule.directive('tsCriteria', function() {
    return {
        require: "^tsWrapper",
        link: function(scope, element, attrs, tsWrapperCtrl) {
            var clickingCallback = function(event) {
                scope.$apply( function() {
                    if( event.shiftKey ) {
                        tsWrapperCtrl.addSortField(attrs.tsCriteria, element);
                    }
                    else {
                        tsWrapperCtrl.setSortField(attrs.tsCriteria, element);
                    }
                } );
            };
            element.bind('click', clickingCallback);
            element.addClass('tablesort-sortable');
            if( "tsDefault" in attrs && attrs.tsDefault !== "0" ) {
                tsWrapperCtrl.addSortField( attrs.tsCriteria, element );
            }
            tsWrapperCtrl.registerHeading( element );
        }
    };
});

tableSortModule.directive("tsRepeat", function() {
    return {
        require: "^tsWrapper",
        priority: 2000,
        compile: function(tElement, tAttrs, transclude) {
            tAttrs.ngRepeat += " | tablesortOrderBy:sortFun";
        }
    };
} );

tableSortModule.filter( 'tablesortOrderBy', function(){
    return function(array, sortfun ) {
        var arrayCopy = [];
        for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
        return arrayCopy.sort( sortfun );
    };
} );

tableSortModule.filter( 'parseInt', function(){
    return function(input) {
        return parseInt( input );
    };
} );

tableSortModule.filter( 'parseFloat', function(){
    return function(input) {
        return parseFloat( input );
    };
} );
<commit_msg>Sort undefined values as empty strings<commit_after>/*
 angular-tablesort v1.0.0
 (c) 2013 Mattias Holmlund, http://mattiash.github.io/angular-tablesort
 License: MIT
*/

var tableSortModule = angular.module( 'tableSort', [] );

tableSortModule.directive('tsWrapper', function( $log, $parse ) {
    return {
        scope: true,
        controller: function($scope) {
            $scope.sortExpression = [];
            $scope.headings = [];

            var parse_sortexpr = function( expr ) {
                return [$parse( expr ), null, false];
            };

            this.setSortField = function( sortexpr, element ) {
                var i;
                var expr = parse_sortexpr( sortexpr );
                if( $scope.sortExpression.length === 1
                    && $scope.sortExpression[0][0] === expr[0] ) {
                    if( $scope.sortExpression[0][2] ) {
                        element.removeClass( "tablesort-desc" );
                        element.addClass( "tablesort-asc" );
                        $scope.sortExpression[0][2] = false;
                    }
                    else {
                        element.removeClass( "tablesort-asc" );
                        element.addClass( "tablesort-desc" );
                        $scope.sortExpression[0][2] = true;
                    }
                }
                else {
                    for( i=0; i<$scope.headings.length; i=i+1 ) {
                        $scope.headings[i]
                            .removeClass( "tablesort-desc" )
                            .removeClass( "tablesort-asc" );
                    }
                    element.addClass( "tablesort-asc" );
                    $scope.sortExpression = [expr];
                }
            };

            this.addSortField = function( sortexpr, element ) {
                var i;
                var toggle_order = false;
                var expr = parse_sortexpr( sortexpr );
                for( i=0; i<$scope.sortExpression.length; i=i+1 ) {
                    if( $scope.sortExpression[i][0] === expr[0] ) {
                        if( $scope.sortExpression[i][2] ) {
                            element.removeClass( "tablesort-desc" );
                            element.addClass( "tablesort-asc" );
                            $scope.sortExpression[i][2] = false;
                        }
                        else {
                            element.removeClass( "tablesort-asc" );
                            element.addClass( "tablesort-desc" );
                            $scope.sortExpression[i][2] = true;
                        }
                        toggle_order = true;
                    }
                }
                if( !toggle_order ) {
                    element.addClass( "tablesort-asc" );
                    $scope.sortExpression.push( expr );
                }
            };

            this.registerHeading = function( headingelement ) {
                $scope.headings.push( headingelement );
            };

            $scope.sortFun = function( a, b ) {
                var i, aval, bval, descending;
                for( i=0; i<$scope.sortExpression.length; i=i+1 ){
                    aval = $scope.sortExpression[i][0](a);
                    bval = $scope.sortExpression[i][0](b);
                    filterFun = b[$scope.sortExpression[i][1]];
                    if( filterFun ) {
                        aval = filterFun( aval );
                        bval = filterFun( bval );
                    }
                    if( aval === undefined ) {
                        aval = "";
                    }
                    if( bval === undefined ) {
                       bval = "";
                    }
                    descending = $scope.sortExpression[i][2];
                    if( aval > bval ) {
                        return descending ? -1 : 1;
                    }
                    else if( aval < bval ) {
                        return descending ? 1 : -1;
                    }
                }
                return 0;
            };
        }
    };
} );

tableSortModule.directive('tsCriteria', function() {
    return {
        require: "^tsWrapper",
        link: function(scope, element, attrs, tsWrapperCtrl) {
            var clickingCallback = function(event) {
                scope.$apply( function() {
                    if( event.shiftKey ) {
                        tsWrapperCtrl.addSortField(attrs.tsCriteria, element);
                    }
                    else {
                        tsWrapperCtrl.setSortField(attrs.tsCriteria, element);
                    }
                } );
            };
            element.bind('click', clickingCallback);
            element.addClass('tablesort-sortable');
            if( "tsDefault" in attrs && attrs.tsDefault !== "0" ) {
                tsWrapperCtrl.addSortField( attrs.tsCriteria, element );
            }
            tsWrapperCtrl.registerHeading( element );
        }
    };
});

tableSortModule.directive("tsRepeat", function() {
    return {
        require: "^tsWrapper",
        priority: 2000,
        compile: function(tElement, tAttrs, transclude) {
            tAttrs.ngRepeat += " | tablesortOrderBy:sortFun";
        }
    };
} );

tableSortModule.filter( 'tablesortOrderBy', function(){
    return function(array, sortfun ) {
        var arrayCopy = [];
        for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
        return arrayCopy.sort( sortfun );
    };
} );

tableSortModule.filter( 'parseInt', function(){
    return function(input) {
        return parseInt( input );
    };
} );

tableSortModule.filter( 'parseFloat', function(){
    return function(input) {
        return parseFloat( input );
    };
} );
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

/**
 * @private
 */
function createError(type: string, name: string, message: string): Error {
  const error = new Error(message);
  error.name = name;
  (error: any).type = type;
  (error: any).framesToPop = 2;
  return error;
}

module.exports = {
  create(name: string, message: string): Error {
    return createError('mustfix', name, message);
  },
  createWarning(name: string, message: string): Error {
    return createError('warn', name, message);
  },
};
<commit_msg>Fix RelayError to use type=error instead of type=mustfix<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

/**
 * @private
 */
function createError(type: string, name: string, message: string): Error {
  const error = new Error(message);
  error.name = name;
  (error: any).type = type;
  (error: any).framesToPop = 2;
  return error;
}

module.exports = {
  create(name: string, message: string): Error {
    return createError('error', name, message);
  },
  createWarning(name: string, message: string): Error {
    return createError('warn', name, message);
  },
};
<|endoftext|>


<commit_before>var settings = {
  time_engine:function(v){
    if(document.activeElement.id !== 'date_time_input'){
      var inp = document.querySelector('#date_time_input');
      if(inp) inp.value = v;
    }
  },
  time_daycycle:function(v){
    if(document.activeElement.id !== 'date_daycycle_input'){
      var inp = document.querySelector('#date_daycycle_input');
      v = v.toString();
      if(inp) inp.value = (v.length < 4 ? (new Array((5-v.length)).join("0")+v) : v);
    }
  },
  time_nightcycle:function(v){
    if(document.activeElement.id !== 'date_nightcycle_input'){
      var inp = document.querySelector('#date_nightcycle_input');
      v = v.toString();
      if(inp) inp.value = (v.length < 4 ? (new Array((5-v.length)).join("0")+v) : v);
    }
  },
  time_play:function(v){

  }
};

function setHeaderLines(){
  var lines = Array.prototype.slice.call(document.querySelectorAll('.section__title__line'));
  lines.forEach(function(line){
    line.style.width = ((window.innerWidth-10)-line.previousElementSibling.clientWidth-30)+'px';
  });

  window.addEventListener('resize',function(){
    lines.forEach(function(line){
      line.style.width = ((window.innerWidth-10)-line.previousElementSibling.clientWidth-30)+'px';
    });
  })
}

function adddropdowns(){
  var dropdowns = Array.prototype.slice.call(document.querySelectorAll('.dropdown'));
  dropdowns.forEach(function(list){
    list.style.height = "0px";

    list.previousElementSibling.onclick = function(){
      if(list.style.height && parseInt(list.style.height,10) === 0){
        list.style.height = null;
      }
      else{
        list.style.height = "0px";
      }
    }
  });
}

function addNav(){
  var links = Array.prototype.slice.call(document.querySelectorAll('.link'));
  links.forEach(function(link){
    link.onclick = function(){
      if(this.className.indexOf('active') === -1)
      {
        var pages = Array.prototype.slice.call(document.querySelectorAll('.page'))
        links.forEach(function(l){
          l.classList.remove('active');
        });
        this.classList.add('active');

        pages.forEach(function(page){
          page.classList.remove('active');
        });
        document.querySelector('#'+this.innerHTML.toLowerCase()).classList.add('active');
        setHeaderLines();
      }
    }
  });
}

function addSettings(win){
  var timeInput = document.querySelector('#date_time_input'),
      timeReg = /(\d){2}:(\d){2}:(\d){2}/,
      timecycles = Array.prototype.slice.call(document.querySelectorAll('.time_cycle')),
      cycleReg = /(\d){1,4}/,
      playbtn = document.querySelector("#play"),
      pausebtn = document.querySelector("#pause");
  timeInput.onkeyup = function(){
    var val = this.value;
    if(val.match(timeReg)){
      var vals = val.split(':').map(function(v){return parseInt(v);}),
          legal = true;

      if(vals[0] < 0 || vals[0] > 23){
        legal = false;
      }
      else if(vals[1] < 0 || vals[1] > 59){
        legal = false;
      }
      else if(vals[2] < 0 || vals[2] > 59){
        legal = false;
      }
      if(legal){
        win.postMessage(JSON.stringify({
          time_engine:val
        }),"*");
      }
    }
  }

  timecycles.forEach(function(cycle){
    cycle.onkeyup = function(e){
      var val = this.value;
      if(val.match(cycleReg)){
        val = parseInt(val);
        if(val !== 0 && val < 1441){
          var obj = {};
          obj[this.name] = val;
            win.postMessage(JSON.stringify(obj),"*");
        }
      }
    }
  });

  playbtn.onclick = function(){
    pausebtn.classList.remove('active');
    this.classList.add('active');
    win.postMessage(JSON.stringify({time_play:true}),"*")
  }

  pausebtn.onclick = function(){
    playbtn.classList.remove('active');
    this.classList.add('active');
    win.postMessage(JSON.stringify({time_play:false}),"*")
  }
}<commit_msg>add from client value for play pause<commit_after>var settings = {
  time_engine:function(v){
    if(document.activeElement.id !== 'date_time_input'){
      var inp = document.querySelector('#date_time_input');
      if(inp) inp.value = v;
    }
  },
  time_daycycle:function(v){
    if(document.activeElement.id !== 'date_daycycle_input'){
      var inp = document.querySelector('#date_daycycle_input');
      v = v.toString();
      if(inp) inp.value = (v.length < 4 ? (new Array((5-v.length)).join("0")+v) : v);
    }
  },
  time_nightcycle:function(v){
    if(document.activeElement.id !== 'date_nightcycle_input'){
      var inp = document.querySelector('#date_nightcycle_input');
      v = v.toString();
      if(inp) inp.value = (v.length < 4 ? (new Array((5-v.length)).join("0")+v) : v);
    }
  },
  time_play:function(v){
    if(v){
      var inp = document.querySelector('#play');
    }
    else{
      var inp = document.querySelector('#pause');
    }
    if(document.activeElement.id !== inp.id){
      var texts = Array.prototype.slice.call(document.querySelectorAll('#game_time .btn_text'));
      texts.forEach(function(btn){
        btn.classList.remove('active')
      });
      inp.classList.add('active');
    }
  }
};

function setHeaderLines(){
  var lines = Array.prototype.slice.call(document.querySelectorAll('.section__title__line'));
  lines.forEach(function(line){
    line.style.width = ((window.innerWidth-10)-line.previousElementSibling.clientWidth-30)+'px';
  });

  window.addEventListener('resize',function(){
    lines.forEach(function(line){
      line.style.width = ((window.innerWidth-10)-line.previousElementSibling.clientWidth-30)+'px';
    });
  })
}

function adddropdowns(){
  var dropdowns = Array.prototype.slice.call(document.querySelectorAll('.dropdown'));
  dropdowns.forEach(function(list){
    list.style.height = "0px";

    list.previousElementSibling.onclick = function(){
      if(list.style.height && parseInt(list.style.height,10) === 0){
        list.style.height = null;
      }
      else{
        list.style.height = "0px";
      }
    }
  });
}

function addNav(){
  var links = Array.prototype.slice.call(document.querySelectorAll('.link'));
  links.forEach(function(link){
    link.onclick = function(){
      if(this.className.indexOf('active') === -1)
      {
        var pages = Array.prototype.slice.call(document.querySelectorAll('.page'))
        links.forEach(function(l){
          l.classList.remove('active');
        });
        this.classList.add('active');

        pages.forEach(function(page){
          page.classList.remove('active');
        });
        document.querySelector('#'+this.innerHTML.toLowerCase()).classList.add('active');
        setHeaderLines();
      }
    }
  });
}

function addSettings(win){
  var timeInput = document.querySelector('#date_time_input'),
      timeReg = /(\d){2}:(\d){2}:(\d){2}/,
      timecycles = Array.prototype.slice.call(document.querySelectorAll('.time_cycle')),
      cycleReg = /(\d){1,4}/,
      playbtn = document.querySelector("#play"),
      pausebtn = document.querySelector("#pause");
  timeInput.onkeyup = function(){
    var val = this.value;
    if(val.match(timeReg)){
      var vals = val.split(':').map(function(v){return parseInt(v);}),
          legal = true;

      if(vals[0] < 0 || vals[0] > 23){
        legal = false;
      }
      else if(vals[1] < 0 || vals[1] > 59){
        legal = false;
      }
      else if(vals[2] < 0 || vals[2] > 59){
        legal = false;
      }
      if(legal){
        win.postMessage(JSON.stringify({
          time_engine:val
        }),"*");
      }
    }
  }

  timecycles.forEach(function(cycle){
    cycle.onkeyup = function(e){
      var val = this.value;
      if(val.match(cycleReg)){
        val = parseInt(val);
        if(val !== 0 && val < 1441){
          var obj = {};
          obj[this.name] = val;
            win.postMessage(JSON.stringify(obj),"*");
        }
      }
    }
  });

  playbtn.onclick = function(){
    pausebtn.classList.remove('active');
    this.classList.add('active');
    win.postMessage(JSON.stringify({time_play:true}),"*")
  }

  pausebtn.onclick = function(){
    playbtn.classList.remove('active');
    this.classList.add('active');
    win.postMessage(JSON.stringify({time_play:false}),"*")
  }
}<|endoftext|>


<commit_before>const inherits = require('util').inherits;
const EventEmitter = require('events').EventEmitter;
const WebSocketClient = require('./../websocketclient');
const Promise = require('bluebird');

const Requestor = require("./../requestor");
const ShTypeParser = require('./typeparser');

// ----------------------- INIT -----------------------

function SmartHome(config) {
    if (!(this instanceof SmartHome)) return new SmartHome();
    EventEmitter.call(this);

    var that = this;

    if (config.debug) {
        Promise.config({
            // Enable warnings
            warnings: true,
            // Enable long stack traces
            longStackTraces: true,
            // Enable cancellation
            cancellation: true,
            // Enable monitoring
            monitoring: true
        });
    }

    this._requestor = Requestor(config);
    this._parser = new ShTypeParser(this, this._requestor);
    this._authRunning = false;
    this._authServer = null;
    this._wsClient = null;
    this._checkAuthTimer = null;
    this._reinitCount = 0;

    this._initialized = false;

    this._requestor.on("needsAuthorization", function (auth, error) {
        that._authRunning = true;
        that.emit("needsAuthorization", auth, error);
    });

    this._requestor.on("needsMobileAccess", function() {
        that._authRunning = true;
        that.emit("needsMobileAccess");
    });

    this.CurrentConfigurationVersion = 0;
    this.device = [];
    this.capability = [];
    this.location = [];

    this.SHC = null;
}

inherits(SmartHome, EventEmitter);
module.exports = SmartHome;

// ----------------------- CLASS FUNCTIONS -----------------------

SmartHome.prototype.getAuthorizationUri = function () {
    return this._requestor._oAuth2.getAuthorizationStartUri(3000);
};

SmartHome.prototype.startAuthorization = function (callback) {
    if (!this._authRunning) {
        var res = this._requestor._oAuth2.startAuthorization(3000, callback);
        this._authServer = res.server;
        return res;
    } else
        return false;
};

SmartHome.prototype.init = function () {
    var that = this;

    this.CurrentConfigurationVersion = 0;
    this.device = [];
    this.capability = [];
    this.location = [];

    this._reinitCount++;

    that._finalize();

    return that._location().then(function () {
        return that._capability().then(function () {
            return that._capabilityStates().then(function () {
                return that._device().then(function () {
                    that._startCheckAuthorization();
                    that._initialized = true;
                    that._reinitCount = 0;

                    that.emit("initializationComplete", that);

                    setTimeout(function() {
                        that._startRealtimeUpdates().then(function () {
                        }, that._errorHandler);
                    }, 1000);

                    return that;
                }, that._errorHandler);
            }, that._errorHandler);
        }, that._errorHandler);
    }, that._errorHandler);
};

SmartHome.prototype.finalize = function () {
    this._finalize();
    return this._uninitialize();
};

SmartHome.prototype.getObjectFromArrayById = function (aArray, aObjectId) {
    var res = null;

    for (var vIndex in aArray) {
        var aObject = aArray[vIndex];

        if (aObject.id === aObjectId) {
            res = aObject;
            break;
        }
    }

    return res;
};

SmartHome.prototype.getCapabilityById = function (aCapabilityId) {
    return this.getObjectFromArrayById(this.capability, aCapabilityId);
};

SmartHome.prototype.getDeviceById = function (aDeviceId) {
    return this.getObjectFromArrayById(this.device, aDeviceId);
};

SmartHome.prototype.resolveLink = function (aLinkToResolve) {
    var res = null;

    if (aLinkToResolve && (typeof aLinkToResolve === "string")) {
        var objectData = aLinkToResolve.substr(1).split("/");

        if (objectData.length == 2) {

            var type = objectData[0];
            var id = objectData[1];

            if (this.hasOwnProperty(type)) {
                res = this.getObjectFromArrayById(this[type], id);
            }
        }
    }

    if (!res)
        console.log("COULD NOT RESOLVE", aLinkToResolve);

    return res;
};

// ----------------------- INTERNAL CLASS FUNCTIONS -----------------------

SmartHome.prototype._finalize = function () {
    if (this._wsClient) {
        try {
            this._wsClient.close();
        } catch (e) {
            // Ignore
        }

        this._wsClient = null;
    }

    if (this._authServer) {
        this._authServer.close();
        this._authServer = null;
    }

    if (this._checkAuthTimer) {
        clearInterval(this._checkAuthTimer);
        this._checkAuthTimer = null;
    }
};

SmartHome.prototype._errorHandler = function (e, callee) {
    if (!this._initialized)
        return;

    var that = this;

    var checkCallee = function () {
        var res = null;

        if (callee)
            res = callee();

        if (res)
            return res;

        return null;
    };

    that.emit("debug", {type: "error_handler", data: e});

    if (e && e.statusCode) {
        switch (e.statusCode) {
            // Deauthorized
            case 403:
                that.emit("needsMobileAccess");
                that.finalize();
                return;
        }
    }

    if (e && e.error && e.error.errorcode) {
        switch (e.error.errorcode) {
            // Session already exists ...
            case 2006:
                return checkCallee();
                break;
            // Remote access not allowed ...
            case 2010:
                that.emit("needsMobileAccess");
                return that.finalize();
                break;
            // Session not found ...
            case 2012:
                return that._requestor.call("initialize").then(function (config) {
                    if (that.CurrentConfigurationVersion !== config.CurrentConfigurationVersion) {
                        return that.init().then(checkCallee, that._errorHandler);
                    } else {
                        return checkCallee();
                    }
                }, that._errorHandler);

                break;
            // Service timeout ...
            case 1002:
                return Promise.delay(30 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                break;
            // Unknown error ...
            case 1000:
                that.finalize();

                return Promise.delay(60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });
            // SHC offline ...
            case 5006:
                this.emit("warning", {error: "SmartHomeClient is offline! Pleaae check your connection..."});

                that.finalize();

                return Promise.delay(5 * 60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                break;

            default:
                that.finalize();

                return Promise.delay(60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                that.emit("warning", e);
        }
    }
};

SmartHome.prototype._startCheckAuthorization = function () {
    var that = this;

    var hasChangedCapabilities = false;

    if (this._checkAuthTimer) {
        clearTimeout(this._checkAuthTimer);
        this._checkAuthTimer = null;
    }

    var updateCallback = function (capabilityChanged, changes) {
        hasChangedCapabilities = true;

        that.emit("debug", {type: "check_timer_detected_state_change", data: capabilityChanged});
        that.emit("stateChanged", capabilityChanged, changes);
    };

    var checkAuth = function (timerOnly) {

        if (that._checkAuthTimer) {
            clearTimeout(that._checkAuthTimer);
            that._checkAuthTimer = null;
        }

        // Generate a random between 0-30 to add this to the timer.
        // This prevents "syncing" timers on API problems
        var randomMinutes = Math.floor(Math.random() * Math.floor(31));
        var checkTimeout = 1000 * 60 * (30 + randomMinutes);

        that._checkAuthTimer = setTimeout(checkAuth, checkTimeout);

        if (timerOnly === true)
            return;

        hasChangedCapabilities = false;

        that.emit("debug", {type: "check_timer"});

        that._capabilityStates(updateCallback).catch(function (e) {
            return that._errorHandler(e);
        }).then(function (res) {

            that.emit("debug", {type: "check_timer_then"});

            if (hasChangedCapabilities) {
                that.emit("debug", {type: "reinit_realtime_updates_due_to_timer_detected_changes"});
                that._startRealtimeUpdates();
            }

            return res;
        });
    };

    checkAuth(true);
};

SmartHome.prototype._initialize = function () {
    var that = this;

    return new Promise(function (resolve, reject) {
        that._requestor.call("initialize").catch(function (e) {

            console.log(e);

            if (e && e.error && e.error.errorcode === 2006) {

                // Does not work atm as "uninitialize" is broken with the last patch ...
                /*return that.finalize().then(function () {
                    return that._requestor.call("initialize");
                });*/

                resolve();
            }
        }).then(function (config) {
            if (config) {
                that.CurrentConfigurationVersion = config.CurrentConfigurationVersion;

                return that._parser.parseConfig(config.Data[0]).then(function () {
                    resolve(config);
                    return config;
                });
            }
        }, reject);
    });
};

SmartHome.prototype._location = function () {
    var that = this;

    return this._requestor.call("location").then(function (config) {
        return that._parser.parseConfig("location", config).then(function (res) {
            that.location = res;
            return res;
        });
    });
};

SmartHome.prototype._device = function () {
    var that = this;

    return this._requestor.call("device").then(function (config) {
        return that._parser.parseConfig("device", config).then(function (res) {

            for (var dIndex in res) {
                var device = res[dIndex];

                // Resolve location ...
                if (device.location)
                    device.Location = that.resolveLink(device.location);

                // Resolve capabilities ...
                for (var cIndex in device.capabilities) {
                    var capId = device.capabilities[cIndex];

                    var cap = that.resolveLink(capId);

                    if (cap) {
                        device.Capabilities.push(cap);
                    }
                }
            }

            that.device = res;
            return res;
        });
    });
};

SmartHome.prototype._deviceStates = function () {
    var that = this;
    var parser = [];

    return this._requestor.call("device/states").then(function (config) {

        console.log("DEVICE CONFIG", JSON.stringify(config, null, 2));

        config.forEach(function (aConfig) {
            var device = that.getDeviceById(aConfig.Id);

            if (device) {
                console.log("DEVICE CONFIG", JSON.stringify(aConfig, null, 2));
                parser.push(device.parseConfig(aConfig));
            }
        });

        return Promise.all(parser).then(function () {
            return that.device;
        });
    });
};

SmartHome.prototype._capability = function () {
    var that = this;

    return this._requestor.call("capability").then(function (config) {
        return that._parser.parseConfig("capability", config).then(function (res) {
            that.capability = res;
            return res;
        }, function(err) {
            console.log("CAP ERR", err);
        });
    });
};

SmartHome.prototype._capabilityStates = function (callback) {
    var that = this;
    var parser = [];

    return this._requestor.call("capability/states").then(function (config) {

        config.forEach(function (aConfig) {

            var cap = that.getCapabilityById(aConfig.id);

            if (cap) {
                parser.push(cap.parseConfig(aConfig, callback));
            }
        });

        return Promise.all(parser).then(function () {
            return that.capability;
        });
    });
};

SmartHome.prototype._startRealtimeUpdates = function () {
    var that = this;

    var deviceFoundTimer  = null;
    var restartTimer = null;

    var _handleRealTimeEvent = function(event, caller) {

        switch (event.type) {
            case "DeviceFound":
            case "ConfigChanged":
            case "/event/UserDataChanged":
                // Wait at least 10 seconds for new devices ...
                if (deviceFoundTimer)
                    clearTimeout(deviceFoundTimer);

                deviceFoundTimer = setTimeout(function () {
                    caller.init();
                }, 1000 * 10);
                break;
            case "Disconnect":
                if (restartTimer)
                    clearTimeout(restartTimer);

                restartTimer = setTimeout(function () {
                    caller.init();
                }, 1000 * 60);
                break;
            case "DeviceDiscoveryStatusChanged":
                break;
            default:
                if (event && event.source) {
                    var cap = caller.resolveLink(event.source);

                    if (cap) {
                        cap.parseEvent(event);
                        caller.emit("stateChanged", cap);
                    }
                } else {
                    console.log("UNKNOWN EVENT TYPE", event.type);
                    console.log(JSON.stringify(event));
                }
                break;
        }
    };

    var createWebSocket = function(status) {
        var ws = new WebSocketClient('wss://' + that._requestor._config.baseConfig.apiHost + that._requestor._config.baseConfig.versionPrefix + 'events?token=' + status.token.access_token);

        ws.on('message', function (data) {
            var eventData = JSON.parse(data);

            that.emit("debug", {type: "realtime_update_received", data: eventData});

            if (Array.isArray(eventData)) {
                eventData.forEach(function (event) {
                    _handleRealTimeEvent(event, that);
                });
            } else {
                _handleRealTimeEvent(eventData, that);
            }
        });

        ws.on('open', function () {
            that.emit('open', {});
        });

        ws.on('reconnect', function () {
            that.emit('reconnect', {});
        });

        ws.on('error', function (e) {
            that.emit('error', e);
        });

        ws.on('close', function (e) {
            that.emit('close', {code: e});
        });

        that._wsClient = ws;
    };

    return new Promise(function (resolve, reject) {
        that._requestor._oAuth2.getAuthorizationStatus(function (error, status) {
            if (error || !status.token)
                reject(error);
            else {
                if (that._wsClient) {
                    try {
                        that._wsClient.close();
                        that._wsClient = null;
                    } catch (e) {
                        // Ignore
                    }
                }

                createWebSocket(status);
                resolve(that._wsClient);
            }
        });
    });
};<commit_msg>- Upgrade to Innogy API 1.1 - Part III<commit_after>const inherits = require('util').inherits;
const EventEmitter = require('events').EventEmitter;
const WebSocketClient = require('./../websocketclient');
const Promise = require('bluebird');

const Requestor = require("./../requestor");
const ShTypeParser = require('./typeparser');

// ----------------------- INIT -----------------------

function SmartHome(config) {
    if (!(this instanceof SmartHome)) return new SmartHome();
    EventEmitter.call(this);

    var that = this;

    if (config.debug) {
        Promise.config({
            // Enable warnings
            warnings: true,
            // Enable long stack traces
            longStackTraces: true,
            // Enable cancellation
            cancellation: true,
            // Enable monitoring
            monitoring: true
        });
    }

    this._requestor = Requestor(config);
    this._parser = new ShTypeParser(this, this._requestor);
    this._authRunning = false;
    this._authServer = null;
    this._wsClient = null;
    this._checkAuthTimer = null;
    this._reinitCount = 0;

    this._initialized = false;

    this._requestor.on("needsAuthorization", function (auth, error) {
        that._authRunning = true;
        that.emit("needsAuthorization", auth, error);
    });

    this._requestor.on("needsMobileAccess", function() {
        that._authRunning = true;
        that.emit("needsMobileAccess");
    });

    this.CurrentConfigurationVersion = 0;
    this.device = [];
    this.capability = [];
    this.location = [];

    this.SHC = null;
}

inherits(SmartHome, EventEmitter);
module.exports = SmartHome;

// ----------------------- CLASS FUNCTIONS -----------------------

SmartHome.prototype.getAuthorizationUri = function () {
    return this._requestor._oAuth2.getAuthorizationStartUri(3000);
};

SmartHome.prototype.startAuthorization = function (callback) {
    if (!this._authRunning) {
        var res = this._requestor._oAuth2.startAuthorization(3000, callback);
        this._authServer = res.server;
        return res;
    } else
        return false;
};

SmartHome.prototype.init = function () {
    var that = this;

    this.CurrentConfigurationVersion = 0;
    this.device = [];
    this.capability = [];
    this.location = [];

    this._reinitCount++;

    that._finalize();

    return that._location().then(function () {
        return that._capability().then(function () {
            return that._capabilityStates().then(function () {
                return that._device().then(function () {
                    that._startCheckAuthorization();
                    that._initialized = true;
                    that._reinitCount = 0;

                    that.emit("initializationComplete", that);

                    setTimeout(function() {
                        that._startRealtimeUpdates().then(function () {
                        }, that._errorHandler);
                    }, 1000);

                    return that;
                }, that._errorHandler);
            }, that._errorHandler);
        }, that._errorHandler);
    }, that._errorHandler);
};

SmartHome.prototype.finalize = function () {
    this._finalize();
    return this._uninitialize();
};

SmartHome.prototype.getObjectFromArrayById = function (aArray, aObjectId) {
    var res = null;

    for (var vIndex in aArray) {
        var aObject = aArray[vIndex];

        if (aObject.id === aObjectId) {
            res = aObject;
            break;
        }
    }

    return res;
};

SmartHome.prototype.getCapabilityById = function (aCapabilityId) {
    return this.getObjectFromArrayById(this.capability, aCapabilityId);
};

SmartHome.prototype.getDeviceById = function (aDeviceId) {
    return this.getObjectFromArrayById(this.device, aDeviceId);
};

SmartHome.prototype.getDeviceByCapability = function(aCapability) {
  var res = null;
  var that = this;

  this.device.forEach(function(aDevice) {
     var cap =  that.getObjectFromArrayById(aDevice.Capabilities, aCapability.id);

     if (cap)
         res = aDevice;
  });

  return res;
};

SmartHome.prototype.resolveLink = function (aLinkToResolve) {
    var res = null;

    if (aLinkToResolve && (typeof aLinkToResolve === "string")) {
        var objectData = aLinkToResolve.substr(1).split("/");

        if (objectData.length == 2) {

            var type = objectData[0];
            var id = objectData[1];

            if (this.hasOwnProperty(type)) {
                res = this.getObjectFromArrayById(this[type], id);
            }
        }
    }

    if (!res)
        console.log("COULD NOT RESOLVE", aLinkToResolve);

    return res;
};

// ----------------------- INTERNAL CLASS FUNCTIONS -----------------------

SmartHome.prototype._finalize = function () {
    if (this._wsClient) {
        try {
            this._wsClient.close();
        } catch (e) {
            // Ignore
        }

        this._wsClient = null;
    }

    if (this._authServer) {
        this._authServer.close();
        this._authServer = null;
    }

    if (this._checkAuthTimer) {
        clearInterval(this._checkAuthTimer);
        this._checkAuthTimer = null;
    }
};

SmartHome.prototype._errorHandler = function (e, callee) {
    if (!this._initialized)
        return;

    var that = this;

    var checkCallee = function () {
        var res = null;

        if (callee)
            res = callee();

        if (res)
            return res;

        return null;
    };

    that.emit("debug", {type: "error_handler", data: e});

    if (e && e.statusCode) {
        switch (e.statusCode) {
            // Deauthorized
            case 403:
                that.emit("needsMobileAccess");
                that.finalize();
                return;
        }
    }

    if (e && e.error && e.error.errorcode) {
        switch (e.error.errorcode) {
            // Session already exists ...
            case 2006:
                return checkCallee();
                break;
            // Remote access not allowed ...
            case 2010:
                that.emit("needsMobileAccess");
                return that.finalize();
                break;
            // Session not found ...
            case 2012:
                return that._requestor.call("initialize").then(function (config) {
                    if (that.CurrentConfigurationVersion !== config.CurrentConfigurationVersion) {
                        return that.init().then(checkCallee, that._errorHandler);
                    } else {
                        return checkCallee();
                    }
                }, that._errorHandler);

                break;
            // Service timeout ...
            case 1002:
                return Promise.delay(30 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                break;
            // Unknown error ...
            case 1000:
                that.finalize();

                return Promise.delay(60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });
            // SHC offline ...
            case 5006:
                this.emit("warning", {error: "SmartHomeClient is offline! Pleaae check your connection..."});

                that.finalize();

                return Promise.delay(5 * 60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                break;

            default:
                that.finalize();

                return Promise.delay(60 * 1000).then(function () {
                    return that.init().then(checkCallee, that._errorHandler);
                });

                that.emit("warning", e);
        }
    }
};

SmartHome.prototype._startCheckAuthorization = function () {
    var that = this;

    var hasChangedCapabilities = false;

    if (this._checkAuthTimer) {
        clearTimeout(this._checkAuthTimer);
        this._checkAuthTimer = null;
    }

    var updateCallback = function (capabilityChanged, changes) {
        hasChangedCapabilities = true;

        that.emit("debug", {type: "check_timer_detected_state_change", data: capabilityChanged});
        that.emit("stateChanged", capabilityChanged, changes);
    };

    var checkAuth = function (timerOnly) {

        if (that._checkAuthTimer) {
            clearTimeout(that._checkAuthTimer);
            that._checkAuthTimer = null;
        }

        // Generate a random between 0-30 to add this to the timer.
        // This prevents "syncing" timers on API problems
        var randomMinutes = Math.floor(Math.random() * Math.floor(31));
        var checkTimeout = 1000 * 60 * (30 + randomMinutes);

        that._checkAuthTimer = setTimeout(checkAuth, checkTimeout);

        if (timerOnly === true)
            return;

        hasChangedCapabilities = false;

        that.emit("debug", {type: "check_timer"});

        that._capabilityStates(updateCallback).catch(function (e) {
            return that._errorHandler(e);
        }).then(function (res) {

            that.emit("debug", {type: "check_timer_then"});

            if (hasChangedCapabilities) {
                that.emit("debug", {type: "reinit_realtime_updates_due_to_timer_detected_changes"});
                that._startRealtimeUpdates();
            }

            return res;
        });
    };

    checkAuth(true);
};

SmartHome.prototype._initialize = function () {
    var that = this;

    return new Promise(function (resolve, reject) {
        that._requestor.call("initialize").catch(function (e) {

            console.log(e);

            if (e && e.error && e.error.errorcode === 2006) {

                // Does not work atm as "uninitialize" is broken with the last patch ...
                /*return that.finalize().then(function () {
                    return that._requestor.call("initialize");
                });*/

                resolve();
            }
        }).then(function (config) {
            if (config) {
                that.CurrentConfigurationVersion = config.CurrentConfigurationVersion;

                return that._parser.parseConfig(config.Data[0]).then(function () {
                    resolve(config);
                    return config;
                });
            }
        }, reject);
    });
};

SmartHome.prototype._location = function () {
    var that = this;

    return this._requestor.call("location").then(function (config) {
        return that._parser.parseConfig("location", config).then(function (res) {
            that.location = res;
            return res;
        });
    });
};

SmartHome.prototype._device = function () {
    var that = this;

    return this._requestor.call("device").then(function (config) {
        return that._parser.parseConfig("device", config).then(function (res) {

            for (var dIndex in res) {
                var device = res[dIndex];

                // Resolve location ...
                if (device.location)
                    device.Location = that.resolveLink(device.location);

                // Resolve capabilities ...
                for (var cIndex in device.capabilities) {
                    var capId = device.capabilities[cIndex];

                    var cap = that.resolveLink(capId);

                    if (cap) {
                        device.Capabilities.push(cap);
                    }
                }
            }

            that.device = res;
            return res;
        });
    });
};

SmartHome.prototype._capability = function () {
    var that = this;

    return this._requestor.call("capability").then(function (config) {
        return that._parser.parseConfig("capability", config).then(function (res) {
            that.capability = res;
            return res;
        }, function(err) {
            console.log("CAP ERR", err);
        });
    });
};

SmartHome.prototype._capabilityStates = function (callback) {
    var that = this;
    var parser = [];

    return this._requestor.call("capability/states").then(function (config) {

        config.forEach(function (aConfig) {

            var cap = that.getCapabilityById(aConfig.id);

            if (cap) {
                parser.push(cap.parseConfig(aConfig, callback));
            }
        });

        return Promise.all(parser).then(function () {
            return that.capability;
        });
    });
};

SmartHome.prototype._startRealtimeUpdates = function () {
    var that = this;

    var deviceFoundTimer  = null;
    var restartTimer = null;

    var _handleRealTimeEvent = function(event, caller) {

        switch (event.type) {
            case "DeviceFound":
            case "ConfigChanged":
            case "/event/UserDataChanged":
                // Wait at least 10 seconds for new devices ...
                if (deviceFoundTimer)
                    clearTimeout(deviceFoundTimer);

                deviceFoundTimer = setTimeout(function () {
                    caller.init();
                }, 1000 * 10);
                break;
            case "Disconnect":
                if (restartTimer)
                    clearTimeout(restartTimer);

                restartTimer = setTimeout(function () {
                    caller.init();
                }, 1000 * 60);
                break;
            case "DeviceDiscoveryStatusChanged":
                break;
            default:
                if (event && event.source) {
                    var cap = caller.resolveLink(event.source);

                    if (cap) {
                        cap.parseEvent(event);
                        caller.emit("stateChanged", cap);
                    }
                } else {
                    console.log("UNKNOWN EVENT TYPE", event.type);
                    console.log(JSON.stringify(event));
                }
                break;
        }
    };

    var createWebSocket = function(status) {
        var ws = new WebSocketClient('wss://' + that._requestor._config.baseConfig.apiHost + that._requestor._config.baseConfig.versionPrefix + 'events?token=' + status.token.access_token);

        ws.on('message', function (data) {
            var eventData = JSON.parse(data);

            that.emit("debug", {type: "realtime_update_received", data: eventData});

            if (Array.isArray(eventData)) {
                eventData.forEach(function (event) {
                    _handleRealTimeEvent(event, that);
                });
            } else {
                _handleRealTimeEvent(eventData, that);
            }
        });

        ws.on('open', function () {
            that.emit('open', {});
        });

        ws.on('reconnect', function () {
            that.emit('reconnect', {});
        });

        ws.on('error', function (e) {
            that.emit('error', e);
        });

        ws.on('close', function (e) {
            that.emit('close', {code: e});
        });

        that._wsClient = ws;
    };

    return new Promise(function (resolve, reject) {
        that._requestor._oAuth2.getAuthorizationStatus(function (error, status) {
            if (error || !status.token)
                reject(error);
            else {
                if (that._wsClient) {
                    try {
                        that._wsClient.close();
                        that._wsClient = null;
                    } catch (e) {
                        // Ignore
                    }
                }

                createWebSocket(status);
                resolve(that._wsClient);
            }
        });
    });
};<|endoftext|>


<commit_before>$.getJSON('/courts', function (allData) {
    var data = [].concat(allData.meilahti, allData.herttoniemi)
    var sameDates = _.sortBy(_.map(_.groupBy(data, 'date'), objectToArray), 'key')

    $('.schedule').html(sameDates.map(function (obj) {
        var isoDate = obj.key
        var times = obj.val
        return '
' + new Date(isoDate).toDateString() + '
' +
        _.sortBy(_.map(_.groupBy(times, 'time'), objectToArray), 'key') .map(function (obj2) {
            var isoTime = obj2.key
            var fields = obj2.val
            return '
' + isoTime + '' +
            fields.map(function (field) {
                return '<button type="button" class="btn btn-' +
                    (field.location === 'meilahti' ? 'primary' : 'success') +
                    ' btn-xs">' + field.field + '</button>'
            }).join('')+'
'
        }).join('')
    }).join(''))
})

function objectToArray(val, key) { return { key: key, val:val}}
<commit_msg>Rename variables<commit_after>$.getJSON('/courts', function (allData) {
    var data = [].concat(allData.meilahti, allData.herttoniemi)
    var sameDates = _.sortBy(_.map(_.groupBy(data, 'date'), objectToArray), 'key')

    $('.schedule').html(sameDates.map(function (dateObject) {
        var isoDate = dateObject.key
        var times = dateObject.val
        return '
' + new Date(isoDate).toDateString() + '
' +
        _.sortBy(_.map(_.groupBy(times, 'time'), objectToArray), 'key') .map(function (timeObject) {
            var isoTime = timeObject.key
            var fields = timeObject.val
            return '
' + isoTime + '' +
            fields.map(function (field) {
                return '<button type="button" class="btn btn-' +
                    (field.location === 'meilahti' ? 'primary' : 'success') +
                    ' btn-xs">' + field.field + '</button>'
            }).join('')+'
'
        }).join('')
    }).join(''))
})

function objectToArray(val, key) { return { key: key, val:val}}
<|endoftext|>


<commit_before>Google = {};

// https://developers.google.com/accounts/docs/OAuth2Login#userinfocall
Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name',
                   'family_name', 'picture', 'locale', 'timezone', 'gender'];

OAuth.registerService('google', 2, null, function(query) {

  var response = getTokens(query);
  var accessToken = response.accessToken;
  var identity = getIdentity(accessToken);

  var serviceData = {
    accessToken: accessToken,
    expiresAt: (+new Date) + (1000 * response.expiresIn)
  };

  var fields = _.pick(identity, Google.whitelistedFields);
  _.extend(serviceData, fields);

  // only set the token in serviceData if it's there. this ensures
  // that we don't lose old ones (since we only get this on the first
  // log in attempt)
  if (response.refreshToken)
    serviceData.refreshToken = response.refreshToken;

  return {
    serviceData: serviceData,
    options: {profile: {name: identity.name}}
  };
});

// returns an object containing:
// - accessToken
// - expiresIn: lifetime of token in seconds
// - refreshToken, if this is the first authorization request
var getTokens = function (query) {
  var config = ServiceConfiguration.configurations.findOne({service: 'google'});
  if (!config)
    throw new ServiceConfiguration.ConfigError();

  var response;
  try {
    response = HTTP.post(
      "https://accounts.google.com/o/oauth2/token", {params: {
        code: query.code,
        client_id: config.clientId,
        client_secret: OAuth.openSecret(config.secret),
        redirect_uri: Meteor.absoluteUrl("_oauth/google?close"),
        grant_type: 'authorization_code'
      }});
  } catch (err) {
    throw _.extend(new Error("Failed to complete OAuth handshake with Google. " + err.message),
                   {response: err.response});
  }

  if (response.data.error) { // if the http response was a json object with an error attribute
    throw new Error("Failed to complete OAuth handshake with Google. " + response.data.error);
  } else {
    return {
      accessToken: response.data.access_token,
      refreshToken: response.data.refresh_token,
      expiresIn: response.data.expires_in
    };
  }
};

var getIdentity = function (accessToken) {
  try {
    return HTTP.get(
      "https://www.googleapis.com/oauth2/v1/userinfo",
      {params: {access_token: accessToken}}).data;
  } catch (err) {
    throw _.extend(new Error("Failed to fetch identity from Google. " + err.message),
                   {response: err.response});
  }
};

Google.retrieveCredential = function(credentialToken) {
  return OAuth.retrieveCredential(credentialToken);
};
<commit_msg>Add credentialSecret to `Google.retrieveCredential`<commit_after>Google = {};

// https://developers.google.com/accounts/docs/OAuth2Login#userinfocall
Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name',
                   'family_name', 'picture', 'locale', 'timezone', 'gender'];

OAuth.registerService('google', 2, null, function(query) {

  var response = getTokens(query);
  var accessToken = response.accessToken;
  var identity = getIdentity(accessToken);

  var serviceData = {
    accessToken: accessToken,
    expiresAt: (+new Date) + (1000 * response.expiresIn)
  };

  var fields = _.pick(identity, Google.whitelistedFields);
  _.extend(serviceData, fields);

  // only set the token in serviceData if it's there. this ensures
  // that we don't lose old ones (since we only get this on the first
  // log in attempt)
  if (response.refreshToken)
    serviceData.refreshToken = response.refreshToken;

  return {
    serviceData: serviceData,
    options: {profile: {name: identity.name}}
  };
});

// returns an object containing:
// - accessToken
// - expiresIn: lifetime of token in seconds
// - refreshToken, if this is the first authorization request
var getTokens = function (query) {
  var config = ServiceConfiguration.configurations.findOne({service: 'google'});
  if (!config)
    throw new ServiceConfiguration.ConfigError();

  var response;
  try {
    response = HTTP.post(
      "https://accounts.google.com/o/oauth2/token", {params: {
        code: query.code,
        client_id: config.clientId,
        client_secret: OAuth.openSecret(config.secret),
        redirect_uri: Meteor.absoluteUrl("_oauth/google?close"),
        grant_type: 'authorization_code'
      }});
  } catch (err) {
    throw _.extend(new Error("Failed to complete OAuth handshake with Google. " + err.message),
                   {response: err.response});
  }

  if (response.data.error) { // if the http response was a json object with an error attribute
    throw new Error("Failed to complete OAuth handshake with Google. " + response.data.error);
  } else {
    return {
      accessToken: response.data.access_token,
      refreshToken: response.data.refresh_token,
      expiresIn: response.data.expires_in
    };
  }
};

var getIdentity = function (accessToken) {
  try {
    return HTTP.get(
      "https://www.googleapis.com/oauth2/v1/userinfo",
      {params: {access_token: accessToken}}).data;
  } catch (err) {
    throw _.extend(new Error("Failed to fetch identity from Google. " + err.message),
                   {response: err.response});
  }
};

Google.retrieveCredential = function(credentialToken, credentialSecret) {
  return OAuth.retrieveCredential(credentialToken, credentialSecret);
};
<|endoftext|>


<commit_before>import TurndownService from "turndown";
import { gfm } from "turndown-plugin-gfm";

var turndownService = new TurndownService({
	hr: "---",
	headingStyle: "atx",
	bulletListMarker: "*",
	codeBlockStyle: "fenced"
});

turndownService.use(gfm);
turndownService.addRule('article', {
	filter: ['span', 'article'],
	replacement: function(content) {
		return content;
	}
});
turndownService.addRule('div', {
	filter: ['div'],
	replacement: function(content) {
		return '\n' + content + '\n';
	}
});
turndownService.addRule('script', {
	filter: ['script', 'noscript', 'form', 'nav', 'iframe', 'input'],
	replacement: function(content) {
		return '';
	}
});

export default {

	parseScript() {
		var elements = [
			"document.querySelector('article') ? document.querySelector('article').innerHTML",
			"document.querySelector('#article_item') ? document.querySelector('#article_item').innerHTML",
			"document.querySelector('*[role=\"article\"]') ? document.querySelector('*[role=\"article\"]').innerHTML",
			"document.querySelector('*[role=\"main\"]') ? document.querySelector('*[role=\"main\"]').innerHTML",
			"document.querySelector('.post-container') ? document.querySelector('.post-container').innerHTML",
			"document.querySelector('.content-body') ? document.querySelector('.content-body').innerHTML",
			"document.querySelector('p + p + p + p') ? document.querySelector('p + p + p + p').parentNode.innerHTML",
			"document.querySelector('body').innerHTML"
		];

		return elements.join(' : ');
	},

	convert(html_source, page_url, page_title) {
		var new_md = turndownService.turndown(html_source);
		new_md = new_md.replace(/\n+/gi, '\n');
		new_md = new_md.replace(/(!\[\]\(.+?\))(\s*\1+)/gi, '$1');
		new_md = new_md.replace(/(\[!\[.*?\].+?\]\(.+?\))/gi, '\n$1\n');
		new_md = new_md.replace(/\]\(\/\//gi, '](http://');

		if (!new_md.match(/^# /gm)) {
			new_md = '# ' + page_title + '\n\n' + new_md;
		}

		if (new_md && page_url) new_md = '[Source](' + page_url + ')\n\n' + new_md;

		return new_md;
	}
};
<commit_msg>article body<commit_after>import TurndownService from "turndown";
import { gfm } from "turndown-plugin-gfm";

var turndownService = new TurndownService({
	hr: "---",
	headingStyle: "atx",
	bulletListMarker: "*",
	codeBlockStyle: "fenced"
});

turndownService.use(gfm);
turndownService.addRule('article', {
	filter: ['span', 'article'],
	replacement: function(content) {
		return content;
	}
});
turndownService.addRule('div', {
	filter: ['div'],
	replacement: function(content) {
		return '\n' + content + '\n';
	}
});
turndownService.addRule('script', {
	filter: ['script', 'noscript', 'form', 'nav', 'iframe', 'input'],
	replacement: function(content) {
		return '';
	}
});

export default {

	parseScript() {
		var elements = [
			"document.querySelector('article') ? document.querySelector('article').innerHTML",
			"document.querySelector('#article_item') ? document.querySelector('#article_item').innerHTML",
			"document.querySelector('*[role=\"article\"]') ? document.querySelector('*[role=\"article\"]').innerHTML",
			"document.querySelector('*[itemprop=\"articleBody\"]') ? document.querySelector('*[itemprop=\"articleBody\"]').parentNode.innerHTML",
			"document.querySelector('*[role=\"main\"]') ? document.querySelector('*[role=\"main\"]').innerHTML",
			"document.querySelector('.post-container') ? document.querySelector('.post-container').innerHTML",
			"document.querySelector('.content-body') ? document.querySelector('.content-body').innerHTML",
			"document.querySelector('p + p + p + p') ? document.querySelector('p + p + p + p').parentNode.innerHTML",
			"document.querySelector('body').innerHTML"
		];

		return elements.join(' : ');
	},

	convert(html_source, page_url, page_title) {
		var new_md = turndownService.turndown(html_source);
		new_md = new_md.replace(/\n+/gi, '\n');
		new_md = new_md.replace(/(!\[\]\(.+?\))(\s*\1+)/gi, '$1');
		new_md = new_md.replace(/(\[!\[.*?\].+?\]\(.+?\))/gi, '\n$1\n');
		new_md = new_md.replace(/\]\(\/\//gi, '](http://');

		if (!new_md.match(/^# /gm)) {
			new_md = '# ' + page_title + '\n\n' + new_md;
		}

		if (new_md && page_url) new_md = '[Source](' + page_url + ')\n\n' + new_md;

		return new_md;
	}
};
<|endoftext|>