<commit_before>(function () {
  'use strict';

  angular.module('app', [
    'angular-filters',
    'angular-loading-bar',
    'angular-locker',
    'angular-intercom',
    'angular-rickshaw',
    'angular-stripe',
    'angulartics',
    'angulartics.google.tagmanager',
    'cfp.hotkeys',
    'checklist-model',
    'debounce',
    'ngAnimate',
    'restangular',
    'satellizer',
    'ui.bootstrap',
    'ui.gravatar',
    'ui.router',
    'xeditable',

    'dialogs.main',
    'dialogs.default-translations',

    'exceptionless',
    'exceptionless.auth',
    'exceptionless.auto-active',
    'exceptionless.billing',
    'exceptionless.date-filter',
    'exceptionless.event',
    'exceptionless.events',
    'exceptionless.filter',
    'exceptionless.intercom',
    'exceptionless.loading-bar',
    'exceptionless.notification',
    'exceptionless.organization',
    'exceptionless.organization-notifications',
    'exceptionless.project',
    'exceptionless.project-filter',
    'exceptionless.rate-limit',
    'exceptionless.refresh',
    'exceptionless.release-notification',
    'exceptionless.search-filter',
    'exceptionless.signalr',
    'exceptionless.stack',
    'exceptionless.stacks',
    'exceptionless.stat',
    'exceptionless.state',
    'exceptionless.ui-nav',
    'exceptionless.ui-scroll',
    'exceptionless.ui-shift',
    'exceptionless.ui-toggle-class',
    'exceptionless.user',
    'app.account',
    'app.admin',
    'app.auth',
    'app.config',
    'app.event',
    'app.organization',
    'app.payment',
    'app.project',
    'app.session',
    'app.stack',
    'app.status'
  ])
  .config(['$locationProvider', '$stateProvider', '$uiViewScrollProvider', '$urlRouterProvider', '$analyticsProvider', 'dialogsProvider', 'gravatarServiceProvider', 'RestangularProvider', 'BASE_URL', 'EXCEPTIONLESS_API_KEY', '$ExceptionlessClient', 'stripeProvider', 'STRIPE_PUBLISHABLE_KEY', 'USE_HTML5_MODE', function ($locationProvider, $stateProvider, $uiViewScrollProvider, $urlRouterProvider, $analyticsProvider, dialogsProvider, gravatarServiceProvider, RestangularProvider, BASE_URL, EXCEPTIONLESS_API_KEY, $ExceptionlessClient, stripeProvider, STRIPE_PUBLISHABLE_KEY, USE_HTML5_MODE) {
    function setRouteFilter(filterService, organizationId, projectId, type) {
      filterService.setOrganizationId(organizationId, true);
      filterService.setProjectId(projectId, true);
      filterService.setEventType(type, true);
    }

    if (EXCEPTIONLESS_API_KEY) {
      var config = $ExceptionlessClient.config;
      config.apiKey = EXCEPTIONLESS_API_KEY;
      config.serverUrl = BASE_URL;
      config.defaultTags.push('UI');
      config.setVersion('@@version');
      config.useReferenceIds();
      config.useSessions();
    }

    $locationProvider.html5Mode({
      enabled: (typeof USE_HTML5_MODE === 'boolean' && USE_HTML5_MODE) || USE_HTML5_MODE === 'true',
      requireBase: false
    });

    $uiViewScrollProvider.useAnchorScroll();

    $analyticsProvider.registerPageTrack(function (path) {
      if (window.fbq) {
        fbq('track', 'PageView');
      }
    });

    $analyticsProvider.registerEventTrack(function (action, properties) {
      if (!window.fbq) {
        return;
      }

      properties = properties || {};
      var eventList = ['ViewContent', 'Search', 'AddToCart', 'AddToWishlist', 'InitiateCheckout', 'AddPaymentInfo', 'Purchase', 'Lead', 'CompleteRegistration'];
      if(eventList.indexOf(action) === -1) {
        fbq('trackCustom', action, properties);
      } else {
        fbq('track', action, properties);
      }
    });

    dialogsProvider.setSize('md');

    gravatarServiceProvider.defaults = {
      'default': 'mm'
    };

    RestangularProvider.setBaseUrl(BASE_URL + '/api/v2');
    RestangularProvider.setFullResponse(true);
    //RestangularProvider.setDefaultHttpFields({ timeout: 10 * 1000 });

    if (!!STRIPE_PUBLISHABLE_KEY) {
      stripeProvider.setPublishableKey(STRIPE_PUBLISHABLE_KEY);
    }

    $stateProvider.state('app', {
      abstract: true,
      templateUrl: 'app/app.tpl.html',
      controller: 'App',
      controllerAs: 'appVm',
      data: {
        requireAuthentication: true
      }
    });

    var routes = [
      { key: 'dashboard', title: 'Dashboard', controller: 'app.Dashboard' },
      { key: 'frequent', title: 'Most Frequent', controller: 'app.Frequent' },
      { key: 'new', title: 'New', controller: 'app.New' },
      { key: 'recent', title: 'Most Recent', controller: 'app.Recent' },
      { key: 'users', title: 'Most Users', controller: 'app.Users' }
    ];
    var resetEventTypeOnExit = ['filterService', function (filterService) { filterService.setEventType(null, true); }];
    routes.forEach(function(route) {
      var routeDefaults = {
        controller: route.controller,
        controllerAs: 'vm',
        templateUrl: 'app/' + route.key + '.tpl.html',
        title: route.title
      };

      $stateProvider.state('app.' + route.key, angular.extend({}, {
        url: '/' + route.key,
        onEnter: ['filterService', function (filterService) {
          setRouteFilter(filterService, null, null, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.project-' + route.key, angular.extend({}, {
        url: '/project/{projectId:[0-9a-fA-F]{24}}/' + route.key,
        onEnter: ['$stateParams', 'filterService', function ($stateParams, filterService) {
          setRouteFilter(filterService, null, $stateParams.projectId, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.project-type-'+ route.key, angular.extend({}, {
        url: '/project/{projectId:[0-9a-fA-F]{24}}/:type/'+ route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-project-dashboard', $stateParams);
          }

          setRouteFilter(filterService, null, $stateParams.projectId, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));

      $stateProvider.state('app.organization-' + route.key, angular.extend({}, {
        url: '/organization/{organizationId:[0-9a-fA-F]{24}}/' + route.key,
        onEnter: ['$stateParams', 'filterService', function ($stateParams, filterService) {
          setRouteFilter(filterService, $stateParams.organizationId, null, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.organization-type-' + route.key, angular.extend({}, {
        url: '/organization/{organizationId:[0-9a-fA-F]{24}}/:type/' + route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-organization-dashboard', $stateParams);
          }

          setRouteFilter(filterService, $stateParams.organizationId, null, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));

      $stateProvider.state('app.type-' + route.key, angular.extend({}, {
        url: '/type/:type/' + route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-dashboard', $stateParams);
          }

          setRouteFilter(filterService, null, null, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));
    });

    var onEnter = ['authService', '$location', '$state', '$timeout', function (authService, $location, $state, $timeout) {
      if ($location.search().code){
        return;
      }

      return $timeout(function () {
        if (authService.isAuthenticated()) {
          $state.transitionTo('app.type-dashboard', {type: 'error'});
        } else {
          $state.transitionTo('auth.login');
        }
      });
    }];

    $stateProvider.state('loading', {
      url: '',
      template: null,
      onEnter: onEnter
    });

    $stateProvider.state('loading-slash', {
      url: '/',
      template: null,
      onEnter: onEnter
    });

    $stateProvider.state('otherwise', {
      url: '*path',
      templateUrl: 'app/not-found.tpl.html',
      onEnter: ['$stateParams', function ($stateParams) {
        $ExceptionlessClient.createNotFound($stateParams.path)
          .setProperty('$stateParams', $stateParams)
          .submit();
      }]
    });
  }])
  .run(['$http', '$rootScope', '$state', 'authService', 'editableOptions', '$location', 'rateLimitService', 'Restangular', 'stateService', 'USE_SSL', '$window', function($http, $rootScope, $state, authService, editableOptions, $location, rateLimitService, Restangular, stateService, USE_SSL, $window) {
    if ($window.top.location.hostname !== $window.self.location.hostname){
      $window.top.location.href = $window.self.location.href;
    }

    if (((typeof USE_SSL === 'boolean' && USE_SSL) || USE_SSL === 'true') && $location.protocol() !== 'https') {
      $window.location.href = $location.absUrl().replace('http', 'https');
    }

    editableOptions.theme = 'bs3';
    Restangular.setErrorInterceptor(function(response, deferred, responseHandler) {
      function handleError(response) {
        if ($state.current.name !== 'status' && (response.status === 0 || response.status === 503)) {
          stateService.save(['auth.', 'status']);
          $state.go('status', { redirect: true });
          return true;
        }

        if (response.status === 401) {
          stateService.save(['auth.']);
          $state.go('auth.login');
          return true;
        }

        if (response.status === 409) {
          return true;
        }

        return false;
      }

      rateLimitService.updateFromResponseHeader(response);

      // Lets retry as long as we are not on the status page.
      if ($state.current.name !== 'status' && (response.status === 0 || response.status === 503)) {
        // No request interceptors will be called on the retry.
        $http(response.config).then(responseHandler, function (response) {
          if (!handleError(response)) {
            deferred.reject(response);
          }
        });

        return false;
      }

      return !handleError(response);
    });

    $rootScope.page = {
      setTitle: function(title) {
        if (title) {
          this.title = title + ' - Exceptionless';
        } else {
          this.title = 'Exceptionless';
        }
      }
    };

    $rootScope.$on('$stateChangeStart', function (event, toState) {
      if (!toState || !toState.data || !toState.data.requireAuthentication)
        return;

      if (!authService.isAuthenticated()) {
        event.preventDefault();
        stateService.save(['auth.']);
        $state.transitionTo('auth.login');
      }

      $rootScope.page.setTitle(toState.title);
    });
  }]);
}());
<commit_msg>added bbq to ignore list<commit_after>/*global fbq:false */
(function () {
  'use strict';

  angular.module('app', [
    'angular-filters',
    'angular-loading-bar',
    'angular-locker',
    'angular-intercom',
    'angular-rickshaw',
    'angular-stripe',
    'angulartics',
    'angulartics.google.tagmanager',
    'cfp.hotkeys',
    'checklist-model',
    'debounce',
    'ngAnimate',
    'restangular',
    'satellizer',
    'ui.bootstrap',
    'ui.gravatar',
    'ui.router',
    'xeditable',

    'dialogs.main',
    'dialogs.default-translations',

    'exceptionless',
    'exceptionless.auth',
    'exceptionless.auto-active',
    'exceptionless.billing',
    'exceptionless.date-filter',
    'exceptionless.event',
    'exceptionless.events',
    'exceptionless.filter',
    'exceptionless.intercom',
    'exceptionless.loading-bar',
    'exceptionless.notification',
    'exceptionless.organization',
    'exceptionless.organization-notifications',
    'exceptionless.project',
    'exceptionless.project-filter',
    'exceptionless.rate-limit',
    'exceptionless.refresh',
    'exceptionless.release-notification',
    'exceptionless.search-filter',
    'exceptionless.signalr',
    'exceptionless.stack',
    'exceptionless.stacks',
    'exceptionless.stat',
    'exceptionless.state',
    'exceptionless.ui-nav',
    'exceptionless.ui-scroll',
    'exceptionless.ui-shift',
    'exceptionless.ui-toggle-class',
    'exceptionless.user',
    'app.account',
    'app.admin',
    'app.auth',
    'app.config',
    'app.event',
    'app.organization',
    'app.payment',
    'app.project',
    'app.session',
    'app.stack',
    'app.status'
  ])
  .config(['$locationProvider', '$stateProvider', '$uiViewScrollProvider', '$urlRouterProvider', '$analyticsProvider', 'dialogsProvider', 'gravatarServiceProvider', 'RestangularProvider', 'BASE_URL', 'EXCEPTIONLESS_API_KEY', '$ExceptionlessClient', 'stripeProvider', 'STRIPE_PUBLISHABLE_KEY', 'USE_HTML5_MODE', function ($locationProvider, $stateProvider, $uiViewScrollProvider, $urlRouterProvider, $analyticsProvider, dialogsProvider, gravatarServiceProvider, RestangularProvider, BASE_URL, EXCEPTIONLESS_API_KEY, $ExceptionlessClient, stripeProvider, STRIPE_PUBLISHABLE_KEY, USE_HTML5_MODE) {
    function setRouteFilter(filterService, organizationId, projectId, type) {
      filterService.setOrganizationId(organizationId, true);
      filterService.setProjectId(projectId, true);
      filterService.setEventType(type, true);
    }

    if (EXCEPTIONLESS_API_KEY) {
      var config = $ExceptionlessClient.config;
      config.apiKey = EXCEPTIONLESS_API_KEY;
      config.serverUrl = BASE_URL;
      config.defaultTags.push('UI');
      config.setVersion('@@version');
      config.useReferenceIds();
      config.useSessions();
    }

    $locationProvider.html5Mode({
      enabled: (typeof USE_HTML5_MODE === 'boolean' && USE_HTML5_MODE) || USE_HTML5_MODE === 'true',
      requireBase: false
    });

    $uiViewScrollProvider.useAnchorScroll();

    $analyticsProvider.registerPageTrack(function (path) {
      if (window.fbq) {
        fbq('track', 'PageView');
      }
    });

    $analyticsProvider.registerEventTrack(function (action, properties) {
      if (!window.fbq) {
        return;
      }

      properties = properties || {};
      var eventList = ['ViewContent', 'Search', 'AddToCart', 'AddToWishlist', 'InitiateCheckout', 'AddPaymentInfo', 'Purchase', 'Lead', 'CompleteRegistration'];
      if(eventList.indexOf(action) === -1) {
        fbq('trackCustom', action, properties);
      } else {
        fbq('track', action, properties);
      }
    });

    dialogsProvider.setSize('md');

    gravatarServiceProvider.defaults = {
      'default': 'mm'
    };

    RestangularProvider.setBaseUrl(BASE_URL + '/api/v2');
    RestangularProvider.setFullResponse(true);
    //RestangularProvider.setDefaultHttpFields({ timeout: 10 * 1000 });

    if (!!STRIPE_PUBLISHABLE_KEY) {
      stripeProvider.setPublishableKey(STRIPE_PUBLISHABLE_KEY);
    }

    $stateProvider.state('app', {
      abstract: true,
      templateUrl: 'app/app.tpl.html',
      controller: 'App',
      controllerAs: 'appVm',
      data: {
        requireAuthentication: true
      }
    });

    var routes = [
      { key: 'dashboard', title: 'Dashboard', controller: 'app.Dashboard' },
      { key: 'frequent', title: 'Most Frequent', controller: 'app.Frequent' },
      { key: 'new', title: 'New', controller: 'app.New' },
      { key: 'recent', title: 'Most Recent', controller: 'app.Recent' },
      { key: 'users', title: 'Most Users', controller: 'app.Users' }
    ];
    var resetEventTypeOnExit = ['filterService', function (filterService) { filterService.setEventType(null, true); }];
    routes.forEach(function(route) {
      var routeDefaults = {
        controller: route.controller,
        controllerAs: 'vm',
        templateUrl: 'app/' + route.key + '.tpl.html',
        title: route.title
      };

      $stateProvider.state('app.' + route.key, angular.extend({}, {
        url: '/' + route.key,
        onEnter: ['filterService', function (filterService) {
          setRouteFilter(filterService, null, null, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.project-' + route.key, angular.extend({}, {
        url: '/project/{projectId:[0-9a-fA-F]{24}}/' + route.key,
        onEnter: ['$stateParams', 'filterService', function ($stateParams, filterService) {
          setRouteFilter(filterService, null, $stateParams.projectId, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.project-type-'+ route.key, angular.extend({}, {
        url: '/project/{projectId:[0-9a-fA-F]{24}}/:type/'+ route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-project-dashboard', $stateParams);
          }

          setRouteFilter(filterService, null, $stateParams.projectId, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));

      $stateProvider.state('app.organization-' + route.key, angular.extend({}, {
        url: '/organization/{organizationId:[0-9a-fA-F]{24}}/' + route.key,
        onEnter: ['$stateParams', 'filterService', function ($stateParams, filterService) {
          setRouteFilter(filterService, $stateParams.organizationId, null, null);
        }]
      }, routeDefaults));

      $stateProvider.state('app.organization-type-' + route.key, angular.extend({}, {
        url: '/organization/{organizationId:[0-9a-fA-F]{24}}/:type/' + route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-organization-dashboard', $stateParams);
          }

          setRouteFilter(filterService, $stateParams.organizationId, null, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));

      $stateProvider.state('app.type-' + route.key, angular.extend({}, {
        url: '/type/:type/' + route.key,
        onEnter: ['$state', '$stateParams', 'filterService', function ($state, $stateParams, filterService) {
          if ($stateParams.type === 'session') {
            return $state.go('app.session-dashboard', $stateParams);
          }

          setRouteFilter(filterService, null, null, $stateParams.type);
        }],
        onExit: resetEventTypeOnExit
      }, routeDefaults));
    });

    var onEnter = ['authService', '$location', '$state', '$timeout', function (authService, $location, $state, $timeout) {
      if ($location.search().code){
        return;
      }

      return $timeout(function () {
        if (authService.isAuthenticated()) {
          $state.transitionTo('app.type-dashboard', {type: 'error'});
        } else {
          $state.transitionTo('auth.login');
        }
      });
    }];

    $stateProvider.state('loading', {
      url: '',
      template: null,
      onEnter: onEnter
    });

    $stateProvider.state('loading-slash', {
      url: '/',
      template: null,
      onEnter: onEnter
    });

    $stateProvider.state('otherwise', {
      url: '*path',
      templateUrl: 'app/not-found.tpl.html',
      onEnter: ['$stateParams', function ($stateParams) {
        $ExceptionlessClient.createNotFound($stateParams.path)
          .setProperty('$stateParams', $stateParams)
          .submit();
      }]
    });
  }])
  .run(['$http', '$rootScope', '$state', 'authService', 'editableOptions', '$location', 'rateLimitService', 'Restangular', 'stateService', 'USE_SSL', '$window', function($http, $rootScope, $state, authService, editableOptions, $location, rateLimitService, Restangular, stateService, USE_SSL, $window) {
    if ($window.top.location.hostname !== $window.self.location.hostname){
      $window.top.location.href = $window.self.location.href;
    }

    if (((typeof USE_SSL === 'boolean' && USE_SSL) || USE_SSL === 'true') && $location.protocol() !== 'https') {
      $window.location.href = $location.absUrl().replace('http', 'https');
    }

    editableOptions.theme = 'bs3';
    Restangular.setErrorInterceptor(function(response, deferred, responseHandler) {
      function handleError(response) {
        if ($state.current.name !== 'status' && (response.status === 0 || response.status === 503)) {
          stateService.save(['auth.', 'status']);
          $state.go('status', { redirect: true });
          return true;
        }

        if (response.status === 401) {
          stateService.save(['auth.']);
          $state.go('auth.login');
          return true;
        }

        if (response.status === 409) {
          return true;
        }

        return false;
      }

      rateLimitService.updateFromResponseHeader(response);

      // Lets retry as long as we are not on the status page.
      if ($state.current.name !== 'status' && (response.status === 0 || response.status === 503)) {
        // No request interceptors will be called on the retry.
        $http(response.config).then(responseHandler, function (response) {
          if (!handleError(response)) {
            deferred.reject(response);
          }
        });

        return false;
      }

      return !handleError(response);
    });

    $rootScope.page = {
      setTitle: function(title) {
        if (title) {
          this.title = title + ' - Exceptionless';
        } else {
          this.title = 'Exceptionless';
        }
      }
    };

    $rootScope.$on('$stateChangeStart', function (event, toState) {
      if (!toState || !toState.data || !toState.data.requireAuthentication)
        return;

      if (!authService.isAuthenticated()) {
        event.preventDefault();
        stateService.save(['auth.']);
        $state.transitionTo('auth.login');
      }

      $rootScope.page.setTitle(toState.title);
    });
  }]);
}());
<|endoftext|>


<commit_before>const { Client, Collection } = require('discord.js');
const { join } = require('path');
const { readdirSync } = require('fs');
const WebSocket = require('uws');

class RobbotClient extends Client {
	constructor(options) {
		super(options);

		this.commands = new Collection();
		this.aliases = new Collection();
		this.events = new Collection();
		this.config = require('../config');
		this.logger = require('../util/Logger');
		this.meguWebSocket = new WebSocket('wss://megumin.love');

		const cmdDir = join(__dirname, '..', 'commands');
		const cmdFiles = readdirSync(cmdDir).filter(file => file.endsWith('.js'));

		for (const file of cmdFiles) {
			const CommandClass = require(`${cmdDir}/${file}`);
			const cmd = new CommandClass();

			for (const alias of cmd.aliases) {
				if (this.aliases.has(alias)) {
					throw Error(`Duplicate alias detected in the '${cmd.name}' command ('${alias}').`);
				}

				if (this.commands.has(alias)) {
					throw Error(`'${alias}' is already registered as a command name.`);
				}

				this.aliases.set(alias, cmd.name);
			}

			if (this.commands.has(cmd.name)) {
				throw Error(`Duplicate command name detected at '${cmd.name}'.`);
			}

			this.commands.set(cmd.name, cmd);
		}

		const validEvents = Object.values(require('discord.js/src/util/Constants').Events);
		const eventDir = join(__dirname, '..', 'events');
		const eventFiles = readdirSync(eventDir).filter(file => file.endsWith('.js') && validEvents.includes(file.slice(0, -3)));

		for (const file of eventFiles) {
			const name = file.slice(0, -3);
			const event = require(`${eventDir}/${name}`);

			this.events.set(name, event);
			this.on(name, (...args) => this.events.get(name)(this, ...args));
		}

		const commandPhrase = this.commands.size !== 1 ? 'commands' : 'command';
		const eventPhrase = eventFiles.length !== 1 ? 'events' : 'event';

		this.logger.info(`Loaded ${this.commands.size} ${commandPhrase} and ${eventFiles.length} ${eventPhrase}.`);

		this.meguWebSocket.on('open', () => this.logger.info('WebSocket connected to wss://megumin.love!'));
	}

	leave(guildIDs = []) {
		const guildPromises = [];
		if (!guildIDs || !guildIDs.length) return Promise.reject(new Error('An array of guild IDs must be provided.'));
		for (const id of guildIDs) {
			const guild = this.guilds.get(id);
			if (guild) guildPromises.push(guild.leave());
			else guildPromises.push(Promise.reject(new Error(`Guild with ID ${id} not found.`)));
		}

		return Promise.all(guildPromises).then(guilds => {
			const g = guilds.map(g => `${g.name} (${g.id})`).join(', ');
			return `Success! The following guilds were left: ${g}`;
		}).catch(err => err);
	}
}

module.exports = RobbotClient;<commit_msg>Make the megumin.love ws reconnect on dc/error<commit_after>const { Client, Collection } = require('discord.js');
const { join } = require('path');
const { readdirSync } = require('fs');
const WebSocket = require('uws');

class RobbotClient extends Client {
	constructor(options) {
		super(options);

		this.commands = new Collection();
		this.aliases = new Collection();
		this.events = new Collection();
		this.config = require('../config');
		this.logger = require('../util/Logger');
		this.meguWebSocket = new WebSocket('wss://megumin.love');

		const cmdDir = join(__dirname, '..', 'commands');
		const cmdFiles = readdirSync(cmdDir).filter(file => file.endsWith('.js'));

		for (const file of cmdFiles) {
			const CommandClass = require(`${cmdDir}/${file}`);
			const cmd = new CommandClass();

			for (const alias of cmd.aliases) {
				if (this.aliases.has(alias)) {
					throw Error(`Duplicate alias detected in the '${cmd.name}' command ('${alias}').`);
				}

				if (this.commands.has(alias)) {
					throw Error(`'${alias}' is already registered as a command name.`);
				}

				this.aliases.set(alias, cmd.name);
			}

			if (this.commands.has(cmd.name)) {
				throw Error(`Duplicate command name detected at '${cmd.name}'.`);
			}

			this.commands.set(cmd.name, cmd);
		}

		const validEvents = Object.values(require('discord.js/src/util/Constants').Events);
		const eventDir = join(__dirname, '..', 'events');
		const eventFiles = readdirSync(eventDir).filter(file => file.endsWith('.js') && validEvents.includes(file.slice(0, -3)));

		for (const file of eventFiles) {
			const name = file.slice(0, -3);
			const event = require(`${eventDir}/${name}`);

			this.events.set(name, event);
			this.on(name, (...args) => this.events.get(name)(this, ...args));
		}

		const commandPhrase = this.commands.size !== 1 ? 'commands' : 'command';
		const eventPhrase = eventFiles.length !== 1 ? 'events' : 'event';

		this.logger.info(`Loaded ${this.commands.size} ${commandPhrase} and ${eventFiles.length} ${eventPhrase}.`);

		this.connectWebSocket(this.meguWebSocket); // recursive function to handle reconnects etc
	}

	leave(guildIDs = []) {
		const guildPromises = [];
		if (!guildIDs || !guildIDs.length) return Promise.reject(new Error('An array of guild IDs must be provided.'));
		for (const id of guildIDs) {
			const guild = this.guilds.get(id);
			if (guild) guildPromises.push(guild.leave());
			else guildPromises.push(Promise.reject(new Error(`Guild with ID ${id} not found.`)));
		}

		return Promise.all(guildPromises).then(guilds => {
			const g = guilds.map(g => `${g.name} (${g.id})`).join(', ');
			return `Success! The following guilds were left: ${g}`;
		}).catch(err => err);
	}

	connectWebSocket(ws) {
		ws = new WebSocket('wss://megumin.love');

		ws.on('open', () => this.logger.info('WebSocket (re-)connected to wss://megumin.love!'));
		ws.on('close', () => {
			this.logger.warn('megumin.love WebSocket closed, trying to reconnect...');
			setTimeout(() => this.connectWebSocket(ws), 1000 * 5);
		});
		ws.on('error', () => {
			this.logger.error('(Re-)Connection to the megumin.love WebSocket failed! Retrying...');
			setTimeout(() => this.connectWebSocket(ws), 1000 * 5);
		});
	}
}

module.exports = RobbotClient;<|endoftext|>


<commit_before>import Label from './label';
import Geo from '../../geo';
import OBB from '../../utils/obb';

export default class LabelPoint extends Label {

    constructor (text, position, size, options) {
        super(text, size, options);

        this.position = position;
        this.aabb = this.computeAABB();
    }

    computeAABB () {
        let width = (this.size.texture_text_size[0] + this.options.buffer[0] * 2) * Geo.units_per_pixel;
        let height = (this.size.texture_text_size[1] + this.options.buffer[1] * 2) * Geo.units_per_pixel;
        // apply offset, x positive, y pointing down
        let p = [this.position[0] + this.options.offset[0], this.position[1] - this.options.offset[1]];
        let obb = new OBB(p[0], p[1], -this.angle, width, height);
        let aabb = obb.getExtent();
        aabb.obb = obb;

        return aabb;
    }

    moveInTile (in_tile) {
        let width = this.aabb[2] - this.aabb[0];
        let height = -this.aabb[3] - (-this.aabb[1]);

        // Move point labels to tile edges
        if (this.position[0] - width/2 < 0) {
            this.position[0] = width/2 + 1;
        }
        else if (this.position[0] + width/2 > Geo.tile_scale) {
            this.position[0] = Geo.tile_scale - (width/2 + 1);
        }

        this.position[1] *= -1; // just doing this so Y coord is positive
        if (this.position[1] - height/2 < 0) { // && this.position[1] > 0) {
            this.position[1] = height/2 + 1;
        }
        else if (this.position[1] + height/2 > Geo.tile_scale) {
            this.position[1] = Geo.tile_scale - (height/2 + 1);
        }
        this.position[1] *= -1;

        this.aabb = this.computeAABB();
        return !this.inTileBounds();
    }

}
<commit_msg>fix point labels<commit_after>import Label from './label';
import Geo from '../../geo';
import OBB from '../../utils/obb';

export default class LabelPoint extends Label {

    constructor (text, position, size, options) {
        super(text, size, options);

        this.position = position;
        this.aabb = this.computeAABB();
    }

    computeAABB () {
        let width = (this.size.texture_text_size[0] + this.options.buffer[0] * 2) * Geo.units_per_pixel;
        let height = (this.size.texture_text_size[1] + this.options.buffer[1] * 2) * Geo.units_per_pixel;
        // apply offset, x positive, y pointing down
        let p = [this.position[0] + this.options.offset[0], this.position[1] - this.options.offset[1]];
        let obb = new OBB(p[0], p[1], 0, width, height);
        let aabb = obb.getExtent();
        aabb.obb = obb;

        return aabb;
    }

    moveInTile (in_tile) {
        let width = this.aabb[2] - this.aabb[0];
        let height = -this.aabb[3] - (-this.aabb[1]);

        // Move point labels to tile edges
        if (this.position[0] - width/2 < 0) {
            this.position[0] = width/2 + 1;
        }
        else if (this.position[0] + width/2 > Geo.tile_scale) {
            this.position[0] = Geo.tile_scale - (width/2 + 1);
        }

        this.position[1] *= -1; // just doing this so Y coord is positive
        if (this.position[1] - height/2 < 0) { // && this.position[1] > 0) {
            this.position[1] = height/2 + 1;
        }
        else if (this.position[1] + height/2 > Geo.tile_scale) {
            this.position[1] = Geo.tile_scale - (height/2 + 1);
        }
        this.position[1] *= -1;

        this.aabb = this.computeAABB();
        return !this.inTileBounds();
    }

}
<|endoftext|>


<commit_before>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FB_TEXT_LIMIT = 640;

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

        async.eachSeries(splittedText, (textPart, callback) => {
            this.sendFBMessage(sender, {text: textPart})
                .then(() => callback())
                .catch(err => callback(err));
        });
    }

     //which webhook event
    getEventText(event) {

        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                return event.message.text;
            }
        }

        //console.log(event.postback, event.postback.payload);
        if (event.postback && event.postback.payload) {
            console.log('Postback Webhook');
            if(event.postback.payload && event.postback.referral) {
                console.log(event.postback.referral.ref);
                return event.postback.referral.ref;
            }
            console.log(event.postback.payload);
            return event.postback.payload;
        }
         //console.log(event.referral);
         if (event.referral.ref) {
            console.log('Referral Webhook');
            console.log(event.referral.ref);
            return event.referral.ref;
        }

        return null;

    }

    processEvent(event) {
        const sender = event.sender.id.toString();
        console.log(event);
        if(!pausedUsers[recipientId]){
        const text = this.getEventText(event);
        }

      ;

        if (text) {

            // Handle a text message from the sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            //get response from api.ai
            apiaiRequest.on('response', (response) => {
                if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                    let responseText = response.result.fulfillment.speech;
                    let responseData = response.result.fulfillment.data;
                    let responseMessages = response.result.fulfillment.messages;

                    let action = response.result.action;

                    if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                        let facebookResponseData = responseData.facebook;
                        this.doDataResponse(sender, facebookResponseData);
                    } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                        this.doRichContentResponse(sender, responseMessages);
                    }
                    else if (this.isDefined(responseText)) {
                        this.doTextResponse(sender, responseText);
                    }

                }
            });

            apiaiRequest.on('error', (error) => console.error(error));
            apiaiRequest.end();
        }
    }

    splitResponse(str) {
        if (str.length <= FB_TEXT_LIMIT) {
            return [str];
        }

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

    chunkString(s, len) {
        let curr = len, prev = 0;

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let currReverse = curr;
                do {
                    if (s.substring(currReverse - 1, currReverse) == ' ') {
                        output.push(s.substring(prev, currReverse));
                        prev = currReverse;
                        curr = currReverse + len;
                        break;
                    }
                    currReverse--;
                } while (currReverse > prev)
            }
        }
        output.push(s.substr(prev));
        return output;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    message: messageData
                }
            }, (error, response) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    sender_action: action
                }
            }, (error, response) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    doSubscribeRequest() {
        request({
                method: 'POST',
                uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription: ', error);
                } else {
                    console.log('Subscription result: ', response.body);
                }
            });
    }

    isDefined(obj) {
        if (typeof obj == 'undefined') {
            return false;
        }
        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

var pausedUsers = {}
app.post('/pause', function (req, res) {
  const userId = req.body.userId;
  const paused = req.body.paused;
  pausedUsers[userId] = paused;
  res.send("ok");
  console.log('paused');
});

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                    if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload || event.referral) {
                            console.log(event);
                            facebookBot.processEvent(event);

                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

facebookBot.doSubscribeRequest();
<commit_msg>Update app.js<commit_after>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FB_TEXT_LIMIT = 640;

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

        async.eachSeries(splittedText, (textPart, callback) => {
            this.sendFBMessage(sender, {text: textPart})
                .then(() => callback())
                .catch(err => callback(err));
        });
    }

     //which webhook event
    getEventText(event) {

        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                return event.message.text;
            }
        }

        //console.log(event.postback, event.postback.payload);
        if (event.postback && event.postback.payload) {
            console.log('Postback Webhook');
            if(event.postback.payload && event.postback.referral) {
                console.log(event.postback.referral.ref);
                return event.postback.referral.ref;
            }
            console.log(event.postback.payload);
            return event.postback.payload;
        }
         //console.log(event.referral);
         if (event.referral.ref) {
            console.log('Referral Webhook');
            console.log(event.referral.ref);
            return event.referral.ref;
        }

        return null;

    }

    processEvent(event) {
        const sender = event.sender.id.toString();
        console.log(event);
        const text = this.getEventText(event);

        if (text) {

            // Handle a text message from the sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            //get response from api.ai
            apiaiRequest.on('response', (response) => {
                if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                    let responseText = response.result.fulfillment.speech;
                    let responseData = response.result.fulfillment.data;
                    let responseMessages = response.result.fulfillment.messages;

                    let action = response.result.action;

                    if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                        let facebookResponseData = responseData.facebook;
                        this.doDataResponse(sender, facebookResponseData);
                    } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                        this.doRichContentResponse(sender, responseMessages);
                    }
                    else if (this.isDefined(responseText)) {
                        this.doTextResponse(sender, responseText);
                    }

                }
            });

            apiaiRequest.on('error', (error) => console.error(error));
            apiaiRequest.end();
        }
    }

    splitResponse(str) {
        if (str.length <= FB_TEXT_LIMIT) {
            return [str];
        }

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

    chunkString(s, len) {
        let curr = len, prev = 0;

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let currReverse = curr;
                do {
                    if (s.substring(currReverse - 1, currReverse) == ' ') {
                        output.push(s.substring(prev, currReverse));
                        prev = currReverse;
                        curr = currReverse + len;
                        break;
                    }
                    currReverse--;
                } while (currReverse > prev)
            }
        }
        output.push(s.substr(prev));
        return output;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    message: messageData
                }
            }, (error, response) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    sender_action: action
                }
            }, (error, response) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    doSubscribeRequest() {
        request({
                method: 'POST',
                uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription: ', error);
                } else {
                    console.log('Subscription result: ', response.body);
                }
            });
    }

    isDefined(obj) {
        if (typeof obj == 'undefined') {
            return false;
        }
        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

var pausedUsers = {}
app.post('/pause', function (req, res) {
  const userId = req.body.userId;
  const paused = req.body.paused;
  pausedUsers[userId] = paused;
  res.send("ok");
  console.log('paused');
});

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                    if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload || event.referral) {
                            console.log(event);
                            facebookBot.processEvent(event);

                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

facebookBot.doSubscribeRequest();
<|endoftext|>


<commit_before>/**
 * @file NeonMob Enhancer
 * @name Client
 *
 * Extension client script code.
 *
 * @author Chris Pelzer <me@chrispelzer.com>
 */

'use strict';

class ExtensionClient {
    constructor() {
        // Grab the set id integer from the data-set-id data attribute
        var setId = $('[data-set-id]').data('set-id');

        // Did we find a setId?
        if (setId > 0) {
            // Get the Set data from the API based on the setId found
            $.get('https://www.neonmob.com/api/setts/' + setId + '/', {format: 'json'})
                .done(function (data) {
                    var message = '';

                    // Have the free packs been discontinued yet?
                    if (data.freebies_discontinued == null) {
                        message = '
' +
                            data.percent_sold_out + '% Total Packs Claimed' +
                            '
';

                        // Don't show if Neonmob is already showing it
                        if ($('#status--free-packs').length === 0 || $('#status--free-packs').html().search('Free Packs Claimed Today') !== -1) {
                            message += '
' +
                                data.free_packs_claimed_percent + '% Free Packs Claimed' +
                                '
';
                        }
                    } else {
                        // If the free packs were sold out then display the date they sold out on
                        var free_soldout = new Date(data.freebies_discontinued);
                        var months = ["January", "February", "March", "April", "May", "June",
                            "July", "August", "September", "October", "November", "December"];
                        message = '
' +
                            'The free packs sold out on
' +
                            months[free_soldout.getMonth()] + ' ' +
                            free_soldout.getDate() + ', ' +
                            free_soldout.getFullYear() +
                            '
';
                    }

                    // Grab the stats for the core and special rarities
                    var stats = data.core_stats;
                    stats.push.apply(stats, data.special_stats);

                    // Loop through each rarity
                    stats.forEach(function (rarity) {
                        // initialize for if we are not on a variant or chase
                        var stat_padding = 'padding-left: 25px';
                        var container_type = 'div';
                        var individual_count = 'Per Print Count: ' + rarity.total_prints / rarity.total;

                        // Find the stat span
                        var stat = $('.rarity-stats--rarity-list .text-rarity-' + rarity.class_name);
                        var stat_html = stat.html();

                        // Update the odd position
                        stat.parent().find('small').css('top', 3);

                        if(rarity.name == 'chase'){
                            if(rarity.total >= 10) {
                                stat_padding = 'padding-left: 85px';
                            }else{
                                stat_padding = 'padding-left: 75px';
                            }
                            container_type = 'span';
                            individual_count = 'Total Print Count: ' + rarity.total_prints;
                        }else if(rarity.name == 'variant'){
                            if(rarity.total >= 10) {
                                stat_padding = 'padding-left: 93px';
                            }else{
                                stat_padding = 'padding-left: 83px';
                            }
                            container_type = 'span';
                            individual_count = 'Total Print Count: ' + rarity.total_prints;
                        }

                        // Build the stat html for the print counts
                        stat_html += '<' + container_type + ' style="' + stat_padding + '">' +
                            (container_type == 'span' ? '
' : '') +
                            individual_count +
                            '</' + container_type + '>';
                        stat.html(stat_html);
                    });

                    // Find the correct status id selector to append the message too
                    if ($('#status--released')) {
                        $('#status--released').append(message);
                    } else if ($('#status--free-packs')) {
                        $('#status--free-packs').append(message);
                    } else if ($('#status--paid')) {
                        $('#status--paid').append(message);
                    }
                });

            // Get the set pieces
            $.get('https://www.neonmob.com/api/sets/' + setId + '/pieces/')
                .done(function (data){
                    var pieces = data.payload.results;
                    pieces.forEach(function(piece){
                        var pieceObj = null;
                        if($('.variant #set-checklist--piece-' + piece.id).length !== 0) {
                            pieceObj = $('.variant #set-checklist--piece-' + piece.id + ' span');
                        }else if($('.chase #set-checklist--piece-' + piece.id).length !== 0){
                            pieceObj = $('.chase #set-checklist--piece-' + piece.id + ' span');
                        }

                        if(pieceObj !== null) {
                            var piece_html = $(pieceObj).html();
                            var message = piece_html + '
(Prints: ' + piece.num_prints_total + ')';
                            $(pieceObj).html(message);
                        }
                    });
                });
        }
    }
}

document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        var run = setInterval(function() {
            if($('[data-set-id]').data('set-id') !== undefined) {
                clearInterval(run);
                new ExtensionClient();
            }
        }, 500);
    }
}
<commit_msg>since the pieces is limited by a max of 100, put it in a static method to call until we get null for the next<commit_after>/**
 * @file NeonMob Enhancer
 * @name Client
 *
 * Extension client script code.
 *
 * @author Chris Pelzer <me@chrispelzer.com>
 */

