<commit_before>/**
 * @fileoverview
This module provides an implementation of "fs-base" as
 * defined by the CommonJS
 * Filesystem/A/0 proposal.
 */

include('io');
include('binary');
require('core/array');

module.shared = true;

export('canonical',
       'changeWorkingDirectory',
       'workingDirectory',
       'exists',
       'isDirectory',
       'isFile',
       'isReadable',
       'isWritable',
       'list',
       'makeDirectory',
       'move',
       'lastModified',
       'openRaw',
       'remove',
       'removeDirectory',
       'size',
       'touch',
       'symbolicLink',
       'hardLink',
       'readLink',
       'isLink',
       'same',
       'sameFilesystem',
       'iterate',
       'Permissions',
       'owner',
       'group',
       'changePermissions',
       'changeOwner',
       'changeGroup',
       'permissions');

var File = java.io.File,
    FileInputStream = java.io.FileInputStream,
    FileOutputStream = java.io.FileOutputStream;

var SEPARATOR = File.separator;

var POSIX;
try {
    POSIX = org.ringojs.wrappers.POSIX.getPOSIX();
} catch (error) {
    print("POSIX not available: " + error.message);
}

function openRaw(path, mode, permissions) {
    // TODO many things missing here
    var file = resolveFile(path);
    mode = mode || {};
    var {read, write, append, create, exclusive, truncate} = mode;
    if (!read && !write && !append) {
        read = true;
    }
    if (read) {
        return new Stream(new FileInputStream(file));
    } else {
        return new Stream(FileOutputStream(file, Boolean(append)));
    }
}

function move(from, to) {
    var source = resolveFile(from);
    var target = resolveFile(to);
    if (!source.renameTo(target)) {
        throw new Error("failed to move file from " + from + " to " + to);
    }
}

function remove(path) {
    var file = resolveFile(path);
    if (!file['delete']()) {
        throw new Error("failed to remove file " + path);
    }
}

function exists(path) {
    var file = resolveFile(path);
    return file.exists();
}

function workingDirectory() {
    return java.lang.System.getProperty('user.dir') + SEPARATOR;
}

function changeWorkingDirectory(path) {
    path = new File(path).getCanonicalPath();
    java.lang.System.setProperty('user.dir', path);
}

function removeDirectory(path) {
    var file = resolveFile(path);
    if (!file['delete']()) {
        throw new Error("failed to remove directory " + path);
    }
}

function list(path) {
    var file = resolveFile(path);
    var list = file.list();
    if (list == null) {
        throw new Error("failed to list directory " + path);
    }
    var result = [];
    for (var i = 0; i < list.length; i++) {
        result[i] = list[i];
    }
    return result;
}

function size(path) {
    var file = resolveFile(path);
    return file.length();
}

function lastModified(path) {
    var file = resolveFile(path);
    return new Date(file.lastModified());
}

function makeDirectory(path) {
    // TODO support permissions, use posix
    var file = resolveFile(path);
    if (!file.isDirectory() && !file.mkdir()) {
        throw new Error("failed to make directory " + path);
    }
}

function isReadable(path) {
    return resolveFile(path).canRead();
}

function isWritable(path) {
    return resolveFile(path).canWrite();
}

function isFile(path) {
    return resolveFile(path).isFile();
}

function isDirectory(path) {
    return resolveFile(path).isDirectory();
}

function isLink(target) {
    var stat = POSIX.lstat(target);
    return stat.isSymlink();
}

function same(pathA, pathB) {
    var stat1 = POSIX.stat(pathA);
    var stat2 = POSIX.stat(pathB);
    return stat1.isIdentical(stat2);
}

function sameFilesystem(pathA, pathB) {
    var stat1 = POSIX.stat(pathA);
    var stat2 = POSIX.stat(pathB);
    return stat1.dev() == stat2.dev();
}

function canonical(path) {
    return resolveFile(path).getCanonicalPath();
}

function touch(path, mtime) {
    mtime = mtime || Date.now();
    return resolveFile(path).setLastModified(mtime);
}

function symbolicLink(source, target) {
    return POSIX.symlink(source, target);
}

function hardLink(source, target) {
    return POSIX.link(source, target);
}

function readLink(path) {
    return POSIX.readlink(path);
}

function iterate(path) {
    var iter = function() {
        for each (var item in list(path)) {
            yield item;
        }
        throw StopIteration;
    }();
    // spec requires iterator(), native iterators/generators only have __iterator__().
    iter.iterator = iter.__iterator__;
    return iter;
}

function Permissions(permissions, constructor) {
    if (!(this instanceof Permissions)) {
        return new Permissions(permissions, constructor);
    }
    this.update(Permissions['default']);
    this.update(permissions);
    this.constructor = constructor;
}

Permissions.prototype.update = function(permissions) {
    var fromNumber = typeof permissions == 'number';
    if (!fromNumber && !(permissions instanceof Object)) {
        return;
    }
    for each (var user in ['owner', 'group', 'other']) {
        this[user] = this[user] || {};
        for each (var perm in ['read', 'write', 'execute']) {
            this[user][perm] = fromNumber ?
                Boolean((permissions <<= 1) & 512) :
                Boolean(permissions[user] && permissions[user][perm]);
        }
    }
};

Permissions.prototype.toNumber = function() {
    var result = 0;
    for each (var user in ['owner', 'group', 'other']) {
        for each (var perm in ['read', 'write', 'execute']) {
            result <<= 1;
            result |= +this[user][perm];
        }
    }
    return result;
};

try {
    // FIXME: no way to get umask without setting it?
    var umask = POSIX.umask(0022);
    if (umask != 0022) {
        POSIX.umask(umask);
    }
    Permissions['default'] = new Permissions(~umask & 0777);
} catch (error) {
    Permissions['default'] = new Permissions(0755);
}

function permissions(path) {
    var stat = POSIX.stat(path);
    return new Permissions(stat.mode() & 0777);
}

function owner(path) {
    try {
        var uid = POSIX.stat(path).uid();
        var owner = POSIX.getpwuid(uid);
        return owner ? owner.pw_name : uid;
    } catch (error) {
        return null;
    }
}

function group(path) {
    try {
        var gid = POSIX.stat(path).gid();
        var group = POSIX.getgrgid(gid);
        return group ? group.gr_name : gid;
    } catch (error) {
        return null;
    }
}

function changePermissions(path, permissions) {
    permissions = new Permissions(permissions);
    var stat = POSIX.stat(path);
    // do not overwrite set-UID bits etc
    var preservedBits = stat.mode() & 07000;
    var newBits = permissions.toNumber();
    POSIX.chmod(path, preservedBits | newBits);
}

// Supports user name string as well as uid int input.
function changeOwner(path, user) {
    return POSIX.chown(path, typeof user === 'string' ?
            POSIX.getpwnam(user).pw_uid : user, -1);
}

// Supports group name string as well as gid int input.
function changeGroup(path, group) {
    return POSIX.chown(path, -1, typeof group === 'string' ?
            POSIX.getgrnam(group).gr_gid : group);
}

var optionsMask = {
    read: 1,
    write: 1,
    append: 1,
    update: 1,
    binary: 1,
    exclusive: 1,
    canonical: 1,
    charset: 1
};

function checkOptions(mode, options) {
    if (!options) {
        options = {};
    } else if (typeof options != 'object') {
        if (typeof options == 'string') {
            // if options is a mode string convert it to options object
            options = applyMode(options);
        } else {
            throw new Error('unsupported options argument');
        }
    } else {
        // run sanity check on user-provided options object
        for (var key in options) {
            if (!(key in optionsMask)) {
                throw new Error("unsupported option: " + key);
            }
            options[key] = key == 'charset' ?
                    String(options[key]) : Boolean(options[key]);
        }
    }
    if (typeof mode == 'string') {
        // apply mode string to options object
        applyMode(mode, options);
    }
    return options;
}

// apply mode string to options object
function applyMode(mode, options) {
    options = options || {};
    for (var i = 0; i < mode.length; i++) {
        switch (mode[i]) {
        case 'r':
            options.read = true;
            break;
        case 'w':
            options.write = true;
            break;
        case 'a':
            options.append = true;
            break;
        case '+':
            options.update = true;
            break;
        case 'b':
            options.binary = true;
            break;
        case 'x':
            options.exclusive = true;
            break;
        case 'c':
            options.canonical = true;
            break;
        default:
            throw new Error("unsupported mode argument: " + options);
        }
    }
    return options;
}

function resolveFile(path) {
    // Fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4117557
    // relative files are not resolved against workingDirectory/user.dir in java,
    // making the file absolute makes sure it is resolved correctly.
    if (path == undefined) {
        throw new Error('undefined path argument');
    }
    var file = file instanceof File ? file : new File(String(path));
    return file.isAbsolute() ? file : file.getAbsoluteFile();
}
<commit_msg>Make sure there is an error message<commit_after>/**
 * @fileoverview
This module provides an implementation of "fs-base" as
 * defined by the CommonJS
 * Filesystem/A/0 proposal.
 */

include('io');
include('binary');
require('core/array');

module.shared = true;

export('canonical',
       'changeWorkingDirectory',
       'workingDirectory',
       'exists',
       'isDirectory',
       'isFile',
       'isReadable',
       'isWritable',
       'list',
       'makeDirectory',
       'move',
       'lastModified',
       'openRaw',
       'remove',
       'removeDirectory',
       'size',
       'touch',
       'symbolicLink',
       'hardLink',
       'readLink',
       'isLink',
       'same',
       'sameFilesystem',
       'iterate',
       'Permissions',
       'owner',
       'group',
       'changePermissions',
       'changeOwner',
       'changeGroup',
       'permissions');

var File = java.io.File,
    FileInputStream = java.io.FileInputStream,
    FileOutputStream = java.io.FileOutputStream;

