<commit_before>const { AkairoClient, CommandHandler, InhibitorHandler, ListenerHandler } = require('discord-akairo');
const { Collection } = require('discord.js');
const Database = require('./Database');
const path = require('path');
const SettingsProvider = require('./SettingsProviders');
const Setting = require('../models/settings');

class HoshiClient extends AkairoClient {
	constructor(config) {
		super({ ownerID: config.owner }, {
			messageCacheMaxSize: 50,
			messageCacheLifetime: 300,
			messageSweepInterval: 900,
			disableEveryone: true,
			disabledEvents: ['TYPING_START'],
			partials: ['MESSAGE']
		});

		this.commandHandler = new CommandHandler(this, {
			directory: path.join(__dirname, '..', 'commands'),
			aliasReplacement: /-/g,
			prefix: message => this.settings.get(message.guild, 'prefix', '*'),
			allowMention: true,
			fetchMembers: true,
			commandUtil: true,
			commandUtilLifetime: 3e5,
			commandUtilSweepInterval: 9e5,
			handleEdits: true,
			defaultCooldown: 2500,
			argumentDefaults: {
				prompt: {
					modifyStart: (msg, text) => text && `${msg.author} **::** ${text}\nType \`cancel\` to cancel this command.`,
					modifyRetry: (msg, text) => text && `${msg.author} **::** ${text}\nType \`cancel\` to cancel this command.`,
					timeout: msg => `${msg.author} **::** Time ran out, command has been cancelled.`,
					ended: msg => `${msg.author} **::** Too many retries, command has been cancelled.`,
					cancel: msg => `${msg.author} **::** Command has been cancelled.`,
					retries: 4,
					time: 30000
				}
			}
		});

		this.inhibitorHandler = new InhibitorHandler(this, { directory: path.join(__dirname, '..', 'inhibitors') });
		this.listenerHandler = new ListenerHandler(this, { directory: path.join(__dirname, '..', 'listeners') });

		this.config = config;
		this.settings = new SettingsProvider(Setting);
		this.starboards = new Collection();

		this.setup();

		setInterval(() => {
			for (const guild of this.guilds.values()) {
				guild.presences.clear();
			}
		}, 900);
	}

	setup() {
		this.commandHandler.useInhibitorHandler(this.inhibitorHandler);
		this.commandHandler.useListenerHandler(this.listenerHandler);
		this.listenerHandler.setEmitters({
			commandHandler: this.commandHandler,
			inhibitorHandler: this.inhibitorHandler,
			listenerHandler: this.listenerHandler
		});

		this.commandHandler.loadAll();
		this.inhibitorHandler.loadAll();
		this.listenerHandler.loadAll();
	}

	async start() {
		await Database.authenticate();
		await this.settings.init();
		return this.login(this.config.token);
	}
}

module.exports = HoshiClient;
<commit_msg>Clear presences every 15 minutes<commit_after>const { AkairoClient, CommandHandler, InhibitorHandler, ListenerHandler } = require('discord-akairo');
const { Collection } = require('discord.js');
const Database = require('./Database');
const path = require('path');
const SettingsProvider = require('./SettingsProviders');
const Setting = require('../models/settings');

class HoshiClient extends AkairoClient {
	constructor(config) {
		super({ ownerID: config.owner }, {
			messageCacheMaxSize: 50,
			messageCacheLifetime: 300,
			messageSweepInterval: 900,
			disableEveryone: true,
			disabledEvents: ['TYPING_START'],
			partials: ['MESSAGE']
		});

		this.commandHandler = new CommandHandler(this, {
			directory: path.join(__dirname, '..', 'commands'),
			aliasReplacement: /-/g,
			prefix: message => this.settings.get(message.guild, 'prefix', '*'),
			allowMention: true,
			fetchMembers: true,
			commandUtil: true,
			commandUtilLifetime: 3e5,
			commandUtilSweepInterval: 9e5,
			handleEdits: true,
			defaultCooldown: 2500,
			argumentDefaults: {
				prompt: {
					modifyStart: (msg, text) => text && `${msg.author} **::** ${text}\nType \`cancel\` to cancel this command.`,
					modifyRetry: (msg, text) => text && `${msg.author} **::** ${text}\nType \`cancel\` to cancel this command.`,
					timeout: msg => `${msg.author} **::** Time ran out, command has been cancelled.`,
					ended: msg => `${msg.author} **::** Too many retries, command has been cancelled.`,
					cancel: msg => `${msg.author} **::** Command has been cancelled.`,
					retries: 4,
					time: 30000
				}
			}
		});

		this.inhibitorHandler = new InhibitorHandler(this, { directory: path.join(__dirname, '..', 'inhibitors') });
		this.listenerHandler = new ListenerHandler(this, { directory: path.join(__dirname, '..', 'listeners') });

		this.config = config;
		this.settings = new SettingsProvider(Setting);
		this.starboards = new Collection();

		this.setup();

		setInterval(() => {
			for (const guild of this.guilds.values()) {
				guild.presences.clear();
			}
		}, 9e5);
	}

	setup() {
		this.commandHandler.useInhibitorHandler(this.inhibitorHandler);
		this.commandHandler.useListenerHandler(this.listenerHandler);
		this.listenerHandler.setEmitters({
			commandHandler: this.commandHandler,
			inhibitorHandler: this.inhibitorHandler,
			listenerHandler: this.listenerHandler
		});

		this.commandHandler.loadAll();
		this.inhibitorHandler.loadAll();
		this.listenerHandler.loadAll();
	}

	async start() {
		await Database.authenticate();
		await this.settings.init();
		return this.login(this.config.token);
	}
}

module.exports = HoshiClient;
<|endoftext|>


<commit_before>'use strict';

/**
 * The MIT License (MIT)
 *
 * Copyright (C) 2015 hellosign.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

var http = require('http');
var https = require('https');
var request = require('request');
var path = require('path');
var when = require('when');
var FormData = require('form-data');
var utils = require('./utils');
var Error = require('./Error');
var fs = require('fs');

var hasOwn = {}.hasOwnProperty;

// Provide extension mechanism for HelloSign Resource Sub-Classes
HelloSignResource.extend = utils.protoExtend;

// Expose method-creator & prepared (basic) methods
HelloSignResource.method = require('./HelloSignMethod');
HelloSignResource.BASIC_METHODS = require('./HelloSignMethod.basic');

/**
 * Encapsulates request logic for a HelloSign Resource
 */
function HelloSignResource(hellosign, urlData) {

    this._hellosign = hellosign;
    this._urlData = urlData || {};

    this.basePath = utils.makeURLInterpolator(hellosign.getApiField('basePath'));
    this.path = utils.makeURLInterpolator(this.path);

    if (this.includeBasic) {
        this.includeBasic.forEach(function(methodName) {
            this[methodName] = HelloSignResource.BASIC_METHODS[methodName];
        }, this);
    }

    this.initialize.apply(this, arguments);

}