'use strict';

class ExtensionClient {
    constructor() {
        // Grab the set id integer from the data-set-id data attribute
        var setId = $('[data-set-id]').data('set-id');

        // Did we find a setId?
        if (setId > 0) {
            // Get the Set data from the API based on the setId found
            $.get('https://www.neonmob.com/api/setts/' + setId + '/', {format: 'json'})
                .done(function (data) {
                    var message = '';

                    // Have the free packs been discontinued yet?
                    if (data.freebies_discontinued == null) {
                        message = '
' +
                            data.percent_sold_out + '% Total Packs Claimed' +
                            '
';

                        // Don't show if Neonmob is already showing it
                        if ($('#status--free-packs').length === 0 || $('#status--free-packs').html().search('Free Packs Claimed Today') !== -1) {
                            message += '
' +
                                data.free_packs_claimed_percent + '% Free Packs Claimed' +
                                '
';
                        }
                    } else {
                        // If the free packs were sold out then display the date they sold out on
                        var free_soldout = new Date(data.freebies_discontinued);
                        var months = ["January", "February", "March", "April", "May", "June",
                            "July", "August", "September", "October", "November", "December"];
                        message = '
' +
                            'The free packs sold out on
' +
                            months[free_soldout.getMonth()] + ' ' +
                            free_soldout.getDate() + ', ' +
                            free_soldout.getFullYear() +
                            '
';
                    }

                    // Grab the stats for the core and special rarities
                    var stats = data.core_stats;
                    stats.push.apply(stats, data.special_stats);

                    // Loop through each rarity
                    stats.forEach(function (rarity) {
                        // initialize for if we are not on a variant or chase
                        var stat_padding = 'padding-left: 25px';
                        var container_type = 'div';
                        var individual_count = 'Per Print Count: ' + rarity.total_prints / rarity.total;

                        // Find the stat span
                        var stat = $('.rarity-stats--rarity-list .text-rarity-' + rarity.class_name);
                        var stat_html = stat.html();

                        // Update the odd position
                        stat.parent().find('small').css('top', 3);

                        if(rarity.name == 'chase'){
                            if(rarity.total >= 10) {
                                stat_padding = 'padding-left: 85px';
                            }else{
                                stat_padding = 'padding-left: 75px';
                            }
                            container_type = 'span';
                            individual_count = 'Total Print Count: ' + rarity.total_prints;
                        }else if(rarity.name == 'variant'){
                            if(rarity.total >= 10) {
                                stat_padding = 'padding-left: 93px';
                            }else{
                                stat_padding = 'padding-left: 83px';
                            }
                            container_type = 'span';
                            individual_count = 'Total Print Count: ' + rarity.total_prints;
                        }

                        // Build the stat html for the print counts
                        stat_html += '<' + container_type + ' style="' + stat_padding + '">' +
                            (container_type == 'span' ? '
' : '') +
                            individual_count +
                            '</' + container_type + '>';
                        stat.html(stat_html);
                    });

                    // Find the correct status id selector to append the message too
                    if ($('#status--released')) {
                        $('#status--released').append(message);
                    } else if ($('#status--free-packs')) {
                        $('#status--free-packs').append(message);
                    } else if ($('#status--paid')) {
                        $('#status--paid').append(message);
                    }
                });

            // Get the set pieces
            ExtensionClient.getPieces(setId, 0, 100)
        }
    }

    static getPieces(setId, offset, limit){
        var pieces = $.get('https://www.neonmob.com/api/sets/' + setId + '/pieces/', {offset: offset, limit: limit})
            .done(function (data){
                var pieces = data.payload.results;
                pieces.forEach(function(piece){
                    var pieceObj = null;
                    if($('.variant #set-checklist--piece-' + piece.id).length !== 0) {
                        pieceObj = $('.variant #set-checklist--piece-' + piece.id + ' span');
                    }else if($('.chase #set-checklist--piece-' + piece.id).length !== 0){
                        pieceObj = $('.chase #set-checklist--piece-' + piece.id + ' span');
                    }

                    if(pieceObj !== null) {
                        var piece_html = $(pieceObj).html();
                        var message = piece_html + '
(Prints: ' + piece.num_prints_total + ')';
                        $(pieceObj).html(message);
                    }
                });

                if(data.payload.metadata.resultset.link.next !== null){
                    ExtensionClient.getPieces(setId, offset + limit, limit);
                }
            });
    }
}

document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        var run = setInterval(function() {
            if($('[data-set-id]').data('set-id') !== undefined) {
                clearInterval(run);
                new ExtensionClient();
            }
        }, 500);
    }
}
<|endoftext|>


