<commit_before>(function() {
  var parser = window.BetterMarkdown,
      MD = parser.Markdown,
      DialectHelpers = parser.DialectHelpers;

  function generateUniqueishIdentifier () {
    // Stolen from StackOverflow: http://stackoverflow.com/a/8809472
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (d + Math.random()*16)%16 | 0;
        d = Math.floor(d/16);
        return (c=='x' ? r : (r&0x3|0x8)).toString(16);
    });
    return uuid;
  }

  function generateJsonML (label, contents, opts) {
    var myId = 'spoilerrific-' + generateUniqueishIdentifier();

    var wrappingDiv = ['div'].concat(contents);

    return [
      'div', { 'class': 'spoilerrific', 'data-prefix': opts.usingDefaultLabel ? 'yes' : 'no', 'data-suffix': opts.usingDefaultLabel ? 'no' : 'yes' },
      [
        'input', { 'type': 'checkbox', 'id': myId }
      ],
      [
        'label', { 'for': myId }, label
      ],
      wrappingDiv
    ];
  }

  // At the moment, Discourse's blocking mechanism seems to be broken
  // such that the below code will only accept block-level Markdown tags
  // (e.g. headers) if they appear as the very first item in the block
  // Therefore, as a (rather hackish) workaround, we recursively invoke
  // the ENTIRE markdown processing chain...
  //var emitter = function(contents, params) {
  //  params = params || '';
  //  var label = params.replace(/(^")|("$)/g, '') || 'FLARD inside!';
  //  return generateJsonML(label, contents);
  //};
  //Discourse.BBCode.register('spoiler', {noWrap: true}, emitter);

  Discourse.Dialect.replaceBlock({
    start: /\[spoiler1(=[^\[\]]+)?\]([\s\S]*)/igm,
    stop: /\[\/spoiler1\]/igm,
    rawContents: true, // this is documented, but doesn't seem to do anything
    emitter: function(blockContents, matches) {
      var params = matches[1] ? matches[1].replace(/^=/g, '') : '',
          label = params.replace(/(^")|("$)/g, ''),
          opts = {
            usingDefaultLabel: false,
          },
          inner = blockContents.join("\n\n"),
          innerTree = parser.toHTMLTree(inner, "Discourse");

      if ( Discourse.User.current() ) {

        if (!label) {
            opts.usingDefaultLabel = true;
            label = Discourse.SiteSettings.spoiler_default_label;
        }

        if (!innerTree || innerTree.length === 0 || innerTree[0] != 'html') { // uh?
            return generateJsonML(label, inner, opts);
        }

        return generateJsonML(label, innerTree.slice(1), opts);

      }
    }
  });

  var spoilerrificRe = /^spoilerrific-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/;
  Discourse.Markdown.whiteListTag('div', 'class', 'spoilerrific');
  Discourse.Markdown.whiteListTag('input', 'type', 'checkbox');
  Discourse.Markdown.whiteListTag('input', 'checked', 'checked');
  Discourse.Markdown.whiteListTag('input', 'id', spoilerrificRe);
  Discourse.Markdown.whiteListTag('label', 'for', spoilerrificRe);
  Discourse.Markdown.whiteListTag('label', 'data-prefix', /^(yes|no)$/);
  Discourse.Markdown.whiteListTag('label', 'data-suffix', /^(yes|no)$/);
})();
<commit_msg>some changes<commit_after>(function() {
  var parser = window.BetterMarkdown,
      MD = parser.Markdown,
      DialectHelpers = parser.DialectHelpers;

  function generateUniqueishIdentifier () {
    // Stolen from StackOverflow: http://stackoverflow.com/a/8809472
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (d + Math.random()*16)%16 | 0;
        d = Math.floor(d/16);
        return (c=='x' ? r : (r&0x3|0x8)).toString(16);
    });
    return uuid;
  }

  function generateJsonML (label, contents, opts) {
    var myId = 'spoilerrific-' + generateUniqueishIdentifier();

    var wrappingDiv = ['div'].concat(contents);

    return [
      'div', { 'class': 'spoilerrific', 'data-prefix': opts.usingDefaultLabel ? 'yes' : 'no', 'data-suffix': opts.usingDefaultLabel ? 'no' : 'yes' },
      [
        'input', { 'type': 'checkbox', 'id': myId }
      ],
      [
        'label', { 'for': myId }, label
      ],
      wrappingDiv
    ];
  }

  // At the moment, Discourse's blocking mechanism seems to be broken
  // such that the below code will only accept block-level Markdown tags
  // (e.g. headers) if they appear as the very first item in the block
  // Therefore, as a (rather hackish) workaround, we recursively invoke
  // the ENTIRE markdown processing chain...
  //var emitter = function(contents, params) {
  //  params = params || '';
  //  var label = params.replace(/(^")|("$)/g, '') || 'FLARD inside!';
  //  return generateJsonML(label, contents);
  //};
  //Discourse.BBCode.register('spoiler', {noWrap: true}, emitter);

  Discourse.Dialect.replaceBlock({
    start: /\[spoiler1(=[^\[\]]+)?\]([\s\S]*)/igm,
    stop: /\[\/spoiler1\]/igm,
    rawContents: true, // this is documented, but doesn't seem to do anything
    emitter: function(blockContents, matches) {
      var params = matches[1] ? matches[1].replace(/^=/g, '') : '',
          label = params.replace(/(^")|("$)/g, ''),
          opts = {
            usingDefaultLabel: false,
          },
          inner = blockContents.join("\n\n"),
          innerTree = parser.toHTMLTree(inner, "Discourse");

      if ( Discourse.User.current() === "object" ) {

        if (!label) {
            opts.usingDefaultLabel = true;
            label = Discourse.SiteSettings.spoiler_default_label;
        }

        if (!innerTree || innerTree.length === 0 || innerTree[0] != 'html') { // uh?
            return generateJsonML(label, inner, opts);
        }

        return generateJsonML(label, innerTree.slice(1), opts);

      } else {
        return '
You need to login to view this code snippet.
'
      }
    }
  });

  var spoilerrificRe = /^spoilerrific-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/;
  Discourse.Markdown.whiteListTag('div', 'class', 'spoilerrific');
  Discourse.Markdown.whiteListTag('input', 'type', 'checkbox');
  Discourse.Markdown.whiteListTag('input', 'checked', 'checked');
  Discourse.Markdown.whiteListTag('input', 'id', spoilerrificRe);
  Discourse.Markdown.whiteListTag('label', 'for', spoilerrificRe);
  Discourse.Markdown.whiteListTag('label', 'data-prefix', /^(yes|no)$/);
  Discourse.Markdown.whiteListTag('label', 'data-suffix', /^(yes|no)$/);
})();
<|endoftext|>