HelloSignResource.prototype = {

    path: '',

    initialize: function() {},

    createFullPath: function(commandPath, urlData, oauthRequest) {

        var pathPrefix = oauthRequest === true ? "/" : this.basePath(urlData);

        return path.join(
            pathPrefix,
            this.path(urlData),
                typeof commandPath == 'function' ?
                commandPath(urlData) : commandPath
        ).replace(/\\/g, '/'); // ugly workaround for Windows
    },

    createUrlData: function() {
        var urlData = {};
        // Merge in baseData
        for (var i in this._urlData) {
            if (hasOwn.call(this._urlData, i)) {
                urlData[i] = this._urlData[i];
            }
        }
        return urlData;
    },

    createDeferred: function(callback) {
        var deferred = when.defer();

        if (callback) {
            // Callback, if provided, is a simply translated to Promise'esque:
            // (Ensure callback is called outside of promise stack)
            deferred.promise.then(function(res) {
                setTimeout(function(){
                    callback(null, res)
                }, 0);
            }, function(err) {
                setTimeout(function(){
                    callback(err, null);
                }, 0);
            });
        }

        return deferred;
    },

    _timeoutHandler: function(timeout, req, callback) {
        var self = this;
        return function() {
            var timeoutErr = new Error('ETIMEDOUT');
            timeoutErr.code = 'ETIMEDOUT';

            req._isAborted = true;
            req.abort();

            callback.call(
                self,
                new Error.HelloSignConnectionError({
                    message: 'Request aborted due to timeout being reached (' + timeout + 'ms)',
                    detail: timeoutErr
                }),
                null
            );
        }
    },

    _responseHandler: function(req, callback) {

        var self = this;
        return function(res) {
            var resHeaders = res.headers;
            var statusCode = res.statusCode;
            var statusMessage = res.statusMessage;

            if ('content-type' in resHeaders && resHeaders['content-type'].indexOf("application/json") !== -1){

                var response = '';
                res.setEncoding('utf8');
                res.on('data', function(chunk) {
                    response += chunk;
                });
                res.on('end', function() {
                    try {
                        if(response == "\n" || response == ""){
                            response = {};
                        } else {
                            response = JSON.parse(response);
                        }

                        response.statusCode = statusCode;
                        response.statusMessage = statusMessage;

                        if (response.error) {
                            var err;
                            var err_data = {};
                            if(typeof response.error === 'object'){
                                err_data = response.error;
                            } else if(typeof response.error === 'string'){
                                err_data['error_name'] = response.error;
                                err_data['error_msg'] = response.error_description;
                            }

                            err = Error.HelloSignError.generate(err_data);
                            return callback.call(self, err, null);
                        }
                    } catch (e) {
                        return callback.call(
                            self,
                            new Error.HelloSignAPIError({
                                message: 'Invalid JSON received from the HelloSign API',
                                response: response,
                                exception: e
                            }),
                            null
                        );
                    }
                    callback.call(self, null, response);
                });
            } else if ('content-transfer-encoding' in resHeaders && resHeaders['content-transfer-encoding'] == "binary"){
                callback.call(self, null, res);
            // Simplified response for code-only statuses
            } else if ('content-length' in resHeaders && resHeaders['content-length'] == "1") {
                response = {};
                response.statusCode = statusCode;
                response.statusMessage = statusMessage;
                callback.call(self, null, response);
            }
        };
    },

    _errorHandler: function(req, callback) {
        var self = this;
        return function(error) {
            if (req._isAborted) return; // already handled
            if (!error || !error.message) {
                error = {
                    message: 'An error occurred with our connection to HelloSign',
                    detail: error
                };
            }
            callback.call(
                self,
                new Error.HelloSignConnectionError(error),
                null
            );
        }
    },
    _prepareOpts : function(data){

        if('signers' in data && Array.isArray(data.signers)){
            for(var i=0; i<data.signers.length;i++) {
                for(var signerIndex in data.signers[i]){
                    if(data.signers[i].hasOwnProperty(signerIndex)){
                        if('role' in data.signers[i]){
                            if(signerIndex == 'role'){
                                continue;
                            }
                            data["signers[" + data.signers[i]['role'] + "][" + signerIndex + "]"] = data.signers[i][signerIndex];
                        } else {
                            data["signers[" + i + "][" + signerIndex + "]"] = data.signers[i][signerIndex];
                        }
                    }
                }
            }
            delete data.signers;
        }
        if('cc_email_addresses' in data && Array.isArray(data.cc_email_addresses)){
            for(var i=0; i<data.cc_email_addresses.length;i++) {
                if(typeof data.cc_email_addresses[i]){
                    data["cc_email_addresses[" + i + "]"] = data.cc_email_addresses[i];
                }
            }
            delete data.cc_email_addresses;
        }

        //embedded endpoints adds
        if ('cc_roles' in data && Array.isArray(data.cc_email_addresses)) {
            for(var i=0; i < data.cc_roles.length; i++) {
                if(typeof data.cc_roles[i]){
                    data['cc_roles['+ i + ']'] = data.cc_roles[i];
                }
            }
            delete data.cc_roles;
        }

        if ('ccs' in data && Array.isArray(data.ccs)){
            for (var i=0; i < data.ccs.length; i++){
                data['ccs[' + data.ccs[i]['role_name'] + '][email_address]'] = data.ccs[i].email_address;
            }
            delete data.ccs;
        }

        if ('signer_roles' in data && Array.isArray(data.signer_roles)){
            for(var i=0; i < data.signer_roles.length; i++){
                if(data.signer_roles[i].hasOwnProperty('name')) {
                    data['signer_roles[' + i + '][name]'] = data.signer_roles[i]['name'];
                }
                if(data.signer_roles[i].hasOwnProperty('order')) {
                    data['signer_roles[' + i + '][order]'] = data.signer_roles[i]['order'];
                }
            }
            delete data.signer_roles;
        }

        if ('merge_fields' in data && Array.isArray(data.merge_fields)){
            data.merge_fields = JSON.stringify(data.merge_fields);
        }

        if ('custom_fields' in data && Array.isArray(data.custom_fields)){
            data.custom_fields = JSON.stringify(data.custom_fields);
        }

        if('template_ids' in data && Array.isArray(data.template_ids)){
            for(var i=0; i<data.template_ids.length;i++) {
                if(typeof data.template_ids[i]){
                    data["template_ids[" + i + "]"] = data.template_ids[i];
                }
            }
            delete data.template_ids;
        }

        if('templates' in data && Array.isArray(data.templates)){
            for(var i=0; i<data.templates.length;i++) {
                for(var templateIndex in data.templates[i]){
                    if(data.templates[i].hasOwnProperty(templateIndex)){
                        data["templates[" + i + "][" + templateIndex + "]"] = data.templates[i][templateIndex];
                    }
                }
            }
            delete data.templates;
        }

        if ('form_fields_per_document' in data && Array.isArray(data.form_fields_per_document)){
            data.form_fields_per_document = JSON.stringify(data.form_fields_per_document);
        }

        // Deprecated, but saving for compatibility
        if('clientId' in data) {
            data['client_id'] = data.clientId;
            delete data.clientId;
        }

        // Correct syntax; will overwrite the above.
        if('client_id' in data) {
            data['client_id'] = data.client_id;
        }

        for(var prop in data){
            if (data.hasOwnProperty(prop)){
                if (typeof data[prop] === "object" && prop != "files"){
                    for(var paramName in data[prop]){
                        if(data[prop].hasOwnProperty(paramName)){
                            data[prop + "[" + paramName + "]"] = data[prop][paramName];
                        }
                    }
                    delete data[prop];
                }
            }
        }

        if('files' in data && Array.isArray(data.files)){
            // submit as form
            var form = new FormData();
            for(var i=0; i<data.files.length;i++) {
                form.append("file[" + i + "]", fs.createReadStream(data.files[i]));
            }
            delete data.files;
            for(var paramName in data){
                if(data.hasOwnProperty(paramName)){
                    form.append(paramName, data[paramName]);
                }
            }
            return {requestData: "", formData: form}
        } else {
            var requestData = utils.stringifyRequestData(data || {});
            return {requestData: requestData, formData: null}
        }
    },
    _request: function(method, path, data, auth, callback) {
        var self = this;
        var apiVersion = this._hellosign.getApiField('version');
        var headers = this._setDefaultHeaders(auth);
        var preparedData = this._prepareOpts(data);

        var form = preparedData.formData;
        var requestData = preparedData.requestData;

        if(form){
            var formHeaders = form.getHeaders();
            for (var i in formHeaders) {
                // Prevent duplicate headers, using form values when sending files
                if (i === 'content-type') {
                  headers['Content-Type'] = formHeaders[i];
                  continue;
                }
                if (hasOwn.call(formHeaders, i)) {
                    headers[i] = formHeaders[i];
                }
            }
        }

        if (apiVersion) {
            headers['HelloSign-Version'] = apiVersion;
        }
        makeRequest();
        function makeRequest() {

            var timeout = self._hellosign.getApiField('timeout');
            var isInsecureConnection = self._hellosign.getApiField('protocol') == 'http';
            var host = self._hellosign.getApiField('host');
            var host = path.indexOf('oauth') === -1 ? host : host.replace('api', 'app');
            // Add params for dev environment
            path = self._hellosign.isDev() ? '/apiapp_dev.php' + path : path;
            if(method == "GET"){
                path = path + "?" + requestData;
            }
            var req = (
                isInsecureConnection ? http : https
                ).request({
                    host: host,
                    port: self._hellosign.getApiField('port'),
                    path: path,
                    method: method,
                    rejectUnauthorized: self._hellosign.isDev()? false : true,
                    requestCert: true,
                    headers: headers,
                    ciphers: "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5"
                });
            if(form != null){
                form.pipe(req);

                form.on('error', self._errorHandler(req, callback));
            }
            process.env.NODE_TLS_REJECT_UNAUTHORIZED = "1";
            req.setTimeout(timeout, self._timeoutHandler(timeout, req, callback));
            req.on('response', self._responseHandler(req, callback));
            req.on('error', self._errorHandler(req, callback));
            req.on('socket', function(socket) {
                socket.on((isInsecureConnection ? 'connect' : 'secureConnect'), function() {
                    // Send payload; we're safe:
                    if (requestData && requestData != "") {
                      req.write(requestData);
                    }
                    // If not using form, end here
                    if (form == null) {
                        req.end();
                    }
                });
            });
            req.on('finish', function(){
                // Waits for finish event when using form
                req.end();
            });

        }
    },

    _setDefaultHeaders: function(auth) {
        var headers = {};

        headers['Authorization'] = this._createAuthHeader(auth);
        headers['Accept'] = 'application/json';
        headers['Content-Type'] = 'application/x-www-form-urlencoded';
        headers['User-Agent'] = 'hellosign-nodejs-sdk/' + this._hellosign.getConstant('PACKAGE_VERSION');

        return headers;
    },

    _createAuthHeader: function(methodAuthKey) {

        var token = this._hellosign.getApiField('oauthToken');
        var authField = this._hellosign.getApiField('auth');

        // Method specific auth key overrides others
        if (methodAuthKey){
            return 'Basic ' + new Buffer(methodAuthKey + ':').toString('base64');
        }

        if (token) {
            return token;
        }

        if (authField) {
            return authField;
        }

    }
};

module.exports = HelloSignResource;
<commit_msg>add res.headers to response for issue #27<commit_after>'use strict';