<commit_before>import fs from 'fs';
import readline from 'readline';
import verEx from 'verbal-expressions';
import csv from 'fast-csv';
import { budgetSegmentsToRead } from './config';

const rootPath = '/Users/allanlukwago/apps/budget-data/samples';

const readFileByLine = readline.createInterface({
  input: fs.createReadStream(`${rootPath}/2014-15.txt`)
});

const csvLineTowrite = (line) => line.split('  ').filter(word => word.length > 1);

const writeLineToFile = (line, csvStream) => {
  const csvLine = csvLineTowrite(line);
  // check whether we have numbers after the first item in the array
  const onlyValues = csvLine.slice(2, csvLine.length - 1);
  const isNotValidLine = onlyValues.every(val => isNaN(val));
  // console.log(`shallow copy : ${isNotValidLine}`, onlyValues);
  if (csvLine.length === 7 && !isNotValidLine) csvStream.write(csvLine);
};

const csvStreamsAndSegments = (budgetSegments) =>
  budgetSegments.map(segment => {
    const tableName = segment.startLine;
    const writableStream = fs.createWriteStream(`${rootPath}/${tableName}.csv`);
    // configuring csv writableStream
    const csvStream = csv.createWriteStream({ headers: true });
    // adding a transformation function that is responsible for the row title
    csvStream.transform(row => ({
      sector: row[0],
      'Approved Budget': row[1],
      released: row[2],
      spent: row[3],
      '% Budget realsed': row[4],
      '% budget spent': row[5],
      '% releases spent': row[6]
    }))
    .pipe(writableStream);
    return { segment, csvStream };
  });