<commit_before>/* global angular */
;(function () {
  angular.module('resilienzManager')
    .controller('resilienzManager-Layout', ['$scope', 'resilienzManagerDataProvider', '$uibModal', '$rootScope', '$window', function ($scope, resilienzManagerDataProvider, $uibModal, $rootScope, $window) {
      var self = this
      self.categories = []
      self.final = false
      self.actionid = $rootScope.action
      self.catLoading = true
      self.pageLoading = true

      self.selectedCategory = {}
      self.selectedLayout = {}
      self.selectedPage = -1

      self.selectCategory = function () {
        self.catLoading = true
        self.selectedPage = self.selectedCategory.startpage
        self.catLoading = false
        reloadLayoutPositions(function () {}) // uses page to selectLayout
      }
      self.selectPage = function () {
        reloadLayoutPositions(function () {}) // uses page to selectLayout
      }
      self.selectLayout = function () {
        if (!self.final) {
          if (self.selectedLayout) {
            self.pageLoading = true
            resilienzManagerDataProvider.actionSaveLayout(self.actionid, self.selectedPage, self.selectedLayout).then(function (something) {
              reloadLayoutPositions(function () { })
            })
          }
        }
      }

      // load cats with layouts and positions
      resilienzManagerDataProvider.categoriesFull().then(function (categories) {
        self.categories = categories.data // {id, sort: -1, name: '', pages: -1, startpage: 0, layouts: [], translation}
        self.selectedCategory = self.categories[0]
        self.selectedPage = self.selectedCategory.startpage
        self.catLoading = false
        resilienzManagerDataProvider.action($rootScope.id).then(function (action) {
          self.final = (action.data.finalized === 1)
          reloadLayoutPositions(function () {})
        }, function (error) {
          console.error(error)
        })
      })

      self.openEditor = function (position) {
        if (!self.final) {
          var data = {}
          data.image = position.image
          data.width = position.width
          data.height = position.height
          var modalInstance = $uibModal.open({
            animation: true,
            templateUrl: 'modals/editor',
            controller: 'resilienzManager-Editor',
            controllerAs: 'ctrl',
            size: 'lg',
            resolve: {
              data: function () {
                return data
              }
            }
          })
          modalInstance.result.then(function (image) {
            position.style['background-image'] = 'url(/layout/image/' + image + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
          })
        }
      }
      self.delete = function (position) {
        if (!self.final) {
          position.deleting = true
          resilienzManagerDataProvider.imageDelete(position.image).then(function (something) {
            position.style['background-image'] = 'url(/layout/image/placeholder)'
            position.image = undefined
          })
        }
      }
      self.uploadError = function (file, errorMessage) {
        console.error(errorMessage)
      }
      function reloadLayoutPositions (callback) {
        resilienzManagerDataProvider.getLayoutImagesByActionPage(self.actionid, self.selectedPage).then(function (layoutWithImages) {
          self.pageLoading = true
          self.selectedLayout = {}
          self.selectedLayout = layoutWithImages.data
          self.pageImage = {
            'background-image': 'url(/layout/background/' + self.selectedPage + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
          }
          var orgWidth = (self.selectedCategory.id === '1') ? 720 : 1440
          var orgHeight = 1040
          var pageHeight = 700
          var pageWidth = ((orgWidth * pageHeight) / orgHeight)
          for (var i = 0; i < self.selectedLayout.positions.length; i++) {
            var position = self.selectedLayout.positions[i]
            position.style = {
              'left': (position.x * pageWidth / orgWidth) + 'px',
              'top': (position.y * pageHeight / orgHeight) + 'px',
              'width': (position.width * pageWidth / orgWidth) + 'px',
              'height': (position.height * pageHeight / orgHeight) + 'px',
              'transform': 'rotate(' + position.spin + 'deg)',
              'background-image': 'url(/layout/image/' + position.image + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
            }
            position.dropzoneConfig = {
              parallelUploads: 1,
              maxFileSize: 10,
              url: position.action,
              paramName: 'dropzone',
              method: 'post'
            }
            position.dragEnter = function (event) {
              event.currentTarget.parentElement.style.outline = '2px solid #1BFF1B'
              $scope.$apply()
            }
            position.dragLeave = function (event) {
              event.currentTarget.parentElement.style.outline = undefined
              $scope.$apply()
            }
            position.sending = function (file, xhr, formData) {
              position.sending = true
              $scope.$apply()
            }
            position.success = function (position) {
              resilienzManagerDataProvider.getPositionImage(self.actionid, position.id).then(function (image) {
                position.image = image.data
                position.sending = false
                position.deleting = false
                position.style['background-image'] = 'url(/layout/image/' + image.data + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
              })
            }
            position.sending = false
            position.deleting = false
          }
          self.pageLoading = false
          callback()
        })
      }
    }])
}())
<commit_msg>dragleave fixing<commit_after>/* global angular */
;(function () {
  angular.module('resilienzManager')
    .controller('resilienzManager-Layout', ['$scope', 'resilienzManagerDataProvider', '$uibModal', '$rootScope', '$window', function ($scope, resilienzManagerDataProvider, $uibModal, $rootScope, $window) {
      var self = this
      self.categories = []
      self.final = false
      self.actionid = $rootScope.action
      self.catLoading = true
      self.pageLoading = true

      self.selectedCategory = {}
      self.selectedLayout = {}
      self.selectedPage = -1

      self.selectCategory = function () {
        self.catLoading = true
        self.selectedPage = self.selectedCategory.startpage
        self.catLoading = false
        reloadLayoutPositions(function () {}) // uses page to selectLayout
      }
      self.selectPage = function () {
        reloadLayoutPositions(function () {}) // uses page to selectLayout
      }
      self.selectLayout = function () {
        if (!self.final) {
          if (self.selectedLayout) {
            self.pageLoading = true
            resilienzManagerDataProvider.actionSaveLayout(self.actionid, self.selectedPage, self.selectedLayout).then(function (something) {
              reloadLayoutPositions(function () { })
            })
          }
        }
      }

      // load cats with layouts and positions
      resilienzManagerDataProvider.categoriesFull().then(function (categories) {
        self.categories = categories.data // {id, sort: -1, name: '', pages: -1, startpage: 0, layouts: [], translation}
        self.selectedCategory = self.categories[0]
        self.selectedPage = self.selectedCategory.startpage
        self.catLoading = false
        resilienzManagerDataProvider.action($rootScope.id).then(function (action) {
          self.final = (action.data.finalized === 1)
          reloadLayoutPositions(function () {})
        }, function (error) {
          console.error(error)
        })
      })

      self.openEditor = function (position) {
        if (!self.final) {
          var data = {}
          data.image = position.image
          data.width = position.width
          data.height = position.height
          var modalInstance = $uibModal.open({
            animation: true,
            templateUrl: 'modals/editor',
            controller: 'resilienzManager-Editor',
            controllerAs: 'ctrl',
            size: 'lg',
            resolve: {
              data: function () {
                return data
              }
            }
          })
          modalInstance.result.then(function (image) {
            position.style['background-image'] = 'url(/layout/image/' + image + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
          })
        }
      }
      self.delete = function (position) {
        if (!self.final) {
          position.deleting = true
          resilienzManagerDataProvider.imageDelete(position.image).then(function (something) {
            position.style['background-image'] = 'url(/layout/image/placeholder)'
            position.image = undefined
          })
        }
      }
      self.uploadError = function (file, errorMessage) {
        console.error(errorMessage)
      }
      function reloadLayoutPositions (callback) {
        resilienzManagerDataProvider.getLayoutImagesByActionPage(self.actionid, self.selectedPage).then(function (layoutWithImages) {
          self.pageLoading = true
          self.selectedLayout = {}
          self.selectedLayout = layoutWithImages.data
          self.pageImage = {
            'background-image': 'url(/layout/background/' + self.selectedPage + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
          }
          var orgWidth = (self.selectedCategory.id === '1') ? 720 : 1440
          var orgHeight = 1040
          var pageHeight = 700
          var pageWidth = ((orgWidth * pageHeight) / orgHeight)
          for (var i = 0; i < self.selectedLayout.positions.length; i++) {
            var position = self.selectedLayout.positions[i]
            position.style = {
              'left': (position.x * pageWidth / orgWidth) + 'px',
              'top': (position.y * pageHeight / orgHeight) + 'px',
              'width': (position.width * pageWidth / orgWidth) + 'px',
              'height': (position.height * pageHeight / orgHeight) + 'px',
              'transform': 'rotate(' + position.spin + 'deg)',
              'background-image': 'url(/layout/image/' + position.image + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
            }
            position.dropzoneConfig = {
              parallelUploads: 1,
              maxFileSize: 10,
              url: position.action,
              paramName: 'dropzone',
              method: 'post'
            }
            position.dragEnter = function (event) {
              event.currentTarget.parentElement.style.outline = '2px solid #1BFF1B'
              $scope.$apply()
            }
            position.dragLeave = function (event) {
              event.currentTarget.parentElement.style.outline = '0px'
              $scope.$apply()
            }
            position.sending = function (file, xhr, formData) {
              position.sending = true
              $scope.$apply()
            }
            position.success = function (position) {
              resilienzManagerDataProvider.getPositionImage(self.actionid, position.id).then(function (image) {
                position.image = image.data
                position.sending = false
                position.deleting = false
                position.style['background-image'] = 'url(/layout/image/' + image.data + '?v=' + Math.floor((Math.random() * 1000) + 1) + ')'
              })
            }
            position.sending = false
            position.deleting = false
          }
          self.pageLoading = false
          callback()
        })
      }
    }])
}())
<|endoftext|>


<commit_before>//
//   Copyright 2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const redis = require('../lib/redis').createClient(),
      outbox = require('../lib/outbox');

// TBD: Instead of FRIENDS and FRIENDSUPDATE, use ADDFRIENDS

exports.sendFriends = function*(userId, sessionId) {
    let command = {
        id: 'FRIENDS',
        friends: []
    };

    let friendIds = yield redis.smembers(`friends:${userId}`);

    // TBD: Do the looping in lua to enhance performance
    for (let friendUserId of friendIds) {
        let last = yield redis.hget(`user:${friendUserId}`, 'lastlogout');
        last = parseInt(last);

        let online = last === 0;

        if (isNaN(last)) {
            last = -1; // No recorded login or logout
        }

        let friendData = {
            userId: friendUserId,
            online: online
        };

        if (!online) {
            friendData.last = last;
        }

        command.friends.push(friendData);
    }

    if (sessionId) {
        yield outbox.queue(userId, sessionId, command);
    } else {
        yield outbox.queueAll(userId, command);
    }
};

exports.sendFriendConfirm = function*(userId, sessionId) {
    let friendRequests = yield redis.smembers(`friendsrequests:${userId}`);

    // Use userId property so that related USERS notification is send automatically
    // See lib/outbox.js for details.
    friendRequests = friendRequests.map(function(userId) {
        return { userId: userId };
    });

    if (friendRequests) {
        yield outbox.queue(userId, sessionId, {
            id: 'FRIENDSCONFIRM',
            friends: friendRequests
        });
    }
};

exports.informStateChange = function*(userId, eventType) {
    let command = {
        id: 'FRIENDSUPDATE',
        userId: userId
    };
    let ts;

    // Zero means the user is currently online
    if (eventType === 'login') {
        ts = 0;
        command.online = true;
    } else {
        ts = Math.round(Date.now() / 1000);
        command.last = ts;
        command.online = false;
    }

    yield redis.hset(`user:${userId}`, 'lastlogout', ts);

    let friendIds = yield redis.smembers(`friends:${userId}`);

    for (let friendUserId of friendIds) {
        yield outbox.queueAll(friendUserId, command);
    }
};
<commit_msg>Don't send empty FRIENDSCONFIRMs<commit_after>//
//   Copyright 2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const redis = require('../lib/redis').createClient(),
      outbox = require('../lib/outbox');

// TBD: Instead of FRIENDS and FRIENDSUPDATE, use ADDFRIENDS

exports.sendFriends = function*(userId, sessionId) {
    let command = {
        id: 'FRIENDS',
        friends: []
    };

    let friendIds = yield redis.smembers(`friends:${userId}`);

    // TBD: Do the looping in lua to enhance performance
    for (let friendUserId of friendIds) {
        let last = yield redis.hget(`user:${friendUserId}`, 'lastlogout');
        last = parseInt(last);

        let online = last === 0;

        if (isNaN(last)) {
            last = -1; // No recorded login or logout
        }

        let friendData = {
            userId: friendUserId,
            online: online
        };

        if (!online) {
            friendData.last = last;
        }

        command.friends.push(friendData);
    }

    if (sessionId) {
        yield outbox.queue(userId, sessionId, command);
    } else {
        yield outbox.queueAll(userId, command);
    }
};

exports.sendFriendConfirm = function*(userId, sessionId) {
    let friendRequests = yield redis.smembers(`friendsrequests:${userId}`);

    if (friendRequests && friendRequests.length > 0) {
        // Uses userId property so that related USERS notification is send automatically
        // See lib/outbox.js for details.
        friendRequests = friendRequests.map(function(userId) {
            return { userId: userId };
        });

        yield outbox.queue(userId, sessionId, {
            id: 'FRIENDSCONFIRM',
            friends: friendRequests
        });
    }
};

exports.informStateChange = function*(userId, eventType) {
    let command = {
        id: 'FRIENDSUPDATE',
        userId: userId
    };
    let ts;

    // Zero means the user is currently online
    if (eventType === 'login') {
        ts = 0;
        command.online = true;
    } else {
        ts = Math.round(Date.now() / 1000);
        command.last = ts;
        command.online = false;
    }

    yield redis.hset(`user:${userId}`, 'lastlogout', ts);

    let friendIds = yield redis.smembers(`friends:${userId}`);

    for (let friendUserId of friendIds) {
        yield outbox.queueAll(friendUserId, command);
    }
};
<|endoftext|>


<commit_before>const _ = require('lodash')
const moment = require('moment')
const excelWriter = require('./excel-writer')
const fs = require('fs')
const enums = require('../shared/enums')
const utils = require('../shared/utils')
var i18n = require('../shared/i18n')

var dateFormat = 'DD.MM.YYYY'