/**
 * The MIT License (MIT)
 *
 * Copyright (C) 2015 hellosign.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

var http = require('http');
var https = require('https');
var request = require('request');
var path = require('path');
var when = require('when');
var FormData = require('form-data');
var utils = require('./utils');
var Error = require('./Error');
var fs = require('fs');

var hasOwn = {}.hasOwnProperty;

// Provide extension mechanism for HelloSign Resource Sub-Classes
HelloSignResource.extend = utils.protoExtend;

// Expose method-creator & prepared (basic) methods
HelloSignResource.method = require('./HelloSignMethod');
HelloSignResource.BASIC_METHODS = require('./HelloSignMethod.basic');

/**
 * Encapsulates request logic for a HelloSign Resource
 */
function HelloSignResource(hellosign, urlData) {

    this._hellosign = hellosign;
    this._urlData = urlData || {};

    this.basePath = utils.makeURLInterpolator(hellosign.getApiField('basePath'));
    this.path = utils.makeURLInterpolator(this.path);

    if (this.includeBasic) {
        this.includeBasic.forEach(function(methodName) {
            this[methodName] = HelloSignResource.BASIC_METHODS[methodName];
        }, this);
    }

    this.initialize.apply(this, arguments);

}

HelloSignResource.prototype = {

    path: '',

    initialize: function() {},

    createFullPath: function(commandPath, urlData, oauthRequest) {

        var pathPrefix = oauthRequest === true ? "/" : this.basePath(urlData);

        return path.join(
            pathPrefix,
            this.path(urlData),
                typeof commandPath == 'function' ?
                commandPath(urlData) : commandPath
        ).replace(/\\/g, '/'); // ugly workaround for Windows
    },

    createUrlData: function() {
        var urlData = {};
        // Merge in baseData
        for (var i in this._urlData) {
            if (hasOwn.call(this._urlData, i)) {
                urlData[i] = this._urlData[i];
            }
        }
        return urlData;
    },

    createDeferred: function(callback) {
        var deferred = when.defer();

        if (callback) {
            // Callback, if provided, is a simply translated to Promise'esque:
            // (Ensure callback is called outside of promise stack)
            deferred.promise.then(function(res) {
                setTimeout(function(){
                    callback(null, res)
                }, 0);
            }, function(err) {
                setTimeout(function(){
                    callback(err, null);
                }, 0);
            });
        }

        return deferred;
    },

    _timeoutHandler: function(timeout, req, callback) {
        var self = this;
        return function() {
            var timeoutErr = new Error('ETIMEDOUT');
            timeoutErr.code = 'ETIMEDOUT';

            req._isAborted = true;
            req.abort();

            callback.call(
                self,
                new Error.HelloSignConnectionError({
                    message: 'Request aborted due to timeout being reached (' + timeout + 'ms)',
                    detail: timeoutErr
                }),
                null
            );
        }
    },

    _responseHandler: function(req, callback) {

        var self = this;
        return function(res) {
            var resHeaders = res.headers;
            var statusCode = res.statusCode;
            var statusMessage = res.statusMessage;

            if ('content-type' in resHeaders && resHeaders['content-type'].indexOf("application/json") !== -1){

                var response = '';
                res.setEncoding('utf8');
                res.on('data', function(chunk) {
                    response += chunk;
                });
                res.on('end', function() {
                    try {
                        if(response == "\n" || response == ""){
                            response = {};
                        } else {
                            response = JSON.parse(response);
                        }

                        response.resHeaders = resHeaders;
                        response.statusCode = statusCode;
                        response.statusMessage = statusMessage;

                        if (response.error) {
                            var err;
                            var err_data = {};
                            if(typeof response.error === 'object'){
                                err_data = response.error;
                            } else if(typeof response.error === 'string'){
                                err_data['error_name'] = response.error;
                                err_data['error_msg'] = response.error_description;
                            }

                            err = Error.HelloSignError.generate(err_data);
                            return callback.call(self, err, null);
                        }
                    } catch (e) {
                        return callback.call(
                            self,
                            new Error.HelloSignAPIError({
                                message: 'Invalid JSON received from the HelloSign API',
                                response: response,
                                exception: e
                            }),
                            null
                        );
                    }
                    callback.call(self, null, response);
                });
            } else if ('content-transfer-encoding' in resHeaders && resHeaders['content-transfer-encoding'] == "binary"){
                callback.call(self, null, res);
            // Simplified response for code-only statuses
            } else if ('content-length' in resHeaders && resHeaders['content-length'] == "1") {
                response = {};
                response.resHeaders = resHeaders;
                response.statusCode = statusCode;
                response.statusMessage = statusMessage;
                callback.call(self, null, response);
            }
        };
    },

    _errorHandler: function(req, callback) {
        var self = this;
        return function(error) {
            if (req._isAborted) return; // already handled
            if (!error || !error.message) {
                error = {
                    message: 'An error occurred with our connection to HelloSign',
                    detail: error
                };
            }
            callback.call(
                self,
                new Error.HelloSignConnectionError(error),
                null
            );
        }
    },
    _prepareOpts : function(data){

        if('signers' in data && Array.isArray(data.signers)){
            for(var i=0; i<data.signers.length;i++) {
                for(var signerIndex in data.signers[i]){
                    if(data.signers[i].hasOwnProperty(signerIndex)){
                        if('role' in data.signers[i]){
                            if(signerIndex == 'role'){
                                continue;
                            }
                            data["signers[" + data.signers[i]['role'] + "][" + signerIndex + "]"] = data.signers[i][signerIndex];
                        } else {
                            data["signers[" + i + "][" + signerIndex + "]"] = data.signers[i][signerIndex];
                        }
                    }
                }
            }
            delete data.signers;
        }
        if('cc_email_addresses' in data && Array.isArray(data.cc_email_addresses)){
            for(var i=0; i<data.cc_email_addresses.length;i++) {
                if(typeof data.cc_email_addresses[i]){
                    data["cc_email_addresses[" + i + "]"] = data.cc_email_addresses[i];
                }
            }
            delete data.cc_email_addresses;
        }

        //embedded endpoints adds
        if ('cc_roles' in data && Array.isArray(data.cc_email_addresses)) {
            for(var i=0; i < data.cc_roles.length; i++) {
                if(typeof data.cc_roles[i]){
                    data['cc_roles['+ i + ']'] = data.cc_roles[i];
                }
            }
            delete data.cc_roles;
        }

        if ('ccs' in data && Array.isArray(data.ccs)){
            for (var i=0; i < data.ccs.length; i++){
                data['ccs[' + data.ccs[i]['role_name'] + '][email_address]'] = data.ccs[i].email_address;
            }
            delete data.ccs;
        }

        if ('signer_roles' in data && Array.isArray(data.signer_roles)){
            for(var i=0; i < data.signer_roles.length; i++){
                if(data.signer_roles[i].hasOwnProperty('name')) {
                    data['signer_roles[' + i + '][name]'] = data.signer_roles[i]['name'];
                }
                if(data.signer_roles[i].hasOwnProperty('order')) {
                    data['signer_roles[' + i + '][order]'] = data.signer_roles[i]['order'];
                }
            }
            delete data.signer_roles;
        }

        if ('merge_fields' in data && Array.isArray(data.merge_fields)){
            data.merge_fields = JSON.stringify(data.merge_fields);
        }

        if ('custom_fields' in data && Array.isArray(data.custom_fields)){
            data.custom_fields = JSON.stringify(data.custom_fields);
        }

        if('template_ids' in data && Array.isArray(data.template_ids)){
            for(var i=0; i<data.template_ids.length;i++) {
                if(typeof data.template_ids[i]){
                    data["template_ids[" + i + "]"] = data.template_ids[i];
                }
            }
            delete data.template_ids;
        }

        if('templates' in data && Array.isArray(data.templates)){
            for(var i=0; i<data.templates.length;i++) {
                for(var templateIndex in data.templates[i]){
                    if(data.templates[i].hasOwnProperty(templateIndex)){
                        data["templates[" + i + "][" + templateIndex + "]"] = data.templates[i][templateIndex];
                    }
                }
            }
            delete data.templates;
        }

        if ('form_fields_per_document' in data && Array.isArray(data.form_fields_per_document)){
            data.form_fields_per_document = JSON.stringify(data.form_fields_per_document);
        }

        // Deprecated, but saving for compatibility
        if('clientId' in data) {
            data['client_id'] = data.clientId;
            delete data.clientId;
        }

        // Correct syntax; will overwrite the above.
        if('client_id' in data) {
            data['client_id'] = data.client_id;
        }

        for(var prop in data){
            if (data.hasOwnProperty(prop)){
                if (typeof data[prop] === "object" && prop != "files"){
                    for(var paramName in data[prop]){
                        if(data[prop].hasOwnProperty(paramName)){
                            data[prop + "[" + paramName + "]"] = data[prop][paramName];
                        }
                    }
                    delete data[prop];
                }
            }
        }

        if('files' in data && Array.isArray(data.files)){
            // submit as form
            var form = new FormData();
            for(var i=0; i<data.files.length;i++) {
                form.append("file[" + i + "]", fs.createReadStream(data.files[i]));
            }
            delete data.files;
            for(var paramName in data){
                if(data.hasOwnProperty(paramName)){
                    form.append(paramName, data[paramName]);
                }
            }
            return {requestData: "", formData: form}
        } else {
            var requestData = utils.stringifyRequestData(data || {});
            return {requestData: requestData, formData: null}
        }
    },
    _request: function(method, path, data, auth, callback) {
        var self = this;
        var apiVersion = this._hellosign.getApiField('version');
        var headers = this._setDefaultHeaders(auth);
        var preparedData = this._prepareOpts(data);

        var form = preparedData.formData;
        var requestData = preparedData.requestData;

        if(form){
            var formHeaders = form.getHeaders();
            for (var i in formHeaders) {
                // Prevent duplicate headers, using form values when sending files
                if (i === 'content-type') {
                  headers['Content-Type'] = formHeaders[i];
                  continue;
                }
                if (hasOwn.call(formHeaders, i)) {
                    headers[i] = formHeaders[i];
                }
            }
        }

        if (apiVersion) {
            headers['HelloSign-Version'] = apiVersion;
        }
        makeRequest();
        function makeRequest() {

            var timeout = self._hellosign.getApiField('timeout');
            var isInsecureConnection = self._hellosign.getApiField('protocol') == 'http';
            var host = self._hellosign.getApiField('host');
            var host = path.indexOf('oauth') === -1 ? host : host.replace('api', 'app');
            // Add params for dev environment
            path = self._hellosign.isDev() ? '/apiapp_dev.php' + path : path;
            if(method == "GET"){
                path = path + "?" + requestData;
            }
            var req = (
                isInsecureConnection ? http : https
                ).request({
                    host: host,
                    port: self._hellosign.getApiField('port'),
                    path: path,
                    method: method,
                    rejectUnauthorized: self._hellosign.isDev()? false : true,
                    requestCert: true,
                    headers: headers,
                    ciphers: "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5"
                });
            if(form != null){
                form.pipe(req);

                form.on('error', self._errorHandler(req, callback));
            }
            process.env.NODE_TLS_REJECT_UNAUTHORIZED = "1";
            req.setTimeout(timeout, self._timeoutHandler(timeout, req, callback));
            req.on('response', self._responseHandler(req, callback));
            req.on('error', self._errorHandler(req, callback));
            req.on('socket', function(socket) {
                socket.on((isInsecureConnection ? 'connect' : 'secureConnect'), function() {
                    // Send payload; we're safe:
                    if (requestData && requestData != "") {
                      req.write(requestData);
                    }
                    // If not using form, end here
                    if (form == null) {
                        req.end();
                    }
                });
            });
            req.on('finish', function(){
                // Waits for finish event when using form
                req.end();
            });

        }
    },

    _setDefaultHeaders: function(auth) {
        var headers = {};

        headers['Authorization'] = this._createAuthHeader(auth);
        headers['Accept'] = 'application/json';
        headers['Content-Type'] = 'application/x-www-form-urlencoded';
        headers['User-Agent'] = 'hellosign-nodejs-sdk/' + this._hellosign.getConstant('PACKAGE_VERSION');

        return headers;
    },

    _createAuthHeader: function(methodAuthKey) {

        var token = this._hellosign.getApiField('oauthToken');
        var authField = this._hellosign.getApiField('auth');

        // Method specific auth key overrides others
        if (methodAuthKey){
            return 'Basic ' + new Buffer(methodAuthKey + ':').toString('base64');
        }

        if (token) {
            return token;
        }

        if (authField) {
            return authField;
        }

    }
};