function readInFile({ segment, csvStream }) {
  let isTable = false;
  let isTableTitle = false;
  const startMining = verEx().find(segment.startLine);
  const endMiningExpression = verEx().find(segment.endLine);
  const isTableItem = verEx().find(segment.firstItem);
  readFileByLine.on('line', (line) => {
    const isEnd = endMiningExpression.test(line);
    if (isEnd) console.log('finished writing table:', segment.startLine);
    if (!isTableTitle) isTableTitle = startMining.test(line);
    if (!isTable && isTableTitle) isTable = isTableItem.test(line); // start writing in new Table
    if (isTable && !isEnd) writeLineToFile(line, csvStream);
  });
}

const closeCsvStreams = (csvStreams) => csvStreams.forEach(stream => stream.end());

const main = (csvWriteStreamsAndSegments) => {
  const csvStreams = [];
  csvWriteStreamsAndSegments.forEach(obj => {
    csvStreams.push(obj.csvStream);
    readInFile(obj);
  });
  readFileByLine.on('close', () => {
    closeCsvStreams(csvStreams);
    console.log('finished reading files closing');
  });
};

main(csvStreamsAndSegments(budgetSegmentsToRead));
<commit_msg>refactor<commit_after>import fs from 'fs';
import readline from 'readline';
import verEx from 'verbal-expressions';
import csv from 'fast-csv';
import { budgetSegmentsToRead } from './config';