exports.constructProgramExportData = function constructProgramExportData(docs, showClassificationAuthor, tmpFile, lang) {
  function translate(txt) { return i18n[lang] ? i18n[lang][txt] || txt : txt }
  var columnsOrig = ["Alkuperäinen nimi", "Suomenkielinen nimi", "Ruotsinkielinen nimi", "Jakso", "Jakson alkuperäinen nimi", "Rekisteröintipäivä", "Kesto", "Luokittelun tilaaja", "Luokittelija", "Uudelleenluokittelija", "Ikäraja", "Luokittelun kriteerit", "Perustelu", "Varoitukset", "Ohjelman tyyppi", "Maa", "Valmistumisvuosi", "Ohjaaja", "Tuotantoyhtiö", "Synopsis", "Id"]
  var columns = _.map(columnsOrig, translate)
  columnWidths = [{"wch":40},{"wch":40},{"wch":40},{"wch":10},{"wch":40},{"wch":15},{"wch":10},{"wch":40},{"wch":25},{"wch":25},{"wch":10},{"wch":40},{"wch":20},{"wch":20},{"wch":20},{"wch":10},{"wch":15},{"wch":20},{"wch":20},{"wch":40},{"wch":10}]

  var ext = tmpFile.substring(tmpFile.lastIndexOf('.'))
  var xlsData = []
  xlsData.push(columns)
  _.forEach(docs, function (doc) {
    var name = listToString(doc.name)
    var classification = enums.util.isTvSeriesName(doc) && doc.episodes ? doc.episodes : doc.classifications && doc.classifications[0] ? doc.classifications[0] : {}
    doc.originalName = enums.util.isTvEpisode(doc) ? (doc.series || {}).name : name
    doc.format = classification.format
    doc.duration = enums.util.isGameType(doc) ? "" :classification.duration
    doc.classificationBuyer = classification.buyer ? classification.buyer.name : ""
    doc.classificationAuthor = classification.author && showClassificationAuthor ? classification.author.name : ""
    doc.agelimit = classification.agelimit
    doc.warnings = classification.warnings ? classification.warnings.map(translate).join(', ') : ""
    doc.criteriaComments = classification.isReclassification ? listToString(_.values(classification.criteriaComments)) : ""
    doc.criteria = classification.criteria
    doc.episodeCode = enums.util.isTvEpisode(doc) ? utils.seasonEpisodeCode(doc) : ""
    doc.episodeName = enums.util.isTvEpisode(doc) ? name : ""
    doc.reclassifier = classification.isReclassification && classification.authorOrganization ? enums.authorOrganization[classification.authorOrganization] : ""
    doc.registrationDate = classification.registrationDate ? moment(classification.registrationDate).format(dateFormat) : ""
    doc.programTypeName = translate((enums.programType[doc.programType] || {}).fi)

    xlsData.push([removeNewlinesIfCsv(doc.originalName), listToString(doc.nameFi), listToString(doc.nameSv), doc.episodeCode, removeNewlinesIfCsv(doc.episodeName), doc.registrationDate, doc.duration, doc.classificationBuyer, doc.classificationAuthor, doc.reclassifier, doc.agelimit, doc.criteria, removeNewlinesIfCsv(doc.criteriaComments), doc.warnings, doc.programTypeName, listToString(doc.country), doc.year, listToString(doc.directors), listToString(doc.productionCompanies), removeNewlinesIfCsv(doc.synopsis), doc.sequenceId])

    function listToString(list) {
      return removeNewlinesIfCsv((list || []).map(function (f) { return f ? f.trim() : '' }).filter(function (f) { return f.length > 0 }).join(', '))
    }

    function removeNewlinesIfCsv(orig) {
      if (orig && ext === '.csv') return orig.replace(/\n/g, ' ')
      return orig
    }
  })

  excelWriter.write(tmpFile, xlsData, columnWidths)
  var fileData = fs.readFileSync(tmpFile)
  fs.unlinkSync(tmpFile)
  return fileData
}
<commit_msg>Explicitly set columnWidth variable<commit_after>const _ = require('lodash')
const moment = require('moment')
const excelWriter = require('./excel-writer')
const fs = require('fs')
const enums = require('../shared/enums')
const utils = require('../shared/utils')
var i18n = require('../shared/i18n')

var dateFormat = 'DD.MM.YYYY'

exports.constructProgramExportData = function constructProgramExportData(docs, showClassificationAuthor, tmpFile, lang) {
  function translate(txt) { return i18n[lang] ? i18n[lang][txt] || txt : txt }
  var columnsOrig = ["Alkuperäinen nimi", "Suomenkielinen nimi", "Ruotsinkielinen nimi", "Jakso", "Jakson alkuperäinen nimi", "Rekisteröintipäivä", "Kesto", "Luokittelun tilaaja", "Luokittelija", "Uudelleenluokittelija", "Ikäraja", "Luokittelun kriteerit", "Perustelu", "Varoitukset", "Ohjelman tyyppi", "Maa", "Valmistumisvuosi", "Ohjaaja", "Tuotantoyhtiö", "Synopsis", "Id"]
  var columns = _.map(columnsOrig, translate)
  var columnWidths = [40, 40, 40, 10, 40, 15, 10, 40, 25, 25, 10, 40, 20, 20, 20, 10, 15, 20, 20, 40, 10]

  var ext = tmpFile.substring(tmpFile.lastIndexOf('.'))
  var xlsData = []
  xlsData.push(columns)
  _.forEach(docs, function (doc) {
    var name = listToString(doc.name)
    var classification = enums.util.isTvSeriesName(doc) && doc.episodes ? doc.episodes : doc.classifications && doc.classifications[0] ? doc.classifications[0] : {}
    doc.originalName = enums.util.isTvEpisode(doc) ? (doc.series || {}).name : name
    doc.format = classification.format
    doc.duration = enums.util.isGameType(doc) ? "" :classification.duration
    doc.classificationBuyer = classification.buyer ? classification.buyer.name : ""
    doc.classificationAuthor = classification.author && showClassificationAuthor ? classification.author.name : ""
    doc.agelimit = classification.agelimit
    doc.warnings = classification.warnings ? classification.warnings.map(translate).join(', ') : ""
    doc.criteriaComments = classification.isReclassification ? listToString(_.values(classification.criteriaComments)) : ""
    doc.criteria = classification.criteria
    doc.episodeCode = enums.util.isTvEpisode(doc) ? utils.seasonEpisodeCode(doc) : ""
    doc.episodeName = enums.util.isTvEpisode(doc) ? name : ""
    doc.reclassifier = classification.isReclassification && classification.authorOrganization ? enums.authorOrganization[classification.authorOrganization] : ""
    doc.registrationDate = classification.registrationDate ? moment(classification.registrationDate).format(dateFormat) : ""
    doc.programTypeName = translate((enums.programType[doc.programType] || {}).fi)

    xlsData.push([removeNewlinesIfCsv(doc.originalName), listToString(doc.nameFi), listToString(doc.nameSv), doc.episodeCode, removeNewlinesIfCsv(doc.episodeName), doc.registrationDate, doc.duration, doc.classificationBuyer, doc.classificationAuthor, doc.reclassifier, doc.agelimit, doc.criteria, removeNewlinesIfCsv(doc.criteriaComments), doc.warnings, doc.programTypeName, listToString(doc.country), doc.year, listToString(doc.directors), listToString(doc.productionCompanies), removeNewlinesIfCsv(doc.synopsis), doc.sequenceId])

    function listToString(list) {
      return removeNewlinesIfCsv((list || []).map(function (f) { return f ? f.trim() : '' }).filter(function (f) { return f.length > 0 }).join(', '))
    }

    function removeNewlinesIfCsv(orig) {
      if (orig && ext === '.csv') return orig.replace(/\n/g, ' ')
      return orig
    }
  })

  excelWriter.write(tmpFile, xlsData, columnWidths.map(function (c) { return {wch: c} }))
  var fileData = fs.readFileSync(tmpFile)
  fs.unlinkSync(tmpFile)
  return fileData
}
<|endoftext|>


<commit_before>"use strict";

  import angular from 'angular';
  import uiRouter from 'angular-ui-router';
  import angularComponent from 'angular-component';
  import Components from './components/components';
  import AppComponent from './app.component';

  angular.module('medup-web', [
    uiRouter,
    Components.name
  ])
    .config(($httpProvider, $urlRouterProvider) => {
      $urlRouterProvider.otherwise('/');
      // $httpProvider.interceptors.push('AttachTokens');
    })
    .component('medupWeb', AppComponent);
    // .factory('AttachTokens', attachTokens)
    //  .run();
//
// function attachTokens($window) {
//
//   let attach = {
//     request: (object) => {
//
//       let jwt = $window.localStorage.getItem('com.pillMeNow');
//
//       if (jwt) {
//         object.headers['x-access-token'] = jwt;
//       }
//
//       object.headers['Allow-Control-Allow-Origin'] = '*';
//
//       return object;
//
//     }
//   };
//
//   return attach;
//
// }
//
// function appRun($rootScope, $state, Auth) {
//   $rootScope.on('$stateChangeStart', (evt, toState) => {
//
//     if (toState.name === 'signin') return;
//
//     if (!Auth.isAuth() && toState.name !== 'signup') {
//       evt.preventDefault();
//       $state.go('signin');
//     }
//   });
// }
<commit_msg>(update) import common modules<commit_after>"use strict";

  import angular from 'angular';
  import uiRouter from 'angular-ui-router';
  import angularComponent from 'angular-component';
  import Common from './common/common';
  import Components from './components/components';
  import AppComponent from './app.component';

  angular.module('medup-web', [
    uiRouter,
    Common.name,
    Components.name
  ])
    .config(($httpProvider, $urlRouterProvider) => {
      $urlRouterProvider.otherwise('/');
      // $httpProvider.interceptors.push('AttachTokens');
    })
    .component('medupWeb', AppComponent);
    // .factory('AttachTokens', attachTokens)
    //  .run();
//
// function attachTokens($window) {
//
//   let attach = {
//     request: (object) => {
//
//       let jwt = $window.localStorage.getItem('com.pillMeNow');
//
//       if (jwt) {
//         object.headers['x-access-token'] = jwt;
//       }
//
//       object.headers['Allow-Control-Allow-Origin'] = '*';
//
//       return object;
//
//     }
//   };
//
//   return attach;
//
// }
//
// function appRun($rootScope, $state, Auth) {
//   $rootScope.on('$stateChangeStart', (evt, toState) => {
//
//     if (toState.name === 'signin') return;
//
//     if (!Auth.isAuth() && toState.name !== 'signup') {
//       evt.preventDefault();
//       $state.go('signin');
//     }
//   });
// }
<|endoftext|>


<commit_before>const Discord = require('discord.js');
const botLogin = require('./config/botlogin.js');
const liveStream = require('./modules/livestream.js');
const fs = require('fs');
const bot = new Discord.Client();
bot.login(botLogin.token);

const adminRole = "admin";

var botVersion = "?#";
try{
	botVersion = require('./package.json').version;

	var notifyChannel = {}
	if((fs.existsSync('./config/notifychannels.json'))){
		notifyChannel = fs.readFileSync('./config/notifychannels.json');
		notifyChannel = JSON.parse(notifyChannel);

	}else{
		fs.writeFileSync('./config/notifychannels.json', "{}");
		notifyChannel = fs.readFileSync('./config/notifychannels.json');
		notifyChannel = JSON.parse(notifyChannel);
	}

} catch(error){
	if(error) {
		console.log("------- ERROR --------");
		console.log(error);
		console.log("----------------------");
	}
}
var CMDINT = "!";
var defaultStatus = "v"+botVersion + " | " + CMDINT + "help";

// Checks if the message is a command input from the user
function isCommand(message, command){
	var init = message.slice(0, 1);
	var cmd = (message.indexOf(' ') !== -1) ? message.slice(1, message.indexOf(' ')) : message.slice(1);

	if(init === CMDINT && cmd.toLowerCase() === command.toLowerCase())
		return true
	else
		return false;
}

// Checks for a specific role the user is in to run admin commands
function isAdmin(message){
	var roles = message.member.roles.array();
	for(var role = 0; role < roles.length; role++){
		if(roles[role].name.toLowerCase() === adminRole)
			return true;
	}
	message.channel.sendMessage("You aren't admin for this command.");
	return false;
}

// Sets the game the bot is "playing"
function setGame(game){
	bot.user.setGame(game);
}

function getChannelByName(guild, channelName){
	var channel = guild.channels.filterArray( channel => {
		if(channel.name === channelName)
			return channel;
	})[0];

	if(channel)
		return channel
	else
		return null;
}

function botLog(message){
	console.log("DISCORD: " + message);
}

function sendError(title, error, channel){
	console.log("-----"  + "ERROR"+ "------");
	console.log(error);
	console.log("----------");
	channel.sendMessage("**" + title + " Error**\n```" + error.message +"```");
}

function displayServers(){
	var guilds = bot.guilds.array();
	var servers = [];

	for(var i = 0; i < guilds.length; i++){
		servers.push(guilds[i].name);
	}

	return "Servers:\n" + servers.join("\n") + "\n";
}