module.exports = HelloSignResource;
<|endoftext|>


<commit_before>/**
 * mediawiki.client has some convenience functions for user agent checks
 *
 * TODO this should be combined with or bootstrap jquery.client.js
 */
( function( mw ) {

	var userAgent = navigator.userAgent;

	mw.isMobileDevice = function(){
		return ( mw.isIphone() || mw.isIpod() || mw.isIpad() || mw.isAndroid() || mw.isWindowsPhone() || mw.getConfig( "EmbedPlayer.ForceNativeComponent") === true )
	};
	mw.isIphone = function(){
		return ( mw.getConfig( "EmbedPlayer.ForceNativeComponent") !== true && navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() ) || mw.isIpod();
	};
	mw.isIE = function() {
		return (/msie/.test(userAgent.toLowerCase()));
	};
    mw.isIE7 = function(){
        return (/msie 7/.test(userAgent.toLowerCase()));
    };
	mw.isIE8 = function(){
		return (/msie 8/.test(userAgent.toLowerCase()));
	};
	mw.isIE9 = function(){
		return (/msie 9/.test(userAgent.toLowerCase()));
	};
	mw.isIE = function() {
		return (/msie/).test(userAgent.toLowerCase());
	};
	mw.isDesktopSafari = function(){
	  return (/safari/).test(userAgent.toLowerCase()) && !mw.isMobileDevice() && !mw.isChrome();
	};
	// Uses hack described at:
	// http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/
	mw.isIphone4 = function(){
		return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) );
	};
	mw.isIpod = function(){
		return (  userAgent.indexOf('iPod') != -1 );
	};
	mw.isIpad = function(){
		return ( userAgent.indexOf('iPad') != -1 );
	};
	mw.isIpad3 = function(){
		return  /OS 3_/.test( userAgent ) && mw.isIpad();
	};
	mw.isAndroid44 = function(){
		return ( userAgent.indexOf( 'Android 4.4') != -1 );
	};
	mw.isAndroid43 = function(){
		return ( userAgent.indexOf( 'Android 4.3') != -1 );
	};
	mw.isAndroid42 = function(){
		return ( userAgent.indexOf( 'Android 4.2') != -1 );
	};
	mw.isAndroid41 = function(){
		return ( userAgent.indexOf( 'Android 4.1') != -1 );
	};
	mw.isAndroid40 = function(){
		return ( userAgent.indexOf( 'Android 4.0') != -1 );
	};
	mw.isAndroid2 = function(){
		return ( userAgent.indexOf( 'Android 2.') != -1 );
	};
	mw.isAndroid = function(){
		return ( userAgent.indexOf( 'Android') != -1 );
	};
	mw.isAndroid4andUp = function(){
		return ( userAgent.indexOf( 'Android 4.') != -1 );
	};
	mw.isFirefox = function(){
		return ( userAgent.indexOf( 'Firefox') != -1 );
	};
	mw.isChrome = function(){
		return ( userAgent.indexOf( 'Chrome') != -1 );
	};
	mw.isAndroidNativeBrowser = function(){
		return (mw.isAndroid() && !mw.isFirefox() && !mw.isChrome());
	};
	mw.isAndroidChromeNativeBrowser = function(){
		return ( mw.isAndroid() && mw.isChrome() && userAgent.indexOf( 'Version/' ) != -1 )
	};
	mw.isMobileChrome = function(){
		return ( userAgent.indexOf( 'Android 4.' ) != -1
					&&
				  userAgent.indexOf( 'Chrome' ) != -1
				)
	};
	mw.isWindowsPhone = function(){
		return (  userAgent.indexOf('Windows Phone') != -1 );
	};
	mw.isIOS = function(){
		return ( mw.isIphone() || mw.isIpod() || mw.isIpad() );
	};
	mw.isIOS3 = function(){
		return /OS 3_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS4 = function(){
		return /OS 4_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS5 = function(){
		return /OS 5_/.test( userAgent ) && mw.isIOS();
	};

	mw.isIOS6 = function(){
		return /OS 6_/.test( userAgent ) && mw.isIOS();
	};

	mw.isIOS7 = function(){
		return /OS 7_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS8 = function(){
		return /Version\/8/.test( userAgent ) && mw.isIOS();
	};

	mw.isSilk = function(){
		return /\bSilk\b/.test(userAgent);
	};

	// Does the client has native touch bindings?
	mw.hasNativeTouchBindings = function(){
		return (mw.isAndroid41() || mw.isAndroid42() || ( mw.isAndroid() && mw.isFirefox() ));
	};

	// Detect small mobile device ( smartphones )
	mw.isDeviceLessThan480P = function(){
		return matchMedia('only screen and (max-device-width: 480px)').matches;
	};

	mw.hasMouseEvents = function(){
		return !mw.isMobileDevice();
	};

	mw.isTouchDevice = function(){
		return !!('ontouchstart' in window);
	};

	/**
	 * Fallforward system by default prefers flash.
	 *
	 * This is separate from the EmbedPlayer library detection to provide
	 * package loading control NOTE: should be phased out in favor of browser
	 * feature detection where possible
	 *
	 */
	mw.isHTML5FallForwardNative = function(){
		if( mw.isMobileHTML5() ){
			return true;
		}
		// Check for url flag to force html5:
		if( document.URL.indexOf('forceMobileHTML5') != -1 ){
			return true;
		}
		// Fall forward native:
		// if the browser supports flash ( don't use html5 )
		if( mw.supportsFlash() ){
			return false;
		}
		// No flash return true if the browser supports html5 video tag with
		// basic support for canPlayType:
		if( mw.supportsHTML5() ){
			return true;
		}

		return false;
	};

	mw.isMobileHTML5 = function(){
		// Check for a mobile html5 user agent:
		if ( mw.isIphone() ||
			 mw.isIpod()   ||
			 mw.isIpad()   ||
			 mw.isAndroid2()
		){
			return true;
		}
		return false;
	};

	mw.supportsHTML5 = function(){
		// Blackberry is evil in its response to canPlayType calls.
		if( userAgent.indexOf('BlackBerry') != -1 ){
			return false ;
		}
		var dummyvid = document.createElement( "video" );
		if( dummyvid.canPlayType ) {
			return true;
		}
		return false;
	};

	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	mw.supportsFlash = function() {
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}

		// Desktop safari flash has "power saving bug" as well as cross domain request issues
		// by default we disable flash on desktop safari.
		if( mw.isDesktopSafari() ){
			return false;
		}

		var majorVersion = this.getFlashVersion().split(',').shift();
		if( majorVersion < 10 ){
			return false;
		} else {
			return true;
		}
	};

	mw.supportSilverlight = function(){
		return Silverlight.isInstalled("4.0");
	};

	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	mw.getFlashVersion = function() {
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length) {
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e) {}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e) {
						return '6,0,0';
					}
				}
			} catch(e) {}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e) {}
		return '0,0,0';
	};

} )( window.mediaWiki );
<commit_msg>#SUP-2901 #comment fix for iOS8 webview- user agent issue  #time 2h<commit_after>/**
 * mediawiki.client has some convenience functions for user agent checks
 *
 * TODO this should be combined with or bootstrap jquery.client.js
 */
