<commit_before>import _ from 'lodash';

import MagicSpoon from '../MagicSpoon';
import Stellarify from '../Stellarify';
import directory from '../../directory';
import Validate from '../Validate';
import Event from '../Event';
import * as EnvConsts from '../../env-consts';

export default function Send(driver) {
    this.event = new Event();

    // Constraint: Each step is allowed to safely assume that the previous steps are finished
    this.step2 = {};
    this.step3 = {};
    this.accountId = '';

    const init = () => {
        this.state = 'setup'; // 'setup' | 'pending' | 'error' | 'success'
        this.memoRequired = false;
        this.memoType = 'none'; // 'none' | 'MEMO_ID' |'MEMO_TEXT' | 'MEMO_HASH' | 'MEMO_RETURN'
        this.memoContent = '';
        this.targetAccount = null;
        this.step = 1; // Starts at 1. Natural indexing corresponds to the step numbers
    };

    // Step state is initialized by the reset functions
    const resetStep1 = () => {
        this.accountId = ''; // After step 1, this will be valid
        this.address = ''; // After step 1, this may or may not be filled in
        this.step1 = {
            destInput: '', // For storing the raw input field
        };
    };

    const resetStep2 = () => {
        this.availableAssets = {};
        this.availableAssets[Stellarify.assetToSlug(new StellarSdk.Asset.native())] = {
            asset: new StellarSdk.Asset.native(),
            sendable: true,
        };
        this.step2 = {
            asset: null,
        };
    };

    const resetStep3 = () => {
        this.step3 = {
            amount: '',
        };
    };

    const resetAll = () => {
        init();
        resetStep1();
        resetStep2();
        resetStep3();
    };

    resetAll();

    const calculateAvailableAssets = () => {
        // Calculate the assets that you can send to the destination
        this.availableAssets = {};
        this.availableAssets[Stellarify.assetToSlug(new StellarSdk.Asset.native())] = {
            asset: new StellarSdk.Asset.native(),
            sendable: true,
        };
        const senderTrusts = {};
        const receiverTrusts = {};

        const sendableAssets = {};
        const unSendableAssets = {};

        _.each(driver.session.account.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }
            if (asset.issuer === this.targetAccount.accountId()) {
                // Edgecase: Receiver is the issuer of the asset
                // Note: Accounts cant extend trust to themselves, so no further edgecases on this situation
                this.availableAssets[slug] = {
                    asset,
                    sendable: true,
                };
                receiverTrusts[slug] = true;
            } else {
                senderTrusts[slug] = true;
            }
        });

        _.each(this.targetAccount.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }
            // We don't really care about the usecase of sending to issuer.
            receiverTrusts[slug] = true;
        });

        _.each(this.targetAccount.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (Object.prototype.hasOwnProperty.call(senderTrusts, slug)) {
                sendableAssets[slug] = {
                    asset,
                    sendable: true,
                };
            } else if (asset.getIssuer() === driver.session.account.accountId()) {
                // Edgecase: Sender is the issuer of the asset
                sendableAssets[slug] = {
                    asset,
                    sendable: true,
                };
            } else {
                // Asset can't be sent.
            }
        });

        // Show stuff the recipient doesn't trust
        _.each(driver.session.account.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }

            if (
                !Object.prototype.hasOwnProperty.call(sendableAssets, slug) &&
                !Object.prototype.hasOwnProperty.call(receiverTrusts, slug)
            ) {
                unSendableAssets[slug] = {
                    asset,
                    sendable: false,
                    reason: 'receiverNoTrust',
                };
            }
        });

        _.each(sendableAssets, (availability, slug) => {
            this.availableAssets[slug] = availability;
        });
        _.each(unSendableAssets, (availability, slug) => {
            this.availableAssets[slug] = availability;
        });

        if (Object.prototype.hasOwnProperty.call(directory.destinations, this.accountId)) {
            const whitelist = directory.destinations[this.accountId].acceptedAssetsWhitelist;
            if (whitelist) {
                this.availableAssets = _.map(this.availableAssets, (availability, slug) => {
                    const termAvailability = availability;
                    if (whitelist.indexOf(slug) === -1) {
                        termAvailability.sendable = false;
                        termAvailability.reason = 'assetNotWhitelisted';
                    }
                    return termAvailability;
                });
            }
        }
    };

    const loadTargetAccountDetails = () => {
        if (Validate.publicKey(this.accountId).ready) {
            driver.Server.loadAccount(this.accountId)
                .then((account) => {
                    if (account.id === this.accountId) {
                        // Prevent race conditions using this check
                        this.targetAccount = account;
                        calculateAvailableAssets();
                        this.event.trigger();
                    }
                })
                .catch(() => {});
        }
    };

    this.handlers = {
        updateDestination: (e) => {
            this.step1.destInput = e.target.value;

            // Reset the defaults
            this.accountId = '';
            this.address = '';
            this.memoRequired = false;
            this.memoContentLocked = false;
            this.addressNotFound = false;

            if (Validate.publicKey(this.step1.destInput).ready) {
                this.accountId = this.step1.destInput;

                // Check for memo requirements in the destination
                if (Object.prototype.hasOwnProperty.call(directory.destinations, this.accountId)) {
                    const destination = directory.destinations[this.accountId];
                    if (destination.requiredMemoType) {
                        this.memoRequired = true;
                        this.memoType = destination.requiredMemoType;
                    }
                }

                // Async loading of target account
                loadTargetAccountDetails();
            } else if (Validate.address(this.step1.destInput).ready) {
                // Prevent race race conditions
                const destInput = this.step1.destInput;
                const targetDomain = destInput.split('*')[1];
                const federationDomain = targetDomain === 'stellarterm.com' ? EnvConsts.HOME_DOMAIN : targetDomain;

                StellarSdk.FederationServer.createForDomain(federationDomain)
                    .then(federationServer => federationServer.resolveAddress(this.step1.destInput))
                    .then((federationRecord) => {
                        if (destInput !== this.step1.destInput) {
                            return;
                        }
                        this.address = this.step1.destInput;
                        if (!Validate.publicKey(federationRecord.account_id).ready) {
                            throw new Error('Invalid account_id from federation response');
                        }
                        this.accountId = federationRecord.account_id;

                        if (federationRecord.memo_type) {
                            switch (federationRecord.memo_type) {
                            case 'id':
                                this.memoType = 'MEMO_ID';
                                break;
                            case 'text':
                                this.memoType = 'MEMO_TEXT';
                                break;
                            case 'hash':
                                this.memoType = 'MEMO_HASH';
                                break;
                            case 'return':
                                this.memoType = 'MEMO_RETURN';
                                break;
                            default:
                                throw new Error('Invalid memo_type from federation response');
                            }
                            console.log(federationRecord);
                            this.memoRequired = true;
                        }

                        if (federationRecord.memo) {
                            this.memoContent = federationRecord.memo;
                            this.memoContentLocked = true;
                        }
                        this.event.trigger();
                        loadTargetAccountDetails();
                    })
                    .catch((error) => {
                        // stellar.toml does not exist or it does not contain information about federation server.
                        if (destInput !== this.step1.destInput) {
                            return;
                        }
                        console.error(error);
                        this.addressNotFound = true;
                        this.event.trigger();
                    });
            }

            this.event.trigger();
        },
        updateMemoType: (e) => {
            this.memoType = e.target.value;
            this.event.trigger();
        },
        updateMemoContent: (e) => {
            this.memoContent = e.target.value;
            this.event.trigger();
        },
        step1Edit: () => {
            this.step = 1;
            resetStep2();
            resetStep3();
            loadTargetAccountDetails();
            this.event.trigger();
        },
        step1Next: () => {
            this.step = 2;
            this.event.trigger();
        },

        step2Edit: () => {
            this.step = 2;
            resetStep3();
            this.event.trigger();
        },
        step2PickAsset: (slug) => {
            // Step 2 doesn't have a next button because this acts as the next button
            this.step2.availability = this.availableAssets[slug];
            this.step = 3;
            this.event.trigger();
        },

        step3Edit: () => {
            this.step = 3;
            this.event.trigger();
        },
        updateAmount: (e) => {
            this.step3.amount = e.target.value;
            this.event.trigger();
        },
        step3Next: () => {
            this.step = 4;
            this.event.trigger();
        },
        submit: async () => {
            try {
                const sendMemo =
                    this.memoType === 'none'
                        ? undefined
                        : {
                            type: this.memoType,
                            content: this.memoContent,
                        };

                const tx = await MagicSpoon.buildTxSendPayment(driver.Server, driver.session.account, {
                    destination: this.accountId,
                    asset: this.step2.availability.asset,
                    amount: this.step3.amount,
                    memo: sendMemo,
                });

                const bssResult = await driver.session.handlers.buildSignSubmit(tx);

                if (bssResult.status === 'finish') {
                    this.state = 'pending';
                    this.event.trigger();

                    const result = await bssResult.serverResult;
                    this.txId = result.hash;
                    this.state = 'success';
                } else if (bssResult.status === 'await_signers') {
                    this.state = 'success_signers';
                    this.event.trigger();
                }
            } catch (err) {
                this.state = 'error';
                if (_.has(err.data, 'extras')) {
                    const errExtra = err.data.extras.result_codes.operations.toString();
                    switch (errExtra) {
                    case 'op_no_trust':
                        this.errorDetails = 'Destination does not have a trust line';
                        break;
                    case 'op_low_reserve':
                        this.errorDetails = 'New account has to have at least 1 XLM';
                        break;
                    default:
                        this.errorDetails = JSON.stringify(err, null, 2);
                    }
                } else {
                    this.errorDetails = err.message;
                }

                this.event.trigger();
            }
        },
        reset: () => {
            resetAll();
            this.event.trigger();
        },
    };
}
<commit_msg>Fixed mistake in error handler (send.js), added error message for "bad sequence"<commit_after>import _ from 'lodash';

import MagicSpoon from '../MagicSpoon';
import Stellarify from '../Stellarify';
import directory from '../../directory';
import Validate from '../Validate';
import Event from '../Event';
import * as EnvConsts from '../../env-consts';