function fileExist(path, data){
	if(!(fs.existsSync(path))){
		fs.writeFileSync(path, data);
		console.log("Config file: " + path + " created.");
	}
}

//	Credit: https://stackoverflow.com/questions/1303646/check-whether-variable-is-number-or-string-in-javascript#1303650
function isNumber(obj) {
	return !isNaN(parseFloat(obj))
}

bot.on('ready', () => {
	console.log("AkeBot v" + botVersion);
	console.log(displayServers());

	setGame(defaultStatus);
});

bot.on('disconnect', event =>{
	console.log("Exited with code: " + event.code);
	if(event.message)
		console.log("Message: " + event.message);
	process.exit(0);
});

bot.on('guildMemberAdd', guildMember =>{
	var generalChannel = getChannelByName(guildMember.guild, 'general');

	generalChannel.sendMessage(guildMember.user.username +" Welcome to " + guildMember.guild.name);
	botLog(guildMember.guild.name + " welcomes " + guildMember.user.username + " to their server.");
});

bot.on('presenceUpdate', (oldGuildMember, newGuildMember) =>{
	if(newGuildMember.presence.game !== null){
		var defaultChannel = "general";
		var textChannel = getChannelByName(newGuildMember.guild, defaultChannel);

		if(!(notifyChannel.hasOwnProperty(newGuildMember.guild.id))){
			notifyChannel[newGuildMember.guild.id] = {
				channel: defaultChannel,
				notify: true
			}
		}

		textChannel = getChannelByName(newGuildMember.guild, notifyChannel[newGuildMember.guild.id].channel);
		if(textChannel === null){
			textChannel = getChannelByName(newGuildMember.guild, defaultChannel);
		}

		if(newGuildMember.presence.game.streaming){
			if(notifyChannel[newGuildMember.guild.id].notify){
				textChannel.sendMessage("**LIVE**\n" +
				newGuildMember.user.username + " is now streaming!\n**Title:** " + newGuildMember.presence.game.name +
				"\n**URL:** " + newGuildMember.presence.game.url);
			}
		}
	}
});

bot.on('message', message => {
	const mContent = message.content;
	const mChannel = message.channel;

	// Admin commands

	if(isCommand(mContent, 'exit') && isAdmin(message)){
		bot.destroy();
	}

	if(isCommand(mContent, 'setgame') && isAdmin(message)){
		if(mContent.indexOf('') !== -1){
			var game = mContent.slice(mContent.indexOf(' ') + 1);
			setGame(game);
			botLog("Game set to: " + game);
		}
	}

	// Sets the preferred channel for live streaming notifications
	if(isCommand(mContent, 'setchannel') && isAdmin(message)){
		var file = './config/notifychannels.json';
		if(mContent.indexOf(' ') !== -1){
			var channel = mContent.split(' ')[1];
			fs.readFile(file, (error, notifyChannel) =>{
				if(error) return sendError("Reading Notify Channels File", error, mChannel);
				try{
					notifyChannel = JSON.parse(notifyChannel);
				}catch(error){
					if(error) return sendError("Parsing Notify Channels File");
				}
				if(getChannelByName(message.guild, channel) !== null){
					if(!(notifyChannel.hasOwnProperty(message.member.guild.id))){
						notifyChannel[message.member.guild.id] = {
							channel: channel,
							notify: true
						}
					} else{
						notifyChannel[message.member.guild.id].channel = channel;
					}

					fs.writeFile(file, JSON.stringify(notifyChannel, null, '\t'), error =>{
						if(error) return sendError("Writing Notify Channels File", error, mChannel);

						mChannel.sendMessage("Channel `" + channel + "` set as default notifications channel");
					});
				}else{
					mChannel.sendMessage("No channel found with that name");
				}
			});
		}
	}

	// Enables or disables streaming notifcations on a server
	if(isCommand(mContent, 'notify') && isAdmin(message)){
		var file = './config/notifychannels.json';
		fs.readFile(file, (error, notifyChannel) =>{
			if(error) return sendError("Reading Notify Channels File", error, mChannel);
			try{
				notifyChannel = JSON.parse(notifyChannel);
			}catch(error){
				if(error) return sendError("Parsing Notify Channels File", error, mChannel);
			}

			if(!(notifyChannel.hasOwnProperty(message.member.guild.id))){
				notifyChannel[message.member.guild.id] = {
					channel: "general",
					notify: true
				}
			} else{
				if(notifyChannel[message.member.guild.id].notify){
					notifyChannel[message.member.guild.id].notify = false;
				} else{
					notifyChannel[message.member.guild.id].notify = true;
				}
			}

			if(notifyChannel[message.member.guild.id].notify){
				mChannel.sendMessage("Notifications for this server set to `true`");
			} else{
				mChannel.sendMessage("Notifications for this server set to `false`");
			}

			fs.writeFile(file, JSON.stringify(notifyChannel, null, '\t'), error =>{
				if(error) return sendError("Reading Stream Black List File", error, mChannel);
			});
		});
	}

	// GENERAL commands

  	if(isCommand(mContent, 'help')){
  		message.channel.sendMessage("**Help**\nIn progress!");
  	}

  	if(isCommand(mContent, 'about')){
  		var content = "**About**\n" + "**Bot Version:** Akephalos Bot v" + botVersion +
  			"\n**Bot Username:** " + bot.user.username +
  			"\n**Servers Connected:** `" + bot.guilds.array().length + "`" +
  			"\n**Author:** Mesmaroth" +
  			"\n**Library:** Discord.js" +
  			"\n**Source:** <https://github.com/Mesmaroth/discord-AkephalosBot>"

  		message.channel.sendFile( bot.user.displayAvatarURL, 'botAvatar.jpg', content);
  	}

  	if(isCommand(message.content, 'source')){
  		message.channel.sendMessage("**Source:** https://github.com/Mesmaroth/discord-AkephalosBot");
  	}

  	if(isCommand(mContent, 'invite')){
  		bot.generateInvite().then( link =>{
  			mChannel.sendMessage("**Invite:** " + link);
  		});
  	}

  	if(isCommand(mContent, 'uptime')){
  		var uptimeSeconds = 0, uptimeMinutes = 0, uptimeHours = 0;

  		uptimeSeconds = Math.floor(bot.uptime/1000);

		if(uptimeSeconds > 60){
			uptimeMinutes = Math.floor(uptimeSeconds/60);
			uptimeSeconds = Math.floor(uptimeSeconds % 60);
		}

		if(uptimeMinutes > 60){
			uptimeHours = Math.floor(uptimeMinutes / 60);
			uptimeMinutes = Math.floor(uptimeMinutes % 60);
		}

  		mChannel.sendMessage("**Uptime:** " + uptimeHours + " hour(s) : " + uptimeMinutes + " minute(s) : " + uptimeSeconds +" second(s)");
  	}

  	if(isCommand(mContent, 'twitch')){
  		if(mContent.indexOf(' ') !== -1){
  			var name = mContent.split(' ')[1];

  			liveStream.getTwitchStream(name, (error, status, gameTitle, streamURL)=> {
  				if(error) return sendError("Getting Twitch Stream Data", error, mChannel);
  				if(status){
  					mChannel.sendMessage(
  					"**Twitch**\n**Name:** " + name +
  					"\n**Status:** `Online`\n**Game:** " + gameTitle +
  					"\n**URL:** " + streamURL);
  				} else{
  					mChannel.sendMessage(
  						"**Twitch**\n**Name:** " + name +
  						"\n**Status:** `Offline`");
  				}
  			});
  		}
  	}

  	if(isCommand(mContent, 'hitbox')){
  		if(mContent.indexOf(' ')!== -1){
  			var name = mContent.split(' ')[1];

  			liveStream.getHitboxStream(name, (error, status, gameTitle, streamURL) =>{
  				if(error) return sendError("Getting HitBox Stream Data", error, mChannel);
  				if(status){
  					mChannel.sendMessage(
  					"**HitBox**\n**Name:**" + name +
  					"\n**Status:** `Online`\n**Game:** " + gameTitle +
  					"\n**URL:** " + streamURL);
  				} else{
  					mChannel.sendMessage(
  					"**HitBox**\n**Name:**" + name +
  					"\n**Status:** `Offline`");
  				}
  			});
  		}
  	}
});<commit_msg>Custom commands added<commit_after>const Discord = require('discord.js');
const botLogin = require('./config/botlogin.js');
const liveStream = require('./modules/livestream.js');
const fs = require('fs');
const bot = new Discord.Client();
bot.login(botLogin.token);

const adminRole = "admin";

var botVersion = "?#";
try{
	botVersion = require('./package.json').version;

	var notifyChannel = {}
	if((fs.existsSync('./config/notifychannels.json'))){
		notifyChannel = fs.readFileSync('./config/notifychannels.json');
		notifyChannel = JSON.parse(notifyChannel);

	}else{
		fs.writeFileSync('./config/notifychannels.json', "{}");
		notifyChannel = fs.readFileSync('./config/notifychannels.json');
		notifyChannel = JSON.parse(notifyChannel);
	}

} catch(error){
	if(error) {
		console.log("------- ERROR --------");
		console.log(error);
		console.log("----------------------");
	}
}
var CMDINT = "!";
var defaultStatus = "v"+botVersion + " | " + CMDINT + "help";

// Checks if the message is a command input from the user
function isCommand(message, command){
	var init = message.slice(0, 1);
	var cmd = (message.indexOf(' ') !== -1) ? message.slice(1, message.indexOf(' ')) : message.slice(1);

	if(init === CMDINT && cmd.toLowerCase() === command.toLowerCase())
		return true
	else
		return false;
}

// Checks for a specific role the user is in to run admin commands
function isAdmin(message){
	var roles = message.member.roles.array();
	for(var role = 0; role < roles.length; role++){
		if(roles[role].name.toLowerCase() === adminRole)
			return true;
	}
	message.channel.sendMessage("You aren't admin for this command.");
	return false;
}

// Sets the game the bot is "playing"
function setGame(game){
	bot.user.setGame(game);
}

function getChannelByName(guild, channelName){
	var channel = guild.channels.filterArray( channel => {
		if(channel.name === channelName)
			return channel;
	})[0];

	if(channel)
		return channel
	else
		return null;
}

function botLog(message){
	console.log("DISCORD: " + message);
}

function sendError(title, error, channel){
	console.log("-----"  + "ERROR"+ "------");
	console.log(error);
	console.log("----------");
	channel.sendMessage("**" + title + " Error**\n```" + error.message +"```");
}

function displayServers(){
	var guilds = bot.guilds.array();
	var servers = [];

	for(var i = 0; i < guilds.length; i++){
		servers.push(guilds[i].name);
	}

	return "Servers:\n" + servers.join("\n") + "\n";
}

function fileExist(path, data){
	if(!(fs.existsSync(path))){
		fs.writeFileSync(path, data);
		console.log("Config file: " + path + " created.");
	}
}

//	Credit: https://stackoverflow.com/questions/1303646/check-whether-variable-is-number-or-string-in-javascript#1303650
function isNumber(obj) {
	return !isNaN(parseFloat(obj))
}

bot.on('ready', () => {
	console.log("AkeBot v" + botVersion);
	console.log(displayServers());

	setGame(defaultStatus);
});

bot.on('disconnect', event =>{
	console.log("Exited with code: " + event.code);
	if(event.message)
		console.log("Message: " + event.message);
	process.exit(0);
});