( function( mw ) {

	var userAgent = navigator.userAgent;

	mw.isMobileDevice = function(){
		return ( mw.isIphone() || mw.isIpod() || mw.isIpad() || mw.isAndroid() || mw.isWindowsPhone() || mw.getConfig( "EmbedPlayer.ForceNativeComponent") === true )
	};
	mw.isIphone = function(){
		return ( mw.getConfig( "EmbedPlayer.ForceNativeComponent") !== true && navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() ) || mw.isIpod();
	};
	mw.isIE = function() {
		return (/msie/.test(userAgent.toLowerCase()));
	};
    mw.isIE7 = function(){
        return (/msie 7/.test(userAgent.toLowerCase()));
    };
	mw.isIE8 = function(){
		return (/msie 8/.test(userAgent.toLowerCase()));
	};
	mw.isIE9 = function(){
		return (/msie 9/.test(userAgent.toLowerCase()));
	};
	mw.isIE = function() {
		return (/msie/).test(userAgent.toLowerCase());
	};
	mw.isDesktopSafari = function(){
	  return (/safari/).test(userAgent.toLowerCase()) && !mw.isMobileDevice() && !mw.isChrome();
	};
	// Uses hack described at:
	// http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/
	mw.isIphone4 = function(){
		return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) );
	};
	mw.isIpod = function(){
		return (  userAgent.indexOf('iPod') != -1 );
	};
	mw.isIpad = function(){
		return ( userAgent.indexOf('iPad') != -1 );
	};
	mw.isIpad3 = function(){
		return  /OS 3_/.test( userAgent ) && mw.isIpad();
	};
	mw.isAndroid44 = function(){
		return ( userAgent.indexOf( 'Android 4.4') != -1 );
	};
	mw.isAndroid43 = function(){
		return ( userAgent.indexOf( 'Android 4.3') != -1 );
	};
	mw.isAndroid42 = function(){
		return ( userAgent.indexOf( 'Android 4.2') != -1 );
	};
	mw.isAndroid41 = function(){
		return ( userAgent.indexOf( 'Android 4.1') != -1 );
	};
	mw.isAndroid40 = function(){
		return ( userAgent.indexOf( 'Android 4.0') != -1 );
	};
	mw.isAndroid2 = function(){
		return ( userAgent.indexOf( 'Android 2.') != -1 );
	};
	mw.isAndroid = function(){
		return ( userAgent.indexOf( 'Android') != -1 );
	};
	mw.isAndroid4andUp = function(){
		return ( userAgent.indexOf( 'Android 4.') != -1 );
	};
	mw.isFirefox = function(){
		return ( userAgent.indexOf( 'Firefox') != -1 );
	};
	mw.isChrome = function(){
		return ( userAgent.indexOf( 'Chrome') != -1 );
	};
	mw.isAndroidNativeBrowser = function(){
		return (mw.isAndroid() && !mw.isFirefox() && !mw.isChrome());
	};
	mw.isAndroidChromeNativeBrowser = function(){
		return ( mw.isAndroid() && mw.isChrome() && userAgent.indexOf( 'Version/' ) != -1 )
	};
	mw.isMobileChrome = function(){
		return ( userAgent.indexOf( 'Android 4.' ) != -1
					&&
				  userAgent.indexOf( 'Chrome' ) != -1
				)
	};
	mw.isWindowsPhone = function(){
		return (  userAgent.indexOf('Windows Phone') != -1 );
	};
	mw.isIOS = function(){
		return ( mw.isIphone() || mw.isIpod() || mw.isIpad() );
	};
	mw.isIOS3 = function(){
		return /OS 3_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS4 = function(){
		return /OS 4_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS5 = function(){
		return /OS 5_/.test( userAgent ) && mw.isIOS();
	};

	mw.isIOS6 = function(){
		return /OS 6_/.test( userAgent ) && mw.isIOS();
	};

	mw.isIOS7 = function(){
		return /OS 7_/.test( userAgent ) && mw.isIOS();
	};
	mw.isIOS8 = function(){
		// Known Limitation - It will return false for iOS8 Simulator
		return ( /OS 8_/.test( userAgent ) || /Version\/8/.test( userAgent ) ) && mw.isIOS();
	};

	mw.isSilk = function(){
		return /\bSilk\b/.test(userAgent);
	};

	// Does the client has native touch bindings?
	mw.hasNativeTouchBindings = function(){
		return (mw.isAndroid41() || mw.isAndroid42() || ( mw.isAndroid() && mw.isFirefox() ));
	};

	// Detect small mobile device ( smartphones )
	mw.isDeviceLessThan480P = function(){
		return matchMedia('only screen and (max-device-width: 480px)').matches;
	};

	mw.hasMouseEvents = function(){
		return !mw.isMobileDevice();
	};

	mw.isTouchDevice = function(){
		return !!('ontouchstart' in window);
	};

	/**
	 * Fallforward system by default prefers flash.
	 *
	 * This is separate from the EmbedPlayer library detection to provide
	 * package loading control NOTE: should be phased out in favor of browser
	 * feature detection where possible
	 *
	 */
	mw.isHTML5FallForwardNative = function(){
		if( mw.isMobileHTML5() ){
			return true;
		}
		// Check for url flag to force html5:
		if( document.URL.indexOf('forceMobileHTML5') != -1 ){
			return true;
		}
		// Fall forward native:
		// if the browser supports flash ( don't use html5 )
		if( mw.supportsFlash() ){
			return false;
		}
		// No flash return true if the browser supports html5 video tag with
		// basic support for canPlayType:
		if( mw.supportsHTML5() ){
			return true;
		}

		return false;
	};

	mw.isMobileHTML5 = function(){
		// Check for a mobile html5 user agent:
		if ( mw.isIphone() ||
			 mw.isIpod()   ||
			 mw.isIpad()   ||
			 mw.isAndroid2()
		){
			return true;
		}
		return false;
	};

	mw.supportsHTML5 = function(){
		// Blackberry is evil in its response to canPlayType calls.
		if( userAgent.indexOf('BlackBerry') != -1 ){
			return false ;
		}
		var dummyvid = document.createElement( "video" );
		if( dummyvid.canPlayType ) {
			return true;
		}
		return false;
	};

	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	mw.supportsFlash = function() {
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}

		// Desktop safari flash has "power saving bug" as well as cross domain request issues
		// by default we disable flash on desktop safari.
		if( mw.isDesktopSafari() ){
			return false;
		}

		var majorVersion = this.getFlashVersion().split(',').shift();
		if( majorVersion < 10 ){
			return false;
		} else {
			return true;
		}
	};

	mw.supportSilverlight = function(){
		return Silverlight.isInstalled("4.0");
	};

	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	mw.getFlashVersion = function() {
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length) {
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e) {}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e) {
						return '6,0,0';
					}
				}
			} catch(e) {}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e) {}
		return '0,0,0';
	};

} )( window.mediaWiki );
<|endoftext|>


<commit_before>const Result = require('../results/Result.js');
const Default = require('../enums/Default.js');
const CommandError = require('../enums/CommandError.js');
const ExceptionResult = require('../results/ExceptionResult.js');

class Handler {
  constructor(registry) {
    this.registry= registry;
  }