export default function Send(driver) {
    this.event = new Event();

    // Constraint: Each step is allowed to safely assume that the previous steps are finished
    this.step2 = {};
    this.step3 = {};
    this.accountId = '';

    const init = () => {
        this.state = 'setup'; // 'setup' | 'pending' | 'error' | 'success'
        this.memoRequired = false;
        this.memoType = 'none'; // 'none' | 'MEMO_ID' |'MEMO_TEXT' | 'MEMO_HASH' | 'MEMO_RETURN'
        this.memoContent = '';
        this.targetAccount = null;
        this.step = 1; // Starts at 1. Natural indexing corresponds to the step numbers
    };

    // Step state is initialized by the reset functions
    const resetStep1 = () => {
        this.accountId = ''; // After step 1, this will be valid
        this.address = ''; // After step 1, this may or may not be filled in
        this.step1 = {
            destInput: '', // For storing the raw input field
        };
    };

    const resetStep2 = () => {
        this.availableAssets = {};
        this.availableAssets[Stellarify.assetToSlug(new StellarSdk.Asset.native())] = {
            asset: new StellarSdk.Asset.native(),
            sendable: true,
        };
        this.step2 = {
            asset: null,
        };
    };

    const resetStep3 = () => {
        this.step3 = {
            amount: '',
        };
    };

    const resetAll = () => {
        init();
        resetStep1();
        resetStep2();
        resetStep3();
    };

    resetAll();

    const calculateAvailableAssets = () => {
        // Calculate the assets that you can send to the destination
        this.availableAssets = {};
        this.availableAssets[Stellarify.assetToSlug(new StellarSdk.Asset.native())] = {
            asset: new StellarSdk.Asset.native(),
            sendable: true,
        };
        const senderTrusts = {};
        const receiverTrusts = {};

        const sendableAssets = {};
        const unSendableAssets = {};

        _.each(driver.session.account.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }
            if (asset.issuer === this.targetAccount.accountId()) {
                // Edgecase: Receiver is the issuer of the asset
                // Note: Accounts cant extend trust to themselves, so no further edgecases on this situation
                this.availableAssets[slug] = {
                    asset,
                    sendable: true,
                };
                receiverTrusts[slug] = true;
            } else {
                senderTrusts[slug] = true;
            }
        });

        _.each(this.targetAccount.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }
            // We don't really care about the usecase of sending to issuer.
            receiverTrusts[slug] = true;
        });

        _.each(this.targetAccount.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (Object.prototype.hasOwnProperty.call(senderTrusts, slug)) {
                sendableAssets[slug] = {
                    asset,
                    sendable: true,
                };
            } else if (asset.getIssuer() === driver.session.account.accountId()) {
                // Edgecase: Sender is the issuer of the asset
                sendableAssets[slug] = {
                    asset,
                    sendable: true,
                };
            } else {
                // Asset can't be sent.
            }
        });

        // Show stuff the recipient doesn't trust
        _.each(driver.session.account.balances, (balance) => {
            const asset = Stellarify.asset(balance);
            const slug = Stellarify.assetToSlug(asset);
            if (asset.isNative()) {
                return;
            }

            if (
                !Object.prototype.hasOwnProperty.call(sendableAssets, slug) &&
                !Object.prototype.hasOwnProperty.call(receiverTrusts, slug)
            ) {
                unSendableAssets[slug] = {
                    asset,
                    sendable: false,
                    reason: 'receiverNoTrust',
                };
            }
        });

        _.each(sendableAssets, (availability, slug) => {
            this.availableAssets[slug] = availability;
        });
        _.each(unSendableAssets, (availability, slug) => {
            this.availableAssets[slug] = availability;
        });

        if (Object.prototype.hasOwnProperty.call(directory.destinations, this.accountId)) {
            const whitelist = directory.destinations[this.accountId].acceptedAssetsWhitelist;
            if (whitelist) {
                this.availableAssets = _.map(this.availableAssets, (availability, slug) => {
                    const termAvailability = availability;
                    if (whitelist.indexOf(slug) === -1) {
                        termAvailability.sendable = false;
                        termAvailability.reason = 'assetNotWhitelisted';
                    }
                    return termAvailability;
                });
            }
        }
    };

    const loadTargetAccountDetails = () => {
        if (Validate.publicKey(this.accountId).ready) {
            driver.Server.loadAccount(this.accountId)
                .then((account) => {
                    if (account.id === this.accountId) {
                        // Prevent race conditions using this check
                        this.targetAccount = account;
                        calculateAvailableAssets();
                        this.event.trigger();
                    }
                })
                .catch(() => {});
        }
    };

    this.handlers = {
        updateDestination: (e) => {
            this.step1.destInput = e.target.value;

            // Reset the defaults
            this.accountId = '';
            this.address = '';
            this.memoRequired = false;
            this.memoContentLocked = false;
            this.addressNotFound = false;

            if (Validate.publicKey(this.step1.destInput).ready) {
                this.accountId = this.step1.destInput;

                // Check for memo requirements in the destination
                if (Object.prototype.hasOwnProperty.call(directory.destinations, this.accountId)) {
                    const destination = directory.destinations[this.accountId];
                    if (destination.requiredMemoType) {
                        this.memoRequired = true;
                        this.memoType = destination.requiredMemoType;
                    }
                }

                // Async loading of target account
                loadTargetAccountDetails();
            } else if (Validate.address(this.step1.destInput).ready) {
                // Prevent race race conditions
                const destInput = this.step1.destInput;
                const targetDomain = destInput.split('*')[1];
                const federationDomain = targetDomain === 'stellarterm.com' ? EnvConsts.HOME_DOMAIN : targetDomain;

                StellarSdk.FederationServer.createForDomain(federationDomain)
                    .then(federationServer => federationServer.resolveAddress(this.step1.destInput))
                    .then((federationRecord) => {
                        if (destInput !== this.step1.destInput) {
                            return;
                        }
                        this.address = this.step1.destInput;
                        if (!Validate.publicKey(federationRecord.account_id).ready) {
                            throw new Error('Invalid account_id from federation response');
                        }
                        this.accountId = federationRecord.account_id;

                        if (federationRecord.memo_type) {
                            switch (federationRecord.memo_type) {
                            case 'id':
                                this.memoType = 'MEMO_ID';
                                break;
                            case 'text':
                                this.memoType = 'MEMO_TEXT';
                                break;
                            case 'hash':
                                this.memoType = 'MEMO_HASH';
                                break;
                            case 'return':
                                this.memoType = 'MEMO_RETURN';
                                break;
                            default:
                                throw new Error('Invalid memo_type from federation response');
                            }
                            console.log(federationRecord);
                            this.memoRequired = true;
                        }

                        if (federationRecord.memo) {
                            this.memoContent = federationRecord.memo;
                            this.memoContentLocked = true;
                        }
                        this.event.trigger();
                        loadTargetAccountDetails();
                    })
                    .catch((error) => {
                        // stellar.toml does not exist or it does not contain information about federation server.
                        if (destInput !== this.step1.destInput) {
                            return;
                        }
                        console.error(error);
                        this.addressNotFound = true;
                        this.event.trigger();
                    });
            }

            this.event.trigger();
        },
        updateMemoType: (e) => {
            this.memoType = e.target.value;
            this.event.trigger();
        },
        updateMemoContent: (e) => {
            this.memoContent = e.target.value;
            this.event.trigger();
        },
        step1Edit: () => {
            this.step = 1;
            resetStep2();
            resetStep3();
            loadTargetAccountDetails();
            this.event.trigger();
        },
        step1Next: () => {
            this.step = 2;
            this.event.trigger();
        },

        step2Edit: () => {
            this.step = 2;
            resetStep3();
            this.event.trigger();
        },
        step2PickAsset: (slug) => {
            // Step 2 doesn't have a next button because this acts as the next button
            this.step2.availability = this.availableAssets[slug];
            this.step = 3;
            this.event.trigger();
        },

        step3Edit: () => {
            this.step = 3;
            this.event.trigger();
        },
        updateAmount: (e) => {
            this.step3.amount = e.target.value;
            this.event.trigger();
        },
        step3Next: () => {
            this.step = 4;
            this.event.trigger();
        },
        submit: async () => {
            try {
                const sendMemo =
                    this.memoType === 'none'
                        ? undefined
                        : {
                            type: this.memoType,
                            content: this.memoContent,
                        };

                const tx = await MagicSpoon.buildTxSendPayment(driver.Server, driver.session.account, {
                    destination: this.accountId,
                    asset: this.step2.availability.asset,
                    amount: this.step3.amount,
                    memo: sendMemo,
                });

                const bssResult = await driver.session.handlers.buildSignSubmit(tx);

                if (bssResult.status === 'finish') {
                    this.state = 'pending';
                    this.event.trigger();

                    const result = await bssResult.serverResult;
                    this.txId = result.hash;
                    this.state = 'success';
                } else if (bssResult.status === 'await_signers') {
                    this.state = 'success_signers';
                    this.event.trigger();
                }
            } catch (err) {
                this.state = 'error';
                if (_.has(err.data, 'extras')) {
                    const { result_codes } = err.data.extras;
                    const errExtra = result_codes.transaction || result_codes.operations;
                    switch (errExtra.toString()) {
                    case 'op_no_trust':
                        this.errorDetails = 'Destination does not have a trust line';
                        break;
                    case 'op_low_reserve':
                        this.errorDetails = 'New account has to have at least 1 XLM';
                        break;
                    case 'tx_bad_seq':
                        this.errorDetails = 'Transaction failed because sequence got out of sync. ' +
                                'Please reload StellarTerm and try again.';
                        break;
                    default:
                        this.errorDetails = JSON.stringify(err, null, 2);
                    }
                } else {
                    this.errorDetails = err.message;
                }

                this.event.trigger();
            }
        },
        reset: () => {
            resetAll();
            this.event.trigger();
        },
    };
}
<|endoftext|>


<commit_before>'use strict';
import { $ } from 'meteor/jquery';
import { _ } from 'meteor/underscore';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { dbArena } from '/db/dbArena';
import { dbArenaFighters, getAttributeNumber } from '/db/dbArenaFighters';
import { dbArenaLog } from '/db/dbArenaLog';
import { inheritedShowLoadingOnSubscribing } from '../layout/loading';
import { shouldStopSubscribe } from '../utils/idle';

const rDisplayPanelList = new ReactiveVar(['fighterList']);
inheritedShowLoadingOnSubscribing(Template.arenaInfo);
Template.arenaInfo.onCreated(function() {
  this.autorun(() => {
    if (shouldStopSubscribe()) {
      return false;
    }
    const arenaId = FlowRouter.getParam('arenaId');
    if (arenaId) {
      this.subscribe('arenaInfo', arenaId);
      this.subscribe('adjacentArena', arenaId);
    }
  });
});
Template.arenaInfo.helpers({
  arenaData() {
    const arenaId = FlowRouter.getParam('arenaId');
    const arenaData = dbArena.findOne(arenaId);
    //更換大賽資訊，自動依據大賽是否已過期來重設選手排列依據
    if (arenaData) {
      if (Date.now() > arenaData.endDate) {
        rFighterSortBy.set('winnerIndex');
        rFighterSortDir.set(1);
      }
      else {
        rFighterSortBy.set('agi');
        rFighterSortDir.set(-1);
      }
    }

    return arenaData;
  },
  nowIsBeforeTimeOf(date) {
    return date ? (Date.now() <= date.getTime()) : false;
  },
  isDisplayPanel(panelType) {
    return _.contains(rDisplayPanelList.get(), panelType);
  }
});
Template.arenaInfo.events({
  'click [data-toggle-panel]'(event) {
    event.preventDefault();
    const $emitter = $(event.currentTarget);
    const panelType = $emitter.attr('data-toggle-panel');
    const displayPanelList = rDisplayPanelList.get();
    if (_.contains(displayPanelList, panelType)) {
      rDisplayPanelList.set(_.without(displayPanelList, panelType));
    }
    else {
      displayPanelList.push(panelType);
      rDisplayPanelList.set(displayPanelList);
    }
  }
});