bot.on('guildMemberAdd', guildMember =>{
	var generalChannel = getChannelByName(guildMember.guild, 'general');

	generalChannel.sendMessage(guildMember.user.username +" Welcome to " + guildMember.guild.name);
	botLog(guildMember.guild.name + " welcomes " + guildMember.user.username + " to their server.");
});

bot.on('presenceUpdate', (oldGuildMember, newGuildMember) =>{
	if(newGuildMember.presence.game !== null){
		var defaultChannel = "general";
		var textChannel = getChannelByName(newGuildMember.guild, defaultChannel);

		if(!(notifyChannel.hasOwnProperty(newGuildMember.guild.id))){
			notifyChannel[newGuildMember.guild.id] = {
				channel: defaultChannel,
				notify: true
			}
		}

		textChannel = getChannelByName(newGuildMember.guild, notifyChannel[newGuildMember.guild.id].channel);
		if(textChannel === null){
			textChannel = getChannelByName(newGuildMember.guild, defaultChannel);
		}

		if(newGuildMember.presence.game.streaming){
			if(notifyChannel[newGuildMember.guild.id].notify){
				textChannel.sendMessage("**LIVE**\n" +
				newGuildMember.user.username + " is now streaming!\n**Title:** " + newGuildMember.presence.game.name +
				"\n**URL:** " + newGuildMember.presence.game.url);
			}
		}
	}
});

bot.on('message', message => {
	const mContent = message.content;
	const mChannel = message.channel;
	const mGuild = message.guild;
	const mMember = message.member;

	// Admin commands

	if(isCommand(mContent, 'exit') && isAdmin(message)){
		bot.destroy();
	}

	if(isCommand(mContent, 'setgame') && isAdmin(message)){
		if(mContent.indexOf('') !== -1){
			var game = mContent.slice(mContent.indexOf(' ') + 1);
			setGame(game);
			botLog("Game set to: " + game);
		}
	}

	// Sets the preferred channel for live streaming notifications
	if(isCommand(mContent, 'setchannel') && isAdmin(message)){
		var file = './config/notifychannels.json';
		if(mContent.indexOf(' ') !== -1){
			var channel = mContent.split(' ')[1];
			fs.readFile(file, (error, notifyChannel) =>{
				if(error) return sendError("Reading Notify Channels File", error, mChannel);
				try{
					notifyChannel = JSON.parse(notifyChannel);
				}catch(error){
					if(error) return sendError("Parsing Notify Channels File");
				}
				if(getChannelByName(message.guild, channel) !== null){
					if(!(notifyChannel.hasOwnProperty(message.member.guild.id))){
						notifyChannel[message.member.guild.id] = {
							channel: channel,
							notify: true
						}
					} else{
						notifyChannel[message.member.guild.id].channel = channel;
					}

					fs.writeFile(file, JSON.stringify(notifyChannel, null, '\t'), error =>{
						if(error) return sendError("Writing Notify Channels File", error, mChannel);

						mChannel.sendMessage("Channel `" + channel + "` set as default notifications channel");
					});
				}else{
					mChannel.sendMessage("No channel found with that name");
				}
			});
		}
	}

	// Enables or disables streaming notifcations on a server
	if(isCommand(mContent, 'notify') && isAdmin(message)){
		var file = './config/notifychannels.json';
		fs.readFile(file, (error, notifyChannel) =>{
			if(error) return sendError("Reading Notify Channels File", error, mChannel);
			try{
				notifyChannel = JSON.parse(notifyChannel);
			}catch(error){
				if(error) return sendError("Parsing Notify Channels File", error, mChannel);
			}

			if(!(notifyChannel.hasOwnProperty(message.member.guild.id))){
				notifyChannel[message.member.guild.id] = {
					channel: "general",
					notify: true
				}
			} else{
				if(notifyChannel[message.member.guild.id].notify){
					notifyChannel[message.member.guild.id].notify = false;
				} else{
					notifyChannel[message.member.guild.id].notify = true;
				}
			}

			if(notifyChannel[message.member.guild.id].notify){
				mChannel.sendMessage("Notifications for this server set to `true`");
			} else{
				mChannel.sendMessage("Notifications for this server set to `false`");
			}

			fs.writeFile(file, JSON.stringify(notifyChannel, null, '\t'), error =>{
				if(error) return sendError("Reading Stream Black List File", error, mChannel);
			});
		});
	}

	// GENERAL commands

  	if(isCommand(mContent, 'help')){
  		message.channel.sendMessage("**Help**\nIn progress!");
  	}

  	if(isCommand(mContent, 'about')){
  		var content = "**About**\n" + "**Bot Version:** Akephalos Bot v" + botVersion +
  			"\n**Bot Username:** " + bot.user.username +
  			"\n**Servers Connected:** `" + bot.guilds.array().length + "`" +
  			"\n**Author:** Mesmaroth" +
  			"\n**Library:** Discord.js" +
  			"\n**Source:** <https://github.com/Mesmaroth/discord-AkephalosBot>"

  		message.channel.sendFile( bot.user.displayAvatarURL, 'botAvatar.jpg', content);
  	}

  	if(isCommand(message.content, 'source')){
  		message.channel.sendMessage("**Source:** https://github.com/Mesmaroth/discord-AkephalosBot");
  	}

  	if(isCommand(mContent, 'invite')){
  		bot.generateInvite().then( link =>{
  			mChannel.sendMessage("**Invite:** " + link);
  		});
  	}

  	if(isCommand(mContent, 'uptime')){
  		var uptimeSeconds = 0, uptimeMinutes = 0, uptimeHours = 0;

  		uptimeSeconds = Math.floor(bot.uptime/1000);

		if(uptimeSeconds > 60){
			uptimeMinutes = Math.floor(uptimeSeconds/60);
			uptimeSeconds = Math.floor(uptimeSeconds % 60);
		}

		if(uptimeMinutes > 60){
			uptimeHours = Math.floor(uptimeMinutes / 60);
			uptimeMinutes = Math.floor(uptimeMinutes % 60);
		}

  		mChannel.sendMessage("**Uptime:** " + uptimeHours + " hour(s) : " + uptimeMinutes + " minute(s) : " + uptimeSeconds +" second(s)");
  	}

  	if(isCommand(mContent, 'twitch')){
  		if(mContent.indexOf(' ') !== -1){
  			var name = mContent.split(' ')[1];

  			liveStream.getTwitchStream(name, (error, status, gameTitle, streamURL)=> {
  				if(error) return sendError("Getting Twitch Stream Data", error, mChannel);
  				if(status){
  					mChannel.sendMessage(
  					"**Twitch**\n**Name:** " + name +
  					"\n**Status:** `Online`\n**Game:** " + gameTitle +
  					"\n**URL:** " + streamURL);
  				} else{
  					mChannel.sendMessage(
  						"**Twitch**\n**Name:** " + name +
  						"\n**Status:** `Offline`");
  				}
  			});
  		}
  	}

  	if(isCommand(mContent, 'hitbox')){
  		if(mContent.indexOf(' ')!== -1){
  			var name = mContent.split(' ')[1];

  			liveStream.getHitboxStream(name, (error, status, gameTitle, streamURL) =>{
  				if(error) return sendError("Getting HitBox Stream Data", error, mChannel);
  				if(status){
  					mChannel.sendMessage(
  					"**HitBox**\n**Name:**" + name +
  					"\n**Status:** `Online`\n**Game:** " + gameTitle +
  					"\n**URL:** " + streamURL);
  				} else{
  					mChannel.sendMessage(
  					"**HitBox**\n**Name:**" + name +
  					"\n**Status:** `Offline`");
  				}
  			});
  		}
  	}

  	// 102910652447752192
	fs.readFile('./config/botCommands.json', (error, commands) =>{
		if(error) return sendError("Reading Bot Commands Config File", error, mChannel);

		try{
			commands = JSON.parse(commands);
		}catch(error){
			if(error) return sendError("Parsing Bot Commands Config File", error, mChannel);
		}

		if(commands.hasOwnProperty('GLOBAL')){
			var globalCommands = commands['GLOBAL'];
			for(var i = 0; i < globalCommands.length; i++){
				if(mContent.toLowerCase() === globalCommands[i].command){
					if(globalCommands[i].type === 'text'){
						mChannel.sendMessage(globalCommands[i].message);
					}else if(globalCommands[i].type === 'image'){
						if(!fs.existsSync(serverCommands[i].file)){
							return sendError("Reading Custom Commands File", {name: "No file found: " + serverCommands[i].file, message: "File not found."}, mChannel);
						}
						if(globalCommands[i].hasOwnProperty('message')){
							mChannel.sendFile(globalCommands[i].file, globalCommands[i].filename, globalCommands[i].message);
						}else{
							mChannel.sendFile(globalCommands[i].file, globalCommands[i].filename);
						}
					}
					return;
				}
			}
		}

		if(commands.hasOwnProperty(mGuild.id)){
			var serverCommands = commands[mGuild.id];
			for(var i = 0; i < serverCommands.length; i++){
				if(mContent.toLowerCase() === serverCommands[i].command){
					if(serverCommands[i].type === 'text'){
						mChannel.sendMessage(serverCommands[i].message);
					}else if(serverCommands[i].type === 'image'){
						if(!fs.existsSync(serverCommands[i].file)){
							return sendError("Reading Custom Commands File", {name: "No file found: " + serverCommands[i].file, message: "File not found"}, mChannel);
						}
						if(serverCommands[i].hasOwnProperty('message')){
							mChannel.sendFile(serverCommands[i].file, serverCommands[i].filename, serverCommands[i].message);
						}else{
							mChannel.sendFile(serverCommands[i].file, serverCommands[i].filename);
						}
					}
					return;
				}
			}
		}
	});

});<|endoftext|>


<commit_before>const express = require('express');
const basicAuth = require('basic-auth');
const models = require('../models');
const Errors = require('../lib/errors');

const Ticket = models.Ticket;
const Service = models.Service;
const router = express.Router({ mergeParams: true });

/**
 * @api {get} /tickets Get all tickets
 * @apiName GetTickets
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiSuccess  {Object[]}  tickets
 * @apiSuccess  {String}    tickets.service
 * @apiSuccess  {Date}      tickets.created
 * @apiSuccess  {Date}      tickets.updated
 * @apiSuccess  {Date}      tickets.completed
 * @apiSuccess  {Object}    tickets.details
 * @apiSuccess  {Object[]}  tickets.comments
 * @apiSuccess  {String}    tickets.comments.author
 * @apiSuccess  {String}    tickets.comments.body
 * @apiSuccess  {Date}      tickets.comments.created
 * @apiSuccess  {Date}      tickets.comments.updated
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    const options = {};
    if (req.body.service_id) {
      options.service = req.body.service_id;
    }

    Ticket.find(options)
      .then((tickets) => {
        res.body = tickets;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /tickets/:ticketId Get specific ticket
 * @apiName GetTicketById
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam    {String}    ticketId
 *
 * @apiSuccess  {String}    service
 * @apiSuccess  {Date}      created
 * @apiSuccess  {Date}      updated
 * @apiSuccess  {Date}      completed
 * @apiSuccess  {Object}    details
 * @apiSuccess  {Object[]}  comments
 * @apiSuccess  {String}    comments.author
 * @apiSuccess  {String}    comments.body
 * @apiSuccess  {Date}      comments.created
 * @apiSuccess  {Date}      comments.updated
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        res.body = ticket;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets Create a ticket
 * @apiName PostTickets
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 * @apiDescription Registered services will post errors information to this resource. All
 * parameters passed into the request body will be recorded.
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission service
 */