  async run(context, prefix) {
    const split = context.message.content.toLowerCase().match(/".+"|\S+/g);

    if (split === null) {
      return new Result({ isSuccess: false, commandError: CommandError.CommandNotFound, errorReason: 'This command does not exist.' });
    }

    const commandName = split.shift().slice(prefix.length);

    let command = this.registry.commands.get(commandName);

    if (command === undefined) {
      const matches = this.registry.commands.filterArray((value) => value.aliases.some((v) => v === commandName));

      if (matches.length > 0) {
        command = matches[0];
      } else {
        return new Result({ isSuccess: false, commandError: CommandError.CommandNotFound, errorReason: 'This command does not exist.' });
      }
    }

    command.trigger = commandName;

    if (command.guildOnly && context.guild === null) {
      return new Result({ isSuccess: false, commandError: CommandError.GuildOnly, errorReason: 'This command may only be used inside a server.' });
    }

    for (const precondition of command.group.preconditions.concat(command.preconditions)) {
      const result = await precondition.run(command, context);

      if (!result.isSuccess) {
        return result;
      }
    }

    const args = {};

    for (let i = 0; i < command.args.length; i++) {
      let input = command.args[i].isRemainder ? split.join(' ') : split.shift();

      if (!input && !command.args[i].isOptional) {
        return new Result({ isSuccess: false, command: command, commandError: CommandError.InvalidArgCount, errorReason: 'You have provided an invalid number of arguments.' });
      } else if (input === undefined && command.args[i].isOptional) {
        switch (command.args[i].default) {
          case Default.Author:
            args[command.args[i].key] = context.author;
            break;
          case Default.Member:
            args[command.args[i].key] = context.guild.member(context.author);
            break;
          case Default.Channel:
            args[command.args[i].key] = context.channel;
            break;
          case Default.Guild:
            args[command.args[i].key] = context.role;
            break;
          case Default.HighestRole:
            args[command.args[i].key] = context.guild.member(context.author).highestRole;
            break;
          default:
            args[command.args[i].key] = command.args[i].default;
            break;
        }

        continue;
      } else {
        input = input.replace(/"/g, '');
      }

      const typeReaderResult = await this.registry.typeReaders.get(command.args[i].type).read(command, context, command.args[i], input);

      if (!typeReaderResult.isSuccess) {
        return typeReaderResult;
      }

      for (const precondition of command.args[i].preconditions) {
        const preconditionResult = await precondition.run(command, context, command.args[i], typeReaderResult.value);

        if (!preconditionResult.isSuccess) {
          return preconditionResult;
        }
      }

      args[command.args[i].key] = typeReaderResult.value;
    }

    try {
      await command.run(context, args);
      return new Result({ isSuccess: true, command: command });
    } catch (err) {
      return ExceptionResult.fromError(command, err);
    }
  }
}

module.exports = Handler;
<commit_msg>try catch precondition results in order to respond to the user<commit_after>const Result = require('../results/Result.js');
const Default = require('../enums/Default.js');
const CommandError = require('../enums/CommandError.js');
const ExceptionResult = require('../results/ExceptionResult.js');

class Handler {
  constructor(registry) {
    this.registry= registry;
  }