var SEPARATOR = File.separator;

var POSIX;
try {
    POSIX = org.ringojs.wrappers.POSIX.getPOSIX();
} catch (error) {
    print("POSIX not available: " + (error.message || error));
}

function openRaw(path, mode, permissions) {
    // TODO many things missing here
    var file = resolveFile(path);
    mode = mode || {};
    var {read, write, append, create, exclusive, truncate} = mode;
    if (!read && !write && !append) {
        read = true;
    }
    if (read) {
        return new Stream(new FileInputStream(file));
    } else {
        return new Stream(FileOutputStream(file, Boolean(append)));
    }
}

function move(from, to) {
    var source = resolveFile(from);
    var target = resolveFile(to);
    if (!source.renameTo(target)) {
        throw new Error("failed to move file from " + from + " to " + to);
    }
}

function remove(path) {
    var file = resolveFile(path);
    if (!file['delete']()) {
        throw new Error("failed to remove file " + path);
    }
}

function exists(path) {
    var file = resolveFile(path);
    return file.exists();
}

function workingDirectory() {
    return java.lang.System.getProperty('user.dir') + SEPARATOR;
}

function changeWorkingDirectory(path) {
    path = new File(path).getCanonicalPath();
    java.lang.System.setProperty('user.dir', path);
}

function removeDirectory(path) {
    var file = resolveFile(path);
    if (!file['delete']()) {
        throw new Error("failed to remove directory " + path);
    }
}

function list(path) {
    var file = resolveFile(path);
    var list = file.list();
    if (list == null) {
        throw new Error("failed to list directory " + path);
    }
    var result = [];
    for (var i = 0; i < list.length; i++) {
        result[i] = list[i];
    }
    return result;
}

function size(path) {
    var file = resolveFile(path);
    return file.length();
}

function lastModified(path) {
    var file = resolveFile(path);
    return new Date(file.lastModified());
}

function makeDirectory(path) {
    // TODO support permissions, use posix
    var file = resolveFile(path);
    if (!file.isDirectory() && !file.mkdir()) {
        throw new Error("failed to make directory " + path);
    }
}

function isReadable(path) {
    return resolveFile(path).canRead();
}

function isWritable(path) {
    return resolveFile(path).canWrite();
}

function isFile(path) {
    return resolveFile(path).isFile();
}

function isDirectory(path) {
    return resolveFile(path).isDirectory();
}

function isLink(target) {
    var stat = POSIX.lstat(target);
    return stat.isSymlink();
}

function same(pathA, pathB) {
    var stat1 = POSIX.stat(pathA);
    var stat2 = POSIX.stat(pathB);
    return stat1.isIdentical(stat2);
}

function sameFilesystem(pathA, pathB) {
    var stat1 = POSIX.stat(pathA);
    var stat2 = POSIX.stat(pathB);
    return stat1.dev() == stat2.dev();
}

function canonical(path) {
    return resolveFile(path).getCanonicalPath();
}

function touch(path, mtime) {
    mtime = mtime || Date.now();
    return resolveFile(path).setLastModified(mtime);
}

function symbolicLink(source, target) {
    return POSIX.symlink(source, target);
}

function hardLink(source, target) {
    return POSIX.link(source, target);
}

function readLink(path) {
    return POSIX.readlink(path);
}

function iterate(path) {
    var iter = function() {
        for each (var item in list(path)) {
            yield item;
        }
        throw StopIteration;
    }();
    // spec requires iterator(), native iterators/generators only have __iterator__().
    iter.iterator = iter.__iterator__;
    return iter;
}

function Permissions(permissions, constructor) {
    if (!(this instanceof Permissions)) {
        return new Permissions(permissions, constructor);
    }
    this.update(Permissions['default']);
    this.update(permissions);
    this.constructor = constructor;
}

Permissions.prototype.update = function(permissions) {
    var fromNumber = typeof permissions == 'number';
    if (!fromNumber && !(permissions instanceof Object)) {
        return;
    }
    for each (var user in ['owner', 'group', 'other']) {
        this[user] = this[user] || {};
        for each (var perm in ['read', 'write', 'execute']) {
            this[user][perm] = fromNumber ?
                Boolean((permissions <<= 1) & 512) :
                Boolean(permissions[user] && permissions[user][perm]);
        }
    }
};

Permissions.prototype.toNumber = function() {
    var result = 0;
    for each (var user in ['owner', 'group', 'other']) {
        for each (var perm in ['read', 'write', 'execute']) {
            result <<= 1;
            result |= +this[user][perm];
        }
    }
    return result;
};

try {
    // FIXME: no way to get umask without setting it?
    var umask = POSIX.umask(0022);
    if (umask != 0022) {
        POSIX.umask(umask);
    }
    Permissions['default'] = new Permissions(~umask & 0777);
} catch (error) {
    Permissions['default'] = new Permissions(0755);
}

function permissions(path) {
    var stat = POSIX.stat(path);
    return new Permissions(stat.mode() & 0777);
}

function owner(path) {
    try {
        var uid = POSIX.stat(path).uid();
        var owner = POSIX.getpwuid(uid);
        return owner ? owner.pw_name : uid;
    } catch (error) {
        return null;
    }
}

function group(path) {
    try {
        var gid = POSIX.stat(path).gid();
        var group = POSIX.getgrgid(gid);
        return group ? group.gr_name : gid;
    } catch (error) {
        return null;
    }
}

function changePermissions(path, permissions) {
    permissions = new Permissions(permissions);
    var stat = POSIX.stat(path);
    // do not overwrite set-UID bits etc
    var preservedBits = stat.mode() & 07000;
    var newBits = permissions.toNumber();
    POSIX.chmod(path, preservedBits | newBits);
}

// Supports user name string as well as uid int input.
function changeOwner(path, user) {
    return POSIX.chown(path, typeof user === 'string' ?
            POSIX.getpwnam(user).pw_uid : user, -1);
}

// Supports group name string as well as gid int input.
function changeGroup(path, group) {
    return POSIX.chown(path, -1, typeof group === 'string' ?
            POSIX.getgrnam(group).gr_gid : group);
}

var optionsMask = {
    read: 1,
    write: 1,
    append: 1,
    update: 1,
    binary: 1,
    exclusive: 1,
    canonical: 1,
    charset: 1
};

function checkOptions(mode, options) {
    if (!options) {
        options = {};
    } else if (typeof options != 'object') {
        if (typeof options == 'string') {
            // if options is a mode string convert it to options object
            options = applyMode(options);
        } else {
            throw new Error('unsupported options argument');
        }
    } else {
        // run sanity check on user-provided options object
        for (var key in options) {
            if (!(key in optionsMask)) {
                throw new Error("unsupported option: " + key);
            }
            options[key] = key == 'charset' ?
                    String(options[key]) : Boolean(options[key]);
        }
    }
    if (typeof mode == 'string') {
        // apply mode string to options object
        applyMode(mode, options);
    }
    return options;
}

// apply mode string to options object
function applyMode(mode, options) {
    options = options || {};
    for (var i = 0; i < mode.length; i++) {
        switch (mode[i]) {
        case 'r':
            options.read = true;
            break;
        case 'w':
            options.write = true;
            break;
        case 'a':
            options.append = true;
            break;
        case '+':
            options.update = true;
            break;
        case 'b':
            options.binary = true;
            break;
        case 'x':
            options.exclusive = true;
            break;
        case 'c':
            options.canonical = true;
            break;
        default:
            throw new Error("unsupported mode argument: " + options);
        }
    }
    return options;
}

function resolveFile(path) {
    // Fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4117557
    // relative files are not resolved against workingDirectory/user.dir in java,
    // making the file absolute makes sure it is resolved correctly.
    if (path == undefined) {
        throw new Error('undefined path argument');
    }
    var file = file instanceof File ? file : new File(String(path));
    return file.isAbsolute() ? file : file.getAbsoluteFile();
}
<|endoftext|>