const rootPath = '/Users/allanlukwago/apps/budget-data/samples';

const readFileByLine = readline.createInterface({
  input: fs.createReadStream(`${rootPath}/2014-15.txt`)
});

const csvLineTowrite = (line) => line.split('  ').filter(word => word.length > 1);

const writeLineToFile = (line, csvStream) => {
  const csvLine = csvLineTowrite(line);
  // check whether we have numbers after the first item in the array
  const onlyValues = csvLine.slice(2, csvLine.length - 1);
  const isNotValidLine = onlyValues.every(val => isNaN(val));
  // console.log(`shallow copy : ${isNotValidLine}`, onlyValues);
  if (csvLine.length === 7 && !isNotValidLine) csvStream.write(csvLine);
};

const csvStreamsAndSegments = (budgetSegments) =>
  budgetSegments.map(segment => {
    const tableName = segment.startLine;
    const writableStream = fs.createWriteStream(`${rootPath}/${tableName}.csv`);
    // configuring csv writableStream
    const csvStream = csv.createWriteStream({ headers: true });
    // adding a transformation function that is responsible for the row title
    csvStream.transform(row => ({
      segment: row[7],
      sector: row[0],
      'Approved Budget': row[1],
      released: row[2],
      spent: row[3],
      '% Budget realsed': row[4],
      '% budget spent': row[5],
      '% releases spent': row[6]
    }))
    .pipe(writableStream);
    return { segment, csvStream };
  });