  async run(context, prefix) {
    const split = context.message.content.toLowerCase().match(/".+"|\S+/g);

    if (split === null) {
      return new Result({ isSuccess: false, commandError: CommandError.CommandNotFound, errorReason: 'This command does not exist.' });
    }

    const commandName = split.shift().slice(prefix.length);

    let command = this.registry.commands.get(commandName);

    if (command === undefined) {
      const matches = this.registry.commands.filterArray((value) => value.aliases.some((v) => v === commandName));

      if (matches.length > 0) {
        command = matches[0];
      } else {
        return new Result({ isSuccess: false, commandError: CommandError.CommandNotFound, errorReason: 'This command does not exist.' });
      }
    }

    command.trigger = commandName;

    if (command.guildOnly && context.guild === null) {
      return new Result({ isSuccess: false, commandError: CommandError.GuildOnly, errorReason: 'This command may only be used inside a server.' });
    }

    for (const precondition of command.group.preconditions.concat(command.preconditions)) {
      try {
        const result = await precondition.run(command, context);

        if (!result.isSuccess) {
          return result;
        }
      } catch (err) {
        return ExceptionResult.fromError(command, err);
      }
    }

    const args = {};

    for (let i = 0; i < command.args.length; i++) {
      let input = command.args[i].isRemainder ? split.join(' ') : split.shift();

      if (!input && !command.args[i].isOptional) {
        return new Result({ isSuccess: false, command: command, commandError: CommandError.InvalidArgCount, errorReason: 'You have provided an invalid number of arguments.' });
      } else if (input === undefined && command.args[i].isOptional) {
        switch (command.args[i].default) {
          case Default.Author:
            args[command.args[i].key] = context.author;
            break;
          case Default.Member:
            args[command.args[i].key] = context.guild.member(context.author);
            break;
          case Default.Channel:
            args[command.args[i].key] = context.channel;
            break;
          case Default.Guild:
            args[command.args[i].key] = context.role;
            break;
          case Default.HighestRole:
            args[command.args[i].key] = context.guild.member(context.author).highestRole;
            break;
          default:
            args[command.args[i].key] = command.args[i].default;
            break;
        }

        continue;
      } else {
        input = input.replace(/"/g, '');
      }

      const typeReaderResult = await this.registry.typeReaders.get(command.args[i].type).read(command, context, command.args[i], input);

      if (!typeReaderResult.isSuccess) {
        return typeReaderResult;
      }

      for (const precondition of command.args[i].preconditions) {
        try {
          const preconditionResult = await precondition.run(command, context, command.args[i], typeReaderResult.value);

          if (!preconditionResult.isSuccess) {
            return preconditionResult;
          }
        } catch (err) {
          return ExceptionResult.fromError(command, err);
        }
      }

      args[command.args[i].key] = typeReaderResult.value;
    }

    try {
      await command.run(context, args);
      return new Result({ isSuccess: true, command: command });
    } catch (err) {
      return ExceptionResult.fromError(command, err);
    }
  }
}

module.exports = Handler;
<|endoftext|>


<commit_before>Flame.SplitView = Flame.View.extend({
    allowResizing: true,
    dividerThickness: 7,

    dividerView: Flame.View.extend(Flame.Statechart, {
        classNames: 'flame-split-view-divider'.w(),
        initialState: 'idle',

        idle: Flame.State.extend({
            mouseDown: function(event) {
                var parentView = this.getPath('owner.parentView');
                if (!parentView.get('allowResizing')) return false;
                parentView.startResize(event);
                this.gotoState('resizing');
                return true;
            },

            doubleClick: function(event) {
                var parentView = this.getPath('owner.parentView');
                if (!parentView.get('allowResizing')) return false;
                parentView.toggleCollapse(event);
                return true;
            }
        }),

        resizing: Flame.State.extend({
            mouseMove: function(event) {
                this.getPath('owner.parentView').resize(event);
                return true;
            },

            mouseUp: Flame.State.gotoHandler('idle')
        })
    })
});
<commit_msg>Resizing Flame.SplitViews with touches<commit_after>Flame.SplitView = Flame.View.extend({
    allowResizing: true,
    dividerThickness: 7,

    dividerView: Flame.View.extend(Flame.Statechart, {
        classNames: 'flame-split-view-divider'.w(),
        initialState: 'idle',

        idle: Flame.State.extend({
            mouseDown: function(event) {
                var parentView = this.getPath('owner.parentView');
                if (!parentView.get('allowResizing')) return false;
                parentView.startResize(event);
                this.gotoState('resizing');
                return true;
            },

            touchStart: function(event) {
                // Normalize the event and send it to mouseDown
                this.mouseDown(this.normalizeTouchEvents(event));
                return true;
            },

            doubleClick: function(event) {
                var parentView = this.getPath('owner.parentView');
                if (!parentView.get('allowResizing')) return false;
                parentView.toggleCollapse(event);
                return true;
            }
        }),

        resizing: Flame.State.extend({
            mouseMove: function(event) {
                this.getPath('owner.parentView').resize(event);
                return true;
            },

            touchMove: function(event) {
                // Don't scroll the page while we're doing this
                event.preventDefault();
                // Normalize the event and send it to mouseDown
                this.mouseMove(this.normalizeTouchEvents(event));
                return true;
            }

            mouseUp: Flame.State.gotoHandler('idle'),
            touchEnd: Flame.State.gotoHandler('idle')
        })
    })
});
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const joi = require('joi');

module.exports = class JSONAPISerializer {
  constructor(opts) {
    this.opts = opts || {};
    this.schemas = {};
  }

  validateOptions(options) {
    const optionsSchema = joi.object({
      id: joi.string().default('id'),
      blackList: joi.array().items(joi.string()).single().default([]),
      links: joi.object().default({}),
      relationships: joi.object().pattern(/.+/, joi.object({
        type: joi.string().required(),
        links: joi.object().default({}),
      })).default({}),
    }).required();

    const validated = joi.validate(options, optionsSchema);

    if (validated.error) {
      throw new Error(validated.error);
    }

    return validated.value;
  }

  register(type, schemaName, options) {
    if (_.isObject(schemaName)) {
      options = schemaName;
      schemaName = 'default';
    }

    const name = schemaName || 'default';
    const opts = this.validateOptions(_.defaults({}, options));

    _.set(this.schemas, [type, name].join('.'), opts);
  }

  serialize(type, data, schemaName) {
    const schema = schemaName || 'default';

    if (!this.schemas[type]) {
      throw new Error('No type registered for ' + type);
    }

    if (schema && !this.schemas[type][schema]) {
      throw new Error('No schema ' + schema + ' registered for ' + type);
    }

    const included = [];
    return _.assign({}, {
      jsonapi: {
        version: '1.0',
      },
      links: this.getLinks(this.opts, this.schemas[type][schema].topLevelLinks),
      data: this.serializeData(type, data, this.schemas[type][schema], included),
      included: this.serializeIncluded(included),
    });
  }

  serializeData(type, data, options, included) {
    // Empty data
    if (_.isEmpty(data)) {
      // Return [] or null
      return _.isArray(data) ? data : null;
    }

    // Array data
    if (_.isArray(data)) {
      return data.map(d => this.serializeData(type, d, options, included));
    }

    // Single data
    const resource = {
      type: type,
      id: data[options.id],
      attributes: this.serializeAttributes(data, options),
      relationships: this.serializeRelationships(data, options, included),
      links: this.getLinks(data, options.links),
    };

    return resource;
  }

  serializeIncluded(included) {
    const serializedIncluded = _.uniqWith(included, _.isEqual);
    return !_.isEmpty(serializedIncluded) ? serializedIncluded : undefined;
  }

  serializeAttributes(data, options) {
    return _.pick(data, _.difference(Object.keys(data), _.concat([options.id], Object.keys(options.relationships), options.blackList)));
  }

  serializeRelationships(data, options, included) {
    const serializedRelationships = {};

    _.forOwn(options.relationships, (rOptions, relationship) => {
      const serializeRelationship = {
        data: this.serializeRelationship(rOptions.type, data[relationship], this.schemas[options.relationships[relationship].type].default, included),
        links: this.getLinks(data, rOptions.links),
      };
      _.set(serializedRelationships, relationship, serializeRelationship);
    });

    return !_.isEmpty(serializedRelationships) ? serializedRelationships : undefined;
  }

  serializeRelationship(rType, rData, rOptions, included) {
    // Empty relationship data
    if (_.isEmpty(rData)) {
      // Return [] or null
      return _.isArray(rData) ? rData : null;
    }

    // To-many relationships
    if (_.isArray(rData)) {
      return rData.map(d => this.serializeRelationship(rType, d, rOptions, included));
    }

    // To-one relationship
    const serializedRelationship = {
      type: rType,
    };

    // support for unpopulated relationships (an id, or array of ids)
    if (!_.isPlainObject(rData)) {
      // Relationship has not been populated
      serializedRelationship.id = rData;
    } else {
      // Relationship has been populated
      serializedRelationship.id = rData[rOptions.id];
      included.push(this.serializeData(rType, rData, rOptions));
    }

    return serializedRelationship;
  }

  getLinks(data, linksOptions) {
    const links = _.mapValues(linksOptions, linkOpts => {
      let link;
      if (_.isFunction(linkOpts)) {
        link = linkOpts(data);
      } else {
        link = linkOpts;
      }
      return link;
    });

    return !_.isEmpty(links) ? links : undefined;
  }
};
<commit_msg>fix: relationships links should be before data<commit_after>'use strict';

const _ = require('lodash');
const joi = require('joi');

module.exports = class JSONAPISerializer {
  constructor(opts) {
    this.opts = opts || {};
    this.schemas = {};
  }

  validateOptions(options) {
    const optionsSchema = joi.object({
      id: joi.string().default('id'),
      blackList: joi.array().items(joi.string()).single().default([]),
      links: joi.object().default({}),
      relationships: joi.object().pattern(/.+/, joi.object({
        type: joi.string().required(),
        links: joi.object().default({}),
      })).default({}),
    }).required();

    const validated = joi.validate(options, optionsSchema);

    if (validated.error) {
      throw new Error(validated.error);
    }

    return validated.value;
  }

  register(type, schemaName, options) {
    if (_.isObject(schemaName)) {
      options = schemaName;
      schemaName = 'default';
    }

    const name = schemaName || 'default';
    const opts = this.validateOptions(_.defaults({}, options));

    _.set(this.schemas, [type, name].join('.'), opts);
  }

  serialize(type, data, schemaName) {
    const schema = schemaName || 'default';

    if (!this.schemas[type]) {
      throw new Error('No type registered for ' + type);
    }

    if (schema && !this.schemas[type][schema]) {
      throw new Error('No schema ' + schema + ' registered for ' + type);
    }

    const included = [];
    return _.assign({}, {
      jsonapi: {
        version: '1.0',
      },
      links: this.getLinks(this.opts, this.schemas[type][schema].topLevelLinks),
      data: this.serializeData(type, data, this.schemas[type][schema], included),
      included: this.serializeIncluded(included),
    });
  }

  serializeData(type, data, options, included) {
    // Empty data
    if (_.isEmpty(data)) {
      // Return [] or null
      return _.isArray(data) ? data : null;
    }

    // Array data
    if (_.isArray(data)) {
      return data.map(d => this.serializeData(type, d, options, included));
    }

    // Single data
    const resource = {
      type: type,
      id: data[options.id],
      attributes: this.serializeAttributes(data, options),
      relationships: this.serializeRelationships(data, options, included),
      links: this.getLinks(data, options.links),
    };

    return resource;
  }

  serializeIncluded(included) {
    const serializedIncluded = _.uniqWith(included, _.isEqual);
    return !_.isEmpty(serializedIncluded) ? serializedIncluded : undefined;
  }

  serializeAttributes(data, options) {
    return _.pick(data, _.difference(Object.keys(data), _.concat([options.id], Object.keys(options.relationships), options.blackList)));
  }

  serializeRelationships(data, options, included) {
    const serializedRelationships = {};

    _.forOwn(options.relationships, (rOptions, relationship) => {
      const serializeRelationship = {
        links: this.getLinks(data, rOptions.links),
        data: this.serializeRelationship(rOptions.type, data[relationship], this.schemas[options.relationships[relationship].type].default, included),
      };
      _.set(serializedRelationships, relationship, serializeRelationship);
    });

    return !_.isEmpty(serializedRelationships) ? serializedRelationships : undefined;
  }

  serializeRelationship(rType, rData, rOptions, included) {
    // Empty relationship data
    if (_.isEmpty(rData)) {
      // Return [] or null
      return _.isArray(rData) ? rData : null;
    }

    // To-many relationships
    if (_.isArray(rData)) {
      return rData.map(d => this.serializeRelationship(rType, d, rOptions, included));
    }

    // To-one relationship
    const serializedRelationship = {
      type: rType,
    };

    // support for unpopulated relationships (an id, or array of ids)
    if (!_.isPlainObject(rData)) {
      // Relationship has not been populated
      serializedRelationship.id = rData;
    } else {
      // Relationship has been populated
      serializedRelationship.id = rData[rOptions.id];
      included.push(this.serializeData(rType, rData, rOptions));
    }

    return serializedRelationship;
  }

  getLinks(data, linksOptions) {
    const links = _.mapValues(linksOptions, linkOpts => {
      let link;
      if (_.isFunction(linkOpts)) {
        link = linkOpts(data);
      } else {
        link = linkOpts;
      }
      return link;
    });

    return !_.isEmpty(links) ? links : undefined;
  }
};
<|endoftext|>


<commit_before>import colors from './colors';

const styleSheet = {
  emptyState: {
    alignItems: 'center',
    backgroundPosition: 'center bottom',
    backgroundSize: 'cover',
    boxSizing: 'border-box',
    display: 'flex',
    flexDirection: 'column',
    height: '100%',
    justifyContent: 'center',
    padding: '24px'
  },
  heading: {
    fontSize: '16',
    fontWeight: 'bold',
    color: colors.primaryText,
    margin: '0',
    textAlign: 'center'
  },
  body: {
    fontSize: '16',
    color: colors.primaryText,
    marginBottom: '30px',
    marginTop: '16px',
    textAlign: 'center'
  }
};

export default styleSheet;
<commit_msg>:bug: Added units, fixed react warning<commit_after>import colors from './colors';

const styleSheet = {
  emptyState: {
    alignItems: 'center',
    backgroundPosition: 'center bottom',
    backgroundSize: 'cover',
    boxSizing: 'border-box',
    display: 'flex',
    flexDirection: 'column',
    height: '100%',
    justifyContent: 'center',
    padding: '24px'
  },
  heading: {
    fontSize: '16px',
    fontWeight: 'bold',
    color: colors.primaryText,
    margin: '0',
    textAlign: 'center'
  },
  body: {
    fontSize: '16px',
    color: colors.primaryText,
    marginBottom: '30px',
    marginTop: '16px',
    textAlign: 'center'
  }
};

export default styleSheet;
<|endoftext|>


<commit_before><commit_msg>Dreamview-V2x:change the v2x text color to red (#12449)<commit_after><|endoftext|>


<commit_before>/*eslint dot-notation:0*/
import {
  Parser,
  ObserverLocator,
  EventManager,
  ListenerExpression,
  BindingExpression,
  CallExpression,
  bindingMode
} from 'aurelia-binding';

import {BehaviorInstruction} from 'aurelia-templating';
import * as LogManager from 'aurelia-logging';

export class SyntaxInterpreter {
  static inject() { return [Parser, ObserverLocator, EventManager]; }
  constructor(parser, observerLocator, eventManager) {
    this.parser = parser;
    this.observerLocator = observerLocator;
    this.eventManager = eventManager;
  }

  interpret(resources, element, info, existingInstruction, context) {
    if (info.command in this) {
      return this[info.command](resources, element, info, existingInstruction, context);
    }

    return this.handleUnknownCommand(resources, element, info, existingInstruction, context);
  }

  handleUnknownCommand(resources, element, info, existingInstruction, context) {
    LogManager.getLogger('templating-binding').warn('Unknown binding command.', info);
    return existingInstruction;
  }

  determineDefaultBindingMode(element, attrName, context) {
    let tagName = element.tagName.toLowerCase();

    if (tagName === 'input') {
      return attrName === 'value' || attrName === 'checked' || attrName === 'files' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (tagName === 'textarea' || tagName === 'select') {
      return attrName === 'value' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (attrName === 'textcontent' || attrName === 'innerhtml') {
      return element.contentEditable === 'true' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (attrName === 'scrolltop' || attrName === 'scrollleft') {
      return bindingMode.twoWay;
    }

    if (context && attrName in context.attributes) {
      return context.attributes[attrName].defaultBindingMode || bindingMode.oneWay;
    }

    return bindingMode.oneWay;
  }

  bind(resources, element, info, existingInstruction, context) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      info.defaultBindingMode || this.determineDefaultBindingMode(element, info.attrName, context),
      resources.lookupFunctions
    );

    return instruction;
  }

  trigger(resources, element, info) {
    return new ListenerExpression(
      this.eventManager,
      info.attrName,
      this.parser.parse(info.attrValue),
      false,
      true,
      resources.lookupFunctions
    );
  }

  delegate(resources, element, info) {
    return new ListenerExpression(
      this.eventManager,
      info.attrName,
      this.parser.parse(info.attrValue),
      true,
      true,
      resources.lookupFunctions
    );
  }

  call(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new CallExpression(
      this.observerLocator,
      info.attrName,
      this.parser.parse(info.attrValue),
      resources.lookupFunctions
    );

    return instruction;
  }

  options(resources, element, info, existingInstruction, context) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);
    let attrValue = info.attrValue;
    let language = this.language;
    let name = null;
    let target = '';
    let current;
    let i;
    let ii;
    let inString = false;
    let inEscape = false

    for (i = 0, ii = attrValue.length; i < ii; ++i) {
      current = attrValue[i];

      if (current === ';' && !inString) {
        info = language.inspectAttribute(resources, name, target.trim());
        language.createAttributeInstruction(resources, element, info, instruction, context);

        if (!instruction.attributes[info.attrName]) {
          instruction.attributes[info.attrName] = info.attrValue;
        }

        target = '';
        name = null;
      } else if (current === ':' && name === null) {
        name = target.trim();
        target = '';
      } else if (current === '\\') {
        target += current;
        inEscape = true;
          continue;
      } else {
        target += current;

        if(name !== null && inEscape === false && current === '\'') {
          inString = !inString;
        }
      }

      inEscape = false;
    }

    if (name !== null) {
      info = language.inspectAttribute(resources, name, target.trim());
      language.createAttributeInstruction(resources, element, info, instruction, context);

      if (!instruction.attributes[info.attrName]) {
        instruction.attributes[info.attrName] = info.attrValue;
      }
    }

    return instruction;
  }

  'for'(resources, element, info, existingInstruction) {
    let parts;
    let keyValue;
    let instruction;
    let attrValue;
    let isDestructuring;

    attrValue = info.attrValue;
    isDestructuring = attrValue.match(/^ *[[].+[\]]/);
    parts = isDestructuring ? attrValue.split('of ') : attrValue.split(' of ');

    if (parts.length !== 2) {
      throw new Error('Incorrect syntax for "for". The form is: "$local of $items" or "[$key, $value] of $items".');
    }

    instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    if (isDestructuring) {
      keyValue = parts[0].replace(/[[\]]/g, '').replace(/,/g, ' ').replace(/\s+/g, ' ').trim().split(' ');
      instruction.attributes.key = keyValue[0];
      instruction.attributes.value = keyValue[1];
    } else {
      instruction.attributes.local = parts[0];
    }

    instruction.attributes.items = new BindingExpression(
      this.observerLocator,
      'items',
      this.parser.parse(parts[1]),
      bindingMode.oneWay,
      resources.lookupFunctions
    );

    return instruction;
  }

  'two-way'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
        this.observerLocator,
        this.attributeMap[info.attrName] || info.attrName,
        this.parser.parse(info.attrValue),
        bindingMode.twoWay,
        resources.lookupFunctions
      );