router.post('/', (req, res, next) => {
  const credentials = basicAuth(req);
  if (!credentials || !credentials.name || !credentials.pass) {
    next(new Errors.Unauthorized());
  } else {
    Service.findById(credentials.name)
      .then(service => service.authorize(credentials.pass))
      .then(() => {
        const currentTime = new Date();
        const ticket = new Ticket({
          created: currentTime,
          updated: currentTime,
          service: credentials.name,
          details: req.body,
        });
        return ticket.save();
      })
      .then((ticket) => {
        res.body = ticket;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets/:ticketId Close a ticket
 * @apiName PostTicketsId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        ticket.completed = new Date();
        return ticket.save();
      })
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

/**
 * @api {delete} /tickets/:ticketId Delete a ticket
 * @apiName DeleteTicketsId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.delete('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then(ticket => ticket.remove())
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /tickets/:ticketId/comments Get all ticket comments
 * @apiName GetTicketsIdComment
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiSuccess  {Object[]}
 * @apiSuccess  {String}  _id     Comment ID
 * @apiSuccess  {String}  body    Comment contents
 * @apiSuccess  {Date}    created Creation time
 * @apiSuccess  {Date}    updated Update time
 * @apiSuccess  {String}  author  Comment's author
 *
 * @apiUse UnauthorizedError
 */
router.get('/:ticketId/comments', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .populate(['comments.author'])
      .then((ticket) => {
        res.body = ticket.comments;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets/:ticketId/comments Comment on a ticket
 * @apiName PostTicketsIdComment
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  message Message contents for comment
 *
 * @apiSuccess  {String}  _id     Comment ID
 * @apiSuccess  {String}  body    Comment contents
 * @apiSuccess  {Date}    created Creation time
 * @apiSuccess  {Date}    updated Update time
 * @apiSuccess  {String}  author  Comment's author
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/:ticketId/comments', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else if (!req.body.message) {
    next(new Errors.Generic('Message required', 400));
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        const comment = {
          author: req.session.user._id,
          body: req.body.message,
        };
        ticket.comments.push(comment);
        return ticket.save()
          .then(() => Promise.resolve(ticket.comments.pop()));
      })
      .then((comment) => {
        res.body = comment;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {put} /tickets/:ticketId/comments/:commentId Update a ticket comment
 * @apiName PutTicketsIdCommentId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */

/**
 * @api {delete} /tickets/:ticketId/comments/:commentId Delete a ticket comment
 * @apiName DeleteTicketsIdCommentId
 * @apiGroup Ticket
 * @apiVersion 0.1.0
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */

module.exports = router;

<commit_msg>implemented edit comment<commit_after>const express = require('express');
const basicAuth = require('basic-auth');
const models = require('../models');
const Errors = require('../lib/errors');

const Ticket = models.Ticket;
const Service = models.Service;
const router = express.Router({ mergeParams: true });

/**
 * @api {get} /tickets Get all tickets
 * @apiName GetTickets
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiSuccess  {Object[]}  tickets
 * @apiSuccess  {String}    tickets.service
 * @apiSuccess  {Date}      tickets.created
 * @apiSuccess  {Date}      tickets.updated
 * @apiSuccess  {Date}      tickets.completed
 * @apiSuccess  {Object}    tickets.details
 * @apiSuccess  {Object[]}  tickets.comments
 * @apiSuccess  {String}    tickets.comments.author
 * @apiSuccess  {String}    tickets.comments.body
 * @apiSuccess  {Date}      tickets.comments.created
 * @apiSuccess  {Date}      tickets.comments.updated
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    const options = {};
    if (req.body.service_id) {
      options.service = req.body.service_id;
    }

    Ticket.find(options)
      .then((tickets) => {
        res.body = tickets;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /tickets/:ticketId Get specific ticket
 * @apiName GetTicketById
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam    {String}    ticketId
 *
 * @apiSuccess  {String}    service
 * @apiSuccess  {Date}      created
 * @apiSuccess  {Date}      updated
 * @apiSuccess  {Date}      completed
 * @apiSuccess  {Object}    details
 * @apiSuccess  {Object[]}  comments
 * @apiSuccess  {String}    comments.author
 * @apiSuccess  {String}    comments.body
 * @apiSuccess  {Date}      comments.created
 * @apiSuccess  {Date}      comments.updated
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        res.body = ticket;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets Create a ticket
 * @apiName PostTickets
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 * @apiDescription Registered services will post errors information to this resource. All
 * parameters passed into the request body will be recorded.
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission service
 */
router.post('/', (req, res, next) => {
  const credentials = basicAuth(req);
  if (!credentials || !credentials.name || !credentials.pass) {
    next(new Errors.Unauthorized());
  } else {
    Service.findById(credentials.name)
      .then(service => service.authorize(credentials.pass))
      .then(() => {
        const currentTime = new Date();
        const ticket = new Ticket({
          created: currentTime,
          updated: currentTime,
          service: credentials.name,
          details: req.body,
        });
        return ticket.save();
      })
      .then((ticket) => {
        res.body = ticket;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets/:ticketId Close a ticket
 * @apiName PostTicketsId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        ticket.completed = new Date();
        return ticket.save();
      })
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

/**
 * @api {delete} /tickets/:ticketId Delete a ticket
 * @apiName DeleteTicketsId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.delete('/:ticketId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then(ticket => ticket.remove())
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /tickets/:ticketId/comments Get all ticket comments
 * @apiName GetTicketsIdComment
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId
 *
 * @apiSuccess  {Object[]}
 * @apiSuccess  {String}  _id     Comment ID
 * @apiSuccess  {String}  body    Comment contents
 * @apiSuccess  {Date}    created Creation time
 * @apiSuccess  {Date}    updated Update time
 * @apiSuccess  {String}  author  Comment's author
 *
 * @apiUse UnauthorizedError
 */
router.get('/:ticketId/comments', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .populate(['comments.author'])
      .then((ticket) => {
        res.body = ticket.comments;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /tickets/:ticketId/comments Comment on a ticket
 * @apiName PostTicketsIdComment
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId  ID of the ticket
 * @apiParam  {String}  message   Message contents for comment
 *
 * @apiSuccess  {String}  _id     Comment ID
 * @apiSuccess  {String}  body    Comment contents
 * @apiSuccess  {Date}    created Creation time
 * @apiSuccess  {Date}    updated Update time
 * @apiSuccess  {String}  author  Comment's author
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/:ticketId/comments', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else if (!req.body.message) {
    next(new Errors.Generic('Message required', 400));
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        const comment = {
          author: req.session.user._id,
          body: req.body.message,
        };
        ticket.comments.push(comment);
        return ticket.save()
          .then(() => Promise.resolve(ticket.comments.pop()));
      })
      .then((comment) => {
        res.body = comment;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {put} /tickets/:ticketId/comments/:commentId Update a ticket comment
 * @apiName PutTicketsIdCommentId
 * @apiGroup Tickets
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  ticketId  ID of the ticket
 * @apiParam  {String}  commentId ID of the comment
 * @apiParam  {String}  message   Message contents for comment
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.put('/:ticketId/comments/:commentId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Ticket.findById(req.params.ticketId)
      .then((ticket) => {
        const comment = ticket.comments.id(req.params.commentId);
        if (!comment || comment.author.toString() !== req.session.user._id) {
          return Promise.reject(new Errors.Unauthorized());
        }
        comment.body = req.body.message;
        return comment.save();
      })
      .then((comment) => {
        res.body = comment;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {delete} /tickets/:ticketId/comments/:commentId Delete a ticket comment
 * @apiName DeleteTicketsIdCommentId
 * @apiGroup Ticket
 * @apiVersion 0.1.0
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */

module.exports = router;

<|endoftext|>


<commit_before>(function (name, context, definition) {
  if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
    module.exports = definition();
  } else if (typeof define === 'function' && typeof define.amd  === 'object') {
    define(function () {
      return definition();
    });
  } else {
    var old = context[name];
    context[name] = definition();
    context[name].noConflict = function(){
      context[name] = old;
      return this;
    };
  }
})('anchor', this, function () {

  function emptyFn(ctx, cb){
    if(typeof cb === 'function')
      cb();
    return true;
  }

  //type checking for params parser
  var types = {

  };
  //params parsing middleware
  function paramsParser(){
    var args = Array.prototype.slice.call(arguments);
    var spec = [];
    var min = 0, max = args.length;
    var i, l;
    for(i = 0, l = args.length; i<l; i++){
      var obj = {};
      var str = args[i];
      var required = str.slice(-1) !== '?';
      obj.required = required;

      if(required)
        min++;
      else
        str = str.slice(0,-1);

      var arg = str.split(':');
      obj.name = arg[0];
      if(arg.length > 1){
        //defined type
        var check = types[arg[1]];
        if(typeof check !== 'function')
          throw new Error('type not exist');
        obj.check = check;
      }else
        obj.check = emptyFn;
      spec.push(obj);
    }
    return function(ctx, next){
      var i, l;
      var args = ctx.args;
      var len = args.length;
      var params = {};
      if(args.length < min)
        return next(new Error('Missing parameters.'));
      var index = 0;
      var offset = 0;
      while(offset < len && index < max){
        while(
          !spec[index].check(args[offset]) &&
          !spec[index].required
        ){
          index++;
          if(args[offset] === null || args[offset] === undefined)
            offset++;
          if(index >= max || offset >= len)
            return next(new Error('Missing parameters.'));
        }
        if( !spec[index].check(args[offset]) )
          return next(new Error('Missing parameters.'));
        params[spec[index].name] = args[offset];
        index++;
        offset++;
      }
      ctx.params = params;
      next();
    };
  }

  //Context constructor
  function Context(){
    this._events = {};
  }
  Context.prototype.on = function (type, fn){
    this._events[type] = this._events[type] || [];

    if(typeof type !== 'string')
      throw new Error('event type is not defined');
    if(typeof fn !== 'function')
      throw new Error('invalid function');

    this._events[type].push(fn);
    return this;
  };
  Context.prototype.emit = function (type, args){
    if(this._events[type]){
      var stack = this._events[type];
      for(var i = 0, l = stack.length; i<l; i++)
        stack[i].apply(this, args);
    }
    return this;
  };

  //Anchor constructor
  function Anchor(scope){
    if(!(this instanceof Anchor))
      return new Anchor(scope);

    scope = scope || {};

    this._scope = scope;
    this._methods = {};
    this._middleware = [];

    var self = this;

    this._scope.use = function(){
      var args = Array.prototype.slice.call(arguments);
      //this refers to scope instance
      //self refers to anchor instance

      var name = null, i, l;

      //method name array
      if(Array.isArray(args[0])){
        name = args.shift();
        for(i = 0, l = name.length; i<l; i++)
          this.use.apply(this, [name[i]].concat(args));
        return this;
      }

      //single method name
      if(typeof args[0] === 'string')
        name = args.shift();

      //no method name, iterate all methods
      if(!name){
        for(name in self._methods)
          this.use.apply(this, [name].concat(args));
        return this;
      }

      //scope var init
      if(!this._middleware)
        this._middleware = {};

      if(!this._middleware[name])
        this._middleware[name] = [];

      for(i = 0, l = args.length; i<l; i++){
        if(typeof args[i] === 'function')
          this._middleware[name].push(args[i]);
        else
          throw new Error('invalid function');
      }

      return this;
    };
  }

  Anchor.prototype.use = function(){
    var args = Array.prototype.slice.call(arguments);
    var name = null, i, l;

    if(Array.isArray(args[0])) {
      name = args.shift();
      for(i = 0, l = name.length; i<l; i++)
        this.use.apply(this, [name[i]].concat(args));
      return this;
    }

    if(typeof args[0] === 'string')
      name = args.shift();

    for(i = 0, l = args.length; i<l; i++){
      if(typeof args[i] === 'function')
        this._middleware.push({
          name: name,
          fn: args[i]
        });
      else
        throw new Error('invalid function');
    }
    return this;
  };

  Anchor.prototype.define = function(){
    var args = Array.prototype.slice.call(arguments);
    var i, l;

    var name = args[0];
    if(Array.isArray(name)) {
      name = args.shift();
      for(i = 0, l = name.length; i<l; i++)
        this.define.apply(this, [name[i]].concat(args));
      return this;
    }

    if(typeof name !== 'string')
      throw new Error('method name is not defined');

    var invoke = args.pop();
    if (typeof invoke !== 'function')
      invoke = emptyFn;

    this.use.apply(this, args);

    //filter local middleware
    var middleware = [];
    for(i = 0, l = this._middleware.length; i<l; i++){
      var _name = this._middleware[i].name;
      if(!_name || _name === name)
        middleware.push(this._middleware[i].fn);
    }

    //define method
    this._methods[name] = {};

    //pipe with local middleware
    var _pipe = [].concat(
      middleware,
      invoke
    );
    //define scope method
    this._scope[name] = function(){
      var args = Array.prototype.slice.call(arguments);

      //this refers to scope instance, not anchor instance
      var self = this;

      var callback = emptyFn;
      if (typeof args[args.length - 1] === 'function')
        callback = args.pop();

      var pipe = _pipe;
      //pipe scope middleware if exists
      if(this._middleware && this._middleware[name])
        pipe = [].concat(
          middleware,
          this._middleware[name],
          invoke
        );

      //context object and next triggerer
      var ctx = new Context();
      ctx.method = name;
      ctx.scope = this;
      ctx.args = args;

      var index = 0;
      function next(){
        //trigger callback if args exist
        if(arguments.length > 0){
          var args = Array.prototype.slice.call(arguments);
          callback.apply(self, args);
          ctx.emit('end', args);
          return;
        }
        index++;
        if(pipe[index]){
          //trigger next
          pipe[index].call(self, ctx, next);
          ctx.emit('next');
        }else{
          //trigger empty callback if no more pipe
          callback.apply(self);
          ctx.emit('end');
        }
      }
      pipe[index].call(self, ctx, next);

      return this;
    };
    return this;
  };

  Anchor.prototype.scope = function(){
    return this._scope;
  };
  Anchor.params = paramsParser;

  return Anchor;
});
<commit_msg>Preparing<commit_after>(function (name, context, definition) {
  if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
    module.exports = definition();
  } else if (typeof define === 'function' && typeof define.amd  === 'object') {
    define(function () {
      return definition();
    });
  } else {
    var old = context[name];
    context[name] = definition();
    context[name].noConflict = function(){
      context[name] = old;
      return this;
    };
  }
})('anchor', this, function () {

  function emptyFn(ctx, cb){
    if(typeof cb === 'function')
      cb();
    return true;
  }

  //type checking for params parser
  var types = {

  };
  //params parsing middleware
  function paramsParser(){
    var args = Array.prototype.slice.call(arguments);
    var spec = [];
    var specLen = args.length;
    var i, l;
    for(i = 0; i<specLen; i++){
      var obj = {};
      var str = args[i];

      obj.required = str.slice(-1) !== '?' || str.slice(-1) === '+';
      obj.list = str.slice(-1) === '+' || str.slice(-1) === '*';

      if(obj.required)
        min++;
      else
        str = str.slice(0,-1);

      var arg = str.split(':');
      obj.name = arg[0];
      if(arg.length > 1){
        //defined type
        var check = types[arg[1]];
        if(typeof check !== 'function')
          throw new Error('type not exist');
        obj.check = check;
      }else
        obj.check = emptyFn;
      spec.push(obj);
    }
    return function(ctx, next){
      var i, l;
      var args = ctx.args;
      var len = args.length;
      var params = {};
      var index = 0;
      var offset = 0;
      var acc = [];
      while(offset < len && index < specLen){
        while(
          !spec[index].check(args[offset]) &&
          !spec[index].required
        ){
          index++;
          if(args[offset] === null || args[offset] === undefined)
            offset++;
          if(index >= specLen || offset >= len)
            return next(new Error('Missing parameters.'));
        }
        if( !spec[index].check(args[offset]) )
          return next(new Error('Missing parameters.'));

        params[spec[index].name] = args[offset];
        index++;
        offset++;
      }
      ctx.params = params;
      next();
    };
  }

  //Context constructor
  function Context(){
    this._events = {};
  }
  Context.prototype.on = function (type, fn){
    this._events[type] = this._events[type] || [];

    if(typeof type !== 'string')
      throw new Error('event type is not defined');
    if(typeof fn !== 'function')
      throw new Error('invalid function');

    this._events[type].push(fn);
    return this;
  };
  Context.prototype.emit = function (type, args){
    if(this._events[type]){
      var stack = this._events[type];
      for(var i = 0, l = stack.length; i<l; i++)
        stack[i].apply(this, args);
    }
    return this;
  };

  //Anchor constructor
  function Anchor(scope){
    if(!(this instanceof Anchor))
      return new Anchor(scope);

    scope = scope || {};

    this._scope = scope;
    this._methods = {};
    this._middleware = [];

    var self = this;

    this._scope.use = function(){
      var args = Array.prototype.slice.call(arguments);
      //this refers to scope instance
      //self refers to anchor instance

      var name = null, i, l;

      //method name array
      if(Array.isArray(args[0])){
        name = args.shift();
        for(i = 0, l = name.length; i<l; i++)
          this.use.apply(this, [name[i]].concat(args));
        return this;
      }

      //single method name
      if(typeof args[0] === 'string')
        name = args.shift();

      //no method name, iterate all methods
      if(!name){
        for(name in self._methods)
          this.use.apply(this, [name].concat(args));
        return this;
      }

      //scope var init
      if(!this._middleware)
        this._middleware = {};

      if(!this._middleware[name])
        this._middleware[name] = [];

      for(i = 0, l = args.length; i<l; i++){
        if(typeof args[i] === 'function')
          this._middleware[name].push(args[i]);
        else
          throw new Error('invalid function');
      }

      return this;
    };
  }

  Anchor.prototype.use = function(){
    var args = Array.prototype.slice.call(arguments);
    var name = null, i, l;

    if(Array.isArray(args[0])) {
      name = args.shift();
      for(i = 0, l = name.length; i<l; i++)
        this.use.apply(this, [name[i]].concat(args));
      return this;
    }

    if(typeof args[0] === 'string')
      name = args.shift();

    for(i = 0, l = args.length; i<l; i++){
      if(typeof args[i] === 'function')
        this._middleware.push({
          name: name,
          fn: args[i]
        });
      else
        throw new Error('invalid function');
    }
    return this;
  };

  Anchor.prototype.define = function(){
    var args = Array.prototype.slice.call(arguments);
    var i, l;

    var name = args[0];
    if(Array.isArray(name)) {
      name = args.shift();
      for(i = 0, l = name.length; i<l; i++)
        this.define.apply(this, [name[i]].concat(args));
      return this;
    }

    if(typeof name !== 'string')
      throw new Error('method name is not defined');

    var invoke = args.pop();
    if (typeof invoke !== 'function')
      invoke = emptyFn;

    this.use.apply(this, args);

    //filter local middleware
    var middleware = [];
    for(i = 0, l = this._middleware.length; i<l; i++){
      var _name = this._middleware[i].name;
      if(!_name || _name === name)
        middleware.push(this._middleware[i].fn);
    }

    //define method
    this._methods[name] = {};

    //pipe with local middleware
    var _pipe = [].concat(
      middleware,
      invoke
    );
    //define scope method
    this._scope[name] = function(){
      var args = Array.prototype.slice.call(arguments);

      //this refers to scope instance, not anchor instance
      var self = this;

      var callback = emptyFn;
      if (typeof args[args.length - 1] === 'function')
        callback = args.pop();

      var pipe = _pipe;
      //pipe scope middleware if exists
      if(this._middleware && this._middleware[name])
        pipe = [].concat(
          middleware,
          this._middleware[name],
          invoke
        );

      //context object and next triggerer
      var ctx = new Context();
      ctx.method = name;
      ctx.scope = this;
      ctx.args = args;

      var index = 0;
      function next(){
        //trigger callback if args exist
        if(arguments.length > 0){
          var args = Array.prototype.slice.call(arguments);
          callback.apply(self, args);
          ctx.emit('end', args);
          return;
        }
        index++;
        if(pipe[index]){
          //trigger next
          pipe[index].call(self, ctx, next);
          ctx.emit('next');
        }else{
          //trigger empty callback if no more pipe
          callback.apply(self);
          ctx.emit('end');
        }
      }
      pipe[index].call(self, ctx, next);

      return this;
    };
    return this;
  };

  Anchor.prototype.scope = function(){
    return this._scope;
  };
  Anchor.params = paramsParser;

  return Anchor;
});
<|endoftext|>


<commit_before>const _ = require('lodash')

const logger = require('../logger')
const config = require('../config')
const {
  saveMessage,
  createChannel, updateTopic,
  joinChannel, leaveChannel, leaveNetwork,
  updateUsers, updateUser, updateNick,
} = require('../rethink/queries')
const { indexMessage } = require('../elastic/queries')
const { ircClient, ctx, isMe, isPM } = require('./index')
const { matchCommand } = require('../commands')
const userStore = require('../userStore')

const onDebug = async (s) => {
  if (!config.irc.debug) {
    return
  }

  logger.debug(s)
}

const onClose = async (err) => {
  logger.warn('Connection to IRC server was closed!')
}

const onConnecting = async () => {
  logger.info('Connecting to IRC server...')
}

const onReconnecting = async (payload) => {
  const { attempt, max_retries } = payload

  logger.info(`Reconnecting to IRC server (${attempt}/${max_retries})...`)
}

const onRegistered = async () => {
  ctx.connectionTime = new Date()

  logger.info('Connected to IRC server!')

  logger.info(`Joining channels: ${config.irc.channels}`)
  _.forEach(config.irc.channels, channel => {
    ircClient.join(channel)
  })
}

const onJoin = async (payload) => {
  await saveMessage({
    kind: 'join',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: '',
  })

  if (isMe(payload.nick)) {
    logger.verbose(`Joined ${payload.channel}!`)

    await createChannel({ name: payload.channel })
  } else {
    await joinChannel({
      id: [payload.channel, payload.nick],
      channel: payload.channel,
      nick: payload.nick,
    })
  }
}

const onQuit = async (payload) => {
  const now = new Date()

  const oldUsers = await leaveNetwork(payload.nick)
  for (const oldUser of oldUsers) {
    await saveMessage({
      kind: 'quit',
      timestamp: now,
      from: payload.nick,
      to: oldUser.channel,
      text: payload.message,
      isOp: oldUser.isOp,
      isVoiced: oldUser.isVoiced,
    })
  }
}

const onPart = async (payload) => {
  const user = userStore.get([payload.channel, payload.nick])

  await leaveChannel(payload.channel, payload.nick)

  await saveMessage({
    kind: 'part',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: payload.message,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
  })

}

const onKick = async (payload) => {
  const reason = payload.message === payload.kicked ? '' : payload.message

  await leaveChannel(payload.channel, payload.kicked)

  const user = userStore.get([payload.channel, payload.nick])

  await saveMessage({
    kind: 'kick',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: reason,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
    kicked: payload.kicked,
  })
}

const onNick = async (payload) => {
  const now = new Date()

  const newUsers = await updateNick(payload.nick, payload.new_nick)

  _.forEach(newUsers, async newUser => {
    await saveMessage({
      kind: 'nick',
      timestamp: now,
      from: payload.nick,
      to: newUser.channel,
      text: '',
      isOp: newUser.isOp,
      isVoiced: newUser.isVoiced,
      newNick: payload.new_nick,
    })
  })
}

const onUserList = async (payload) => {
  const users = _.map(payload.users, ({ nick, modes }) => ({
    id: [payload.channel, nick],
    isOp: _.includes(modes, 'o'),
    isVoiced: _.includes(modes, 'v'),
    channel: payload.channel,
    nick,
  }))

  await updateUsers(payload.channel, users)
}

const onMode = async (payload) => {
  const now = new Date()

  for (const { mode, param } of payload.modes) {
    const isOp = _.includes(['+o', '-o'], mode)
    const isVoiced = _.includes(['+v', '-v'], mode)

    if (!isOp && !isVoiced) {
      return
    }

    const targetUser = _.assign(
      userStore.get([payload.target, param]),
      { [isOp ? 'isOp' : 'isVoiced']: mode[0] === '+' }
    )

    await updateUser(targetUser)

    const user = userStore.get([payload.target, payload.nick])

    await saveMessage({
      kind: 'mode',
      timestamp: now,
      from: payload.nick,
      to: payload.target,
      text: mode,
      isOp: user ? user.isOp : false,
      isVoiced: user ? user.isVoiced : false,
      param,
    })
  }
}

const onTopic = async (payload) => {
  if (payload.nick) {
    const user = userStore.get([payload.channel, payload.nick])

    await saveMessage({
      kind: 'topic',
      timestamp: new Date(),
      from: payload.nick,
      to: payload.channel,
      text: payload.topic,
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  await updateTopic(payload.channel, payload.topic)
}

const onMessage = async (payload) => {
  const now = new Date()

  let message = {
    kind: 'message',
    timestamp: now,
    from: payload.nick,
    to: payload.target,
    text: payload.message,
  }

  const isPrivate = isPM(message)

  if (!isPrivate) {
    const user = userStore.get([payload.target, payload.nick])

    message = _.assign(message, {
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  message = await saveMessage(message)
  await indexMessage(message)

  const isSilent = _.includes(config.irc.silentChannels, message.to)
  if (isSilent) {
    return
  }

  const command = matchCommand(message)

  if (!command) {
    return
  }

  const responseText = await command()

  if (!responseText) {
    return
  }

  let responseMessage = {
    kind: 'message',
    timestamp: new Date(),
    from: ircClient.user.nick,
    to: isPrivate ? message.from : message.to,
    text: responseText,
  }

  if (!isPrivate) {
    const responseUser = userStore.get([responseMessage.to, responseMessage.from])

    responseMessage = _.assign(responseMessage, {
      isOp: responseUser.isOp,
      isVoiced: responseUser.isVoiced,
    })
  }

  ircClient.say(responseMessage.to, responseMessage.text)

  responseMessage = await saveMessage(responseMessage)
  await indexMessage(responseMessage)
}

const onAction = async (payload) => {
  const user = userStore.get([payload.target, payload.nick])

  await saveMessage({
    kind: 'action',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.target,
    text: payload.message,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
  })
}

const onNotice = async (payload) => {
  const user = userStore.get([payload.target, payload.nick])

  let message = {
    kind: 'notice',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.target,
    text: payload.message,
  }

  if (user) {
    message = _.assign(message, {
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  await saveMessage(message)
}

module.exports = {
  onDebug,
  onClose,
  onConnecting,
  onReconnecting,
  onRegistered,
  onJoin,
  onQuit,
  onPart,
  onKick,
  onNick,
  onUserList,
  onMode,
  onTopic,
  onMessage,
  onAction,
  onNotice,
}
<commit_msg>Actually index action messages and notices<commit_after>const _ = require('lodash')

const logger = require('../logger')
const config = require('../config')
const {
  saveMessage,
  createChannel, updateTopic,
  joinChannel, leaveChannel, leaveNetwork,
  updateUsers, updateUser, updateNick,
} = require('../rethink/queries')
const { indexMessage } = require('../elastic/queries')
const { ircClient, ctx, isMe, isPM } = require('./index')
const { matchCommand } = require('../commands')
const userStore = require('../userStore')

const onDebug = async (s) => {
  if (!config.irc.debug) {
    return
  }

  logger.debug(s)
}

const onClose = async (err) => {
  logger.warn('Connection to IRC server was closed!')
}

const onConnecting = async () => {
  logger.info('Connecting to IRC server...')
}

const onReconnecting = async (payload) => {
  const { attempt, max_retries } = payload

  logger.info(`Reconnecting to IRC server (${attempt}/${max_retries})...`)
}

const onRegistered = async () => {
  ctx.connectionTime = new Date()

  logger.info('Connected to IRC server!')

  logger.info(`Joining channels: ${config.irc.channels}`)
  _.forEach(config.irc.channels, channel => {
    ircClient.join(channel)
  })
}

const onJoin = async (payload) => {
  await saveMessage({
    kind: 'join',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: '',
  })

  if (isMe(payload.nick)) {
    logger.verbose(`Joined ${payload.channel}!`)

    await createChannel({ name: payload.channel })
  } else {
    await joinChannel({
      id: [payload.channel, payload.nick],
      channel: payload.channel,
      nick: payload.nick,
    })
  }
}

const onQuit = async (payload) => {
  const now = new Date()

  const oldUsers = await leaveNetwork(payload.nick)
  for (const oldUser of oldUsers) {
    await saveMessage({
      kind: 'quit',
      timestamp: now,
      from: payload.nick,
      to: oldUser.channel,
      text: payload.message,
      isOp: oldUser.isOp,
      isVoiced: oldUser.isVoiced,
    })
  }
}

const onPart = async (payload) => {
  const user = userStore.get([payload.channel, payload.nick])

  await leaveChannel(payload.channel, payload.nick)

  await saveMessage({
    kind: 'part',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: payload.message,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
  })

}

const onKick = async (payload) => {
  const reason = payload.message === payload.kicked ? '' : payload.message

  await leaveChannel(payload.channel, payload.kicked)

  const user = userStore.get([payload.channel, payload.nick])

  await saveMessage({
    kind: 'kick',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.channel,
    text: reason,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
    kicked: payload.kicked,
  })
}

const onNick = async (payload) => {
  const now = new Date()

  const newUsers = await updateNick(payload.nick, payload.new_nick)

  _.forEach(newUsers, async newUser => {
    await saveMessage({
      kind: 'nick',
      timestamp: now,
      from: payload.nick,
      to: newUser.channel,
      text: '',
      isOp: newUser.isOp,
      isVoiced: newUser.isVoiced,
      newNick: payload.new_nick,
    })
  })
}

const onUserList = async (payload) => {
  const users = _.map(payload.users, ({ nick, modes }) => ({
    id: [payload.channel, nick],
    isOp: _.includes(modes, 'o'),
    isVoiced: _.includes(modes, 'v'),
    channel: payload.channel,
    nick,
  }))

  await updateUsers(payload.channel, users)
}

const onMode = async (payload) => {
  const now = new Date()

  for (const { mode, param } of payload.modes) {
    const isOp = _.includes(['+o', '-o'], mode)
    const isVoiced = _.includes(['+v', '-v'], mode)

    if (!isOp && !isVoiced) {
      return
    }

    const targetUser = _.assign(
      userStore.get([payload.target, param]),
      { [isOp ? 'isOp' : 'isVoiced']: mode[0] === '+' }
    )

    await updateUser(targetUser)

    const user = userStore.get([payload.target, payload.nick])

    await saveMessage({
      kind: 'mode',
      timestamp: now,
      from: payload.nick,
      to: payload.target,
      text: mode,
      isOp: user ? user.isOp : false,
      isVoiced: user ? user.isVoiced : false,
      param,
    })
  }
}

const onTopic = async (payload) => {
  if (payload.nick) {
    const user = userStore.get([payload.channel, payload.nick])

    await saveMessage({
      kind: 'topic',
      timestamp: new Date(),
      from: payload.nick,
      to: payload.channel,
      text: payload.topic,
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  await updateTopic(payload.channel, payload.topic)
}

const onMessage = async (payload) => {
  const now = new Date()

  let message = {
    kind: 'message',
    timestamp: now,
    from: payload.nick,
    to: payload.target,
    text: payload.message,
  }

  const isPrivate = isPM(message)

  if (!isPrivate) {
    const user = userStore.get([payload.target, payload.nick])

    message = _.assign(message, {
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  message = await saveMessage(message)
  await indexMessage(message)

  const isSilent = _.includes(config.irc.silentChannels, message.to)
  if (isSilent) {
    return
  }

  const command = matchCommand(message)

  if (!command) {
    return
  }

  const responseText = await command()

  if (!responseText) {
    return
  }

  let responseMessage = {
    kind: 'message',
    timestamp: new Date(),
    from: ircClient.user.nick,
    to: isPrivate ? message.from : message.to,
    text: responseText,
  }

  if (!isPrivate) {
    const responseUser = userStore.get([responseMessage.to, responseMessage.from])

    responseMessage = _.assign(responseMessage, {
      isOp: responseUser.isOp,
      isVoiced: responseUser.isVoiced,
    })
  }

  ircClient.say(responseMessage.to, responseMessage.text)

  responseMessage = await saveMessage(responseMessage)
  await indexMessage(responseMessage)
}

const onAction = async (payload) => {
  const user = userStore.get([payload.target, payload.nick])

  const message = await saveMessage({
    kind: 'action',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.target,
    text: payload.message,
    isOp: user.isOp,
    isVoiced: user.isVoiced,
  })
  await indexMessage(message)
}

const onNotice = async (payload) => {
  const user = userStore.get([payload.target, payload.nick])

  let message = {
    kind: 'notice',
    timestamp: new Date(),
    from: payload.nick,
    to: payload.target,
    text: payload.message,
  }

  if (user) {
    message = _.assign(message, {
      isOp: user.isOp,
      isVoiced: user.isVoiced,
    })
  }

  message = await saveMessage(message)
  await indexMessage(message)
}

module.exports = {
  onDebug,
  onClose,
  onConnecting,
  onReconnecting,
  onRegistered,
  onJoin,
  onQuit,
  onPart,
  onKick,
  onNick,
  onUserList,
  onMode,
  onTopic,
  onMessage,
  onAction,
  onNotice,
}
<|endoftext|>