<commit_before>define(['text!./actors-list.html', 'app','moment','filters/trunc','filters/hack','factories/km-utilities','directives/actor' ], function(template, app,moment) {
    'use strict';

    app.directive('actorsList', ['$http','$location','locale',  function($http,$location,locale) {
        return {
            restrict: 'E',
            template: template,
            replace: false,
            require:'actorsList',
            scope: {},

            //=======================================================================
            //
            //=======================================================================
            link: function($scope, $element, $attr,ctrl) {
                  $scope.loadingC=true;
                  $http.get('https://api.cbd.int/api/v2015/countries', { cache:true, params: { f : { code : 1, name : 1 } } }).then(function(res) {

                      res.data.forEach(function(c) {
                          c.code = c.code.toLowerCase();
                          c.name = c.name[locale];
                      });
                      $scope.countries = res.data;
                      $scope.loadingC=false;
                  });

                  if ($attr.hideSearch)
                    $scope.hideSearch = true;
                  else {
                    $scope.hideSearch = false;
                  }

                  $scope.currentPage = 0;

                  if ($attr.partnersOnly)
                      $scope.partnersOnly = true;

                  if ($attr.blgOnly)
                      $scope.blgOnly = true;

                  if ($attr.jlgOnly)
                      $scope.jlgOnly = true;

                  if ($attr.ABTTFOnly)
                      $scope.ABTTFOnly = true;

                  if ($attr.hidePagenation)
                      $scope.hidePagenation = true;

                  if($attr.country)
                    $scope.country=$attr.country;
                  if ($attr.itemsPerPage)
                      $scope.itemsPerPage = $attr.itemsPerPage;

                  if (!$attr.startEmpty || typeof possiblyUndefinedVariable === "undefined"){
                    $scope.startEmpty=false;
                    ctrl.search();

                  }else
                      $scope.startEmpty=true;

      console.log($scope.startEmpty);
            }, //link

            //=======================================================================
            //
            //=======================================================================
            controller: ['$scope','$timeout', function($scope,$timeout) {
              $scope.country ='';
              $scope.search='';
              $timeout(function(){

                $scope.$watch('search', function(newValue, oldValue) {
                  if(newValue!==oldValue)
                    search();
                });
                $scope.$watch('currentPage', function(newValue, oldValue) {
                    if(newValue!==oldValue)
                      search();
                });
              },1000);

              //=======================================================================
          		//
          		//=======================================================================
              $scope.getNumberPages = function() {

                  if($scope.count && $scope.itemsPerPage && ($scope.count > $scope.itemsPerPage))
                      return new Array(Math.floor($scope.count/$scope.itemsPerPage)+1);
                  else
                      return new Array(1);

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.changePage = function(index) {
                  $scope.prevDate=false;
                  $scope.currentPage=index;

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.isActive = function(index) {
                  return ($scope.currentPage===(index));

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.getCountryFlag = function(code) {
                  return 'https://www.cbd.int/images/flags/48/flag-'+code+'-48.png';

              };

              //=======================================================================
          		//
          		//=======================================================================
          		$scope.goTo= function (url,code){
                if(code)
          			   $location.url(url+code);
                else
                  $location.url(url);
          		};

              //=======================================================================
          		//
          		//=======================================================================
              $scope.sectionTitle = function(date) {

                  return moment(date,moment.ISO_8601).format('MMMM YYYY');
              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.showSection = function(date,index) {
                if(index===0)$scope.prevDate=false;

                  if(!$scope.prevDate || !(moment($scope.prevDate).isSame(date,'year') && moment($scope.prevDate).isSame(date,'month'))){
                    $scope.prevDate=date;
                    return true;
                  }else {
                    $scope.prevDate=date;
                    return false;
                  }
              };

              //=======================================================================
              //
              //=======================================================================
              function search() {

                var q = 'schema_s:undbPartner AND _state_s:public';
                $scope.loading=true;

                if($scope.blgOnly)
                    q= q+' AND description_t:(blgblg*)';

                if($scope.jlgOnly)
                    q= q+' AND description_t:(jlgjlg*)';

                if($scope.ABTTFOnly)
                    q= q+' AND description_t:(ABTTF*)';

                if($scope.partnersOnly)
                  q= q+' AND NOT description_t:(blgblg*) AND NOT description_t:(ABTTF*) AND NOT description_t:(jlgjlg*)';
                if($scope.search)
                    q= q+' AND (title_t:"' + $scope.search + '*" OR description_t:"' + $scope.search + '*")';
                if($scope.country)
                  q= q+' AND country_s:us';//+$scope.country;

                var queryParameters = {
                  'q': q,
                  'wt': 'json',
                  'sort': 'title_s asc',
                  'start': $scope.currentPage * $scope.itemsPerPage,
  								'rows': $scope.itemsPerPage,
                };

                  $http.get('https://api.cbd.int/api/v2013/index/select', {
                    params: queryParameters,
                    cache: true
                  }).success(function(data) {

                    $scope.count = data.response.numFound;
                    $scope.partners = data.response.docs;
                    $scope.loading = false;
                  });
              }
              this.search = search;

          		//=======================================================================
          		//
          		//=======================================================================
          		$scope.clearSearch = function() {
          				$scope.search='';
          				$scope.searchYear='';
          				$scope.searchMonth='';
          				$scope.searchCountry='';
          		};
            }],
        }; // return
    }]); //app.directive('searchFilterCountries

}); // define
<commit_msg>cleaning<commit_after>define(['text!./actors-list.html', 'app','moment','filters/trunc','filters/hack','factories/km-utilities','directives/actor' ], function(template, app,moment) {
    'use strict';

    app.directive('actorsList', ['$http','$location','locale',  function($http,$location,locale) {
        return {
            restrict: 'E',
            template: template,
            replace: false,
            require:'actorsList',
            scope: {},

            //=======================================================================
            //
            //=======================================================================
            link: function($scope, $element, $attr,ctrl) {
                  $scope.loadingC=true;
                  $http.get('https://api.cbd.int/api/v2015/countries', { cache:true, params: { f : { code : 1, name : 1 } } }).then(function(res) {

                      res.data.forEach(function(c) {
                          c.code = c.code.toLowerCase();
                          c.name = c.name[locale];
                      });
                      $scope.countries = res.data;
                      $scope.loadingC=false;
                  });

                  if ($attr.hideSearch)
                    $scope.hideSearch = true;
                  else {
                    $scope.hideSearch = false;
                  }

                  $scope.currentPage = 0;

                  if ($attr.partnersOnly)
                      $scope.partnersOnly = true;

                  if ($attr.blgOnly)
                      $scope.blgOnly = true;

                  if ($attr.jlgOnly)
                      $scope.jlgOnly = true;

                  if ($attr.ABTTFOnly)
                      $scope.ABTTFOnly = true;

                  if ($attr.hidePagenation)
                      $scope.hidePagenation = true;

                  if($attr.country)
                    $scope.country=$attr.country;
                  if ($attr.itemsPerPage)
                      $scope.itemsPerPage = $attr.itemsPerPage;

                  if (!$attr.startEmpty || typeof possiblyUndefinedVariable === "undefined"){
                    $scope.startEmpty=false;
                    ctrl.search();

                  }else
                      $scope.startEmpty=true;

            }, //link

            //=======================================================================
            //
            //=======================================================================
            controller: ['$scope','$timeout', function($scope,$timeout) {
              $scope.country ='';
              $scope.search='';
              $timeout(function(){

                $scope.$watch('search', function(newValue, oldValue) {
                  if(newValue!==oldValue)
                    search();
                });
                $scope.$watch('currentPage', function(newValue, oldValue) {
                    if(newValue!==oldValue)
                      search();
                });
              },1000);

              //=======================================================================
          		//
          		//=======================================================================
              $scope.getNumberPages = function() {

                  if($scope.count && $scope.itemsPerPage && ($scope.count > $scope.itemsPerPage))
                      return new Array(Math.floor($scope.count/$scope.itemsPerPage)+1);
                  else
                      return new Array(1);

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.changePage = function(index) {
                  $scope.prevDate=false;
                  $scope.currentPage=index;

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.isActive = function(index) {
                  return ($scope.currentPage===(index));

              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.getCountryFlag = function(code) {
                  return 'https://www.cbd.int/images/flags/48/flag-'+code+'-48.png';

              };

              //=======================================================================
          		//
          		//=======================================================================
          		$scope.goTo= function (url,code){
                if(code)
          			   $location.url(url+code);
                else
                  $location.url(url);
          		};

              //=======================================================================
          		//
          		//=======================================================================
              $scope.sectionTitle = function(date) {

                  return moment(date,moment.ISO_8601).format('MMMM YYYY');
              };

              //=======================================================================
          		//
          		//=======================================================================
              $scope.showSection = function(date,index) {
                if(index===0)$scope.prevDate=false;

                  if(!$scope.prevDate || !(moment($scope.prevDate).isSame(date,'year') && moment($scope.prevDate).isSame(date,'month'))){
                    $scope.prevDate=date;
                    return true;
                  }else {
                    $scope.prevDate=date;
                    return false;
                  }
              };

              //=======================================================================
              //
              //=======================================================================
              function search() {

                var q = 'schema_s:undbPartner AND _state_s:public';
                $scope.loading=true;

                if($scope.blgOnly)
                    q= q+' AND description_t:(blgblg*)';

                if($scope.jlgOnly)
                    q= q+' AND description_t:(jlgjlg*)';

                if($scope.ABTTFOnly)
                    q= q+' AND description_t:(ABTTF*)';

                if($scope.partnersOnly)
                  q= q+' AND NOT description_t:(blgblg*) AND NOT description_t:(ABTTF*) AND NOT description_t:(jlgjlg*)';
                if($scope.search)
                    q= q+' AND (title_t:"' + $scope.search + '*" OR description_t:"' + $scope.search + '*")';
                if($scope.country)
                  q= q+' AND country_s:us';//+$scope.country;

                var queryParameters = {
                  'q': q,
                  'wt': 'json',
                  'sort': 'title_s asc',
                  'start': $scope.currentPage * $scope.itemsPerPage,
  								'rows': $scope.itemsPerPage,
                };

                  $http.get('https://api.cbd.int/api/v2013/index/select', {
                    params: queryParameters,
                    cache: true
                  }).success(function(data) {

                    $scope.count = data.response.numFound;
                    $scope.partners = data.response.docs;
                    $scope.loading = false;
                  });
              }
              this.search = search;

          		//=======================================================================
          		//
          		//=======================================================================
          		$scope.clearSearch = function() {
          				$scope.search='';
          				$scope.searchYear='';
          				$scope.searchMonth='';
          				$scope.searchCountry='';
          		};
            }],
        }; // return
    }]); //app.directive('searchFilterCountries

}); // define
<|endoftext|>


<commit_before>/**
 * @fileoverview Utility functions related to URIs.
 */

/**
 * Returns the value of a key in a query string.
 */
function getParameterValue(key, opt_uri) {
  var uri = opt_uri || window.location.href;
  key = key.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
  var regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
  var results = regex.exec(uri);
  return results === null ? null : results[1];
}

module.exports = {
  getParameterValue: getParameterValue
};
<commit_msg>Add uri.rewriteParams()<commit_after>/**
 * @fileoverview Utility functions related to URIs.
 */

var objects = require('./objects');

/**
 * Returns the value of a key in a query string.
 */
function getParameterValue(key, opt_uri) {
  var uri = opt_uri || window.location.href;
  key = key.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
  var regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
  var results = regex.exec(uri);
  return results === null ? null : results[1];
}

var RewriteParamsDefaultConfig = {
  selector: 'a.ak-rewrite-params[href]',
  attr: 'href',
  params: null,  // required
};

/**
 * Updates the URL attribute of elements with query params from the current URL.
 * @param {Object} config Config object. Properties are:
 *     selector: CSS query selector of elements to act upon.
 *     attr: The element attribute to update.
 *     params: A list of URL params (string or RegExp) to set on the element
 *         attr from the current URL.
 */
function rewriteParams(config) {
  var c = objects.clone(RewriteParamsDefaultConfig);
  objects.merge(c, config);
  var selector = c.selector;
  var attr = c.attr;
  var params = c.params;
  if (!params) {
    throw '`params` is required';
  }

  var vals = {};
  var currentUrl = new URL(location.href);
  var keysIter = currentUrl.searchParams.keys();
  while (true) {
    var item = keysIter.next();
    if (item.done) {
      break;
    }
    var key = item.value;
    for (var i = 0; i < params.length; i++) {
      // TODO(stevenle): support keys that have multiple values.
      var param = params[i];
      if (param instanceof RegExp) {
        if (key.match(param)) {
          vals[key] = currentUrl.searchParams.get(key);
        }
      } else {
        if (param === key) {
          vals[key] = currentUrl.searchParams.get(key);
        }
      }
    }
  }

  var els = document.querySelectorAll(selector);
  for (var i = 0, el; el = els[i]; i++) {
    var href = el.getAttribute(attr);
    if (href && !href.startsWith('#')) {
      var url = new URL(el.getAttribute(attr), currentUrl);
      for (key in vals) {
        url.searchParams.set(key, vals[key]);
      }
      el.setAttribute(attr, url.toString());
    }
  }
}

module.exports = {
  getParameterValue: getParameterValue,
  rewriteParams: rewriteParams
};
<|endoftext|>


<commit_before>'use strict';
var chokidar = require('chokidar');
const readChunk = require('read-chunk'); // npm install read-chunk
const fileType = require('file-type');
const mv = require('mv');
const path_object = require('path');
const exec = require('child_process').exec;

var fs = require('fs');
var Buffer = require('buffer').Buffer;

var log = console.log.bind(console);

var config = {};
  config['watched_folder'] = '/Users/dsteplight/Downloads';
  config['jpeg_folder'] = '/Users/dsteplight/Documents/JPEG';
  config['pdf_folder'] = '/Users/dsteplight/Documents/PDF';
  config['zip_folder'] = '/Users/dsteplight/ZIP';

for (var key in config)
{
   //make sure there is a path set and skipped over the watch folder
   if ((typeof config[key]) != 'undefined' && key !== 'watched_folder') {
       let path_string = config[key];
      if (!fs.existsSync(path_string)){
          fs.mkdirSync(path_string);
         console.log('A NEW FOLDER HAS BEEN CREATED: '+path_string);
      }
   }
}

var watcher = chokidar.watch(config.watched_folder, {
  ignored: /[\/\\]\./,
  interval: 10000,
  persistent: true,
  depth: 0
});

watcher
  .on('add', function(path) {

      //const buffer = readChunk.sync(path, 0, 262);
      //var path_type = fileType(buffer);

      const allowed_file_types = [".jpg", ".jpeg"];
      const file_name = path_object.basename(path);
      const file_type = path_object.extname(path);

      const target_folder = config.jpeg_folder;
      const targeted_file = target_folder+path_object.sep+file_name;
         if( file_type !== null )
         {
            if( allowed_file_types.indexOf(file_type) !== -1)
            {

               mv(path, targeted_file, function(err) {
                   log('This file has been moved to ', targeted_file);
               });

            }
         }

   })
  .on('addDir', function(path) {

   fs.stat(path, function (err, stats){

     if (err) {
       //this should always exsits since we are only dealing with directories right now
     }

     if (stats.isDirectory()) {
      let directory_name = path_object.basename(path);
      let child = exec("zip -r "+directory_name+".zip "+path,{maxBuffer: 1024 * 500}, function (error, stdout, stderr) {
        if (error !== null) {
          console.log('exec error: ' + error);
        }
         else{
            console.log("THERE SHOULD BE A NEW ZIP FOLDER "+directory_name+".zip");
            let file_name = directory_name+".zip";
            let target_folder = config.zip_folder;
            let targeted_file = target_folder+path_object.sep+file_name;

            //the newly created zip folder will exist in the same folder where this script is running and not in the config.watched_folder path
            mv(file_name, targeted_file, function(err) {
                log('This zippped file has been moved to ', targeted_file);
            });
         }

      });

     }

   });

  })
  .on('change', function(path) {

})
  .on('unlink', function(path) {
  })
  .on('unlinkDir', function(path) {
  })
  .on('error', function(error) {
  })
  .on('ready', function() { log('Initial scan complete. Ready for changes.'); })

<commit_msg>removing folders from config.watched_folder after they are zipped up and MVed<commit_after>'use strict';
var chokidar = require('chokidar');
const readChunk = require('read-chunk'); // npm install read-chunk
const fileType = require('file-type');
const mv = require('mv');
const path_object = require('path');
const exec = require('child_process').exec;
const rmdir = require('rmdir');

var fs = require('fs');
var Buffer = require('buffer').Buffer;

var log = console.log.bind(console);

var config = {};
  config['watched_folder'] = '/Users/dsteplight/Downloads';
  config['jpeg_folder'] = '/Users/dsteplight/Documents/JPEG';
  config['pdf_folder'] = '/Users/dsteplight/Documents/PDF';
  config['zip_folder'] = '/Users/dsteplight/ZIP';

for (var key in config)
{
   //make sure there is a path set and skipped over the watch folder
   if ((typeof config[key]) != 'undefined' && key !== 'watched_folder') {
       let path_string = config[key];
      if (!fs.existsSync(path_string)){
          fs.mkdirSync(path_string);
         console.log('A NEW FOLDER HAS BEEN CREATED: '+path_string);
      }
   }
}

var watcher = chokidar.watch(config.watched_folder, {
  ignored: /[\/\\]\./,
  interval: 10000,
  persistent: true,
  depth: 0
});

watcher
  .on('add', function(path) {

      //const buffer = readChunk.sync(path, 0, 262);
      //var path_type = fileType(buffer);

      const allowed_file_types = [".jpg", ".jpeg"];
      const file_name = path_object.basename(path);
      const file_type = path_object.extname(path);

      const target_folder = config.jpeg_folder;
      const targeted_file = target_folder+path_object.sep+file_name;
         if( file_type !== null )
         {
            if( allowed_file_types.indexOf(file_type) !== -1)
            {

               mv(path, targeted_file, function(err) {
                   log('This file has been moved to ', targeted_file);
               });

            }
         }

   })
  .on('addDir', function(path) {

   fs.stat(path, function (err, stats){

     if (err) {
       //this should always exsits since we are only dealing with directories right now
     }

     if (stats.isDirectory()) {
      let directory_name = path_object.basename(path);
      let child = exec("zip -r "+directory_name+".zip "+path,{maxBuffer: 1024 * 1000}, function (error, stdout, stderr) {
        if (error !== null) {
          console.log('exec error: ' + error);
        }
         else{
            console.log("THERE SHOULD BE A NEW ZIP FOLDER "+directory_name+".zip");
            let file_name = directory_name+".zip";
            let target_folder = config.zip_folder;
            let targeted_file = target_folder+path_object.sep+file_name;

            //the newly created zip folder will exist in the same folder where this script is running and not in the config.watched_folder path
            mv(file_name, targeted_file, function(err) {
                log('This zippped file has been moved to ', targeted_file);
                //now delete the folder from the config.watched_files directory
                rmdir(path, function (err, dirs, files)
                {
                 //console.log(dirs);
                 //console.log(files);
                 console.log('all files are removed from '+ path);
                });

            });
         }

      });

     }

   });

  })
  .on('change', function(path) {

})
  .on('unlink', function(path) {
  })
  .on('unlinkDir', function(path) {
  })
  .on('error', function(error) {
  })
  .on('ready', function() { log('Initial scan complete. Ready for changes.'); })

<|endoftext|>


<commit_before>
const bot = require('./../bot');
const nemoji = require('node-emoji');
const request = require('request-promise-native')
/**
 * This method should return the response directly to the channel
 * @param {*string array} params
 * @param {*message} message
 */
async function command(params, message) {
    if (params[0]) {
        if (/\<\:.+\:\d+\>/.test(params[0])) {
            let url = `https://cdn.discordapp.com/emojis/${params[0].match(/(\d+)/)[1]}.png`;
            message.channel.send('', { file: url });
        } else {
            let em = await request('https://api.github.com/emojis');
            em = JSON.parse(em);
            let url = em[params[0]];
            if (url)
                message.channel.send('', { file: url });
            else
                message.channel.sendMessage('Invalid emoji');
        }
    } else
        message.channel.sendMessage('Not enough arguments!');

}
/**
 * description of the command
 */
const description = "Gets url of the emoji";
/**
 * Define Exports
 */
module.exports = {
    execute: command,
    description: description
};
<commit_msg>Add useragent<commit_after>
const bot = require('./../bot');
const nemoji = require('node-emoji');
const request = require('request-promise-native')
/**
 * This method should return the response directly to the channel
 * @param {*string array} params
 * @param {*message} message
 */
async function command(params, message) {
    if (params[0]) {
        if (/\<\:.+\:\d+\>/.test(params[0])) {
            let url = `https://cdn.discordapp.com/emojis/${params[0].match(/(\d+)/)[1]}.png`;
            message.channel.send('', { file: url });
        } else {
            let em = await request({
                uri: 'https://api.github.com/emojis',
                headers: {
                    'User-Agent': 'Revive-Bot'
                }
            });
            em = JSON.parse(em);
            let url = em[params[0]];
            if (url)
                message.channel.send('', { file: url });
            else
                message.channel.sendMessage('Invalid emoji');
        }
    } else
        message.channel.sendMessage('Not enough arguments!');

}
/**
 * description of the command
 */
const description = "Gets url of the emoji";
/**
 * Define Exports
 */
module.exports = {
    execute: command,
    description: description
};
<|endoftext|>


<commit_before>import assign from 'lodash/assign'
import Bluebird from 'bluebird'
import every from 'lodash/every'
import filter from 'lodash/filter'
import isArray from 'lodash/isArray'
import isPlainObject from 'lodash/isPlainObject'
import map from 'lodash/map'
import mapValues from 'lodash/mapValues'
import size from 'lodash/size'
import some from 'lodash/some'
import { BaseError } from 'make-error'
import { timeout } from 'promise-toolbox'

import { crossProduct } from './math'
import {
  serializeError,
  thunkToArray
} from './utils'

export class JobExecutorError extends BaseError {}
export class UnsupportedJobType extends JobExecutorError {
  constructor (job) {
    super('Unknown job type: ' + job.type)
  }
}
export class UnsupportedVectorType extends JobExecutorError {
  constructor (vector) {
    super('Unknown vector type: ' + vector.type)
  }
}

// ===================================================================

const match = (pattern, value) => {
  if (isPlainObject(pattern)) {
    if (size(pattern) === 1) {
      let op
      if ((op = pattern.__or) !== undefined) {
        return some(op, subpattern => match(subpattern, value))
      }
      if ((op = pattern.__not) !== undefined) {
        return !match(op, value)
      }
    }

    return isPlainObject(value) && every(pattern, (subpattern, key) => (
      value[key] !== undefined && match(subpattern, value[key])
    ))
  }

  if (isArray(pattern)) {
    return isArray(value) && every(pattern, subpattern =>
      some(value, subvalue => match(subpattern, subvalue))
    )
  }

  return pattern === value
}

const paramsVectorActionsMap = {
  extractProperties ({ mapping, value }) {
    return mapValues(mapping, key => value[key])
  },
  crossProduct ({ items }) {
    return thunkToArray(crossProduct(
      map(items, value => resolveParamsVector.call(this, value))
    ))
  },
  fetchObjects ({ pattern }) {
    return filter(this.xo.getObjects(), object => match(pattern, object))
  },
  map ({ collection, iteratee, paramName = 'value' }) {
    return map(resolveParamsVector.call(this, collection), value => {
      return resolveParamsVector.call(this, {
        ...iteratee,
        [paramName]: value
      })
    })
  },
  set: ({ values }) => values
}

export function resolveParamsVector (paramsVector) {
  const visitor = paramsVectorActionsMap[paramsVector.type]
  if (!visitor) {
    throw new Error(`Unsupported function '${paramsVector.type}'.`)
  }

  return visitor.call(this, paramsVector)
}

// ===================================================================

export default class JobExecutor {
  constructor (xo) {
    this.xo = xo
    this._extractValueCb = {
      'set': items => items.values
    }

    // The logger is not available until Xo has started.
    xo.on('start', () => xo.getLogger('jobs').then(logger => {
      this._logger = logger
    }))
  }

  async exec (job) {
    const runJobId = this._logger.notice(`Starting execution of ${job.id}.`, {
      event: 'job.start',
      userId: job.userId,
      jobId: job.id,
      key: job.key
    })

    try {
      if (job.type === 'call') {
        const execStatus = await this._execCall(job, runJobId)

        this.xo.emit('job:terminated', execStatus)
      } else {
        throw new UnsupportedJobType(job)
      }

      this._logger.notice(`Execution terminated for ${job.id}.`, {
        event: 'job.end',
        runJobId
      })
    } catch (error) {
      this._logger.error(`The execution of ${job.id} has failed.`, {
        event: 'job.end',
        runJobId,
        error: serializeError(error)
      })

      throw error
    }
  }

  async _execCall (job, runJobId) {
    const { paramsVector } = job
    const paramsFlatVector = paramsVector
      ? resolveParamsVector.call(this, paramsVector)
      : [{}] // One call with no parameters

    const connection = this.xo.createUserConnection()

    connection.set('user_id', job.userId)

    const execStatus = {
      runJobId,
      start: Date.now(),
      calls: {}
    }

    await Bluebird.map(paramsFlatVector, params => {
      const runCallId = this._logger.notice(`Starting ${job.method} call. (${job.id})`, {
        event: 'jobCall.start',
        runJobId,
        method: job.method,
        params
      })

      const call = execStatus.calls[runCallId] = {
        method: job.method,
        params,
        start: Date.now()
      }
      let promise = this.xo.callApiMethod(connection, job.method, assign({}, params))
      if (job.timeout) {
        promise = promise::timeout(job.timeout)
      }

      return promise.then(
        value => {
          this._logger.notice(`Call ${job.method} (${runCallId}) is a success. (${job.id})`, {
            event: 'jobCall.end',
            runJobId,
            runCallId,
            returnedValue: value
          })

          call.returnedValue = value
          call.end = Date.now()
        },
        reason => {
          this._logger.notice(`Call ${job.method} (${runCallId}) has failed. (${job.id})`, {
            event: 'jobCall.end',
            runJobId,
            runCallId,
            error: serializeError(reason)
          })

          call.error = reason
          call.end = Date.now()
        }
      )
    }, {
      concurrency: 2
    })

    connection.close()
    execStatus.end = Date.now()

    return execStatus
  }
}
<commit_msg>feat(job-executor/execStatus): inject timezone from related schedule (#547)<commit_after>import assign from 'lodash/assign'
import Bluebird from 'bluebird'
import every from 'lodash/every'
import filter from 'lodash/filter'
import find from 'lodash/find'
import isArray from 'lodash/isArray'
import isPlainObject from 'lodash/isPlainObject'
import map from 'lodash/map'
import mapValues from 'lodash/mapValues'
import size from 'lodash/size'
import some from 'lodash/some'
import { BaseError } from 'make-error'
import { timeout } from 'promise-toolbox'

import { crossProduct } from './math'
import {
  serializeError,
  thunkToArray
} from './utils'

export class JobExecutorError extends BaseError {}
export class UnsupportedJobType extends JobExecutorError {
  constructor (job) {
    super('Unknown job type: ' + job.type)
  }
}
export class UnsupportedVectorType extends JobExecutorError {
  constructor (vector) {
    super('Unknown vector type: ' + vector.type)
  }
}

// ===================================================================

const match = (pattern, value) => {
  if (isPlainObject(pattern)) {
    if (size(pattern) === 1) {
      let op
      if ((op = pattern.__or) !== undefined) {
        return some(op, subpattern => match(subpattern, value))
      }
      if ((op = pattern.__not) !== undefined) {
        return !match(op, value)
      }
    }

    return isPlainObject(value) && every(pattern, (subpattern, key) => (
      value[key] !== undefined && match(subpattern, value[key])
    ))
  }

  if (isArray(pattern)) {
    return isArray(value) && every(pattern, subpattern =>
      some(value, subvalue => match(subpattern, subvalue))
    )
  }

  return pattern === value
}

const paramsVectorActionsMap = {
  extractProperties ({ mapping, value }) {
    return mapValues(mapping, key => value[key])
  },
  crossProduct ({ items }) {
    return thunkToArray(crossProduct(
      map(items, value => resolveParamsVector.call(this, value))
    ))
  },
  fetchObjects ({ pattern }) {
    return filter(this.xo.getObjects(), object => match(pattern, object))
  },
  map ({ collection, iteratee, paramName = 'value' }) {
    return map(resolveParamsVector.call(this, collection), value => {
      return resolveParamsVector.call(this, {
        ...iteratee,
        [paramName]: value
      })
    })
  },
  set: ({ values }) => values
}

export function resolveParamsVector (paramsVector) {
  const visitor = paramsVectorActionsMap[paramsVector.type]
  if (!visitor) {
    throw new Error(`Unsupported function '${paramsVector.type}'.`)
  }

  return visitor.call(this, paramsVector)
}

// ===================================================================

export default class JobExecutor {
  constructor (xo) {
    this.xo = xo
    this._extractValueCb = {
      'set': items => items.values
    }

    // The logger is not available until Xo has started.
    xo.on('start', () => xo.getLogger('jobs').then(logger => {
      this._logger = logger
    }))
  }

  async exec (job) {
    const runJobId = this._logger.notice(`Starting execution of ${job.id}.`, {
      event: 'job.start',
      userId: job.userId,
      jobId: job.id,
      key: job.key
    })

    try {
      if (job.type === 'call') {
        const execStatus = await this._execCall(job, runJobId)

        this.xo.emit('job:terminated', execStatus)
      } else {
        throw new UnsupportedJobType(job)
      }

      this._logger.notice(`Execution terminated for ${job.id}.`, {
        event: 'job.end',
        runJobId
      })
    } catch (error) {
      this._logger.error(`The execution of ${job.id} has failed.`, {
        event: 'job.end',
        runJobId,
        error: serializeError(error)
      })

      throw error
    }
  }

  async _execCall (job, runJobId) {
    const { paramsVector } = job
    const paramsFlatVector = paramsVector
      ? resolveParamsVector.call(this, paramsVector)
      : [{}] // One call with no parameters

    const connection = this.xo.createUserConnection()

    connection.set('user_id', job.userId)

    const schedule = find(await this.xo.getAllSchedules(), { job: job.id })

    const execStatus = {
      calls: {},
      runJobId,
      start: Date.now(),
      timezone: schedule !== undefined ? schedule.timezone : undefined
    }

    await Bluebird.map(paramsFlatVector, params => {
      const runCallId = this._logger.notice(`Starting ${job.method} call. (${job.id})`, {
        event: 'jobCall.start',
        runJobId,
        method: job.method,
        params
      })

      const call = execStatus.calls[runCallId] = {
        method: job.method,
        params,
        start: Date.now()
      }
      let promise = this.xo.callApiMethod(connection, job.method, assign({}, params))
      if (job.timeout) {
        promise = promise::timeout(job.timeout)
      }

      return promise.then(
        value => {
          this._logger.notice(`Call ${job.method} (${runCallId}) is a success. (${job.id})`, {
            event: 'jobCall.end',
            runJobId,
            runCallId,
            returnedValue: value
          })

          call.returnedValue = value
          call.end = Date.now()
        },
        reason => {
          this._logger.notice(`Call ${job.method} (${runCallId}) has failed. (${job.id})`, {
            event: 'jobCall.end',
            runJobId,
            runCallId,
            error: serializeError(reason)
          })

          call.error = reason
          call.end = Date.now()
        }
      )
    }, {
      concurrency: 2
    })

    connection.close()
    execStatus.end = Date.now()

    return execStatus
  }
}
<|endoftext|>


<commit_before>const express = require("express");
const router = express();
const { createWebAPIRequest } = require("../util/util");

router.get("/", (req, res) => {
  const cookie = req.get("Cookie") ? req.get("Cookie") : "";
  const user_ids = req.query.user_ids;
  const data = {
    id: req.query.id,
    type: "playlist",
    msg: req.query.msg,
    userIds: user_ids,
    csrf_token: ""
  };
  createWebAPIRequest(
    "music.163.com",
    `/weapi/msg/private/send`,
    "POST",
    data,
    cookie,
    music_req => res.send(music_req),
    err => res.status(502).send("fetch error")
  );
});

module.exports = router;
<commit_msg>Update send_playlist.js<commit_after>const express = require("express");
const router = express();
const { createWebAPIRequest } = require("../util/util");

router.get("/", (req, res) => {
  const cookie = req.get("Cookie") ? req.get("Cookie") : "";
  const user_ids = req.query.user_ids;
  const data = {
    id: req.query.playlist,
    type: "playlist",
    msg: req.query.msg,
    userIds: user_ids,
    csrf_token: ""
  };
  createWebAPIRequest(
    "music.163.com",
    `/weapi/msg/private/send`,
    "POST",
    data,
    cookie,
    music_req => res.send(music_req),
    err => res.status(502).send("fetch error")
  );
});

module.exports = router;
<|endoftext|>


<commit_before>const Message = require('./../../orm/Message');
const m2e = require('./../lib/message2embed');
const bot = require('./../bot');
/**
 * This method should return the response directly to the channel
 * @param {*string array} params
 * @param {*message} message
 */
async function command(params, message) {
    if (params.length < 1)
        return message.reply("incorrect usage\nSyntax: ~qoute <messageID>");
    let m = Message.where('messageID', params[0]).fetch();
    if(m)
    {
        console.log(m);
        const ch = bot.channels.get(m.channel);
        m = ch.fetch(m.messageID);
        ch.sendEmbed(m2e(m));
    }
}
/**
 * description of the command
 */
const description = "qoutes a message via id";
/**
 * Define Exports
 */
module.exports = {
    execute: command,
    description: description
};
<commit_msg>Update qoute.js<commit_after>const Message = require('./../../orm/Message');
const m2e = require('./../lib/message2embed');
const bot = require('./../bot');
/**
 * This method should return the response directly to the channel
 * @param {*string array} params
 * @param {*message} message
 */
async function command(params, message) {
    if (params.length < 1)
        return message.reply("incorrect usage\nSyntax: ~qoute <messageID>");
    let m = await Message.where('messageID', params[0]).fetch();
    if(m)
    {
        console.log(m);
        const ch = bot.channels.get(m.channel);
        m = ch.fetch(m.messageID);
        ch.sendEmbed(m2e(m));
    }
}
/**
 * description of the command
 */
const description = "qoutes a message via id";
/**
 * Define Exports
 */
module.exports = {
    execute: command,
    description: description
};
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
* @author mig <michel.gutierrez@gmail.com>
* @module jquery-jocly
* @overview Board game site integration.
*/

(function($) {

	var iframeIdRef = 1;

	function Applet(jqElm) {
		this.jqElm = jqElm;
		this.ready = false;
		this.queuedMessages = [];
	}
	Applet.prototype.init = function(options) {
		var $this=this;
		this.options = {
			//width : '100%',
			//height : 450,
			mode : "splash",
			maxWidth: 1000,
			ratio: 1,
			baseURL: "http://embed.jocly.net",
			masked: false,
		}
		if (options)
			$.extend(this.options, options);
		var iframeUrl = this.options.baseURL+"/jocly/plazza/embed";
		if(this.options.game)
			iframeUrl+="/"+this.options.game;
		iframeUrl+="?mode=" + this.options.mode;
		this.iframeId = iframeIdRef++;
		this.options.jei = this.iframeId;
		this.listener=function(event) {
			if(event.origin!=$this.options.baseURL || event.data.jei!=$this.iframeId)
				return;
			$this.messageListener(event.data);
		}
		window.addEventListener("message",this.listener,false);
		var iframeName = "jocly-iframe-" + this.iframeId;
		this.iframe = $("<iframe/>").attr("name", iframeName).attr(
				"frameborder", 0).attr("src", "about:blank");
		this.content = this.jqElm.html();
		this.jqElm.empty();

		var canvas=$("<canvas/>").attr("width",this.options.maxWidth).attr("height",this.options.maxWidth*this.options.ratio);
		var image=new Image();
		image.src = canvas[0].toDataURL("image/png");

		this.wrapper=$("<div/>").css({
			position: "relative",
			"white-space": "nowrap",
		}).appendTo(this.jqElm);

		this.wrapper.append($(image).css({
			width: "auto",
			height: "auto",
			"max-width": "100%",
			"max-height": "100%",
			"vertical-align": "bottom",
		}));

		this.container=$("<div/>").css("padding-top",this.options.ratio*100+"%").appendTo(
			$("<div/>").css({
				position: "absolute",
				top: 0,
				bottom: 0,
				left: 0,
				right: 0,
			}).appendTo(this.wrapper)
		);

		this.iframe.attr("width","100%").attr("height","100%").css({
			position: "absolute",
			top: 0,
			right: 0,
			bottom: 0,
			left: 0,
			"white-space": "normal",
		}).appendTo(this.container);

		this.maskElm=$("<div/>").css({
			display: this.options.masked?"block":"none",
			position: "absolute",
			top: 0,
			right: 0,
			width: "100%",
			height: "100%",
			'background-color': 'rgba(0,0,0,.8)',
			"z-index": 1,
		}).appendTo(this.wrapper);

		var initForm = $("<form/>").attr("action", iframeUrl).attr("method",
				"post").attr("target", iframeName);
		$("<input/>").attr("type", "hidden").attr("name", "data").attr("value",
				JSON.stringify(this.options)).appendTo(initForm);
		initForm.appendTo($("body"));
		initForm[0].submit();
		initForm.remove();
	}
	Applet.prototype.remove = function() {
		window.removeEventListener("message",this.listener,false);
		this.jqElm.empty();
		this.jqElm.html(this.content);
		this.jqElm.data("jocly-applet", null);
	}
	Applet.prototype.update = function(options) {
		this.remove();
		this.init(options);
	}
	Applet.prototype.messageListener = function(message) {
		console.log("jocly-applet received message from iframe",message);
		switch(message.type) {
		case 'ready':
			this.ready=true;
			this.queuedMessages.forEach(function(message) {
				this.sendMessage(message);
			},this);
			this.queuedMessages=[];
			break;
		case 'display':
			if(message.initial || message.moves) {
				var crc=$.joclyCRC32(message.initial || '');
				if(message.moves)
					message.moves.forEach(function(move) {
						crc=$.joclyCRC32(move.str,crc);
					});
				$(".jocly-listener").trigger('jocly',{
					type: 'display',
					crc: crc,
				});
			} else
				$(".jocly-listener").trigger('jocly',{
					type: 'undisplay',
				});
			break;
		default:
			$(".jocly-listener").trigger('jocly',message);
		}
	}
	Applet.prototype.sendMessage = function(message) {
		if(this.ready)
			this.iframe[0].contentWindow.postMessage(message,this.options.baseURL);
		else
			this.queuedMessages.push(message);
	}
	Applet.prototype.view = function(gameName,spec) {
		this.sendMessage({
			type: "view",
			gameName: gameName,
			data: spec,
		});
	}
	Applet.prototype.localPlay = function(gameName,spec) {
		this.sendMessage({
			type: "localPlay",
			gameName: gameName,
			data: spec || {},
		});
	}
	Applet.prototype.setFeatures = function(features) {
		this.sendMessage({
			type: "features",
			features: features,
		});
	}
	Applet.prototype.getId = function() {
		return this.iframeId;
	}
	Applet.prototype.emptyBoard = function(gameName) {
		this.sendMessage({
			type: "emptyBoard",
			gameName: gameName,
		});
	}
	Applet.prototype.viewOptions = function(options) {
		this.sendMessage({
			type: "viewOptions",
			options: options,
		});
	}
	Applet.prototype.mask = function(masked) {
		if(masked)
			this.maskElm.show();
		else
			this.maskElm.hide();
	}

	$.fn.jocly = function() {
		var $arguments = arguments;
		var retVal = this;
		this.each(function() {
			var applet = $(this).data("jocly-applet");
			var justCreated=false;
			if (!applet) {
				applet = new Applet($(this));
				justCreated=true;
				var options = $arguments[0] || null;
				var dataAttr = $(this).attr("data-jocly");
				if (dataAttr)
					try {
						options = eval("(" + dataAttr + ")"); // jshint ignore:line
					} catch (e) {
						console
								.error("Jocly applet: invalid data-jocly "
										+ dataAttr);
					}
				applet.init(options);
				$(this).data("jocly-applet", applet);
			}
			if ($arguments.length > 0) {
				var method = $arguments[0];
				if(justCreated && typeof method == "object")
					return;
				if (typeof method != "string")
					throw new Error(
							"Jocly applet: first argument must be a string specifying the method to be called");
				if (typeof applet[method] != "function")
					throw new Error("Jocly applet: no such method '"
							+ method + "'");
				var retVal0 = applet[method].apply(applet, Array.prototype.splice
						.call($arguments, 1));
				if(retVal0 !== undefined)
					console.log("method",method,"returns",retVal0)
			}
		});
		return retVal;
	};

	$(document).ready(function() {

		$("[data-jocly]").each(function() {
			var $this=$(this);
			$this.jocly();
			if(this.hasAttribute("data-jocly-init")) {
				var attr=$this.attr("data-jocly-init");
				if(attr.length===0)
					return;
				try {
					var arr=JSON.parse(attr);
					try {
						if(!Array.isArray(arr)) {
							console.warn("jquery.jocly: data-jocly-init attribute is not an array");
						}
						for(var i=0;i<arr.length;i++) {
							var element=arr[i];
							if(Array.isArray(element))
								$this.jocly.apply($this,element);
							else {
								$this.jocly.apply($this,arr);
								return;
							}
						}
					} catch(e) {
						console.warn("jquery.jocly: data-jocly-init error:",e);
					}
				} catch(e) {
					console.warn("jquery.jocly: data-jocly-init attribute has no JSON valid value");
				}
			}
		});

	});

}(jQuery));

<commit_msg>added camera method<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
* @author mig <michel.gutierrez@gmail.com>
* @module jquery-jocly
* @overview Board game site integration.
*/

(function($) {

	var iframeIdRef = 1;

	function Applet(jqElm) {
		this.jqElm = jqElm;
		this.ready = false;
		this.queuedMessages = [];
	}
	Applet.prototype.init = function(options) {
		var $this=this;
		this.options = {
			//width : '100%',
			//height : 450,
			mode : "splash",
			maxWidth: 1000,
			ratio: 1,
			baseURL: "http://embed.jocly.net",
			masked: false,
		}
		if (options)
			$.extend(this.options, options);
		var iframeUrl = this.options.baseURL+"/jocly/plazza/embed";
		if(this.options.game)
			iframeUrl+="/"+this.options.game;
		iframeUrl+="?mode=" + this.options.mode;
		this.iframeId = iframeIdRef++;
		this.options.jei = this.iframeId;
		this.listener=function(event) {
			if(event.origin!=$this.options.baseURL || event.data.jei!=$this.iframeId)
				return;
			$this.messageListener(event.data);
		}
		window.addEventListener("message",this.listener,false);
		var iframeName = "jocly-iframe-" + this.iframeId;
		this.iframe = $("<iframe/>").attr("name", iframeName).attr(
				"frameborder", 0).attr("src", "about:blank");
		this.content = this.jqElm.html();
		this.jqElm.empty();

		var canvas=$("<canvas/>").attr("width",this.options.maxWidth).attr("height",this.options.maxWidth*this.options.ratio);
		var image=new Image();
		image.src = canvas[0].toDataURL("image/png");

		this.wrapper=$("<div/>").css({
			position: "relative",
			"white-space": "nowrap",
		}).appendTo(this.jqElm);

		this.wrapper.append($(image).css({
			width: "auto",
			height: "auto",
			"max-width": "100%",
			"max-height": "100%",
			"vertical-align": "bottom",
		}));

		this.container=$("<div/>").css("padding-top",this.options.ratio*100+"%").appendTo(
			$("<div/>").css({
				position: "absolute",
				top: 0,
				bottom: 0,
				left: 0,
				right: 0,
			}).appendTo(this.wrapper)
		);

		this.iframe.attr("width","100%").attr("height","100%").css({
			position: "absolute",
			top: 0,
			right: 0,
			bottom: 0,
			left: 0,
			"white-space": "normal",
		}).appendTo(this.container);

		this.maskElm=$("<div/>").css({
			display: this.options.masked?"block":"none",
			position: "absolute",
			top: 0,
			right: 0,
			width: "100%",
			height: "100%",
			'background-color': 'rgba(0,0,0,.8)',
			"z-index": 1,
		}).appendTo(this.wrapper);

		var initForm = $("<form/>").attr("action", iframeUrl).attr("method",
				"post").attr("target", iframeName);
		$("<input/>").attr("type", "hidden").attr("name", "data").attr("value",
				JSON.stringify(this.options)).appendTo(initForm);
		initForm.appendTo($("body"));
		initForm[0].submit();
		initForm.remove();
	}
	Applet.prototype.remove = function() {
		window.removeEventListener("message",this.listener,false);
		this.jqElm.empty();
		this.jqElm.html(this.content);
		this.jqElm.data("jocly-applet", null);
	}
	Applet.prototype.update = function(options) {
		this.remove();
		this.init(options);
	}
	Applet.prototype.messageListener = function(message) {
		console.log("jocly-applet received message from iframe",message);
		switch(message.type) {
		case 'ready':
			this.ready=true;
			this.queuedMessages.forEach(function(message) {
				this.sendMessage(message);
			},this);
			this.queuedMessages=[];
			break;
		case 'display':
			if(message.initial || message.moves) {
				var crc=$.joclyCRC32(message.initial || '');
				if(message.moves)
					message.moves.forEach(function(move) {
						crc=$.joclyCRC32(move.str,crc);
					});
				$(".jocly-listener").trigger('jocly',{
					type: 'display',
					crc: crc,
				});
			} else
				$(".jocly-listener").trigger('jocly',{
					type: 'undisplay',
				});
			break;
		default:
			$(".jocly-listener").trigger('jocly',message);
		}
	}
	Applet.prototype.sendMessage = function(message) {
		if(this.ready)
			this.iframe[0].contentWindow.postMessage(message,this.options.baseURL);
		else
			this.queuedMessages.push(message);
	}
	Applet.prototype.view = function(gameName,spec) {
		this.sendMessage({
			type: "view",
			gameName: gameName,
			data: spec,
		});
	}
	Applet.prototype.localPlay = function(gameName,spec) {
		this.sendMessage({
			type: "localPlay",
			gameName: gameName,
			data: spec || {},
		});
	}
	Applet.prototype.setFeatures = function(features) {
		this.sendMessage({
			type: "features",
			features: features,
		});
	}
	Applet.prototype.getId = function() {
		return this.iframeId;
	}
	Applet.prototype.emptyBoard = function(gameName) {
		this.sendMessage({
			type: "emptyBoard",
			gameName: gameName,
		});
	}
	Applet.prototype.viewOptions = function(options) {
		this.sendMessage({
			type: "viewOptions",
			options: options,
		});
	}
	Applet.prototype.mask = function(masked) {
		if(masked)
			this.maskElm.show();
		else
			this.maskElm.hide();
	}
	Applet.prototype.camera = function(camera,delay) {
		this.sendMessage({
			type: "camera",
			camera: camera,
			delay: delay,
		});
	}

	$.fn.jocly = function() {
		var $arguments = arguments;
		var retVal = this;
		this.each(function() {
			var applet = $(this).data("jocly-applet");
			var justCreated=false;
			if (!applet) {
				applet = new Applet($(this));
				justCreated=true;
				var options = $arguments[0] || null;
				var dataAttr = $(this).attr("data-jocly");
				if (dataAttr)
					try {
						options = eval("(" + dataAttr + ")"); // jshint ignore:line
					} catch (e) {
						console
								.error("Jocly applet: invalid data-jocly "
										+ dataAttr);
					}
				applet.init(options);
				$(this).data("jocly-applet", applet);
			}
			if ($arguments.length > 0) {
				var method = $arguments[0];
				if(justCreated && typeof method == "object")
					return;
				if (typeof method != "string")
					throw new Error(
							"Jocly applet: first argument must be a string specifying the method to be called");
				if (typeof applet[method] != "function")
					throw new Error("Jocly applet: no such method '"
							+ method + "'");
				var retVal0 = applet[method].apply(applet, Array.prototype.splice
						.call($arguments, 1));
				if(retVal0 !== undefined)
					console.log("method",method,"returns",retVal0)
			}
		});
		return retVal;
	};

	$(document).ready(function() {

		$("[data-jocly]").each(function() {
			var $this=$(this);
			$this.jocly();
			if(this.hasAttribute("data-jocly-init")) {
				var attr=$this.attr("data-jocly-init");
				if(attr.length===0)
					return;
				try {
					var arr=JSON.parse(attr);
					try {
						if(!Array.isArray(arr)) {
							console.warn("jquery.jocly: data-jocly-init attribute is not an array");
						}
						for(var i=0;i<arr.length;i++) {
							var element=arr[i];
							if(Array.isArray(element))
								$this.jocly.apply($this,element);
							else {
								$this.jocly.apply($this,arr);
								return;
							}
						}
					} catch(e) {
						console.warn("jquery.jocly: data-jocly-init error:",e);
					}
				} catch(e) {
					console.warn("jquery.jocly: data-jocly-init attribute has no JSON valid value");
				}
			}
		});

	});

}(jQuery));

<|endoftext|>


<commit_before>/**
 * User session service
 * @module services/session
 */
const moment = require('moment-timezone');
const jwt = require('jsonwebtoken');
const geoip = require('geoip-lite');

class Session {
    /**
     * Create the service
     * @param {App} app                         The application
     * @param {object} config                   Configuration
     * @param {Logger} logger                   Logger service
     * @param {Util} util                       Util service
     * @param {SessionRepository} sessionRepo   Session repository
     * @param {UserRepository} userRepo         User repository
     */
    constructor(app, config, logger, util, sessionRepo, userRepo) {
        this.cache = new Map();

        this._app = app;
        this._config = config;
        this._logger = logger;
        this._util = util;
        this._sessionRepo = sessionRepo;
        this._userRepo = userRepo;
    }

    /**
     * Service name is 'session'
     * @type {string}
     */
    static get provides() {
        return 'session';
    }

    /**
     * Dependencies as constructor arguments
     * @type {string[]}
     */
    static get requires() {
        return [ 'app', 'config', 'logger', 'util', 'repositories.session', 'repositories.user' ];
    }

    /**
     * This service is a singleton
     * @type {string}
     */
    static get lifecycle() {
        return 'singleton';
    }

    /**
     * Update session in the DB interval
     */
    static get saveInterval() {
        return 60 * 1000; // ms
    }

    /**
     * Cookie name
     * @return {string}
     */
    get cookieName() {
        return `${this._config.project}sid`;
    }

    /**
     * Encode JWT
     * @param {SessionModel} session            Session model
     * @return {string}                         Returns JWT
     */
    encodeJwt(session) {
        return jwt.sign({ token: session.token }, this._config.get('session.secret'));
    }

    /**
     * Start session of a user
     * @param {UserModel} user                  User model
     * @param {object} req                      Request data
     * @return {Promise}                        Resolves to session model
     */
    start(user, req) {
        let session = this._app.get('models.session');
        session.token = this._util.getRandomString(32, { lower: true, upper: true, digits: true, special: true });
        session.userId = user.id;
        session.payload = {};
        session.info = this._getInfo(req);
        session.createdAt = moment();
        session.updatedAt = session.createdAt;

        return this._sessionRepo.save(session)
            .then(() => {
                return session;
            });
    }

    /**
     * Load session by JWT
     * @param {string} token                    JWT
     * @param {object} req                      Request data
     * @return {Promise}                        Resolves to session model
     */
    load(token, req) {
        if (typeof token !== 'string' || !token.length)
            return Promise.resolve(null);

        return new Promise(resolve => {
                jwt.verify(token, this._config.get('session.secret'), (error, payload) => {
                    if (error)
                        this._logger.debug('session', error.message);

                    if (error || !payload || !payload.token)
                        return resolve(null);

                    resolve(payload);
                });
            })
            .then(payload => {
                if (!payload)
                    return [ null, null ];

                return this._sessionRepo.findByToken(payload.token)
                    .then(sessions => {
                        let session = sessions.length && sessions[0];
                        if (!session)
                            return null;

                        let cached = this.cache.get(session.id);
                        if (cached && cached.updatedAt.isAfter(session.updatedAt))
                            return cached;

                        return session;
                    })
                    .then(session => {
                        if (!session)
                            return [ null, null ];

                        session.info = this._getInfo(req);
                        this.update(session);

                        if (!session.userId)
                            return [ session, null ];

                        return this._userRepo.find(session.userId)
                            .then(users => {
                                let user = users.length && users[0];
                                return [ session, user || null ];
                            });
                    });
            });
    }

    /**
     * Update session in the DB
     * @param {SessionModel} session            The session
     */
    update(session) {
        let id = session.id;
        if (!this.cache.has(id)) {
            let schedule = session.updatedAt.add(this.constructor.saveInterval, 'milliseconds').valueOf() - moment().valueOf();
            setTimeout(
                () => {
                    let session = this.cache.get(id);
                    if (!session)
                        return;

                    this.cache.delete(id);

                    this._sessionRepo.save(session)
                        .catch(error => {
                            this._logger.error(new WError(error, 'Session._update()'));
                        });
                },
                schedule > 0 ? schedule : 0
            );
            console.log(`scheduled for ${schedule / 1000}`)
        }

        session.updatedAt = moment();
        this.cache.set(id, session);
    }

    /**
     * Prepare info object
     * @param {object} req                      Request data
     * @return {object}
     */
    _getInfo(req) {
        let ip, ipHeader = this._config.get('session.ip_header');
        if (ipHeader)
            ip = req.headers[ipHeader] && req.headers[ipHeader].trim();
        if (!ip)
            ip = req.ip;

        let forwarded = req.headers['x-forwarded-for'] && req.headers['x-forwarded-for'].trim();
        let agent = req.headers['user-agent'] && req.headers['user-agent'].trim();

        return {
            ip: ip,
            forwarded_for: forwarded || null,
            user_agent: agent || null,
            geoip: geoip.lookup(ip),
        }
    }
}

module.exports = Session;
<commit_msg>Removed debug<commit_after>/**
 * User session service
 * @module services/session
 */
const moment = require('moment-timezone');
const jwt = require('jsonwebtoken');
const geoip = require('geoip-lite');

class Session {
    /**
     * Create the service
     * @param {App} app                         The application
     * @param {object} config                   Configuration
     * @param {Logger} logger                   Logger service
     * @param {Util} util                       Util service
     * @param {SessionRepository} sessionRepo   Session repository
     * @param {UserRepository} userRepo         User repository
     */
    constructor(app, config, logger, util, sessionRepo, userRepo) {
        this.cache = new Map();

        this._app = app;
        this._config = config;
        this._logger = logger;
        this._util = util;
        this._sessionRepo = sessionRepo;
        this._userRepo = userRepo;
    }

    /**
     * Service name is 'session'
     * @type {string}
     */
    static get provides() {
        return 'session';
    }

    /**
     * Dependencies as constructor arguments
     * @type {string[]}
     */
    static get requires() {
        return [ 'app', 'config', 'logger', 'util', 'repositories.session', 'repositories.user' ];
    }

    /**
     * This service is a singleton
     * @type {string}
     */
    static get lifecycle() {
        return 'singleton';
    }

    /**
     * Update session in the DB interval
     */
    static get saveInterval() {
        return 60 * 1000; // ms
    }

    /**
     * Cookie name
     * @return {string}
     */
    get cookieName() {
        return `${this._config.project}sid`;
    }

    /**
     * Encode JWT
     * @param {SessionModel} session            Session model
     * @return {string}                         Returns JWT
     */
    encodeJwt(session) {
        return jwt.sign({ token: session.token }, this._config.get('session.secret'));
    }

    /**
     * Start session of a user
     * @param {UserModel} user                  User model
     * @param {object} req                      Request data
     * @return {Promise}                        Resolves to session model
     */
    start(user, req) {
        let session = this._app.get('models.session');
        session.token = this._util.getRandomString(32, { lower: true, upper: true, digits: true, special: true });
        session.userId = user.id;
        session.payload = {};
        session.info = this._getInfo(req);
        session.createdAt = moment();
        session.updatedAt = session.createdAt;

        return this._sessionRepo.save(session)
            .then(() => {
                return session;
            });
    }

    /**
     * Load session by JWT
     * @param {string} token                    JWT
     * @param {object} req                      Request data
     * @return {Promise}                        Resolves to session model
     */
    load(token, req) {
        if (typeof token !== 'string' || !token.length)
            return Promise.resolve(null);

        return new Promise(resolve => {
                jwt.verify(token, this._config.get('session.secret'), (error, payload) => {
                    if (error)
                        this._logger.debug('session', error.message);

                    if (error || !payload || !payload.token)
                        return resolve(null);

                    resolve(payload);
                });
            })
            .then(payload => {
                if (!payload)
                    return [ null, null ];

                return this._sessionRepo.findByToken(payload.token)
                    .then(sessions => {
                        let session = sessions.length && sessions[0];
                        if (!session)
                            return null;

                        let cached = this.cache.get(session.id);
                        if (cached && cached.updatedAt.isAfter(session.updatedAt))
                            return cached;

                        return session;
                    })
                    .then(session => {
                        if (!session)
                            return [ null, null ];

                        session.info = this._getInfo(req);
                        this.update(session);

                        if (!session.userId)
                            return [ session, null ];

                        return this._userRepo.find(session.userId)
                            .then(users => {
                                let user = users.length && users[0];
                                return [ session, user || null ];
                            });
                    });
            });
    }

    /**
     * Update session in the DB
     * @param {SessionModel} session            The session
     */
    update(session) {
        let id = session.id;
        if (!this.cache.has(id)) {
            let schedule = session.updatedAt.add(this.constructor.saveInterval, 'milliseconds').valueOf() - moment().valueOf();
            setTimeout(
                () => {
                    let session = this.cache.get(id);
                    if (!session)
                        return;

                    this.cache.delete(id);

                    this._sessionRepo.save(session)
                        .catch(error => {
                            this._logger.error(new WError(error, 'Session._update()'));
                        });
                },
                schedule > 0 ? schedule : 0
            );
        }

        session.updatedAt = moment();
        this.cache.set(id, session);
    }

    /**
     * Prepare info object
     * @param {object} req                      Request data
     * @return {object}
     */
    _getInfo(req) {
        let ip, ipHeader = this._config.get('session.ip_header');
        if (ipHeader)
            ip = req.headers[ipHeader] && req.headers[ipHeader].trim();
        if (!ip)
            ip = req.ip;

        let forwarded = req.headers['x-forwarded-for'] && req.headers['x-forwarded-for'].trim();
        let agent = req.headers['user-agent'] && req.headers['user-agent'].trim();

        return {
            ip: ip,
            forwarded_for: forwarded || null,
            user_agent: agent || null,
            geoip: geoip.lookup(ip),
        }
    }
}

module.exports = Session;
<|endoftext|>