Template.arenaInfoNav.helpers({
  arenaLinkAttrs(linkType) {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    if (currentArenaData) {
      switch (linkType) {
        case 'prev': {
          const navArenaData = dbArena.findOne(
            {
              beginDate: {
                $lt: currentArenaData.beginDate
              }
            },
            {
              sort: {
                beginDate: -1
              }
            }
          );
          if (navArenaData) {
            return {
              'class': 'btn btn-info btn-sm float-left',
              'href': FlowRouter.path('arenaInfo', {
                arenaId: navArenaData._id
              })
            };
          }
          else {
            return {
              'class': 'btn btn-info btn-sm float-left disabled',
              'href': FlowRouter.path('arenaInfo', {arenaId})
            };
          }
        }
        case 'next': {
          const navArenaData = dbArena.findOne(
            {
              beginDate: {
                $gt: currentArenaData.beginDate
              }
            },
            {
              sort: {
                beginDate: 1
              }
            }
          );
          if (navArenaData && navArenaData._id !== arenaId) {
            return {
              'class': 'btn btn-info btn-sm float-right',
              'href': FlowRouter.path('arenaInfo', {
                arenaId: navArenaData._id
              })
            };
          }
          else {
            return {
              'class': 'btn btn-info btn-sm float-right disabled',
              'href': FlowRouter.path('arenaInfo', {arenaId})
            };
          }
        }
      }
    }
  },
  arenaBegin() {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    return currentArenaData ? currentArenaData.beginDate : null;
  },
  arenaEnd() {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    return currentArenaData ? currentArenaData.endDate : null;
  }
});

//auto load company/fighter name info
const rFighterIdList = new ReactiveVar([]);
const rFighterUrlHash = new ReactiveVar({});
const rFighterNameHash = new ReactiveVar({});
const rManagerIdList = new ReactiveVar([]);
const rManagerUrlHash = new ReactiveVar({});
const rManagerNameHash = new ReactiveVar({});
Template.arenaInfo.onCreated(function() {
  this.autorun(() => {
    const arenaId = FlowRouter.getParam('arenaId');
    const fighterIdList = new Set();
    const managerIdList = new Set();
    dbArenaFighters.find({arenaId}).forEach((fighter) => {
      fighterIdList.add(fighter.companyId);
      managerIdList.add(fighter.manager);
    });
    rFighterIdList.set([...fighterIdList]);
    rManagerIdList.set([...managerIdList]);
  });
  const fighterAjaxList = [];
  this.autorun(() => {
    _.invoke(fighterAjaxList, 'abort');
    fighterAjaxList.splice(0);
    const fighterUrlHash = {};
    const fighterNameHash = {};
    _.each(rFighterIdList.get(), (companyId) => {
      fighterUrlHash[companyId] = FlowRouter.path('companyDetail', {companyId});
      const ajaxResult = $.ajax({
        url: '/companyInfo',
        data: {
          id: companyId
        },
        dataType: 'json',
        success: (companyData) => {
          fighterNameHash[companyId] = companyData.name;
        },
        error: () => {
          fighterNameHash[companyId] = '???';
        }
      });
      fighterAjaxList.push(ajaxResult);
    });
    $.when(...fighterAjaxList).always(() => {
      rFighterUrlHash.set(fighterUrlHash);
      rFighterNameHash.set(fighterNameHash);
    });
  });
  const managerAjaxList = [];
  this.autorun(() => {
    _.invoke(managerAjaxList, 'abort');
    managerAjaxList.splice(0);
    const managerUrlHash = {};
    const managerNameHash = {};
    _.each(rManagerIdList.get(), (userId) => {
      managerUrlHash[userId] = FlowRouter.path('accountInfo', {userId});
      const ajaxResult = $.ajax({
        url: '/userInfo',
        data: {
          id: userId
        },
        dataType: 'json',
        success: (userData) => {
          managerNameHash[userId] = userData.name;
        },
        error: () => {
          managerNameHash[userId] = '???';
        }
      });
      managerAjaxList.push(ajaxResult);
    });
    $.when(...managerAjaxList).always(() => {
      rManagerUrlHash.set(managerUrlHash);
      rManagerNameHash.set(managerNameHash);
    });
  });
});

const rFighterSortBy = new ReactiveVar('');
const rFighterSortDir = new ReactiveVar(-1);
Template.arenaFighterTable.onCreated(function() {
  if (Date.now() > this.data.endDate) {
    rFighterSortBy.set('winnerIndex');
    rFighterSortDir.set(1);
  }
  else {
    rFighterSortBy.set('agi');
    rFighterSortDir.set(-1);
  }
});
Template.arenaFighterTable.onRendered(function() {
  if (Date.now() > this.data.endDate) {
    rFighterSortBy.set('winnerIndex');
    rFighterSortDir.set(1);
  }
  else {
    rFighterSortBy.set('agi');
    rFighterSortDir.set(-1);
  }
});
Template.arenaFighterTable.helpers({
  getSortIcon(fieldName) {
    if (fieldName === rFighterSortBy.get()) {
      if (rFighterSortDir.get() === -1) {
        return `<i class="fa fa-sort-amount-desc" aria-hidden="true"></i>`;
      }
      else {
        return `<i class="fa fa-sort-amount-asc" aria-hidden="true"></i>`;
      }
    }

    return '';
  },
  fighterList() {
    const winnerList = this.winnerList;
    const arenaId = this._id;

    const fighterList = dbArenaFighters
      .find({arenaId})
      .map((figher) => {
        if (winnerList.length) {
          figher.winnerIndex = _.indexOf(winnerList, figher.companyId) + 1;
        }
        else {
          figher.winnerIndex = '';
        }

        return figher;
      });
    const sortBy = rFighterSortBy.get();
    const sortDir = rFighterSortDir.get();

    return fighterList.sort((fighter1, fighter2) => {
      switch (sortBy) {
        case 'agi': {
          const agi1 = fighter1.agi;
          const agi2 = fighter2.agi;
          //agi相等時比較createdAt的逆序
          if (agi1 === agi2) {
            return (fighter1.createdAt.getTime() - fighter2.createdAt.getTime()) * sortDir * -1;
          }
          else {
            return (agi1 - agi2) * sortDir;
          }
        }
        default: {
          return (fighter1[sortBy] - fighter2[sortBy]) * sortDir;
        }
      }
    });
  },
  fighterUrl(companyId) {
    return rFighterUrlHash.get()[companyId];
  },
  fighterName(companyId) {
    return rFighterNameHash.get()[companyId];
  },
  managerUrl(manager) {
    return rManagerUrlHash.get()[manager];
  },
  managerName(manager) {
    return rManagerNameHash.get()[manager];
  },
  getAttributeNumber(fighter, attributeName) {
    return getAttributeNumber(attributeName, fighter[attributeName]);
  }
});
Template.arenaFighterTable.events({
  'click [data-sort]'(event) {
    const sortBy = $(event.currentTarget).attr('data-sort');
    if (rFighterSortBy.get() === sortBy) {
      rFighterSortDir.set(rFighterSortDir.get() * -1);
    }
    else {
      rFighterSortBy.set(sortBy);
      rFighterSortDir.set(-1);
    }
  }
});

const rLogOffset = new ReactiveVar(0);
const rFilterCompanyId = new ReactiveVar('');
const rFilterResultList = new ReactiveVar([]);
inheritedShowLoadingOnSubscribing(Template.arenaLogList);
Template.arenaLogList.onCreated(function() {
  rLogOffset.set(0);
  this.autorun(() => {
    if (shouldStopSubscribe()) {
      return false;
    }
    const arenaId = FlowRouter.getParam('arenaId');
    if (arenaId) {
      this.subscribe('arenaLog', arenaId, rFilterCompanyId.get(), rLogOffset.get());
    }
  });
});
Template.arenaLogList.helpers({
  hasFilterResult() {
    return rFilterResultList.get().length > 0;
  },
  filterResultList() {
    return rFilterResultList.get();
  },
  logList() {
    const arenaId = FlowRouter.getParam('arenaId');
    window.dbArenaLog = dbArenaLog;

    return dbArenaLog
      .find({arenaId}, {
        sort: {
          sequence: 1
        },
        limit: 30
      })
      .map((log) => {
        log.attackerId = log.companyId[0];
        log.defenderId = log.companyId[1];

        return log;
      });
  },
  displaySp(log) {
    if (log.attackManner > 0) {
      return `(SP:${log.attackerSp})`;
    }
    else {
      const arenaId = log.arenaId;
      const companyId = log.attackerId;
      const attacker = dbArenaFighters.findOne({arenaId, companyId});

      return `(SP:${log.attackerSp}<span class="text-danger">-${attacker.spCost}</span>)`;
    }
  },
  displayAttackManaer(log) {
    let result = '';
    const arenaId = log.arenaId;
    const companyId = log.attackerId;
    const attacker = dbArenaFighters.findOne({arenaId, companyId});
    if (attacker) {
      if (log.attackManner > 0) {
        result += '普通攻擊';
        const mannerName = attacker.normalManner[log.attackManner - 1];
        if (mannerName) {
          result += '「' + mannerName + '」';
        }
      }
      else {
        result += '特殊攻擊';
        const mannerName = attacker.specialManner[(log.attackManner * -1) - 1];
        if (mannerName) {
          result += '「' + mannerName + '」';
        }
      }

      return result;
    }
    else {
      return '???';
    }
  },
  paginationData() {
    return {
      useVariableForTotalCount: 'totalCountOfArenaLog',
      dataNumberPerPage: 30,
      offset: rLogOffset
    };
  }
});
Template.arenaLogList.events({
  'focus [name="companyId"]': generateFilterResult,
  'keyup [name="companyId"]': generateFilterResult,
  'submit'(event) {
    event.preventDefault();
  },
  'click [data-filter]'(event, templateInstance) {
    event.preventDefault();
    const companyId = $(event.currentTarget).attr('data-filter');
    rFilterCompanyId.set(companyId);
    rLogOffset.set(0);
    rFilterResultList.set([]);
    const fighterData = _.find(rFighterList.get(), (fighter) => {
      return fighter._id === companyId;
    });
    if (fighterData) {
      templateInstance.$('[name="companyId"]').val(fighterData.name || '');
    }
  }
});

function generateFilterResult(event) {
  const searchName = $(event.currentTarget).val();
  if (searchName) {
    const searchRegExp = new RegExp(searchName);
    const filterResultList = _.filter(rFighterList.get(), (fighter) => {
      return searchRegExp.test(fighter.name);
    });
    rFilterResultList.set(filterResultList);
  }
  else {
    rFilterResultList.set([]);
  }
}
<commit_msg>eslint<commit_after>'use strict';
import { $ } from 'meteor/jquery';
import { _ } from 'meteor/underscore';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { dbArena } from '/db/dbArena';
import { dbArenaFighters, getAttributeNumber } from '/db/dbArenaFighters';
import { dbArenaLog } from '/db/dbArenaLog';
import { inheritedShowLoadingOnSubscribing } from '../layout/loading';
import { shouldStopSubscribe } from '../utils/idle';