function readInFile({ segment, csvStream }) {
  let isTable = false;
  let isTableTitle = false;
  const startMining = verEx().find(segment.startLine);
  const endMiningExpression = verEx().find(segment.endLine);
  const isTableItem = verEx().find(segment.firstItem);
  readFileByLine.on('line', (line) => {
    const isEnd = endMiningExpression.test(line);
    if (isEnd) console.log('finished writing table:', segment.startLine);
    if (!isTableTitle) isTableTitle = startMining.test(line);
    if (!isTable && isTableTitle) isTable = isTableItem.test(line); // start writing in new Table
    if (isTable && !isEnd) writeLineToFile(line, csvStream);
  });
}

const closeCsvStreams = (csvStreams) => csvStreams.forEach(stream => stream.end());

const main = (csvWriteStreamsAndSegments) => {
  const csvStreams = [];
  csvWriteStreamsAndSegments.forEach(obj => {
    csvStreams.push(obj.csvStream);
    readInFile(obj);
  });
  readFileByLine.on('close', () => {
    closeCsvStreams(csvStreams);
    console.log('finished reading files closing');
  });
};

main(csvStreamsAndSegments(budgetSegmentsToRead));
<|endoftext|>


<commit_before>'use strict';
function Config() {
    this.links = [
        { link: "projects", name: "Projects" },
        { link: "presentations", name: "Presentations" },
        { link: "volunteering", name: "Volunteering" },
        { link: "about", name: "About" }
    ];

}
Config.prototype.makeMetaTags = function makeMetaTags(data) {
    var metaData = {
        title: 'Gavin Mogan Dot Com',
        //canonical: 'https://www.gavinmogan.com/',
        meta: {
            'httpEquiv': {
                'x-ua-compatible': 'ie=edge'
            },
            name: {
                'viewport': 'width=device-width, initial-scale=1',
                'twitter:card': 'summary',
                'twitter:site': '@halkeye',
                'twitter:creator': '@halkeye'
            },
            charSet: 'utf-8'
        }
    };
    if (data.title) {
        metaData.title = data.title + ' - ' + metaData.title;
        metaData.meta.name['twitter:title'] = metaData.title;
        metaData.meta.name['og:title'] = metaData.title;
    }
    if (data.description) {
        metaData.descripton = data.description;
        metaData.meta.name['twitter:description'] = metaData.description;
        metaData.meta.name['og:description'] = metaData.description;
    }
    return metaData;
};