    return instruction;
  }

  'one-way'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      bindingMode.oneWay,
      resources.lookupFunctions
    );

    return instruction;
  }

  'one-time'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      bindingMode.oneTime,
      resources.lookupFunctions
    );

    return instruction;
  }
}
<commit_msg>chore(syntax-interpreter): fix lint errors<commit_after>/*eslint dot-notation:0*/
import {
  Parser,
  ObserverLocator,
  EventManager,
  ListenerExpression,
  BindingExpression,
  CallExpression,
  bindingMode
} from 'aurelia-binding';

import {BehaviorInstruction} from 'aurelia-templating';
import * as LogManager from 'aurelia-logging';

export class SyntaxInterpreter {
  static inject() { return [Parser, ObserverLocator, EventManager]; }
  constructor(parser, observerLocator, eventManager) {
    this.parser = parser;
    this.observerLocator = observerLocator;
    this.eventManager = eventManager;
  }

  interpret(resources, element, info, existingInstruction, context) {
    if (info.command in this) {
      return this[info.command](resources, element, info, existingInstruction, context);
    }

    return this.handleUnknownCommand(resources, element, info, existingInstruction, context);
  }

  handleUnknownCommand(resources, element, info, existingInstruction, context) {
    LogManager.getLogger('templating-binding').warn('Unknown binding command.', info);
    return existingInstruction;
  }

  determineDefaultBindingMode(element, attrName, context) {
    let tagName = element.tagName.toLowerCase();

    if (tagName === 'input') {
      return attrName === 'value' || attrName === 'checked' || attrName === 'files' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (tagName === 'textarea' || tagName === 'select') {
      return attrName === 'value' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (attrName === 'textcontent' || attrName === 'innerhtml') {
      return element.contentEditable === 'true' ? bindingMode.twoWay : bindingMode.oneWay;
    } else if (attrName === 'scrolltop' || attrName === 'scrollleft') {
      return bindingMode.twoWay;
    }

    if (context && attrName in context.attributes) {
      return context.attributes[attrName].defaultBindingMode || bindingMode.oneWay;
    }

    return bindingMode.oneWay;
  }

  bind(resources, element, info, existingInstruction, context) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      info.defaultBindingMode || this.determineDefaultBindingMode(element, info.attrName, context),
      resources.lookupFunctions
    );

    return instruction;
  }

  trigger(resources, element, info) {
    return new ListenerExpression(
      this.eventManager,
      info.attrName,
      this.parser.parse(info.attrValue),
      false,
      true,
      resources.lookupFunctions
    );
  }

  delegate(resources, element, info) {
    return new ListenerExpression(
      this.eventManager,
      info.attrName,
      this.parser.parse(info.attrValue),
      true,
      true,
      resources.lookupFunctions
    );
  }

  call(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new CallExpression(
      this.observerLocator,
      info.attrName,
      this.parser.parse(info.attrValue),
      resources.lookupFunctions
    );

    return instruction;
  }

  options(resources, element, info, existingInstruction, context) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);
    let attrValue = info.attrValue;
    let language = this.language;
    let name = null;
    let target = '';
    let current;
    let i;
    let ii;
    let inString = false;
    let inEscape = false;

    for (i = 0, ii = attrValue.length; i < ii; ++i) {
      current = attrValue[i];

      if (current === ';' && !inString) {
        info = language.inspectAttribute(resources, name, target.trim());
        language.createAttributeInstruction(resources, element, info, instruction, context);

        if (!instruction.attributes[info.attrName]) {
          instruction.attributes[info.attrName] = info.attrValue;
        }

        target = '';
        name = null;
      } else if (current === ':' && name === null) {
        name = target.trim();
        target = '';
      } else if (current === '\\') {
        target += current;
        inEscape = true;
        continue;
      } else {
        target += current;

        if (name !== null && inEscape === false && current === '\'') {
          inString = !inString;
        }
      }

      inEscape = false;
    }

    if (name !== null) {
      info = language.inspectAttribute(resources, name, target.trim());
      language.createAttributeInstruction(resources, element, info, instruction, context);

      if (!instruction.attributes[info.attrName]) {
        instruction.attributes[info.attrName] = info.attrValue;
      }
    }

    return instruction;
  }

  'for'(resources, element, info, existingInstruction) {
    let parts;
    let keyValue;
    let instruction;
    let attrValue;
    let isDestructuring;

    attrValue = info.attrValue;
    isDestructuring = attrValue.match(/^ *[[].+[\]]/);
    parts = isDestructuring ? attrValue.split('of ') : attrValue.split(' of ');

    if (parts.length !== 2) {
      throw new Error('Incorrect syntax for "for". The form is: "$local of $items" or "[$key, $value] of $items".');
    }

    instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    if (isDestructuring) {
      keyValue = parts[0].replace(/[[\]]/g, '').replace(/,/g, ' ').replace(/\s+/g, ' ').trim().split(' ');
      instruction.attributes.key = keyValue[0];
      instruction.attributes.value = keyValue[1];
    } else {
      instruction.attributes.local = parts[0];
    }

    instruction.attributes.items = new BindingExpression(
      this.observerLocator,
      'items',
      this.parser.parse(parts[1]),
      bindingMode.oneWay,
      resources.lookupFunctions
    );

    return instruction;
  }

  'two-way'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
        this.observerLocator,
        this.attributeMap[info.attrName] || info.attrName,
        this.parser.parse(info.attrValue),
        bindingMode.twoWay,
        resources.lookupFunctions
      );

    return instruction;
  }

  'one-way'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      bindingMode.oneWay,
      resources.lookupFunctions
    );

    return instruction;
  }

  'one-time'(resources, element, info, existingInstruction) {
    let instruction = existingInstruction || BehaviorInstruction.attribute(info.attrName);

    instruction.attributes[info.attrName] = new BindingExpression(
      this.observerLocator,
      this.attributeMap[info.attrName] || info.attrName,
      this.parser.parse(info.attrValue),
      bindingMode.oneTime,
      resources.lookupFunctions
    );

    return instruction;
  }
}
<|endoftext|>