const rDisplayPanelList = new ReactiveVar(['fighterList']);
inheritedShowLoadingOnSubscribing(Template.arenaInfo);
Template.arenaInfo.onCreated(function() {
  this.autorun(() => {
    if (shouldStopSubscribe()) {
      return false;
    }
    const arenaId = FlowRouter.getParam('arenaId');
    if (arenaId) {
      this.subscribe('arenaInfo', arenaId);
      this.subscribe('adjacentArena', arenaId);
    }
  });
});
Template.arenaInfo.helpers({
  arenaData() {
    const arenaId = FlowRouter.getParam('arenaId');
    const arenaData = dbArena.findOne(arenaId);
    //更換大賽資訊，自動依據大賽是否已過期來重設選手排列依據
    if (arenaData) {
      if (Date.now() > arenaData.endDate) {
        rFighterSortBy.set('winnerIndex');
        rFighterSortDir.set(1);
      }
      else {
        rFighterSortBy.set('agi');
        rFighterSortDir.set(-1);
      }
    }

    return arenaData;
  },
  nowIsBeforeTimeOf(date) {
    return date ? (Date.now() <= date.getTime()) : false;
  },
  isDisplayPanel(panelType) {
    return _.contains(rDisplayPanelList.get(), panelType);
  }
});
Template.arenaInfo.events({
  'click [data-toggle-panel]'(event) {
    event.preventDefault();
    const $emitter = $(event.currentTarget);
    const panelType = $emitter.attr('data-toggle-panel');
    const displayPanelList = rDisplayPanelList.get();
    if (_.contains(displayPanelList, panelType)) {
      rDisplayPanelList.set(_.without(displayPanelList, panelType));
    }
    else {
      displayPanelList.push(panelType);
      rDisplayPanelList.set(displayPanelList);
    }
  }
});

Template.arenaInfoNav.helpers({
  arenaLinkAttrs(linkType) {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    if (currentArenaData) {
      switch (linkType) {
        case 'prev': {
          const navArenaData = dbArena.findOne(
            {
              beginDate: {
                $lt: currentArenaData.beginDate
              }
            },
            {
              sort: {
                beginDate: -1
              }
            }
          );
          if (navArenaData) {
            return {
              'class': 'btn btn-info btn-sm float-left',
              'href': FlowRouter.path('arenaInfo', {
                arenaId: navArenaData._id
              })
            };
          }
          else {
            return {
              'class': 'btn btn-info btn-sm float-left disabled',
              'href': FlowRouter.path('arenaInfo', {arenaId})
            };
          }
        }
        case 'next': {
          const navArenaData = dbArena.findOne(
            {
              beginDate: {
                $gt: currentArenaData.beginDate
              }
            },
            {
              sort: {
                beginDate: 1
              }
            }
          );
          if (navArenaData && navArenaData._id !== arenaId) {
            return {
              'class': 'btn btn-info btn-sm float-right',
              'href': FlowRouter.path('arenaInfo', {
                arenaId: navArenaData._id
              })
            };
          }
          else {
            return {
              'class': 'btn btn-info btn-sm float-right disabled',
              'href': FlowRouter.path('arenaInfo', {arenaId})
            };
          }
        }
      }
    }
  },
  arenaBegin() {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    return currentArenaData ? currentArenaData.beginDate : null;
  },
  arenaEnd() {
    const arenaId = FlowRouter.getParam('arenaId');
    const currentArenaData = dbArena.findOne(arenaId);

    return currentArenaData ? currentArenaData.endDate : null;
  }
});

//auto load company/fighter name info
const rFighterIdList = new ReactiveVar([]);
const rFighterUrlHash = new ReactiveVar({});
const rFighterNameHash = new ReactiveVar({});
const rManagerIdList = new ReactiveVar([]);
const rManagerUrlHash = new ReactiveVar({});
const rManagerNameHash = new ReactiveVar({});
Template.arenaInfo.onCreated(function() {
  this.autorun(() => {
    const arenaId = FlowRouter.getParam('arenaId');
    const fighterIdList = new Set();
    const managerIdList = new Set();
    dbArenaFighters.find({arenaId}).forEach((fighter) => {
      fighterIdList.add(fighter.companyId);
      managerIdList.add(fighter.manager);
    });
    rFighterIdList.set([...fighterIdList]);
    rManagerIdList.set([...managerIdList]);
  });
  const fighterAjaxList = [];
  this.autorun(() => {
    _.invoke(fighterAjaxList, 'abort');
    fighterAjaxList.splice(0);
    const fighterUrlHash = {};
    const fighterNameHash = {};
    _.each(rFighterIdList.get(), (companyId) => {
      fighterUrlHash[companyId] = FlowRouter.path('companyDetail', {companyId});
      const ajaxResult = $.ajax({
        url: '/companyInfo',
        data: {
          id: companyId
        },
        dataType: 'json',
        success: (companyData) => {
          fighterNameHash[companyId] = companyData.name;
        },
        error: () => {
          fighterNameHash[companyId] = '???';
        }
      });
      fighterAjaxList.push(ajaxResult);
    });
    $.when(...fighterAjaxList).always(() => {
      rFighterUrlHash.set(fighterUrlHash);
      rFighterNameHash.set(fighterNameHash);
    });
  });
  const managerAjaxList = [];
  this.autorun(() => {
    _.invoke(managerAjaxList, 'abort');
    managerAjaxList.splice(0);
    const managerUrlHash = {};
    const managerNameHash = {};
    _.each(rManagerIdList.get(), (userId) => {
      managerUrlHash[userId] = FlowRouter.path('accountInfo', {userId});
      const ajaxResult = $.ajax({
        url: '/userInfo',
        data: {
          id: userId
        },
        dataType: 'json',
        success: (userData) => {
          managerNameHash[userId] = userData.name;
        },
        error: () => {
          managerNameHash[userId] = '???';
        }
      });
      managerAjaxList.push(ajaxResult);
    });
    $.when(...managerAjaxList).always(() => {
      rManagerUrlHash.set(managerUrlHash);
      rManagerNameHash.set(managerNameHash);
    });
  });
});

const rFighterSortBy = new ReactiveVar('');
const rFighterSortDir = new ReactiveVar(-1);
Template.arenaFighterTable.onCreated(function() {
  if (Date.now() > this.data.endDate) {
    rFighterSortBy.set('winnerIndex');
    rFighterSortDir.set(1);
  }
  else {
    rFighterSortBy.set('agi');
    rFighterSortDir.set(-1);
  }
});
Template.arenaFighterTable.onRendered(function() {
  if (Date.now() > this.data.endDate) {
    rFighterSortBy.set('winnerIndex');
    rFighterSortDir.set(1);
  }
  else {
    rFighterSortBy.set('agi');
    rFighterSortDir.set(-1);
  }
});
Template.arenaFighterTable.helpers({
  getSortIcon(fieldName) {
    if (fieldName === rFighterSortBy.get()) {
      if (rFighterSortDir.get() === -1) {
        return `<i class="fa fa-sort-amount-desc" aria-hidden="true"></i>`;
      }
      else {
        return `<i class="fa fa-sort-amount-asc" aria-hidden="true"></i>`;
      }
    }

    return '';
  },
  fighterList() {
    const winnerList = this.winnerList;
    const arenaId = this._id;

    const fighterList = dbArenaFighters
      .find({arenaId})
      .map((figher) => {
        if (winnerList.length) {
          figher.winnerIndex = _.indexOf(winnerList, figher.companyId) + 1;
        }
        else {
          figher.winnerIndex = '';
        }

        return figher;
      });
    const sortBy = rFighterSortBy.get();
    const sortDir = rFighterSortDir.get();

    return fighterList.sort((fighter1, fighter2) => {
      switch (sortBy) {
        case 'agi': {
          const agi1 = fighter1.agi;
          const agi2 = fighter2.agi;
          //agi相等時比較createdAt的逆序
          if (agi1 === agi2) {
            return (fighter1.createdAt.getTime() - fighter2.createdAt.getTime()) * sortDir * -1;
          }
          else {
            return (agi1 - agi2) * sortDir;
          }
        }
        default: {
          return (fighter1[sortBy] - fighter2[sortBy]) * sortDir;
        }
      }
    });
  },
  fighterUrl(companyId) {
    return rFighterUrlHash.get()[companyId];
  },
  fighterName(companyId) {
    return rFighterNameHash.get()[companyId];
  },
  managerUrl(manager) {
    return rManagerUrlHash.get()[manager];
  },
  managerName(manager) {
    return rManagerNameHash.get()[manager];
  },
  getAttributeNumber(fighter, attributeName) {
    return getAttributeNumber(attributeName, fighter[attributeName]);
  }
});
Template.arenaFighterTable.events({
  'click [data-sort]'(event) {
    const sortBy = $(event.currentTarget).attr('data-sort');
    if (rFighterSortBy.get() === sortBy) {
      rFighterSortDir.set(rFighterSortDir.get() * -1);
    }
    else {
      rFighterSortBy.set(sortBy);
      rFighterSortDir.set(-1);
    }
  }
});

const rLogOffset = new ReactiveVar(0);
const rFilterCompanyId = new ReactiveVar('');
const rFilterResultList = new ReactiveVar([]);
inheritedShowLoadingOnSubscribing(Template.arenaLogList);
Template.arenaLogList.onCreated(function() {
  rLogOffset.set(0);
  this.autorun(() => {
    if (shouldStopSubscribe()) {
      return false;
    }
    const arenaId = FlowRouter.getParam('arenaId');
    if (arenaId) {
      this.subscribe('arenaLog', arenaId, rFilterCompanyId.get(), rLogOffset.get());
    }
  });
});
Template.arenaLogList.helpers({
  hasFilterResult() {
    return rFilterResultList.get().length > 0;
  },
  filterResultList() {
    return rFilterResultList.get();
  },
  logList() {
    const arenaId = FlowRouter.getParam('arenaId');
    window.dbArenaLog = dbArenaLog;

    return dbArenaLog
      .find({arenaId}, {
        sort: {
          sequence: 1
        },
        limit: 30
      })
      .map((log) => {
        log.attackerId = log.companyId[0];
        log.defenderId = log.companyId[1];

        return log;
      });
  },
  displaySp(log) {
    if (log.attackManner > 0) {
      return `(SP:${log.attackerSp})`;
    }
    else {
      const arenaId = log.arenaId;
      const companyId = log.attackerId;
      const attacker = dbArenaFighters.findOne({arenaId, companyId});

      return `(SP:${log.attackerSp}<span class="text-danger">-${attacker.spCost}</span>)`;
    }
  },
  displayAttackManaer(log) {
    let result = '';
    const arenaId = log.arenaId;
    const companyId = log.attackerId;
    const attacker = dbArenaFighters.findOne({arenaId, companyId});
    if (attacker) {
      if (log.attackManner > 0) {
        result += '普通攻擊';
        const mannerName = attacker.normalManner[log.attackManner - 1];
        if (mannerName) {
          result += '「' + mannerName + '」';
        }
      }
      else {
        result += '特殊攻擊';
        const mannerName = attacker.specialManner[(log.attackManner * -1) - 1];
        if (mannerName) {
          result += '「' + mannerName + '」';
        }
      }

      return result;
    }
    else {
      return '???';
    }
  },
  paginationData() {
    return {
      useVariableForTotalCount: 'totalCountOfArenaLog',
      dataNumberPerPage: 30,
      offset: rLogOffset
    };
  }
});
Template.arenaLogList.events({
  'focus [name="companyId"]': generateFilterResult,
  'keyup [name="companyId"]': generateFilterResult,
  'submit'(event) {
    event.preventDefault();
  },
  'click [data-filter]'(event, templateInstance) {
    event.preventDefault();
    const companyId = $(event.currentTarget).attr('data-filter');
    rFilterCompanyId.set(companyId);
    rLogOffset.set(0);
    rFilterResultList.set([]);
    const fighterName = rFighterNameHash.get()[companyId];
    templateInstance.$('[name="companyId"]').val(fighterName || '');
  }
});