module.exports = new Config();
<commit_msg>fix description tags<commit_after>'use strict';
function Config() {
    this.links = [
        { link: "projects", name: "Projects" },
        { link: "presentations", name: "Presentations" },
        { link: "volunteering", name: "Volunteering" },
        { link: "about", name: "About" }
    ];

}
Config.prototype.makeMetaTags = function makeMetaTags(data) {
    var metaData = {
        title: 'Gavin Mogan Dot Com',
        //canonical: 'https://www.gavinmogan.com/',
        meta: {
            'httpEquiv': {
                'x-ua-compatible': 'ie=edge'
            },
            name: {
                'viewport': 'width=device-width, initial-scale=1',
                'twitter:card': 'summary',
                'twitter:site': '@halkeye',
                'twitter:creator': '@halkeye'
            },
            charSet: 'utf-8'
        }
    };
    if (data.title) {
        metaData.title = data.title + ' - ' + metaData.title;
        metaData.meta.name['twitter:title'] = metaData.title;
        metaData.meta.name['og:title'] = metaData.title;
    }
    if (data.description) {
        metaData.description = data.description;
        metaData.meta.name['twitter:description'] = metaData.description;
        metaData.meta.name['og:description'] = metaData.description;
    }
    return metaData;
};

module.exports = new Config();
<|endoftext|>


<commit_before>describe("transforms", function() {
    var mapal;

    requireDependencies(["transforms"], function(cls) {
        mapal = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("_convertToIframes", function() {
        it("Keep non-html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/plain">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(1);
        });

        it("Transform text/html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/html" data="about:blank">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(0);
            var $iframe = $lab.find("iframe");
            expect($iframe.length).toBe(1);
            expect($iframe[0].src).toBe("about:blank");
        });
    });

    describe("transformContent", function() {
        it("Convert legend to p.legend", function() {
            var $lab = $("#lab");
            $lab.append("<fieldset><legend>Fieldset title</legend></fieldset>");
            mapal.transformContent($lab[0]);
            expect($lab.html()).toBe('<fieldset>
Fieldset title
</fieldset>');
        });

        it("Keep text/html objects on non-IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie;
            spyOn(mapal, "_convertToIframes");
            try {
                old_msie=false;
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
            }
        });

        it("Convert text/html objects to iframes on IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="7.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });

        it("Keep text/html objects IE > 8", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="9.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Fix a transform test error.<commit_after>describe("transforms", function() {
    var mapal;

    requireDependencies(["transforms"], function(cls) {
        mapal = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("_convertToIframes", function() {
        it("Keep non-html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/plain">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(1);
        });

        it("Transform text/html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/html" data="about:blank">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(0);
            var $iframe = $lab.find("iframe");
            expect($iframe.length).toBe(1);
            expect($iframe[0].src).toBe("about:blank");
        });
    });

    describe("transformContent", function() {
        it("Convert legend to p.legend", function() {
            var $lab = $("#lab");
            $lab.append("<fieldset><legend>Fieldset title</legend></fieldset>");
            mapal.transformContent($lab);
            expect($lab.html()).toBe('<fieldset>
Fieldset title
</fieldset>');
        });

        it("Keep text/html objects on non-IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie;
            spyOn(mapal, "_convertToIframes");
            try {
                old_msie=false;
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
            }
        });

        it("Convert text/html objects to iframes on IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="7.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });

        it("Keep text/html objects IE > 8", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="9.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before><commit_msg>for testing ...<commit_after><|endoftext|>


<commit_before>describe("transforms", function() {
    var mapal;

    requireDependencies(["transforms"], function(cls) {
        mapal = cls;
    });

    beforeEach(function() {
        $("
", {id: "lab"}).appendTo(document.body);
    });

    afterEach(function() {
        $("#lab").remove();
    });

    describe("_convertToIframes", function() {
        it("Keep non-html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/plain">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(1);
        });

        it("Transform text/html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/html" data="about:blank">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(0);
            var $iframe = $lab.find("iframe");
            expect($iframe.length).toBe(1);
            expect($iframe[0].src).toBe("about:blank");
        });
    });

    describe("transformContent", function() {
        it("Convert legend to p.legend", function() {
            var $lab = $("#lab");
            $lab.append("<fieldset><legend>Fieldset title</legend></fieldset>");
            mapal.transformContent($lab[0]);
            expect($lab.html()).toBe('<fieldset>
Fieldset title
</fieldset>');
        });

        it("Keep text/html objects on non-IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie;
            spyOn(mapal, "_convertToIframes");
            try {
                old_msie=false;
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
            }
        });

        it("Convert text/html objects to iframes on IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="7.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });

        it("Keep text/html objects IE > 8", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="9.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Fix a transform test error.<commit_after>describe("transforms", function() {
    var mapal;

    requireDependencies(["transforms"], function(cls) {
        mapal = cls;
    });

    beforeEach(function() {
        $("
", {id: "lab"}).appendTo(document.body);
    });

    afterEach(function() {
        $("#lab").remove();
    });

    describe("_convertToIframes", function() {
        it("Keep non-html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/plain">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(1);
        });

        it("Transform text/html objects", function() {
            var $lab = $("#lab");
            $lab.append('<object type="text/html" data="about:blank">Plain content</object>');
            mapal._convertToIframes($lab);
            expect($lab.find("object").length).toBe(0);
            var $iframe = $lab.find("iframe");
            expect($iframe.length).toBe(1);
            expect($iframe[0].src).toBe("about:blank");
        });
    });

    describe("transformContent", function() {
        it("Convert legend to p.legend", function() {
            var $lab = $("#lab");
            $lab.append("<fieldset><legend>Fieldset title</legend></fieldset>");
            mapal.transformContent($lab);
            expect($lab.html()).toBe('<fieldset>
Fieldset title
</fieldset>');
        });

        it("Keep text/html objects on non-IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie;
            spyOn(mapal, "_convertToIframes");
            try {
                old_msie=false;
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
            }
        });

        it("Convert text/html objects to iframes on IE", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="7.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });

        it("Keep text/html objects IE > 8", function() {
            var $lab = $("#lab"),
                old_msie = $.browser.msie,
                old_version = $.browser.version;
            spyOn(mapal, "_convertToIframes");
            try {
                $.browser.msie=true;
                $.browser.version="9.0";
                mapal.transformContent($lab[0]);
                expect(mapal._convertToIframes).not.toHaveBeenCaled();
            } catch (e) {
                $.browser.msie = old_msie;
                $.browser.version = old_version;
            }
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>