function generateFilterResult(event) {
  const searchName = $(event.currentTarget).val();
  if (searchName) {
    const searchRegExp = new RegExp(searchName);
    const filterResultList = [];
    _.each(rFighterNameHash.get(), (fighterName, companyId) => {
      if (searchRegExp.test(fighterName)) {
        filterResultList.push({
          _id: companyId,
          name: fighterName
        });
      }
    });
    rFilterResultList.set(filterResultList);
  }
  else {
    rFilterResultList.set([]);
  }
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

/*global process,__dirname,define,run,suite,test*/

var assert = require('assert');
var path = require('path');
var glob = require('glob');
var istanbul = require('istanbul');
var jsdom = require('jsdom-no-contextify');
var minimatch = require('minimatch');
var async = require('async');
var TEST_GLOB = '**/test/**/*.test.js';

var optimist = require('optimist')
	.usage('Run the Code tests. All mocha options apply.')
	.describe('build', 'Run from out-build').boolean('build')
	.describe('run', 'Run a single file').string('run')
	.describe('coverage', 'Generate a coverage report').boolean('coverage')
	.describe('browser', 'Run tests in a browser').boolean('browser')
	.alias('h', 'help').boolean('h')
	.describe('h', 'Show help');

var argv = optimist.argv;

if (argv.help) {
	optimist.showHelp();
	process.exit(1);
}

var out = argv.build ? 'out-build' : 'out';
var loader = require('../' + out + '/vs/loader');
var src = path.join(path.dirname(__dirname), out);

function loadSingleTest(test) {
	var moduleId = path.relative(src, path.resolve(test)).replace(/\.js$/, '');

	return function (cb) {
		define([moduleId], function () {
			cb(null);
		});
	};
}

function loadClientTests(cb) {
	glob(TEST_GLOB, { cwd: src }, function (err, files) {
		var modules = files.map(function (file) {
			return file.replace(/\.js$/, '');
		});

		// load all modules
		define(modules, function () {
			cb(null);
		});
	});
}

function loadPluginTests(cb) {
	var root = path.join(path.dirname(__dirname), 'extensions');
	glob(TEST_GLOB, { cwd: root }, function (err, files) {

		var modules = files.map(function (file) {
			return 'extensions/' + file.replace(/\.js$/, '');
		});

		define(modules, function() {
			cb();
		});
	});
}

function main() {
	process.on('uncaughtException', function (e) {
		console.error(e.stack || e);
	});

	var loaderConfig = {
		nodeRequire: require,
		nodeMain: __filename,
		baseUrl: path.join(path.dirname(__dirname)),
		paths: {
			'vs': out + '/vs',
			'lib': out + '/lib',
			'bootstrap': out + '/bootstrap'
		},
		catchError: true
	};

	if (argv.coverage) {
		var instrumenter = new istanbul.Instrumenter();

		loaderConfig.nodeInstrumenter = function (contents, source) {
			if (minimatch(source, TEST_GLOB)) {
				return contents;
			}

			return instrumenter.instrumentSync(contents, source);
		};

		process.on('exit', function (code) {
			if (code !== 0) {
				return;
			}

			var collector = new istanbul.Collector();
			collector.add(global.__coverage__);

			var reporter = new istanbul.Reporter(null, path.join(path.dirname(path.dirname(__dirname)), 'Code-Coverage'));
			reporter.add('html');
			reporter.write(collector, true, function () {});
		});
	}

	loader.config(loaderConfig);

	global.define = loader;
	global.document = jsdom.jsdom('<!doctype html>');
	global.self = global.window = global.document.parentWindow;

	global.Element = global.window.Element;
	global.HTMLElement = global.window.HTMLElement;
	global.Node = global.window.Node;
	global.navigator = global.window.navigator;
	global.XMLHttpRequest = global.window.XMLHttpRequest;

	var didErr = false;
	var write = process.stderr.write;
	process.stderr.write = function (data) {
		didErr = didErr || !!data;
		write.apply(process.stderr, arguments);
	};

	var loadTasks = [];

	if (argv.run) {
		var tests = (typeof argv.run === 'string') ? [argv.run] : argv.run;

		loadTasks = loadTasks.concat(tests.map(function (test) {
			return loadSingleTest(test);
		}));
	} else {
		loadTasks.push(loadClientTests);
		loadTasks.push(loadPluginTests);
	}

	async.parallel(loadTasks, function () {
		process.stderr.write = write;

		if (!argv.run) {
			// set up last test
			suite('Loader', function () {
				test('should not explode while loading', function () {
					assert.ok(!didErr, 'should not explode while loading');
				});
			});
		}

		// report failing test for every unexpected error during any of the tests
		var unexpectedErrors = [];
		suite('Errors', function () {
			test('should not have unexpected errors in tests', function () {
				if (unexpectedErrors.length) {
					unexpectedErrors.forEach(function (stack) {
						console.error('');
						console.error(stack);
					});

					assert.ok(false);
				}
			});
		});

		// replace the default unexpected error handler to be useful during tests
		loader('vs/base/common/errors').setUnexpectedErrorHandler(function (err) {
			try {
				throw new Error('oops');
			} catch (e) {
				unexpectedErrors.push((err && err.message ? err.message : err) + '\n' + e.stack);
			}
		});

		// fire up mocha
		run();
	});
}

if (process.argv.some(function (a) { return /^--browser/.test(a); })) {
	require('./browser');
} else {
	main();
}<commit_msg>fail mocha upon loader fail<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

/*global process,__dirname,define,run,suite,test*/

var assert = require('assert');
var path = require('path');
var glob = require('glob');
var istanbul = require('istanbul');
var jsdom = require('jsdom-no-contextify');
var minimatch = require('minimatch');
var async = require('async');
var TEST_GLOB = '**/test/**/*.test.js';

var optimist = require('optimist')
	.usage('Run the Code tests. All mocha options apply.')
	.describe('build', 'Run from out-build').boolean('build')
	.describe('run', 'Run a single file').string('run')
	.describe('coverage', 'Generate a coverage report').boolean('coverage')
	.describe('browser', 'Run tests in a browser').boolean('browser')
	.alias('h', 'help').boolean('h')
	.describe('h', 'Show help');

var argv = optimist.argv;

if (argv.help) {
	optimist.showHelp();
	process.exit(1);
}

var out = argv.build ? 'out-build' : 'out';
var loader = require('../' + out + '/vs/loader');
var src = path.join(path.dirname(__dirname), out);

function loadSingleTest(test) {
	var moduleId = path.relative(src, path.resolve(test)).replace(/\.js$/, '');

	return function (cb) {
		var onExit = function () {
			console.error('Failed to load test.');
			process.exit(1);
		};

		process.once('exit', onExit);

		define([moduleId], function () {
			process.removeListener('exit', onExit);
			cb(null);
		});
	};
}

function loadClientTests(cb) {
	glob(TEST_GLOB, { cwd: src }, function (err, files) {
		var modules = files.map(function (file) {
			return file.replace(/\.js$/, '');
		});

		var onExit = function () {
			console.error('Failed to load all client tests.');
			process.exit(1);
		};

		process.once('exit', onExit);

		// load all modules
		define(modules, function () {
			process.removeListener('exit', onExit);
			cb(null);
		});
	});
}

function loadPluginTests(cb) {
	var root = path.join(path.dirname(__dirname), 'extensions');
	glob(TEST_GLOB, { cwd: root }, function (err, files) {

		var modules = files.map(function (file) {
			return 'extensions/' + file.replace(/\.js$/, '');
		});

		var onExit = function () {
			console.error('Failed to load plugin tests.');
			process.exit(1);
		};

		process.once('exit', onExit);

		define(modules, function() {
			process.removeListener('exit', onExit);
			cb();
		});
	});
}

function main() {
	process.on('uncaughtException', function (e) {
		console.error(e.stack || e);
	});

	var loaderConfig = {
		nodeRequire: require,
		nodeMain: __filename,
		baseUrl: path.join(path.dirname(__dirname)),
		paths: {
			'vs': out + '/vs',
			'lib': out + '/lib',
			'bootstrap': out + '/bootstrap'
		},
		catchError: true
	};

	if (argv.coverage) {
		var instrumenter = new istanbul.Instrumenter();

		loaderConfig.nodeInstrumenter = function (contents, source) {
			if (minimatch(source, TEST_GLOB)) {
				return contents;
			}

			return instrumenter.instrumentSync(contents, source);
		};

		process.on('exit', function (code) {
			if (code !== 0) {
				return;
			}

			var collector = new istanbul.Collector();
			collector.add(global.__coverage__);

			var reporter = new istanbul.Reporter(null, path.join(path.dirname(path.dirname(__dirname)), 'Code-Coverage'));
			reporter.add('html');
			reporter.write(collector, true, function () {});
		});
	}

	loader.config(loaderConfig);

	global.define = loader;
	global.document = jsdom.jsdom('<!doctype html>');
	global.self = global.window = global.document.parentWindow;

	global.Element = global.window.Element;
	global.HTMLElement = global.window.HTMLElement;
	global.Node = global.window.Node;
	global.navigator = global.window.navigator;
	global.XMLHttpRequest = global.window.XMLHttpRequest;

	var didErr = false;
	var write = process.stderr.write;
	process.stderr.write = function (data) {
		didErr = didErr || !!data;
		write.apply(process.stderr, arguments);
	};

	var loadTasks = [];

	if (argv.run) {
		var tests = (typeof argv.run === 'string') ? [argv.run] : argv.run;

		loadTasks = loadTasks.concat(tests.map(function (test) {
			return loadSingleTest(test);
		}));
	} else {
		loadTasks.push(loadClientTests);
		loadTasks.push(loadPluginTests);
	}

	async.parallel(loadTasks, function () {
		process.stderr.write = write;

		if (!argv.run) {
			// set up last test
			suite('Loader', function () {
				test('should not explode while loading', function () {
					assert.ok(!didErr, 'should not explode while loading');
				});
			});
		}

		// report failing test for every unexpected error during any of the tests
		var unexpectedErrors = [];
		suite('Errors', function () {
			test('should not have unexpected errors in tests', function () {
				if (unexpectedErrors.length) {
					unexpectedErrors.forEach(function (stack) {
						console.error('');
						console.error(stack);
					});

					assert.ok(false);
				}
			});
		});

		// replace the default unexpected error handler to be useful during tests
		loader('vs/base/common/errors').setUnexpectedErrorHandler(function (err) {
			try {
				throw new Error('oops');
			} catch (e) {
				unexpectedErrors.push((err && err.message ? err.message : err) + '\n' + e.stack);
			}
		});

		// fire up mocha
		run();
	});
}

if (process.argv.some(function (a) { return /^--browser/.test(a); })) {
	require('./browser');
} else {
	main();
}<|endoftext|>


<commit_before>'use strict';

var diacritics = require('diacritics').remove,
    repeat = require('repeat-string'),
    words = require('./words.json');

for (var i in words) {
    words[i] = words[i].replace(/(\w)/g, '$1+');
}

var j = words.join(')|(')
    .replace(/a/g, '[a24\@]')
    .replace(/e/g, '[e3\&]')
    .replace(/g/g, '[g9')
    .replace(/i/g, '[i1]')
    .replace(/l/g, '[l1]')
    .replace(/o/g, '[o08\@]')
    .replace(/q/g, '[q9]')
    .replace(/t/g, '[t7]')
    .replace(/s/g, '[s5\$]');

var re = new RegExp('\\b((' + j + '))\\b', 'gi');

module.exports = function (string, censura) {

    if (!string && !censura) {
      return undefined;
    }

    if (censura) {
        if (censura.length !== 1) {
            censura = '*';
        }
    } else {
        censura = '*';
    }

    var str = diacritics(string);

    str = str.replace(re, function (p) {
        return repeat(censura, p.length);
    });

    var s = '';

    for (var i = 0; i < string.length; i++) {
        if (string[i] !== str[i] && str[i] === censura) {
            s += str[i];
        } else {
            s += string[i]
        }
    }

    return s;
};
<commit_msg>Substituir palavra inteira #1<commit_after>'use strict';

var diacritics = require('diacritics').remove,
    repeat = require('repeat-string'),
    words = require('./words.json');

for (var i in words) {
    words[i] = words[i].replace(/(\w)/g, '$1+');
}

var j = words.join(')|(')
    .replace(/a/g, '[a24\@]')
    .replace(/e/g, '[e3\&]')
    .replace(/g/g, '[g9')
    .replace(/i/g, '[i1]')
    .replace(/l/g, '[l1]')
    .replace(/o/g, '[o08\@]')
    .replace(/q/g, '[q9]')
    .replace(/t/g, '[t7]')
    .replace(/s/g, '[s5\$]');

var re = new RegExp('\\b((' + j + '))\\b', 'gi');

function replaceWords(original, censurado, censura) {
    var coords = [];
    var iniciado = false;

    for (var i = 0; i < original.length; i++) {
        if (censurado[i] === original[i] && !iniciado) {
            coords.push(i);

            iniciado = true;
        } else {
            if (censurado[i] !== original[i] && iniciado) {
                coords.push(i);

                iniciado = false;
            }
        }
    }

    if (coords.length % 2 !== 0) coords.push(original.length);

    var partes = [];

    if (censurado[0] !== original[0]) partes.push('');

    for (var i = 0; i < coords.length; i += 2) {
        partes.push(censurado.substring(coords[i], coords[i + 1]));
    }

    var ultimo = original.length - 1;

    if (censurado[ultimo] !== original[ultimo]) {
        partes.push('');
    }

    return partes.join(censura);
}

module.exports = function (string, censura, completo) {

    if (!string && !censura) {
      return undefined;
    }

    var cens;

    if (censura) {
        if (completo) {
            cens = '*'
        } else {
            if (censura.length === 1) {
                cens = censura;
            } else {
                cens = '*';
            }
        }
    } else {
        cens = '*';
    }

    var str = diacritics(string);

    str = str.replace(re, function (p) {
        return repeat(cens, p.length);
    });

    var s = '';

    for (var i = 0; i < string.length; i++) {
        if (string[i] !== str[i] && str[i] === cens) {
            s += str[i];
        } else {
            s += string[i]
        }
    }

    if (completo) {
        return replaceWords(string, s, censura);
    }

    return s;
};
<|endoftext|>


<commit_before>'use babel';
'use strict';

/**
 * Handles dispatching commands
 * @class CommandDispatcher
 * @param {Bot} bot - Bot instance
 */
export default class CommandDispatcher
{
	constructor(bot)
	{
		/**
		 * Bot instance
		 * @memberof CommandDispatcher
		 * @type {Bot}
		 * @name bot
		 * @instance
		 */
		this.bot = bot;

		this.bot.on('message', message =>
		{
			this.handleMessage(message);
		});
	}

	/**
	 * Determine if message is a valid command call and send to {@link CommandDispatcher#dispatch}
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {*}
	 */
	handleMessage(message)
	{
		let config = this.bot.config;
		if (this.bot.selfbot && message.author !== this.bot.user) return false;
		if (message.author.bot) return false;
		let original = message.content;

		let { command, mentions, args, content, dm } = this.processContent(message);
		message.content = content;

		if (dm && !command)
		{
			return this.commandNotFoundError(message);
		}
		else if (!command)
		{
			message.content = original;
			return false;
		}

		let guildStorage = !dm ? this.bot.guildStorages.get(message.guild) : null;
		if (!dm && guildStorage.settingExists('disabledGroups')
			&& guildStorage.getSetting('disabledGroups').includes(command.group)) return false;
		if (command.ownerOnly && !config.owner.includes(message.author.id)) return false;
		if (dm && command.guildOnly) return this.guildOnlyError(message);

		let missingPermissions = this.checkPermissions(dm, message, command);
		if (missingPermissions.length > 0) return this.missingPermissionsError(missingPermissions, message);

		if (!this.hasRoles(dm, message, command)) return this.missingRolesError(message, command);

		return this.dispatch(command, message, args, mentions, original);
	}

	/**
	 * Processes message content, finding the command to execute and creating an
	 * object containing the found command, mentions, args, processed content, dm?,
	 * and original raw message content
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Object}
	 */
	processContent(message)
	{
		let dm = message.channel.type === 'dm';
		let mentions;
		let duplicateMention;
		let regexMentions = message.content.match(/<@!?\d+>/g);
		if (regexMentions && regexMentions.length > 1)
		{
			let firstMention = regexMentions.shift();
			duplicateMention = regexMentions.includes(firstMention);
		}
		mentions = message.mentions.users.array().sort((a, b) =>
			message.content.indexOf(a.id) - message.content.indexOf(b.id));

		let botMention = /^<@!?\d+>.+/.test(message.content)
			&& mentions[0].id === this.bot.user.id
			&& !this.bot.selfbot;

		let content;
		if (botMention && !duplicateMention)
		{
			content = message.content.replace(/<@!?\d+>/g, '').trim();
			mentions = mentions.slice(1);
		}
		else if (botMention && duplicateMention)
		{
			content = message.content.replace(/<@!?\d+>/g, '').trim();
		}
		else if (!dm && (message.content.startsWith(this.bot.getPrefix(message.guild))
			|| !this.bot.getPrefix(message.guild)))
		{
			content = message.content.slice(this.bot.getPrefix(message.guild)
				? this.bot.getPrefix(message.guild).length : 0).replace(/<@!?\d+>/g, '').trim();
		}
		else if (dm)
		{
			if (/<@!?\d+>.+/.test(message.content))
			{
				content = message.content.replace(/<@!?\d+>/g, '').trim();
				mentions = mentions.slice(1);
			}
			else
			{
				content = message.content.trim();
			}
		}
		else
		{
			return false;
		}
		content = content.replace(/ +/g, ' ');

		let commandName = content.split(' ')[0];
		let command = this.bot.commands.filter(c =>
			c.name === commandName || c.aliases.includes(commandName)).first();

		let args = content.split(' ').slice(1)
			.map(a => !isNaN(a) && !command.stringArgs ? parseFloat(a) : a);

		return { command: command, mentions: mentions, args: args, content: content, dm: dm };
	}

	/**
	 * Get a list of missing permissions for the given command, if any
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {boolean} dm - Whether the message is a DM
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {external:PermissionResolvable[]}
	 */
	checkPermissions(dm, message, command)
	{
		let missing = [];
		command.permissions.forEach(permission =>
		{
			if (!dm && !message.channel // eslint-disable-line curly
				.permissionsFor(message.author)
				.hasPermission(permission))
				missing.push(permission);
		});
		return missing;
	}

	/**
	 * Checks if the user has roles for the given command
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {boolean} dm - Whether the message is a DM
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {boolean}
	 */
	hasRoles(dm, message, command)
	{
		if (command.roles.length === 0) return true;
		let matchedRoles = message.member.roles
			.filter(role => !dm && command.roles.includes(role.name));
		if (matchedRoles.size > 0) return true;
		return false;
	}

	/**
	 * Send a 'command not found' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	commandNotFoundError(message)
	{
		return message.channel.sendMessage(``
			+ `Sorry, I didn't recognize any command in your message.\n`
			+ `Try saying "help" to view a list of commands you can use in `
			+ `this DM, or try calling the\nhelp command in a server channel `
			+ `to see what commands you can use there!`);
	}

	/**
	 * Send a 'guild only' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	guildOnlyError(message)
	{
		return message.channel.sendMessage(``
			+ `That command is for servers only. Try saying "help" to see a `
			+ `list of commands you can use in this DM`);
	}

	/**
	 * Send a 'missing permissions' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:PermissionResolvable[]} missing - Array of missing permissions
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	missingPermissionsError(missing, message)
	{
		return message[`${this.bot.selfbot ? 'channel' : 'author'}`].sendMessage(``
			+ `**You're missing the following permission`
			+ `${missing.length > 1 ? 's' : ''} `
			+ `for that command:**\n\`\`\`css\n`
			+ `${missing.join(', ')}\n\`\`\``)
				.then(response =>
				{
					if (this.bot.selfbot) response.delete(10 * 1000);
				});
	}

	/**
	 * Send a 'missing roles' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {Promise<external:Message>}
	 */
	missingRolesError(message, command)
	{
		return message[`${this.bot.selfbot ? 'channel' : 'author'}`].sendMessage(``
			+ `**You must have ${command.roles.length > 1
				? 'one of the following roles' : 'the following role'}`
			+ ` to use that command:**\n\`\`\`css\n`
			+ `${command.roles.join(', ')}\n\`\`\``)
				.then(response =>
				{
					if (this.bot.selfbot) response.delete(10 * 1000);
				});
	}

	/**
	 * Pass the necessary items to the found Command's {@link Command#action} method
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {Command} command - The command found by the dispatcher
	 * @param {external:Message} message - Discord.js message object
	 * @param {args[]} args - An array containing the args parsed from the command calling message
	 * @param {external:User[]} mentions - An array containing the Discord.js User
	 * objects parsed from the mentions contained in a message
	 * @param {string} original - The original raw content of the message that called the command
	 */
	async dispatch(command, message, args, mentions, original)
	{
		command.action(message, args, mentions, original).catch(console.log); // eslint-disable-line no-unused-expressions, no-console
	}
}
<commit_msg>Stifle unhandledPromiseRejection error<commit_after>'use babel';
'use strict';

/**
 * Handles dispatching commands
 * @class CommandDispatcher
 * @param {Bot} bot - Bot instance
 */
export default class CommandDispatcher
{
	constructor(bot)
	{
		/**
		 * Bot instance
		 * @memberof CommandDispatcher
		 * @type {Bot}
		 * @name bot
		 * @instance
		 */
		this.bot = bot;

		this.bot.on('message', message =>
		{
			this.handleMessage(message);
		});
	}

	/**
	 * Determine if message is a valid command call and send to {@link CommandDispatcher#dispatch}
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {*}
	 */
	handleMessage(message)
	{
		let config = this.bot.config;
		if (this.bot.selfbot && message.author !== this.bot.user) return false;
		if (message.author.bot) return false;
		let original = message.content;

		let { command, mentions, args, content, dm } = this.processContent(message);
		message.content = content;

		if (dm && !command)
		{
			return this.commandNotFoundError(message);
		}
		else if (!command)
		{
			message.content = original;
			return false;
		}

		let guildStorage = !dm ? this.bot.guildStorages.get(message.guild) : null;
		if (!dm && guildStorage.settingExists('disabledGroups')
			&& guildStorage.getSetting('disabledGroups').includes(command.group)) return false;
		if (command.ownerOnly && !config.owner.includes(message.author.id)) return false;
		if (dm && command.guildOnly) return this.guildOnlyError(message);

		let missingPermissions = this.checkPermissions(dm, message, command);
		if (missingPermissions.length > 0) return this.missingPermissionsError(missingPermissions, message);

		if (!this.hasRoles(dm, message, command)) return this.missingRolesError(message, command);

		return this.dispatch(command, message, args, mentions, original);
	}

	/**
	 * Processes message content, finding the command to execute and creating an
	 * object containing the found command, mentions, args, processed content, dm?,
	 * and original raw message content
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Object}
	 */
	processContent(message)
	{
		let dm = message.channel.type === 'dm';
		let mentions;
		let duplicateMention;
		let regexMentions = message.content.match(/<@!?\d+>/g);
		if (regexMentions && regexMentions.length > 1)
		{
			let firstMention = regexMentions.shift();
			duplicateMention = regexMentions.includes(firstMention);
		}
		mentions = message.mentions.users.array().sort((a, b) =>
			message.content.indexOf(a.id) - message.content.indexOf(b.id));

		let botMention = /^<@!?\d+>.+/.test(message.content)
			&& mentions[0].id === this.bot.user.id
			&& !this.bot.selfbot;

		let content;
		if (botMention && !duplicateMention)
		{
			content = message.content.replace(/<@!?\d+>/g, '').trim();
			mentions = mentions.slice(1);
		}
		else if (botMention && duplicateMention)
		{
			content = message.content.replace(/<@!?\d+>/g, '').trim();
		}
		else if (!dm && (message.content.startsWith(this.bot.getPrefix(message.guild))
			|| !this.bot.getPrefix(message.guild)))
		{
			content = message.content.slice(this.bot.getPrefix(message.guild)
				? this.bot.getPrefix(message.guild).length : 0).replace(/<@!?\d+>/g, '').trim();
		}
		else if (dm)
		{
			if (/<@!?\d+>.+/.test(message.content))
			{
				content = message.content.replace(/<@!?\d+>/g, '').trim();
				mentions = mentions.slice(1);
			}
			else
			{
				content = message.content.trim();
			}
		}
		else
		{
			return false;
		}
		content = content.replace(/ +/g, ' ');

		let commandName = content.split(' ')[0];
		let command = this.bot.commands.filter(c =>
			c.name === commandName || c.aliases.includes(commandName)).first();

		let args = content.split(' ').slice(1)
			.map(a => !isNaN(a) && !command.stringArgs ? parseFloat(a) : a);

		return { command: command, mentions: mentions, args: args, content: content, dm: dm };
	}

	/**
	 * Get a list of missing permissions for the given command, if any
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {boolean} dm - Whether the message is a DM
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {external:PermissionResolvable[]}
	 */
	checkPermissions(dm, message, command)
	{
		let missing = [];
		command.permissions.forEach(permission =>
		{
			if (!dm && !message.channel // eslint-disable-line curly
				.permissionsFor(message.author)
				.hasPermission(permission))
				missing.push(permission);
		});
		return missing;
	}

	/**
	 * Checks if the user has roles for the given command
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {boolean} dm - Whether the message is a DM
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {boolean}
	 */
	hasRoles(dm, message, command)
	{
		if (command.roles.length === 0) return true;
		let matchedRoles = message.member.roles
			.filter(role => !dm && command.roles.includes(role.name));
		if (matchedRoles.size > 0) return true;
		return false;
	}

	/**
	 * Send a 'command not found' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	commandNotFoundError(message)
	{
		return message.channel.sendMessage(``
			+ `Sorry, I didn't recognize any command in your message.\n`
			+ `Try saying "help" to view a list of commands you can use in `
			+ `this DM, or try calling the\nhelp command in a server channel `
			+ `to see what commands you can use there!`);
	}

	/**
	 * Send a 'guild only' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	guildOnlyError(message)
	{
		return message.channel.sendMessage(``
			+ `That command is for servers only. Try saying "help" to see a `
			+ `list of commands you can use in this DM`);
	}

	/**
	 * Send a 'missing permissions' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:PermissionResolvable[]} missing - Array of missing permissions
	 * @param {external:Message} message - Discord.js message object
	 * @returns {Promise<external:Message>}
	 */
	missingPermissionsError(missing, message)
	{
		return message[`${this.bot.selfbot ? 'channel' : 'author'}`].sendMessage(``
			+ `**You're missing the following permission`
			+ `${missing.length > 1 ? 's' : ''} `
			+ `for that command:**\n\`\`\`css\n`
			+ `${missing.join(', ')}\n\`\`\``)
				.then(response =>
				{
					if (this.bot.selfbot) response.delete(10 * 1000);
				});
	}

	/**
	 * Send a 'missing roles' error message to the channel
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {external:Message} message - Discord.js message object
	 * @param {Command} command - Command found by the dispatcher
	 * @returns {Promise<external:Message>}
	 */
	missingRolesError(message, command)
	{
		return message[`${this.bot.selfbot ? 'channel' : 'author'}`].sendMessage(``
			+ `**You must have ${command.roles.length > 1
				? 'one of the following roles' : 'the following role'}`
			+ ` to use that command:**\n\`\`\`css\n`
			+ `${command.roles.join(', ')}\n\`\`\``)
				.then(response =>
				{
					if (this.bot.selfbot) response.delete(10 * 1000);
				});
	}

	/**
	 * Pass the necessary items to the found Command's {@link Command#action} method
	 * @memberof CommandDispatcher
	 * @instance
	 * @param {Command} command - The command found by the dispatcher
	 * @param {external:Message} message - Discord.js message object
	 * @param {args[]} args - An array containing the args parsed from the command calling message
	 * @param {external:User[]} mentions - An array containing the Discord.js User
	 * objects parsed from the mentions contained in a message
	 * @param {string} original - The original raw content of the message that called the command
	 */
	async dispatch(command, message, args, mentions, original)
	{
		try
		{
			command.action(message, args, mentions, original); // eslint-disable-line no-unused-expressions, no-console
		}
		catch (err)
		{
			console.log(err);
		}
	}
}
<|endoftext|>


<commit_before>//! moment.js locale configuration
//! locale : norwegian bokmål (nb)
//! authors : Espen Hovlandsdal : https://github.com/rexxars
//!           Sigurd Gartmann : https://github.com/sigurdga

/*;(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined'
       && typeof require === 'function' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define(['moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';
*/

    moment.locale('nb', {
        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
        monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
        monthsParseExact : true,
        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
        weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
        weekdaysParseExact : true,
        longDateFormat : {
            LT : 'HH:mm',
            LTS : 'HH:mm:ss',
            L : 'DD.MM.YYYY',
            LL : 'D. MMMM YYYY',
            LLL : 'D. MMMM YYYY [kl.] HH:mm',
            LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
        },
        calendar : {
            sameDay: '[i dag kl.] LT',
            nextDay: '[i morgen kl.] LT',
            nextWeek: 'dddd [kl.] LT',
            lastDay: '[i går kl.] LT',
            lastWeek: '[forrige] dddd [kl.] LT',
            sameElse: 'L'
        },
        relativeTime : {
            future : 'om %s',
            past : '%s siden',
            s : 'noen sekunder',
            m : 'ett minutt',
            mm : '%d minutter',
            h : 'en time',
            hh : '%d timer',
            d : 'en dag',
            dd : '%d dager',
            M : 'en måned',
            MM : '%d måneder',
            y : 'ett år',
            yy : '%d år'
        },
        ordinalParse: /\d{1,2}\./,
        ordinal : '%d.',
        week : {
            dow : 1, // Monday is the first day of the week.
            doy : 4  // The week that contains Jan 4th is the first week of the year.
        }
    });

/*
    return nb;

}));*/
<commit_msg>Update config.js<commit_after>moment.locale('nb', {
	months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
	monthsParseExact : true,
	weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
	weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
	weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
	weekdaysParseExact : true,
	longDateFormat : {
		LT : 'HH:mm',
		LTS : 'HH:mm:ss',
		L : 'DD.MM.YYYY',
		LL : 'D. MMMM YYYY',
		LLL : 'D. MMMM YYYY [kl.] HH:mm',
		LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
	},
	calendar : {
		sameDay: '[i dag kl.] LT',
		nextDay: '[i morgen kl.] LT',
		nextWeek: 'dddd [kl.] LT',
		lastDay: '[i går kl.] LT',
		lastWeek: '[forrige] dddd [kl.] LT',
		sameElse: 'L'
	},
	relativeTime : {
		future : 'om %s',
		past : '%s siden',
		s : 'noen sekunder',
		m : 'ett minutt',
		mm : '%d minutter',
		h : 'en time',
		hh : '%d timer',
		d : 'en dag',
		dd : '%d dager',
		M : 'en måned',
		MM : '%d måneder',
		y : 'ett år',
		yy : '%d år'
	},
	ordinalParse: /\d{1,2}\./,
	ordinal : '%d.',
	week : {
		dow : 1, // Monday is the first day of the week.
		doy : 4  // The week that contains Jan 4th is the first week of the year.
	}
});
<|endoftext|>


<commit_before>
// Create images filestore
var imageFilesystemStorage = new FS.Store.FileSystem("images", {path: "images"});

// Create images collection
Images = new FS.Collection("images", {
    stores: [imageFilesystemStorage]
});
<commit_msg>Updated image path.<commit_after>// Create images filestore
var imageFilesystemStorage = new FS.Store.FileSystem("images", {path: "public/images"});

// Create images collection
Images = new FS.Collection("images", {
    stores: [imageFilesystemStorage]
});
<|endoftext|>


<commit_before>export { default as LoginForm } from './LoginForm/LoginForm';
export { default as Message } from './Message/Message';
export { default as MessageInput } from './MessageInput/MessageInput';
export { default as MessageText } from './MessageText/MessageText';
export { default as MessageMenu } from './MessageMenu/MessageMenu';
export { default as Icon } from './Icon/Icon';
export { default as Counter } from './Counter/Counter';
export { default as Avatar } from './Avatar/Avatar';
export { default as UserTooltip } from './UserTooltip/UserTooltip';
export { default as Row } from './Row/Row';
export { default as Column } from './Column/Column';
export { default as Title } from './Title/Title';
export { default as NavigationMenu } from './NavigationMenu/NavigationMenu';
<commit_msg>clean index.js from un-existence components<commit_after>export { default as LoginForm } from './LoginForm/LoginForm';
export { default as Message } from './Message/Message';
export { default as MessageInput } from './MessageInput/MessageInput';
export { default as MessageMenu } from './MessageMenu/MessageMenu';
export { default as Icon } from './Icon/Icon';
export { default as Avatar } from './Avatar/Avatar';
export { default as Row } from './Row/Row';
export { default as Column } from './Column/Column';
export { default as Title } from './Title/Title';
export { default as NavigationMenu } from './NavigationMenu/NavigationMenu';
<|endoftext|>


<commit_before>// Dep: [KadOH]/core/stateeventemitter

(function(exports) {

  var KadOH             = exports,
      Event             = KadOH.core.Event,
      StateEventEmitter = KadOH.core.StateEventEmitter;

  KadOH.core = KadOH.core || {};
  var Deferred = KadOH.core.Deferred = StateEventEmitter.extend({

    initialize: function() {
      this.supr();

      this._events.rejected = new Event(true, true); // memory && once
      this._events.resolved = new Event(true, true); // memory && once
      this._events.progress = new Event(true);       // memory

      this.setState('progress');
    },

    //
    // Callbacks functions
    //

    then: function(callback, errback, progress) {
      var context = arguments[arguments.length - 1];

      if (typeof context === 'function')
        context = this;

      this.addCallback(callback, context)
          .addErrback(errback,   context)
          .addProgress(progress, context);

      return this;
    },

    addCallback: function(callback, context) {
      if (typeof callback === 'function')
        this.on('resolved', callback, context || this);
      return this;
    },

    addErrback: function(errback, context) {
      if (typeof errback === 'function')
        this.on('rejected', errback, context || this);
      return this;
    },

    addProgress: function(progress, context) {
      if (typeof progress === 'function')
        this.on('progress', progress, context || this);
      return this;
    },

    //
    // Firing functions
    //

    resolve: function() {
      this.disable('rejected');
      this._complete('resolved', arguments);
      return this;
    },

    reject: function() {
      this.disable('resolved');
      this._complete('rejected', arguments);
      return this;
    },

    _complete: function(state, args) {
      if (this.isResolved() || this.isRejected()) {
        KadOH.log.error('deferred already completed');
        return;
      }
      Array.prototype.splice.call(args, 0, 0, state);
      this.setState.apply(this, args);
    },

    progress: function() {
      if (!this.isCompleted()) {
        Array.prototype.splice.call(arguments, 0, 0, 'progress');
        this.emit.apply(this, arguments);
      }
      return this;
    },

    //
    // Helpers
    //

    isCompleted: function() {
      return (
        this.fired('resolved') ||
        this.fired('rejected')
      );
    },

    isResolved: function() {
      return this.stateIs('resolved');
    },

    isRejected: function() {
      return this.stateIs('rejected');
    },

    cancel: function() {
      this.disable('resolved');
      this.disable('rejected');
    }

  });

  Deferred.statics({

    /**
     * Static function which accepts a promise object
     * or any kind of object and returns a promise.
     * If the given object is a promise, it simply returns
     * the same object, if it's a value it returns a
     * new resolved deferred object
     *
     * @param  {Object} promise Promise or value
     * @return {Deferred}
     */
    when: function(promise) {
      if (this.isPromise(promise))
        return promise;

      return new Deferred().resolve(promise);
    },

    //
    // Inspired by when.js from Brian Cavalier
    //
    whenAtLeast: function(promises, toResolve) {
      var deferred = new Deferred();
      var resolved = 0;

      toResolve    = Math.max(1, Math.min(toResolve || 1, promises.length));
      promisesLeft = promises.length;

      var failure = function() {
        if (--promisesLeft === 0) {
          if (resolved >= toResolve) {
            deferred.resolve();
          } else {
            deferred.reject();
          }
        }
      };

      var success = function() {
        resolved++;
        failure();
      };

      for (var i = 0; i < promises.length; i++) {
        Deferred.when(promises[i]).then(success, failure, deferred.progress);
      }
      return deferred;
    },

    whenAll: function(promises) {
      return Deferred.whenSome(promises, promises.length);
    },

    whenSome: function(promises, toResolve) {
      var results  = [];
      var deferred = new Deferred();

      toResolve = Math.max(0, Math.min(toResolve, promises.length));
      var success = function() {
        results.push(arguments);
        if (--toResolve === 0) {
          deferred.resolve.apply(deferred, results);
        }
      };

      if (toResolve === 0) {
        deferred.resolve.apply(deferred, results);
      } else {
        for (var i = 0; i < promises.length; i++) {
          Deferred.when(promises[i])
                  .then(success, deferred.reject, deferred.progress);
        }
      }
      return deferred;
    },

    isPromise: function(promise) {
      return promise && typeof promise.then === 'function';
    }

  });

})('object' === typeof module ? module.exports : (this.KadOH = this.KadOH || {}));
<commit_msg>adding getResolvePassedArgs and getRejectPasserArgs functions<commit_after>// Dep: [KadOH]/core/stateeventemitter

(function(exports) {

  var KadOH             = exports,
      Event             = KadOH.core.Event,
      StateEventEmitter = KadOH.core.StateEventEmitter;

  KadOH.core = KadOH.core || {};
  var Deferred = KadOH.core.Deferred = StateEventEmitter.extend({

    initialize: function() {
      this.supr();

      this._events.rejected = new Event(true, true); // memory && once
      this._events.resolved = new Event(true, true); // memory && once
      this._events.progress = new Event(true);       // memory

      this.setState('progress');
    },

    //
    // Callbacks functions
    //

    then: function(callback, errback, progress) {
      var context = arguments[arguments.length - 1];

      if (typeof context === 'function')
        context = this;

      this.addCallback(callback, context)
          .addErrback(errback,   context)
          .addProgress(progress, context);

      return this;
    },

    addCallback: function(callback, context) {
      if (typeof callback === 'function')
        this.on('resolved', callback, context || this);
      return this;
    },

    addErrback: function(errback, context) {
      if (typeof errback === 'function')
        this.on('rejected', errback, context || this);
      return this;
    },

    addProgress: function(progress, context) {
      if (typeof progress === 'function')
        this.on('progress', progress, context || this);
      return this;
    },

    //
    // Firing functions
    //

    resolve: function() {
      this.disable('rejected');
      this._complete('resolved', arguments);
      return this;
    },

    reject: function() {
      this.disable('resolved');
      this._complete('rejected', arguments);
      return this;
    },

    _complete: function(state, args) {
      if (this.isResolved() || this.isRejected()) {
        KadOH.log.error('deferred already completed');
        return;
      }
      Array.prototype.splice.call(args, 0, 0, state);
      this.setState.apply(this, args);
    },

    progress: function() {
      if (!this.isCompleted()) {
        Array.prototype.splice.call(arguments, 0, 0, 'progress');
        this.emit.apply(this, arguments);
      }
      return this;
    },

    //
    // Helpers
    //

    getResolvePassedArgs: function() {
      if(!this.isResolved()) {
        throw new Error('not resolved');
      } else {
        return Array.prototype.slice.call(this._events.resolved.args, 1);
      }
    },

    getRejectPassedArgs: function() {
      if(!this.isRejected()) {
        throw new Error('not rejected');
      } else {
        return Array.prototype.slice.call(this._events.rejected.args, 1);
      }
    },

    isCompleted: function() {
      return (
        this.fired('resolved') ||
        this.fired('rejected')
      );
    },

    isResolved: function() {
      return this.stateIs('resolved');
    },

    isRejected: function() {
      return this.stateIs('rejected');
    },

    cancel: function() {
      this.disable('resolved');
      this.disable('rejected');
    }

  });

  Deferred.statics({

    /**
     * Static function which accepts a promise object
     * or any kind of object and returns a promise.
     * If the given object is a promise, it simply returns
     * the same object, if it's a value it returns a
     * new resolved deferred object
     *
     * @param  {Object} promise Promise or value
     * @return {Deferred}
     */
    when: function(promise) {
      if (this.isPromise(promise))
        return promise;

      return new Deferred().resolve(promise);
    },

    //
    // Inspired by when.js from Brian Cavalier
    //
    whenAtLeast: function(promises, toResolve) {
      var deferred = new Deferred();
      var resolved = 0;

      toResolve    = Math.max(1, Math.min(toResolve || 1, promises.length));
      promisesLeft = promises.length;

      var failure = function() {
        if (--promisesLeft === 0) {
          if (resolved >= toResolve) {
            deferred.resolve();
          } else {
            deferred.reject();
          }
        }
      };

      var success = function() {
        resolved++;
        failure();
      };

      for (var i = 0; i < promises.length; i++) {
        Deferred.when(promises[i]).then(success, failure, deferred.progress);
      }
      return deferred;
    },

    whenAll: function(promises) {
      return Deferred.whenSome(promises, promises.length);
    },

    whenSome: function(promises, toResolve) {
      var results  = [];
      var deferred = new Deferred();

      toResolve = Math.max(0, Math.min(toResolve, promises.length));
      var success = function() {
        results.push(arguments);
        if (--toResolve === 0) {
          deferred.resolve.apply(deferred, results);
        }
      };

      if (toResolve === 0) {
        deferred.resolve.apply(deferred, results);
      } else {
        for (var i = 0; i < promises.length; i++) {
          Deferred.when(promises[i])
                  .then(success, deferred.reject, deferred.progress);
        }
      }
      return deferred;
    },

    isPromise: function(promise) {
      return promise && typeof promise.then === 'function';
    }

  });

})('object' === typeof module ? module.exports : (this.KadOH = this.KadOH || {}));
<|endoftext|>