<commit_before>/**
 * parser optarg
 *
 * @class parser
 */
function parser(argv, optstring,  opts) {
  var ii;

  if (!(this instanceof parser))
    return new parser(argv, optstring, opts);

  if (!opts && Array.isArray(optstring)) {
    opts = optstring;
    optstring = undefined;
  }

  argv = argv || process.argv;
  optstring = optstring || "";
  opts = opts || [];

  if (typeof optstring !== 'string') {
    throw new Error('a optstring is a string');
  }
  if (!Array.isArray(opts)) {
    throw new Error('opts should be a object');
  }
  if (!Array.isArray(argv)) {
    throw new Error('argv should be a array');
  }

  this.optind = 2;
  this.opterr = 1;
  this.options = {};
  this.usage = "";
  // create Array to save arg
  this.argArray = new Array();

  this.optArgv = new Array(argv.length);

  for (ii = 0; ii < argv.length; ++ii) {
    this.optArgv[ii] = argv[ii];
  }

  this.parserOptstr(optstring, opts);

  return this;
}

parser.prototype.addUsage = function(str) {
  this.usage = str;
  return this;
};

parser.prototype.addOption = function(flag, dest, harg) {
  if (typeof flag !== 'string' || flag[0] !== '-') {
    throw new Error('flag should be -[a-z]');
  }
  if (typeof dest !== 'string') {
    throw new Error('dest should be string');
  }

  harg = harg || true;

  if (flag.length > 2) {
    if (flag[1] !== '-')
      throw new Error('error flag');
    this.options[flag.slice(2)] = {
      has_arg: harg,
      val: flag[2],
      name: dest
    };
  }
  else if (flag.length > 1) {
    this.options[flag[1]] = {
      has_arg: harg,
      val: flag[1],
      name: dest
    };
  }
  else {
    throw new Error('not a flag');
  }

  return this;
};

parser.prototype.parseArgs = function() {
  var ret = {};
  var opt;
  while ((opt = this.getopt_long()) !== undefined) {
    if (opt.name && opt.option !== '?') {
      ret[opt.name] = opt.arg || true;
    }
    else if (opt.arg) {
      ret[opt.option] = opt.arg;
    }
    else {
      ret[opt.option] = true;
    }
  }
  ret['args'] = this.getArg();
  return ret;
};

parser.prototype.parserOptstr = function(optstr, opts) {
  var ii, chr, arg;

  ii = 0;
  while (ii < optstr.length) {
    chr = optstr[ii];
    arg = false;

    if (!/^\w$/.test(chr))
      throw (new Error('invalid optstring: ' + chr));

    if (ii + 1 < optstr.length && optstr[ii+1] === ':') {
      arg = true;
      ii++;
    }

    this.options[chr] = {
      has_arg: arg,
      val: chr
    };

    ii++;
  }

  if (opts !== undefined) {
    for (var j = 0; j < opts.length; ++j) {
      this.options[opts[j].name] = {
	has_arg: opts[j].has_arg,
	val: opts[j].val
      };
    }
  }

};

parser.prototype.getoptind = function() {
  return this.optind;
};

parser.prototype.getopt = function() {
  if (this.optind >= this.optArgv.length) {
    return (undefined);
  }
  var arg = this.optArgv[this.optind];

  if ('-' !== arg[0]) {
    this.argArray.push(arg);
    this.optind++;
    return this.getopt();
  }

  var chr = arg[1];

  if (!(chr in this.options)) {
    this.optind++;
    return {
      option: '?'
    };
  }
  var ar;

  this.optind++;
  if (this.options[chr].has_arg) {
    if (arg.length > 2) {
      ar = arg.slice(2);
      var ret = {
	option: this.options[chr].val,
	arg: ar,
	name: this.options[chr].name
      };
//      if (this.options[chr].name)
//	ret[this.options[chr].name] = ar;
      return ret;
    }
    else {
      ar = this.optArgv[this.optind++];
      return {
	option: this.options[chr].val,
	arg: ar,
	name: this.options[chr].name
      };
    }
  }
  else {
    return {
      option: this.options[chr].val,
      name: this.options[chr].name
    };
  }
};

parser.prototype.getopt_long = function() {
  if (this.optind >= this.optArgv.length) {
    return (undefined);
  }
  var arg = this.optArgv[this.optind];

  if (arg.length >= 2 && arg[0] === '-' && arg[1] === '-') {
    var ar = arg.slice(2);
    if (ar in this.options) {
      this.optind++;
      if (this.options[ar].has_arg) {
	return {
	  option: this.options[ar].val,
	  arg: this.optArgv[this.optind++],
	  name: this.options[ar].name
	};
      }
      else {
	return {
	  option: this.options[ar].val,
	  name: this.options[ar].name
	};
      }
    }
    else
      return this.getopt();
  }

  else
    return this.getopt();

};

parser.prototype.getArg = function() {
  return this.argArray;
};

module.exports = parser;
<commit_msg>add help descript<commit_after>/**
 * parser optarg
 *
 * @class parser
 */
function parser(argv, optstring,  opts) {
  var ii;

  if (!(this instanceof parser))
    return new parser(argv, optstring, opts);

  if (!opts && Array.isArray(optstring)) {
    opts = optstring;
    optstring = undefined;
  }

  argv = argv || process.argv;
  optstring = optstring || "";
  opts = opts || [];

  if (typeof optstring !== 'string') {
    throw new Error('a optstring is a string');
  }
  if (!Array.isArray(opts)) {
    throw new Error('opts should be a object');
  }
  if (!Array.isArray(argv)) {
    throw new Error('argv should be a array');
  }

  this.optind = 2;
  this.opterr = 1;
  this.options = {};
  this.usage = "";
  // create Array to save arg
  this.argArray = new Array();

  this.optArgv = new Array(argv.length);

  for (ii = 0; ii < argv.length; ++ii) {
    this.optArgv[ii] = argv[ii];
  }

  this.parserOptstr(optstring, opts);

  return this;
}

parser.prototype.addUsage = function(str) {
  this.usage = str;
  return this;
};

parser.prototype.addOption = function(flag, dest, harg, help) {
  if (typeof flag !== 'string' || flag[0] !== '-') {
    throw new Error('flag should be -[a-z]');
  }
  if (typeof dest !== 'string') {
    throw new Error('dest should be string');
  }

  harg = harg || true;
  help = help || "";

  if (flag.length > 2) {
    if (flag[1] !== '-')
      throw new Error('error flag');
    this.options[flag.slice(2)] = {
      has_arg: harg,
      val: flag[2],
      name: dest
    };
  }
  else if (flag.length > 1) {
    this.options[flag[1]] = {
      has_arg: harg,
      val: flag[1],
      name: dest
    };
  }
  else {
    throw new Error('not a flag');
  }

  return this;
};

parser.prototype.parseArgs = function() {
  var ret = {};
  var opt;
  while ((opt = this.getopt_long()) !== undefined) {
    if (opt.name && opt.option !== '?') {
      ret[opt.name] = opt.arg || true;
    }
    else if (opt.arg) {
      ret[opt.option] = opt.arg;
    }
    else {
      ret[opt.option] = true;
    }
  }
  ret['args'] = this.getArg();
  return ret;
};

parser.prototype.parserOptstr = function(optstr, opts) {
  var ii, chr, arg;

  ii = 0;
  while (ii < optstr.length) {
    chr = optstr[ii];
    arg = false;

    if (!/^\w$/.test(chr))
      throw (new Error('invalid optstring: ' + chr));

    if (ii + 1 < optstr.length && optstr[ii+1] === ':') {
      arg = true;
      ii++;
    }

    this.options[chr] = {
      has_arg: arg,
      val: chr
    };

    ii++;
  }

  if (opts !== undefined) {
    for (var j = 0; j < opts.length; ++j) {
      this.options[opts[j].name] = {
	has_arg: opts[j].has_arg,
	val: opts[j].val
      };
    }
  }

};

parser.prototype.getoptind = function() {
  return this.optind;
};

parser.prototype.getopt = function() {
  if (this.optind >= this.optArgv.length) {
    return (undefined);
  }
  var arg = this.optArgv[this.optind];

  if ('-' !== arg[0]) {
    this.argArray.push(arg);
    this.optind++;
    return this.getopt();
  }

  var chr = arg[1];

  if (!(chr in this.options)) {
    this.optind++;
    return {
      option: '?'
    };
  }
  var ar;

  this.optind++;
  if (this.options[chr].has_arg) {
    if (arg.length > 2) {
      ar = arg.slice(2);
      var ret = {
	option: this.options[chr].val,
	arg: ar,
	name: this.options[chr].name
      };
//      if (this.options[chr].name)
//	ret[this.options[chr].name] = ar;
      return ret;
    }
    else {
      ar = this.optArgv[this.optind++];
      return {
	option: this.options[chr].val,
	arg: ar,
	name: this.options[chr].name
      };
    }
  }
  else {
    return {
      option: this.options[chr].val,
      name: this.options[chr].name
    };
  }
};

parser.prototype.getopt_long = function() {
  if (this.optind >= this.optArgv.length) {
    return (undefined);
  }
  var arg = this.optArgv[this.optind];

  if (arg.length >= 2 && arg[0] === '-' && arg[1] === '-') {
    var ar = arg.slice(2);
    if (ar in this.options) {
      this.optind++;
      if (this.options[ar].has_arg) {
	return {
	  option: this.options[ar].val,
	  arg: this.optArgv[this.optind++],
	  name: this.options[ar].name
	};
      }
      else {
	return {
	  option: this.options[ar].val,
	  name: this.options[ar].name
	};
      }
    }
    else
      return this.getopt();
  }

  else
    return this.getopt();

};

parser.prototype.getArg = function() {
  return this.argArray;
};

module.exports = parser;
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');

var MongoClient = require('mongodb').MongoClient

var app = express();
var db;

var isDev = process.argv[2] === 'dev';

app.use(bodyParser.json());

app.set('port', (process.env.PORT || 5000));
app.set('connectionString', isDev ?
  'mongodb://dgretho:password@ds119508.mlab.com:19508/adjudicator-dev' :
  'mongodb://dgretho:password@ds129018.mlab.com:29018/adjudicator');

app.use(express.static(__dirname + '/public'));

app.use(express.static(__dirname + '/bin'));

app.get('/', function(request, response) {
  response.render('index');
});

app.get('/cases', function(request, response) {
  getCases((cases) => {
    response.send(cases);
  });
});

app.get('/case/:caseId', function(request, response) {
  getCases((cases) => {
    var caseId = parseInt(request.params.caseId);
    var requestedCase = cases.find(function(existingCase) {
      return existingCase.caseReference === caseId;
    });

    if (requestedCase === undefined) {
      requestedCase = {};
    }

    response.send(requestedCase);
  });
});

app.post('/case', function(request, response) {
  getCases((cases) => {
    request.body.caseReference = getCaseReference(cases);
    request.body.landlordEvidence = [];
    request.body.tenantEvidence = [];
    request.body.status = 'awaiting evidence';

    createCase(request.body);
  });

  response.sendStatus(200);
});

app.post('/evidence', function(request, response) {
  getCases((cases) => {
    var caseToUpdate = cases.find(function(existingCase) {
      return existingCase.caseReference === request.body.caseReference;
    });

    var evidenceProperty = request.body.evidenceOwner + 'Evidence';
    var evidenceList = caseToUpdate[evidenceProperty];
    evidenceList.push(request.body.evidence);
    var evidenceUpdate = { $set: {} };
    evidenceUpdate.$set[evidenceProperty] = evidenceList;
    updateCase(request.body.caseReference, evidenceUpdate);
  });

  response.sendStatus(200);
});

app.post('/markForAdjudication', function(request, response) {
  updateCase(request.body.caseReference, { $set: { status: 'awaiting adjudication' }});

  response.sendStatus(200);
});

MongoClient.connect(app.get('connectionString'), (err, database) => {
  if (err) {
    return console.log(err);
  }
  db = database;
  app.listen(app.get('port'), function() {
    console.log('Node app is running on port', app.get('port'));
  });
});

function getCases(callback) {
  db.collection('cases').find().toArray((err, cases) => {
    if (err) {
      return console.log(err);
    }

    callback(cases !== null ? cases : []);
  });
}

function createCase(newCase) {
  db.collection('cases').save(newCase, (error) => {
    if (error) {
      return console.log(error);
    }

    console.log('created case ' + newCase.caseReference);
  });
}

function updateCase(caseReference, update) {
  db.collection('cases').findOneAndUpdate(
    { caseReference: caseReference },
    update,
    {},
    (error) => {
      if (error) {
        return console.log(error);
      }

      console.log('updated case ' + caseReference);
    });
}

function getCaseReference(cases) {
  if (cases.length === 0) {
    return 1;
  }

  var caseReferences = cases.map((aCase) => {
    return aCase.caseReference;
  });
  return Math.max.apply(Math, caseReferences) + 1;
}
<commit_msg>Remove race condition on server (#23)<commit_after>var express = require('express');
var bodyParser = require('body-parser');

var MongoClient = require('mongodb').MongoClient

var app = express();
var db;

var isDev = process.argv[2] === 'dev';

app.use(bodyParser.json());

app.set('port', (process.env.PORT || 5000));
app.set('connectionString', isDev ?
  'mongodb://dgretho:password@ds119508.mlab.com:19508/adjudicator-dev' :
  'mongodb://dgretho:password@ds129018.mlab.com:29018/adjudicator');

app.use(express.static(__dirname + '/public'));

app.use(express.static(__dirname + '/bin'));

app.get('/', function(request, response) {
  response.render('index');
});

app.get('/cases', function(request, response) {
  getCases((cases) => {
    response.send(cases);
  });
});

app.get('/case/:caseId', function(request, response) {
  getCases((cases) => {
    var caseId = parseInt(request.params.caseId);
    var requestedCase = cases.find(function(existingCase) {
      return existingCase.caseReference === caseId;
    });

    if (requestedCase === undefined) {
      requestedCase = {};
    }

    response.send(requestedCase);
  });
});

app.post('/case', function(request, response) {
  getCases((cases) => {
    request.body.caseReference = getCaseReference(cases);
    request.body.landlordEvidence = [];
    request.body.tenantEvidence = [];
    request.body.status = 'awaiting evidence';

    createCase(request.body, () => {
      response.sendStatus(200);
    });
  });
});

app.post('/evidence', function(request, response) {
  getCases((cases) => {
    var caseToUpdate = cases.find(function(existingCase) {
      return existingCase.caseReference === request.body.caseReference;
    });

    var evidenceProperty = request.body.evidenceOwner + 'Evidence';
    var evidenceList = caseToUpdate[evidenceProperty];
    evidenceList.push(request.body.evidence);
    var evidenceUpdate = { $set: {} };
    evidenceUpdate.$set[evidenceProperty] = evidenceList;
    updateCase(request.body.caseReference, evidenceUpdate, () => {
      response.sendStatus(200);
    });
  });
});

app.post('/markForAdjudication', function(request, response) {
  updateCase(request.body.caseReference, { $set: { status: 'awaiting adjudication' }}, () => {
    response.sendStatus(200);
  });
});

MongoClient.connect(app.get('connectionString'), (err, database) => {
  if (err) {
    return console.log(err);
  }
  db = database;
  app.listen(app.get('port'), function() {
    console.log('Node app is running on port', app.get('port'));
  });
});

function getCases(callback) {
  db.collection('cases').find().toArray((err, cases) => {
    if (err) {
      return console.log(err);
    }

    callback(cases !== null ? cases : []);
  });
}

function createCase(newCase, callback) {
  db.collection('cases').save(newCase, (error) => {
    if (callback) {
      callback(error);
    }

    if (error) {
      return console.log(error);
    }

    console.log('created case ' + newCase.caseReference);
  });
}

function updateCase(caseReference, update, callback) {
  db.collection('cases').findOneAndUpdate(
    { caseReference: caseReference },
    update,
    {},
    (error) => {
      if (callback) {
        callback(error);
      }

      if (error) {
        return console.log(error);
      }

      console.log('updated case ' + caseReference);
    });
}

function getCaseReference(cases) {
  if (cases.length === 0) {
    return 1;
  }

  var caseReferences = cases.map((aCase) => {
    return aCase.caseReference;
  });
  return Math.max.apply(Math, caseReferences) + 1;
}
<|endoftext|>


<commit_before>var normalize = require('./normalize')
var createVAO = require('gl-vao')

module.exports = GLGeometry

function GLGeometry(gl) {
  if (!(this instanceof GLGeometry))
    return new GLGeometry(gl)

  this._attributes = []
  this._dirty = true
  this._length = 0
  this._index = null
  this._vao = null
  this._keys = []
  this.gl = gl
}

GLGeometry.prototype.dispose = function() {
  for (var i = 0; i < this._attributes.length; i++) {
    this._attributes[i].buffer.dispose()
  }

  this._attributes = []

  if (this._index) {
    this._index.dispose()
    this._index = null
  }

  if (this._vao) {
    this._vao.dispose()
    this._vao = null
  }
}

GLGeometry.prototype.faces = function faces(attr, opts) {
  var size = opts && opts.size || 3
  attr = attr.cells ? attr.cells : attr

  this._dirty = true

  if (this._index) {
    this._index.dispose()
  }

  this._index = normalize(this.gl
    , attr
    , size
    , this.gl.ELEMENT_ARRAY_BUFFER
    , 'uint16'
  )

  this._length = this._index.length * size
  this._index = this._index.buffer

  return this
}

GLGeometry.prototype.attr = function attr(name, attr, opts) {
  opts = opts || {}
  this._dirty = true

  var gl = this.gl
  var first = !this._attributes.length
  var size = opts.size || 3

  var attribute = normalize(gl, attr, size, gl.ARRAY_BUFFER, 'float32')
  if (!attribute) {
    throw new Error(
        'Unexpected attribute format: needs an ndarray, array, typed array, '
      + 'gl-buffer or simplicial complex'
    )
  }

  var buffer = attribute.buffer
  var length = attribute.length
  var index  = attribute.index

  this._keys.push(name)
  this._attributes.push({
      size: size
    , buffer: buffer
  })

  if (first) {
    this._length = length
  }

  if (first && index) {
    this._index = index
  }

  return this
}

GLGeometry.prototype.bind = function bind(shader) {
  this.update()
  this._vao.bind()

  if (!shader) return
  shader.bind()

  if (!this._keys) return
  for (var i = 0; i < this._keys.length; i++) {
    var attr = shader.attributes[this._keys[i]]
    if (attr) attr.location = i
  }
}

GLGeometry.prototype.draw = function draw(mode) {
  this.update()
  if(mode === undefnied) {
    mode = this.gl.TRIANGLES
  }
  this._vao.draw(mode, this._length)
}

GLGeometry.prototype.unbind = function unbind() {
  this.update()
  this._vao.unbind()
}

GLGeometry.prototype.update = function update() {
  if (!this._dirty) return
  this._dirty = false
  if (this._vao) this._vao.dispose()

  this._vao = createVAO(
      this.gl
    , this._attributes
    , this._index
  )
}
<commit_msg>spelling<commit_after>var normalize = require('./normalize')
var createVAO = require('gl-vao')

module.exports = GLGeometry

function GLGeometry(gl) {
  if (!(this instanceof GLGeometry))
    return new GLGeometry(gl)

  this._attributes = []
  this._dirty = true
  this._length = 0
  this._index = null
  this._vao = null
  this._keys = []
  this.gl = gl
}

GLGeometry.prototype.dispose = function() {
  for (var i = 0; i < this._attributes.length; i++) {
    this._attributes[i].buffer.dispose()
  }

  this._attributes = []

  if (this._index) {
    this._index.dispose()
    this._index = null
  }

  if (this._vao) {
    this._vao.dispose()
    this._vao = null
  }
}

GLGeometry.prototype.faces = function faces(attr, opts) {
  var size = opts && opts.size || 3
  attr = attr.cells ? attr.cells : attr

  this._dirty = true

  if (this._index) {
    this._index.dispose()
  }

  this._index = normalize(this.gl
    , attr
    , size
    , this.gl.ELEMENT_ARRAY_BUFFER
    , 'uint16'
  )

  this._length = this._index.length * size
  this._index = this._index.buffer

  return this
}

GLGeometry.prototype.attr = function attr(name, attr, opts) {
  opts = opts || {}
  this._dirty = true

  var gl = this.gl
  var first = !this._attributes.length
  var size = opts.size || 3

  var attribute = normalize(gl, attr, size, gl.ARRAY_BUFFER, 'float32')
  if (!attribute) {
    throw new Error(
        'Unexpected attribute format: needs an ndarray, array, typed array, '
      + 'gl-buffer or simplicial complex'
    )
  }

  var buffer = attribute.buffer
  var length = attribute.length
  var index  = attribute.index

  this._keys.push(name)
  this._attributes.push({
      size: size
    , buffer: buffer
  })

  if (first) {
    this._length = length
  }

  if (first && index) {
    this._index = index
  }

  return this
}

GLGeometry.prototype.bind = function bind(shader) {
  this.update()
  this._vao.bind()

  if (!shader) return
  shader.bind()

  if (!this._keys) return
  for (var i = 0; i < this._keys.length; i++) {
    var attr = shader.attributes[this._keys[i]]
    if (attr) attr.location = i
  }
}

GLGeometry.prototype.draw = function draw(mode) {
  this.update()
  if(mode === undefined) {
    mode = this.gl.TRIANGLES
  }
  this._vao.draw(mode, this._length)
}

GLGeometry.prototype.unbind = function unbind() {
  this.update()
  this._vao.unbind()
}

GLGeometry.prototype.update = function update() {
  if (!this._dirty) return
  this._dirty = false
  if (this._vao) this._vao.dispose()

  this._vao = createVAO(
      this.gl
    , this._attributes
    , this._index
  )
}
<|endoftext|>


<commit_before>'use strict'

const {log, BaseKonnector, saveBills, request} = require('cozy-konnector-libs')
const moment = require('moment')
const bluebird = require('bluebird')

let rq = request({
  // debug: true,
  cheerio: true,
  json: false,
  jar: true
})

module.exports = new BaseKonnector(function fetch (fields) {
  return checkLogin(fields)
  .then(() => logIn(fields))
  .then($ => parsePage($))
  .then(entries => {
    // get custom bank identifier if any
    let identifiers = 'C.P.A.M.'
    if (fields.bank_identifier && fields.bank_identifier.length) {
      identifiers = fields.bank_identifier
    }

    return saveBills(entries, fields.folderPath, {
      timeout: Date.now() + 60 * 1000,
      identifiers,
      dateDelta: 10,
      amountDelta: 0.1
    })
  })
})

const checkLogin = function (fields) {
  log('info', 'Checking the length of the login')
  if (fields.login.length > 13) return Promise.reject(new Error('LOGIN_FAILED'))

  return Promise.resolve()
}

// Procedure to login to Ameli website.
const logIn = function (fields) {
  log('info', 'Now logging in')
  const loginUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/assure?_somtc=true'

  const submitUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/' +
    'assure?_nfpb=true&_windowLabel=connexioncompte_2&connexioncompte_2_' +
    'actionOverride=/portlets/connexioncompte/validationconnexioncompte&_pageLabel=as_login_page'

  const reimbursementUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_paiements_page'

  const form = {
    'connexioncompte_2numSecuriteSociale': fields.login,
    'connexioncompte_2codeConfidentiel': fields.password,
    'connexioncompte_2actionEvt': 'connecter',
    'submit': 'Valider'
  }

  return rq({
    url: loginUrl,
    resolveWithFullResponse: true
  })
  // First request to get the cookie
  .then(res => rq({
    method: 'POST',
    form,
    url: submitUrl
  }))
  // Second request to authenticate
  .then($ => {
    if ($('[title="Déconnexion du compte ameli"]').length !== 1) {
      throw new Error('LOGIN_FAILED')
    }

    log('info', 'Correctly logged in')
    return rq(reimbursementUrl)
  })
}

// Parse the fetched page to extract bill data.
const parsePage = function ($) {
  log('info', 'Fetching the list of bills')
  const entries = []

  // Get the start and end date to generate the bill's url
  const endDate = $('#paiements_1dateFin').attr('value')

  const baseUrl = 'https://assure.ameli.fr/PortailAS/paiements.do?actionEvt='

  // We can get the history only 6 months back
  const startDate = moment(endDate, 'DD/MM/YYYY').subtract(6, 'months').format('DD/MM/YYYY')

  const billUrl = `${baseUrl}afficherPaiementsComplementaires&DateDebut=${startDate}&DateFin=${endDate}\
&Beneficiaire=tout_selectionner&afficherReleves=false&afficherIJ=false&afficherInva=false&afficherRentes=false\
&afficherRS=false&indexPaiement=&idNotif=`

  return rq(billUrl)
  .then($ => {
    let i = 0

    // Each bloc represents a month that includes 0 to n reimbursement
    $('.blocParMois').each(function () {
      // It would be too easy to get the full date at the same place
      let year = $($(this).find('.rowdate .mois').get(0)).text()
      year = year.split(' ')[1]

      return $(`[id^=lignePaiement${i++}]`).each(function () {
        let amount = $($(this).find('.col-montant').get(0)).text()
        amount = amount.replace(' €', '').replace(',', '.')
        amount = parseFloat(amount)

        const month = $($(this).find('.col-date .mois').get(0)).text()
        const day = $($(this).find('.col-date .jour').get(0)).text()
        let date = `${day} ${month} ${year}`
        moment.locale('fr')
        date = moment(date, 'Do MMMM YYYY')

        const label = $($(this).find('.col-label').get(0)).text()

        // Retrieve and extract the infos needed to generate the pdf
        const attrInfos = $(this).attr('onclick')
        const tokens = attrInfos.split("'")

        const idPaiement = tokens[1]
        const naturePaiement = tokens[3]
        const indexGroupe = tokens[5]
        const indexPaiement = tokens[7]

        const detailsUrl = `${baseUrl}chargerDetailPaiements\
&idPaiement=${idPaiement}\
&naturePaiement=${naturePaiement}\
&indexGroupe=${indexGroupe}\
&indexPaiement=${indexPaiement}`

        let lineId = indexGroupe + indexPaiement

        let bill = {
          amount,
          type: 'health',
          subtype: label,
          date: date.toDate(),
          vendor: 'Ameli',
          lineId,
          detailsUrl
        }

        if (bill.amount != null) { return entries.push(bill) }
      })
    })
    return bluebird.each(entries, getPdf)
  })
}

const getPdf = function (bill) {
  // Request the generated url to get the detailed pdf
  return rq(bill.detailsUrl)
  .then($ => {
    let pdfUrl = $(`[id=liendowndecompte${bill.lineId}]`).attr('href')
    if (pdfUrl) {
      bill.fileurl = `https://assure.ameli.fr${pdfUrl}`
      bill.filename = getFileName(bill.date)
    }
    return bill
  })
}

function getFileName (date) {
  return `${moment(date).format('YYYYMMDD')}_ameli.pdf`
}
<commit_msg>fix: on keeps the reimbursement to the user<commit_after>'use strict'

const {log, BaseKonnector, saveBills, request} = require('cozy-konnector-libs')
const moment = require('moment')
const bluebird = require('bluebird')

let rq = request({
  // debug: true,
  cheerio: true,
  json: false,
  jar: true
})

module.exports = new BaseKonnector(function fetch (fields) {
  return checkLogin(fields)
  .then(() => logIn(fields))
  .then($ => parsePage($))
  .then(entries => {
    // get custom bank identifier if any
    let identifiers = 'C.P.A.M.'
    if (fields.bank_identifier && fields.bank_identifier.length) {
      identifiers = fields.bank_identifier
    }

    return saveBills(entries, fields.folderPath, {
      timeout: Date.now() + 60 * 1000,
      identifiers,
      dateDelta: 10,
      amountDelta: 0.1
    })
  })
})

const checkLogin = function (fields) {
  log('info', 'Checking the length of the login')
  if (fields.login.length > 13) return Promise.reject(new Error('LOGIN_FAILED'))

  return Promise.resolve()
}

// Procedure to login to Ameli website.
const logIn = function (fields) {
  log('info', 'Now logging in')
  const loginUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/assure?_somtc=true'

  const submitUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/' +
    'assure?_nfpb=true&_windowLabel=connexioncompte_2&connexioncompte_2_' +
    'actionOverride=/portlets/connexioncompte/validationconnexioncompte&_pageLabel=as_login_page'

  const reimbursementUrl = 'https://assure.ameli.fr/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_paiements_page'

  const form = {
    'connexioncompte_2numSecuriteSociale': fields.login,
    'connexioncompte_2codeConfidentiel': fields.password,
    'connexioncompte_2actionEvt': 'connecter',
    'submit': 'Valider'
  }

  return rq({
    url: loginUrl,
    resolveWithFullResponse: true
  })
  // First request to get the cookie
  .then(res => rq({
    method: 'POST',
    form,
    url: submitUrl
  }))
  // Second request to authenticate
  .then($ => {
    if ($('[title="Déconnexion du compte ameli"]').length !== 1) {
      throw new Error('LOGIN_FAILED')
    }

    log('info', 'Correctly logged in')
    return rq(reimbursementUrl)
  })
}

// Parse the fetched page to extract bill data.
const parsePage = function ($) {
  log('info', 'Fetching the list of bills')
  const entries = []

  // Get the start and end date to generate the bill's url
  const endDate = $('#paiements_1dateFin').attr('value')

  const baseUrl = 'https://assure.ameli.fr/PortailAS/paiements.do?actionEvt='

  // We can get the history only 6 months back
  const startDate = moment(endDate, 'DD/MM/YYYY').subtract(6, 'months').format('DD/MM/YYYY')

  const billUrl = `${baseUrl}afficherPaiementsComplementaires&DateDebut=${startDate}&DateFin=${endDate}\
&Beneficiaire=tout_selectionner&afficherReleves=false&afficherIJ=false&afficherInva=false&afficherRentes=false\
&afficherRS=false&indexPaiement=&idNotif=`

  return rq(billUrl)
  .then($ => {
    let i = 0

    // Each bloc represents a month that includes 0 to n reimbursement
    $('.blocParMois').each(function () {
      // It would be too easy to get the full date at the same place
      let year = $($(this).find('.rowdate .mois').get(0)).text()
      year = year.split(' ')[1]

      return $(`[id^=lignePaiement${i++}]`).each(function () {
        let amount = $($(this).find('.col-montant').get(0)).text()
        amount = amount.replace(' €', '').replace(',', '.')
        amount = parseFloat(amount)

        const month = $($(this).find('.col-date .mois').get(0)).text()
        const day = $($(this).find('.col-date .jour').get(0)).text()
        let date = `${day} ${month} ${year}`
        moment.locale('fr')
        date = moment(date, 'Do MMMM YYYY')

        const label = $($(this).find('.col-label').get(0)).text()

        // Retrieve and extract the infos needed to generate the pdf
        const attrInfos = $(this).attr('onclick')
        const tokens = attrInfos.split("'")

        const idPaiement = tokens[1]
        const naturePaiement = tokens[3]
        const indexGroupe = tokens[5]
        const indexPaiement = tokens[7]

        const detailsUrl = `${baseUrl}chargerDetailPaiements\
&idPaiement=${idPaiement}\
&naturePaiement=${naturePaiement}\
&indexGroupe=${indexGroupe}\
&indexPaiement=${indexPaiement}`

        let lineId = indexGroupe + indexPaiement

        let bill = {
          amount,
          type: 'health',
          subtype: label,
          date: date.toDate(),
          vendor: 'Ameli',
          lineId,
          detailsUrl
        }

        if (bill.amount != null && naturePaiement === 'REMBOURSEMENT_SOINS') { return entries.push(bill) }
      })
    })
    return bluebird.each(entries, getPdf)
  })
}

const getPdf = function (bill) {
  // Request the generated url to get the detailed pdf
  return rq(bill.detailsUrl)
  .then($ => {
    let pdfUrl = $(`[id=liendowndecompte${bill.lineId}]`).attr('href')
    if (pdfUrl) {
      bill.fileurl = `https://assure.ameli.fr${pdfUrl}`
      bill.filename = getFileName(bill.date)
    }
    return bill
  })
}

function getFileName (date) {
  return `${moment(date).format('YYYYMMDD')}_ameli.pdf`
}
<|endoftext|>


<commit_before>var fis = module.exports = require('fis3');
var path = require('path');
var _ = fis.util;

fis.require.prefixes.unshift('gfis');
fis.cli.name = 'gfis';
fis.cli.info = require('./package.json');

// 添加自定义命令
fis.require._cache['command-init'] = require('./command/init.js');
fis.set('modules.commands', ['init','install','release','server','inspect']);

var gfis = {
    /**
     * 初始化
     */
    init: function() {
        this.config = this._getConfig();
        this.setEvnCommonConfig();
        this.setEnvPrivateConfig();
    },
    /**
     * 设置环境通用配置
     */
    setEvnCommonConfig: function() {
        this._setBaseCommon();
        this._preCompile();
        this._processFileByMd5();
        this._processFileByCompress();
        this._processCssSprite();
        this._processFileByReleasePattern();
    },
    /**
     * 设置环境私有配置
     */
    setEnvPrivateConfig: function() {
        this._setDevEvnConfig();
        this._setUatEvnConfig();
        this._setPreEvnConfig();
        this._setPrdEvnConfig();
    },
    /**
     * 设置基础配置
     */
    _setBaseCommon: function() {
        //关闭编译缓存
        fis.match('*', {
            useCache: false
        });

        //不发布build文件
        fis.match('/build/**', {
            release: false
        });
    },
    /**
     * 异构语言预编译处理
     */
    _preCompile: function() {
        if (this.config.release.sass) {
            //sass的规范,_打头的文件都不release.
            fis.match('/sass/{**/_*.scss,_*.scss}', {
                release: false
            });

            //发布到css目录下，并且后缀设置为.css
            fis.match('/sass/**.{scss,css}', {
                parser: fis.plugin('node-sass'),
                rExt: '.css',
                release: '/css$0'
            });

            //预编译内嵌的sass
            fis.match('/html/**.{html,ftl}:scss', {
                parser: fis.plugin('node-sass')
            });
        }
    },
    /**
     * 处理文件MD5
     */
    _processFileByMd5: function() {
        if (this.config.release.cssMd5) {
            //css md5
            fis.match('/css/**.css', {
                useHash: true
            });

            //sass md5
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    useHash: true
                });
            }
        }

        //js md5
        if (this.config.release.jsMd5) {
            fis.match('/js/**.js', {
                useHash: true
            });
        }

        //image md5
        if (this.config.release.imageMd5) {
            fis.match('::image', {
                useHash: true
            });
        }
    },
    /**
     * 处理文件压缩
     */
    _processFileByCompress: function() {
        //js压缩
        if (this.config.release.jsCompress) {
            fis.match('/js/**.js', {
                optimizer: fis.plugin('uglify-js')
            });

            //处理内嵌的js代码
            fis.match('/html/**.{html,ftl}:js', {
                optimizer: fis.plugin('uglify-js')
            });
        }

        //css压缩
        if (this.config.release.cssCompress) {
            fis.match('/css/**.css', {
                optimizer: fis.plugin('clean-css')
            });

            //处理内嵌的css代码
            fis.match('/html/**.{html,ftl}:css', {
                optimizer: fis.plugin('clean-css')
            });

            //sass压缩
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    optimizer: fis.plugin('clean-css')
                });

                //处理内嵌的sass代码
                fis.match('/html/**.{html,ftl}:scss', {
                    optimizer: fis.plugin('clean-css')
                });
            }
        }

        //png图片压缩
        if (this.config.release.pngCompress) {
            fis.match('**.png', {
                optimizer: fis.plugin('png-compressor')
            });
        }

        //html压缩
        if (this.config.release.htmlCompress) {
            fis.match('/html/**.{html,ftl}', {
                optimizer: fis.plugin('html-minifier')
            });
        }
    },
    /**
     * 处理雪碧图
     */
    _processCssSprite: function() {
        if (this.config.release.cssSprite) {
            fis.match('::packager', {
                spriter: fis.plugin('csssprites')
            });

            //css雪碧图
            fis.match('/css/**.css', {
                useSprite: true
            });

            //sass雪碧图
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    useSprite: true
                });
            }
        }
    },
    /**
     * 处理文件的发布规则
     */
    _processFileByReleasePattern: function() {
        var ignoreReleaseFiles = this.config.release.ignoreReleaseFiles;
        if (ignoreReleaseFiles !== null) {
            ignoreReleaseFiles.forEach(function(glob) {
                fis.match(glob, {
                    release: false
                });
            });
        }
    },
    /**
     * 设置开发环境配置
     */
    _setDevEvnConfig: function() {
        //为了方便server预览，开发环境将.ftl改为.html
        fis.match('/html/**.ftl', {
            rExt: '.html'
        });

        //设置freemarker解析和ssi
        fis.match('/html/**.{ftl,html}', {
                parser: [
                    fis.plugin('gfe-freemarker'),
                    fis.plugin('gfe-ssi', {
                        ssiDomain: 'http://www.gome.com.cn'
                    })
                ]
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.uatDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.uatDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置uat环境配置
     */
    _setUatEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('uat')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.uatDomain.css,
                        jsDomain: this.config.release.uatDomain.js
                    })
                });
        }

        fis
            .media('uat')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.uatDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.uatDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.uatDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.uatDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置pre环境配置
     */
    _setPreEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('pre')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.preDomain.css,
                        jsDomain: this.config.release.preDomain.js
                    })
                });
        }

        fis
            .media('pre')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.preDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.preDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.preDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.preDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置prd环境配置
     */
    _setPrdEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('prd')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.prdDomain.css,
                        jsDomain: this.config.release.prdDomain.js,
                        debugDomain: this.config.release.debugDomain
                    })
                });
        }

        fis
            .media('prd')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.prdDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.prdDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.prdDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.prdDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 获取配置文件
     */
    _getConfig: function() {
        var config = require('./lib/defaults.js');
        var gfeConfigPath = path.join(process.cwd(), 'gfe-config.json');
        if (_.exists(gfeConfigPath)) {
            var gfeConfig = _.readJSON(gfeConfigPath);
            config = _.merge(config, gfeConfig);
        } else {
            _.write(gfeConfigPath, JSON.stringify(config, null, 4), 'utf-8');
        }

        return config;
    }
};

gfis.init();
<commit_msg>覆盖fis3的cli部分方法<commit_after>var fis = module.exports = require('fis3');
var argv = require('minimist')(process.argv.slice(2));
var path = require('path');
var _ = fis.util;

fis.require.prefixes.unshift('gfis');
// 添加自定义命令
fis.require._cache['command-init'] = require('./command/init.js');
fis.set('modules.commands', ['init', 'release', 'server', 'inspect']);
//重置命令行信息
var cli = fis.cli;
cli.name = 'gfis';
cli.info = require('./package.json');
cli.version = function(){
    console.log('v' + cli.info.version);
};
cli.options = {
  '-h, --help': 'print this help message',
  '-v, --version': 'print product version and exit',
};
//覆盖run方法，去除fis.log.info
var oldCliRunMethod = "cli.run = " + cli.run.toString();

var newCliRunMethod = oldCliRunMethod.replace(/fis.log.info.*?;/g,'');
eval(newCliRunMethod);

var gfis = {
    /**
     * 初始化
     */
    init: function() {
        this.config = this._getConfig();
        this.setEvnCommonConfig();
        this.setEnvPrivateConfig();
    },
    /**
     * 设置环境通用配置
     */
    setEvnCommonConfig: function() {
        this._setBaseCommon();
        this._preCompile();
        this._processFileByMd5();
        this._processFileByCompress();
        this._processCssSprite();
        this._processFileByReleasePattern();
    },
    /**
     * 设置环境私有配置
     */
    setEnvPrivateConfig: function() {
        this._setDevEvnConfig();
        this._setUatEvnConfig();
        this._setPreEvnConfig();
        this._setPrdEvnConfig();
    },
    /**
     * 设置基础配置
     */
    _setBaseCommon: function() {
        //关闭编译缓存
        fis.match('*', {
            useCache: false
        });

        //不发布build文件
        fis.match('/build/**', {
            release: false
        });
    },
    /**
     * 异构语言预编译处理
     */
    _preCompile: function() {
        if (this.config.release.sass) {
            //sass的规范,_打头的文件都不release.
            fis.match('/sass/{**/_*.scss,_*.scss}', {
                release: false
            });

            //发布到css目录下，并且后缀设置为.css
            fis.match('/sass/**.{scss,css}', {
                parser: fis.plugin('node-sass'),
                rExt: '.css',
                release: '/css$0'
            });

            //预编译内嵌的sass
            fis.match('/html/**.{html,ftl}:scss', {
                parser: fis.plugin('node-sass')
            });
        }
    },
    /**
     * 处理文件MD5
     */
    _processFileByMd5: function() {
        if (this.config.release.cssMd5) {
            //css md5
            fis.match('/css/**.css', {
                useHash: true
            });

            //sass md5
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    useHash: true
                });
            }
        }

        //js md5
        if (this.config.release.jsMd5) {
            fis.match('/js/**.js', {
                useHash: true
            });
        }

        //image md5
        if (this.config.release.imageMd5) {
            fis.match('::image', {
                useHash: true
            });
        }
    },
    /**
     * 处理文件压缩
     */
    _processFileByCompress: function() {
        //js压缩
        if (this.config.release.jsCompress) {
            fis.match('/js/**.js', {
                optimizer: fis.plugin('uglify-js')
            });

            //处理内嵌的js代码
            fis.match('/html/**.{html,ftl}:js', {
                optimizer: fis.plugin('uglify-js')
            });
        }

        //css压缩
        if (this.config.release.cssCompress) {
            fis.match('/css/**.css', {
                optimizer: fis.plugin('clean-css')
            });

            //处理内嵌的css代码
            fis.match('/html/**.{html,ftl}:css', {
                optimizer: fis.plugin('clean-css')
            });

            //sass压缩
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    optimizer: fis.plugin('clean-css')
                });

                //处理内嵌的sass代码
                fis.match('/html/**.{html,ftl}:scss', {
                    optimizer: fis.plugin('clean-css')
                });
            }
        }

        //png图片压缩
        if (this.config.release.pngCompress) {
            fis.match('**.png', {
                optimizer: fis.plugin('png-compressor')
            });
        }

        //html压缩
        if (this.config.release.htmlCompress) {
            fis.match('/html/**.{html,ftl}', {
                optimizer: fis.plugin('html-minifier')
            });
        }
    },
    /**
     * 处理雪碧图
     */
    _processCssSprite: function() {
        if (this.config.release.cssSprite) {
            fis.match('::packager', {
                spriter: fis.plugin('csssprites')
            });

            //css雪碧图
            fis.match('/css/**.css', {
                useSprite: true
            });

            //sass雪碧图
            if (this.config.release.sass) {
                fis.match('/sass/**.{scss,css}', {
                    useSprite: true
                });
            }
        }
    },
    /**
     * 处理文件的发布规则
     */
    _processFileByReleasePattern: function() {
        var ignoreReleaseFiles = this.config.release.ignoreReleaseFiles;
        if (ignoreReleaseFiles !== null) {
            ignoreReleaseFiles.forEach(function(glob) {
                fis.match(glob, {
                    release: false
                });
            });
        }
    },
    /**
     * 设置开发环境配置
     */
    _setDevEvnConfig: function() {
        //为了方便server预览，开发环境将.ftl改为.html
        fis.match('/html/**.ftl', {
            rExt: '.html'
        });

        //设置freemarker解析和ssi
        fis.match('/html/**.{ftl,html}', {
                parser: [
                    fis.plugin('gfe-freemarker'),
                    fis.plugin('gfe-ssi', {
                        ssiDomain: 'http://www.gome.com.cn'
                    })
                ]
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.uatDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.uatDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置uat环境配置
     */
    _setUatEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('uat')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.uatDomain.css,
                        jsDomain: this.config.release.uatDomain.js
                    })
                });
        }

        fis
            .media('uat')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.uatDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.uatDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.uatDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.uatDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置pre环境配置
     */
    _setPreEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('pre')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.preDomain.css,
                        jsDomain: this.config.release.preDomain.js
                    })
                });
        }

        fis
            .media('pre')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.preDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.preDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.preDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.preDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 设置prd环境配置
     */
    _setPrdEvnConfig: function() {
        //是否开启debug输出
        if (this.config.release.debug) {
            fis
                .media('prd')
                .match('::package', {
                    //输出debug文件
                    prepackager: fis.plugin('gfe-debug-output', {
                        cssDomain: this.config.release.prdDomain.css,
                        jsDomain: this.config.release.prdDomain.js,
                        debugDomain: this.config.release.debugDomain
                    })
                });
        }

        fis
            .media('prd')
            .match('**.js', { //js添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.prdDomain.js
            })
            .match('**.{css,scss}', { //css添加域名和项目前缀
                url: '/' + this.config.projectPath,
                domain: this.config.release.prdDomain.css
            })
            .match('::image', { //图片添加项目前缀
                url: '/' + this.config.projectPath
            })
            .match('/html/**.{html,ftl}', {
                parser: null
            })
            .match('/html/**.ftl', {
                rExt: '.ftl'
            })
            .match('*', {
                deploy: [
                    fis.plugin('gfe-combo-url', {
                        useCombo: this.config.release.urlCombo
                    }),
                    fis.plugin('gfe-script-inbottom'),
                    fis.plugin('gfe-script-place'),
                    fis.plugin('gfe-replace', {
                        patterns: [{
                            match: '__JS_DOMAIN__',
                            replacement: this.config.release.prdDomain.js
                        }, {
                            match: '__CSS_DOMAIN__',
                            replacement: this.config.release.prdDomain.css
                        }]
                    }),
                    fis.plugin('local-deliver', {
                        to: './build'
                    })
                ]
            });
    },
    /**
     * 获取配置文件
     */
    _getConfig: function() {
        var config = require('./lib/defaults.js');
        var gfeConfigPath = path.join(process.cwd(), 'gfe-config.json');
        if (_.exists(gfeConfigPath)) {
            var gfeConfig = _.readJSON(gfeConfigPath);
            config = _.merge(config, gfeConfig);
        } else {
            _.write(gfeConfigPath, JSON.stringify(config, null, 4), 'utf-8');
        }

        return config;
    }
};

//当执行gfis release/inspect命令时，初始化参数信息
var cmdName = argv._[0];
if(~['release', 'inspect'].indexOf(cmdName)){
    console.log(111);
    gfis.init();
}<|endoftext|>


<commit_before>
var fs = require('fs'),
  path = require('path'),
  zlib = require('zlib'),
  fson = module.exports = function (path) {
    var object = path

    if (typeof path === 'string') {
      object = toObject(path)
    }

    object.__proto__ = fson

    return object
  }

fson.gzip = function (to, replacer, space) {
  var streamOut = fs.createWriteStream(to)
  zlib.gzip(this.toString(replacer, space), function (_, result) {
    streamOut.end(result)
  })
  return this
}

fson.remove = function (properties) {
  remove(this, properties)
  return this
}

fson.save = function (to, replacer, space) {
  var file = fs.createWriteStream(to)
  file.write(this.toString(replacer, space))
  file.end()
  return this
}

fson.toString = function (replacer, space) {
  return JSON.stringify(this, replacer, space)
}

function remove(data, properties) {

  properties.replace(/\w+/g, function (property) {
    if (property in data) {
      delete data[property]
    }
  })

  if (data.children) {
    data.children.forEach(function (child) {
      remove(child, properties)
    })
  }

}

function toObject(dir) {

  var walk = function (dir) {

    var info = {
      name: path.basename(dir)
    }

    var stats = fs.statSync(dir)

    if (stats.isDirectory()) {

      info.children = []
      var files = []

      fs.readdirSync(dir).forEach(function (child) {
        var childPath = path.join(dir, child)
        if (fs.statSync(childPath).isDirectory()) {
          info.children.push(walk(childPath))
        }
        else {
          files.push(childPath)
        }
      })

      files.forEach(function (childPath) {
        info.children.push(walk(childPath))
      })

    }

    else {

      info.date = stats.mtime
      info.size = stats.size

    }

    return info

  }

  return walk(dir)

}

<commit_msg>Add save(,,callback)<commit_after>
var fs = require('fs'),
  path = require('path'),
  zlib = require('zlib'),
  fson = module.exports = function (path) {
    var object = path

    if (typeof path === 'string') {
      object = toObject(path)
    }

    object.__proto__ = fson

    return object
  }

fson.gzip = function (to, replacer, space) {
  var streamOut = fs.createWriteStream(to)
  zlib.gzip(this.toString(replacer, space), function (_, result) {
    streamOut.end(result)
  })
  return this
}

fson.remove = function (properties) {
  remove(this, properties)
  return this
}

fson.save = function (to, replacer, space, callback) {
  var a = Array.prototype.slice.call(arguments)
  if (typeof a[1] === 'function') a.splice(1, 0, undefined)
  if (typeof a[2] === 'function') a.splice(2, 0, undefined)
  fs.writeFile(a[0], this.toString(a[1], a[2]), a[3])
  return this
}

fson.toString = function (replacer, space) {
  return JSON.stringify(this, replacer, space)
}

function remove(data, properties) {

  properties.replace(/\w+/g, function (property) {
    if (property in data) {
      delete data[property]
    }
  })

  if (data.children) {
    data.children.forEach(function (child) {
      remove(child, properties)
    })
  }

}

function toObject(dir) {

  var walk = function (dir) {

    var info = {
      name: path.basename(dir)
    }

    var stats = fs.statSync(dir)

    if (stats.isDirectory()) {

      info.children = []
      var files = []

      fs.readdirSync(dir).forEach(function (child) {
        var childPath = path.join(dir, child)
        if (fs.statSync(childPath).isDirectory()) {
          info.children.push(walk(childPath))
        }
        else {
          files.push(childPath)
        }
      })

      files.forEach(function (childPath) {
        info.children.push(walk(childPath))
      })

    }

    else {

      info.date = stats.mtime
      info.size = stats.size

    }

    return info

  }

  return walk(dir)

}

<|endoftext|>


<commit_before>var AWS = require("aws-sdk");

var s3 = new AWS.S3({
  accessKeyId: process.env.AWS_KEY,
  secretAccessKey: process.env.AWS_SECRET
});

var importer = require("./importer")(s3);

if (!process.env.ELASTICSEARCH_URL) {
  console.log("You must specify ELASTICSEARCH_URL");
  process.exit(1);
}

if (process.env.S3_BUCKET) {
  importer.importFolder(process.env.S3_BUCKET, process.env.ELASTICSEARCH_URL).then(function(data) {
    console.log(data);
  }, function(error) {
    if (typeof(error) === "object" && error.message) {
      console.error(error.message);
      if (error.stack) {
        console.error(error.stack);
      }
    } else {
      console.error(error);
    }
    process.exit(1);
  });
} else {
  console.error("You must specify S3_BUCKET");
  process.exit(1);
}
<commit_msg>Add support for debug mode<commit_after>var AWS = require("aws-sdk");

var s3 = new AWS.S3({
  accessKeyId: process.env.AWS_KEY,
  secretAccessKey: process.env.AWS_SECRET
});

var elasticsearchUrl = process.env.ELASTICSEARCH_URL;
var s3Bucket = process.env.S3_BUCKET;
var debug = process.env.DEBUG;
var importer = require("./importer")(s3, {debug: debug});

if (!elasticsearchUrl) {
  console.log("You must specify ELASTICSEARCH_URL");
  process.exit(1);
}

if (s3Bucket) {
  importer.importFolder(s3Bucket, elasticsearchUrl).then(function(data) {
    console.log("Finished importing from bucket", s3Bucket, "to", elasticsearchUrl);
    console.log("Summary:", data);
  }, function(error) {
    if (typeof(error) === "object" && error.message) {
      console.error(error.message);
      if (error.stack) {
        console.error(error.stack);
      }
    } else {
      console.error(error);
    }
    process.exit(1);
  });
} else {
  console.error("You must specify S3_BUCKET");
  process.exit(1);
}
<|endoftext|>


<commit_before>var AmazonController,
  request = require('request'),
  parseXML = require('xml2js').parseString,
  Promise = require('es6-promise').Promise,
  crypto = require('crypto');

AmazonController = function(Secret_Key, AWS_ID, Associate_Tag) {
  var Credentials = {
    Secret_Key: Secret_Key,
    AWS_ID: AWS_ID,
    Associate_Tag: Associate_Tag
  }

  function generateSignature(stringToSign, awsSecret) {
    var hmac = crypto.createHmac('sha256', awsSecret);
    var signature = hmac.update(stringToSign).digest('base64');

    return signature;
  }

  function EncapsulateItemArray(prefix, ItemArray) {
    if(!Array.isArray(ItemArray)) {
      throw new Error("Parameters not array");
    }

    var ReturnArr = new Array();

    for(var i = 0; i < ItemArray.length; i++) {
      if(typeof ItemArray[i] === "object") {
        for(var name in ItemArray[i]) {
          ReturnArr.push(prefix + "." + (i+1) + "." + name + "=" + encodeURIComponent(ItemArray[i][name]));
        }
      } else {
        ReturnArr.push(prefix + "." + (i+1) + "=" + encodeURIComponent(ItemArray[i]));
      }
    }

    return ReturnArr.join("&");
  }

  function GenerateURL(query) {
    if(typeof query !== "object") {
      throw new Error("Query not Object");
    }

    var domain = "com";
    var amazonQuery = {
      ASIN: null,
      AWSAccessKeyId: Credentials.AWS_ID,
      Action: null,
      AssociateTag: Credentials.Associate_Tag,
      CartId: null,
      CartItemId: null,
      Condition: "New",
      HMAC: null,
      IdType: null,
      IncludeReviewsSummary: null,
      Item: null,
      ItemId: null,
      ItemLookup: null,
      MarketplaceDomain: null,
      MerchantId: null,
      OfferListingId: null,
      Operation: "ItemLookup",
      Quantity: null,
      RelatedItemPage: null,
      RelationshipType: null,
      ResponseGroup: "Small",
      SearchIndex: null,
      Service: "AWSECommerceService",
      SimilarityType: null,
      Timestamp: (new Date()).toISOString(),
      TruncateReviewsAt: null,
      Validate: null,
      VariationPage: null,
      Version: "2013-08-01",
      XMLEscaping: null
    };

    for(var name in query) {
      if(typeof amazonQuery[name] !== "undefined") {
        if(name === "domain") {
          domain = query[name];
        } else {
          amazonQuery[name] = query[name];
        }
      }
    }

    var unsignedString = new Array();

    for(var name in amazonQuery) {
      if(amazonQuery[name] !== null) {
        if(Array.isArray(amazonQuery[name])) {
          unsignedString.push(EncapsulateItemArray(name, amazonQuery[name]));
        } else {
          unsignedString.push(name + "=" + encodeURIComponent(amazonQuery[name]));
        }
      }
    }

    var signature = encodeURIComponent(generateSignature('GET\nwebservices.amazon.' + domain + '\n/onca/xml\n' + unsignedString.join("&"), Credentials.Secret_Key)).replace(/\+/g, '%2B');
    var queryString = 'http://webservices.amazon.' + domain + '/onca/xml?' + unsignedString.join("&") + '&Signature=' + signature;

    return queryString;
  }

  this.Query = function(query, callback) {
    var url = GenerateURL(query);

    if (typeof callback === 'function') {
      request(url, function(err, response, body) {
        if (err) {
          callback(err);
        }

        if (response.statusCode != 200) {
          parseXML(body, function(err, resp){
            if (err){
              callback(err);
            }
            callback(resp[query.Operation + "ErrorResponse"]);
          });
        } else {
          parseXML(body, function(err, resp){
            callback(null, resp[query.Operation + "Response"].Items);
          });
        }
      });

    }

    var promise = new Promise(function(resolve, reject) {
      request(url, function(err, response, body) {
        if (err) {
          reject(err);
        }

        if (response.statusCode != 200) {
          parseXML(body, {explicitArray: false}, function(err, resp){
            if(err){
              reject(err)
            }
            for(var name in resp) {
              reject((resp[name]));
              break;
            }
          });
        } else {
          parseXML(body, {explicitArray: false}, function(err, resp){
            for(var name in resp) {
              resolve((resp[name]));
              break;
            }
          });
        }
      });
    });

    return promise;
  }
};

module.exports = AmazonController;
<commit_msg>Domain fix<commit_after>var AmazonController,
  request = require('request'),
  parseXML = require('xml2js').parseString,
  Promise = require('es6-promise').Promise,
  crypto = require('crypto');

AmazonController = function(Secret_Key, AWS_ID, Associate_Tag) {
  var Credentials = {
    Secret_Key: Secret_Key,
    AWS_ID: AWS_ID,
    Associate_Tag: Associate_Tag
  }

  function generateSignature(stringToSign, awsSecret) {
    var hmac = crypto.createHmac('sha256', awsSecret);
    var signature = hmac.update(stringToSign).digest('base64');

    return signature;
  }

  function EncapsulateItemArray(prefix, ItemArray) {
    if(!Array.isArray(ItemArray)) {
      throw new Error("Parameters not array");
    }

    var ReturnArr = new Array();

    for(var i = 0; i < ItemArray.length; i++) {
      if(typeof ItemArray[i] === "object") {
        for(var name in ItemArray[i]) {
          ReturnArr.push(prefix + "." + (i+1) + "." + name + "=" + encodeURIComponent(ItemArray[i][name]));
        }
      } else {
        ReturnArr.push(prefix + "." + (i+1) + "=" + encodeURIComponent(ItemArray[i]));
      }
    }

    return ReturnArr.join("&");
  }

  function GenerateURL(query) {
    if(typeof query !== "object") {
      throw new Error("Query not Object");
    }

    var domain = "com";
    var amazonQuery = {
      ASIN: null,
      AWSAccessKeyId: Credentials.AWS_ID,
      Action: null,
      AssociateTag: Credentials.Associate_Tag,
      CartId: null,
      CartItemId: null,
      Condition: "New",
      HMAC: null,
      IdType: null,
      IncludeReviewsSummary: null,
      Item: null,
      ItemId: null,
      ItemLookup: null,
      MarketplaceDomain: null,
      MerchantId: null,
      OfferListingId: null,
      Operation: "ItemLookup",
      Quantity: null,
      RelatedItemPage: null,
      RelationshipType: null,
      ResponseGroup: "Small",
      SearchIndex: null,
      Service: "AWSECommerceService",
      SimilarityType: null,
      Timestamp: (new Date()).toISOString(),
      TruncateReviewsAt: null,
      Validate: null,
      VariationPage: null,
      Version: "2013-08-01",
      XMLEscaping: null
    };

    for(var name in query) {
      if(name === "domain") {
        domain = query[name];
      } else {
        if(typeof amazonQuery[name] !== "undefined") {
          amazonQuery[name] = query[name];
        }
      }
    }

    var unsignedString = new Array();

    for(var name in amazonQuery) {
      if(amazonQuery[name] !== null) {
        if(Array.isArray(amazonQuery[name])) {
          unsignedString.push(EncapsulateItemArray(name, amazonQuery[name]));
        } else {
          unsignedString.push(name + "=" + encodeURIComponent(amazonQuery[name]));
        }
      }
    }

    var signature = encodeURIComponent(generateSignature('GET\nwebservices.amazon.' + domain + '\n/onca/xml\n' + unsignedString.join("&"), Credentials.Secret_Key)).replace(/\+/g, '%2B');
    var queryString = 'http://webservices.amazon.' + domain + '/onca/xml?' + unsignedString.join("&") + '&Signature=' + signature;

    return queryString;
  }

  this.Query = function(query, callback) {
    var url = GenerateURL(query);

    if (typeof callback === 'function') {
      request(url, function(err, response, body) {
        if (err) {
          callback(err);
        }

        if (response.statusCode != 200) {
          parseXML(body, function(err, resp){
            if (err){
              callback(err);
            }
            callback(resp[query.Operation + "ErrorResponse"]);
          });
        } else {
          parseXML(body, function(err, resp){
            callback(null, resp[query.Operation + "Response"].Items);
          });
        }
      });

    }

    var promise = new Promise(function(resolve, reject) {
      request(url, function(err, response, body) {
        if (err) {
          reject(err);
        }

        if (response.statusCode != 200) {
          parseXML(body, {explicitArray: false}, function(err, resp){
            if(err){
              reject(err)
            }
            for(var name in resp) {
              reject((resp[name]));
              break;
            }
          });
        } else {
          parseXML(body, {explicitArray: false}, function(err, resp){
            for(var name in resp) {
              resolve((resp[name]));
              break;
            }
          });
        }
      });
    });

    return promise;
  }
};

module.exports = AmazonController;
<|endoftext|>


<commit_before>#!/usr/bin/env node

const fs = require('fs')
const walk = require('walk')
const moment = require('moment')
const _ = require('underscore')
const path = require('path')
const opn = require('opn')
const cli = require('meow')([`
  Usage
    $ journall <input>

  Options
    -t, --title A title you want as a heading
    -p, --program The program to open with
    --path The path to the folder (Can be specifed with $JOURNALL)

  Examples
    $ get-github-user -t 'Test'
    # Will open a document with test
`], {
  alias: {
    t: 'title',
    p: 'program'
  }
})

const journalFolder = cli.flags.path || path.resolve(process.env['JOURNALL'])
const files = []
const filename = moment().format('YYYY.MM.DD') + '.md'
const fullPath = path.resolve(journalFolder + '/' + filename)
const program = cli.flags.program || process.env['JOURNALL_PROGRAM']
const title = cli.flags.title || cli.input
const walker = walk.walk(journalFolder, { followLinks: false })

function openFile (text) {
  console.log(`${text} Opening page.`)
  opn(fullPath, {app: program, wait: false})
  process.exit(0)
}

function wrapTitle (title) {
  return `\n## ${title}\n`
}

walker.on('file', function (root, stat, next) {
  files.push(stat.name)
  next()
})

walker.on('end', function () {
  var header = `# ${moment().format('YYYY MMMM Do')}\n\n`

  if (!_.contains(files, filename)) {
    // Add the date and an optional title to the header
    if (title && title.length !== 0) {
      header += wrapTitle(title)
    }

    // Create file with simple header
    fs.writeFile(fullPath, header, function (err) {
      if (err) {
        throw new Error(err)
      }
      openFile('Log entered.')
    })
  } else if (title) {
    // Add the optional title at the end of the file
    fs.appendFile(fullPath, wrapTitle(title), function (err) {
      if (err) {
        throw new Error('Writing the new header did not work', err)
      }
      openFile('Date already exists.')
    })
  } else {
    openFile('Date already exists.')
  }
})
<commit_msg>Show error + usage when no path is set.<commit_after>#!/usr/bin/env node

const fs = require('fs')
const walk = require('walk')
const moment = require('moment')
const _ = require('underscore')
const path = require('path')
const opn = require('opn')
const cli = require('meow')([`
  Usage
    $ journall <input>

  Options
    -t, --title A title you want as a heading
    -p, --program The program to open with
    --path The path to the folder (Can be specifed with $JOURNALL)

  Examples
    $ get-github-user -t 'Test'
    # Will open a document with test
`], {
  alias: {
    t: 'title',
    p: 'program'
  }
})

if (!cli.flags.path && !process.env['JOURNALL']) {
  console.log('ERROR: You must either specify --path or set $JOURNALL to a path.')
  cli.showHelp(1)
}

const journalFolder = cli.flags.path || path.resolve(process.env['JOURNALL'])
const files = []
const filename = moment().format('YYYY.MM.DD') + '.md'
const fullPath = path.resolve(journalFolder + '/' + filename)
const program = cli.flags.program || process.env['JOURNALL_PROGRAM']
const title = cli.flags.title || cli.input
const walker = walk.walk(journalFolder, { followLinks: false })

function openFile (text) {
  console.log(`${text} Opening page.`)
  opn(fullPath, {app: program, wait: false})
  process.exit(0)
}

function wrapTitle (title) {
  return `\n## ${title}\n`
}

walker.on('file', function (root, stat, next) {
  files.push(stat.name)
  next()
})

walker.on('end', function () {
  var header = `# ${moment().format('YYYY MMMM Do')}\n\n`

  if (!_.contains(files, filename)) {
    // Add the date and an optional title to the header
    if (title && title.length !== 0) {
      header += wrapTitle(title)
    }

    // Create file with simple header
    fs.writeFile(fullPath, header, function (err) {
      if (err) {
        throw new Error(err)
      }
      openFile('Log entered.')
    })
  } else if (title) {
    // Add the optional title at the end of the file
    fs.appendFile(fullPath, wrapTitle(title), function (err) {
      if (err) {
        throw new Error('Writing the new header did not work', err)
      }
      openFile('Date already exists.')
    })
  } else {
    openFile('Date already exists.')
  }
})
<|endoftext|>


<commit_before>'use strict';

var io = require('../../server.js'),
    fs = require('fs'),
    squirrel = require('squirrel'),
    EventEmitter = require('events').EventEmitter,
    emitter = new EventEmitter(),
    log = require('../../lib/logger'),
    History = require('./backend/history');

// To let another bundle's index.js take advantage of sublistener, we must export an event listener.
// Socket.io dosn't work for inter-index.js communication, because broadcasts don't loopback.
module.exports = emitter;

var cfgPath = __dirname + '/config.json';
if (!fs.existsSync(cfgPath)) {
    throw new Error('[eol-sublistener] config.json was not present in bundles/eol-sublistener, aborting');
}
var config = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));

var history = {};
config['twitch-irc'].channels.forEach(function(channel) {
    history['#' + channel] = new History();
});

// Lazy-load and lazy-install the twitch-irc npm package if necessary
squirrel('twitch-irc', function twitchIrcLoaded(err, irc) {
    var client = new irc.client(config['twitch-irc']);

    client.connect();

    client.addListener('connected', function onConnected(address, port) {
        var msg = '[eol-sublistener] Listening for subscribers on ' + config['twitch-irc'].channels;
        log.info(msg);
    });

    client.addListener('disconnected', function onDisconnected(reason) {
        log.warn('[eol-sublistener] DISCONNECTED:', reason);
    });

    client.addListener('connectfail', function () {
        throw new Error("[eol-sublistener] Failed to connect, reached maximum number of retries");
    });

    client.addListener('subscription', function onSubscription(channel, username) {
        if (!isDuplicate(arg, channel)) {
            acceptSubscription(username)
        }
    });

    if (config.chatevents) {
        log.warn('[eol-sublistener] Chat events are on, may cause high CPU usage');
        client.addListener('chat', function onChat(channel, user, message) {
            if (!isBroadcaster(user, channel) && !isModerator(user))
                return;

            var parts = message.split(' ',2);
            var cmd = parts[0];
            var arg = parts.length > 1 ? parts[1] : null;

            if (!arg)
                return;

            switch (cmd) {
                case '!sendsub':
                    if (isDuplicate(arg, channel)) {
                        client.say(channel, 'That username, ' + arg + ', appears to be a duplicate. Use !sendsubforce to override.');
                        break;
                    }
                case '!sendsubforce':
                    history[channel].add(arg);
                    acceptSubscription(channel, arg);
                    client.say(channel, 'Added ' + arg + ' as a subscriber');
            }
        });
    }
});

function isBroadcaster(user, channel) {
    // Remove the leading "#" from channel when comparing
    return user.username === channel.slice(1);
}

function isModerator(user) {
    return user.special.indexOf('moderator') >= 0;
}

function isDuplicate(username, channel) {
    return history[channel].find(username) >= 0;
}

function acceptSubscription(username) {
    var content = { name: username, resub: false }; //resub not implemented
    io.sockets.json.send({
        bundleName: 'eol-sublistener',
        messageName: 'subscriber',
        content: content
    });
    emitter.emit('subscriber', content);
}
<commit_msg>Send channel when sending a sub event<commit_after>'use strict';

var io = require('../../server.js'),
    fs = require('fs'),
    squirrel = require('squirrel'),
    EventEmitter = require('events').EventEmitter,
    emitter = new EventEmitter(),
    log = require('../../lib/logger'),
    History = require('./backend/history');

// To let another bundle's index.js take advantage of sublistener, we must export an event listener.
// Socket.io dosn't work for inter-index.js communication, because broadcasts don't loopback.
module.exports = emitter;

var cfgPath = __dirname + '/config.json';
if (!fs.existsSync(cfgPath)) {
    throw new Error('[eol-sublistener] config.json was not present in bundles/eol-sublistener, aborting');
}
var config = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));

var history = {};
config['twitch-irc'].channels.forEach(function(channel) {
    history['#' + channel] = new History();
});

// Lazy-load and lazy-install the twitch-irc npm package if necessary
squirrel('twitch-irc', function twitchIrcLoaded(err, irc) {
    var client = new irc.client(config['twitch-irc']);

    client.connect();

    client.addListener('connected', function onConnected(address, port) {
        var msg = '[eol-sublistener] Listening for subscribers on ' + config['twitch-irc'].channels;
        log.info(msg);
    });

    client.addListener('disconnected', function onDisconnected(reason) {
        log.warn('[eol-sublistener] DISCONNECTED:', reason);
    });

    client.addListener('connectfail', function () {
        throw new Error("[eol-sublistener] Failed to connect, reached maximum number of retries");
    });

    client.addListener('subscription', function onSubscription(channel, username) {
        if (!isDuplicate(arg, channel)) {
            acceptSubscription(username)
        }
    });

    if (config.chatevents) {
        log.warn('[eol-sublistener] Chat events are on, may cause high CPU usage');
        client.addListener('chat', function onChat(channel, user, message) {
            if (!isBroadcaster(user, channel) && !isModerator(user))
                return;

            var parts = message.split(' ',2);
            var cmd = parts[0];
            var arg = parts.length > 1 ? parts[1] : null;

            if (!arg)
                return;

            switch (cmd) {
                case '!sendsub':
                    if (isDuplicate(arg, channel)) {
                        client.say(channel, 'That username, ' + arg + ', appears to be a duplicate. Use !sendsubforce to override.');
                        break;
                    }
                case '!sendsubforce':
                    history[channel].add(arg);
                    acceptSubscription(arg, channel);
                    client.say(channel, 'Added ' + arg + ' as a subscriber');
            }
        });
    }
});

function isBroadcaster(user, channel) {
    // Remove the leading "#" from channel when comparing
    return user.username === channel.slice(1);
}

function isModerator(user) {
    return user.special.indexOf('moderator') >= 0;
}

function isDuplicate(username, channel) {
    return history[channel].find(username) >= 0;
}

function acceptSubscription(username) {
    var content = { name: username, resub: false, channel: channel }; //resub not implemented
    io.sockets.json.send({
        bundleName: 'eol-sublistener',
        messageName: 'subscriber',
        content: content
    });
    emitter.emit('subscriber', content);
}
<|endoftext|>


<commit_before>'use strict';

/*
 * pogo : *r -> promise r
 * pogo : ((...args -> *r), ...args) -> promise r
 */
export default function pogo(genOrStar, ...args) {
  const gen = isGen(genOrStar) ? genOrStar : genOrStar(...args)
  const cachedPromisifications = new WeakMap
  return new Promise((ok, notOk) => {
    bounce()

    function bounce(input) {
      let output
      try { output = gen.next(input) }
      catch (e) { return notOk(e) }
      decode(output)
    }
    function toss(error) {
      let output
      try { output = gen.throw(error) }
      catch (e) { return notOk(e) }
      decode(output)
    }

    function decode(output) {
      if (output.done) return ok(output.value)

      const instr = output.value
      if (isPromise(instr)) return instr.then(bounce, toss)
      if (instr instanceof Channel) return instr.take(gen).then(bounce)
      if (instr instanceof Put) return instr.ch.put(gen, instr.val).then(bounce)
      if (instr instanceof Race) {
        const race = { finished: false }
        return instr.ops.forEach(op => {
          if (isPromise(op)) {
            op.then(i => { if (!race.finished) { race.finished = true; bounce(i) } },
                    e => { if (!race.finished) { race.finished = true; toss(e) } })
          }
          if (op instanceof Channel) {
            op.take(race).then(i => bounce({ value: i, channel: op }))
          }
          if (op instanceof Put) {
            op.ch.put(race, op.val).then(() => bounce({ channel: op }))
          }
          if (isGen(op)) {
            if (!cachedPromisifications.has(op)) cachedPromisifications.set(op, pogo(op))
            cachedPromisifications.get(op).then(i => {
              if (!race.finished) { race.finished = true; bounce(i) }
            }, e => {
              if (!race.finished) { race.finished = true; toss(e) }
            })
          }
        })
      }
      if (isGen(instr)) {
        if (!cachedPromisifications.has(instr)) cachedPromisifications.set(instr, pogo(instr))
        return cachedPromisifications.get(instr).then(bounce, toss)
      }

      notOk(new Error("Invalid yield instruction: " + instr + "."))
    }
  })
}

class Put {
  constructor(ch, val) {
    this.ch = ch
    this.val = val
  }
}
pogo.put = (ch, val) => new Put(ch, val)

class Race {
  constructor(ops) {
    this.ops = ops
  }
}
pogo.race = ops => new Race(ops)

class Channel {
  constructor(buf) {
    this.takings = []
    this.putings = buf || new Buffer(0)
  }

  _take(taker, ok, notOk) {
    if (taker.finished) return notOk()

    this._disqualifySlowRacers()
    if (!this.putings.empty()) {
      const puting = this.putings.shift()
      if (puting.alreadyResumed) return ok(puting.value)
      if (puting.puter.finished !== undefined) puting.puter.finished = true
      puting.ok()

      if (taker.finished !== undefined) taker.finished = true
      ok(puting.value)
    } else {
      this.takings.push({taker, ok, notOk})
    }
  }

  _put(puter, value, ok, notOk) {
    if (puter.finished) return notOk()

    this._disqualifySlowRacers()
    if (this.takings.length) {
      const taking = this.takings.shift()
      if (taking.taker.finished !== undefined) taking.taker.finished = true
      taking.ok(value)
      if (puter.finished !== undefined) puter.finished = true
      ok()
    } else if (this.putings.underCapacity()) {
      this.putings.push({value, alreadyResumed: true})
      ok()
    } else {
      this.putings.push({puter, ok, notOk, value})
    }
  }

  put(puter, value) { return new Promise(this._put.bind(this, puter, value)) }
  putAsync(value, ok = noOp) { this._put('async', value, ok) }

  take(taker) { return new Promise(this._take.bind(this, taker)) }
  takeAsync(ok = noOp) { return this._take('async', ok) }

  _disqualifySlowRacers() {
    for (let t of this.takings) {
      if (t.taker.finished) t.notOk()
    }
    this.takings = this.takings.filter(t => !t.taker.finished)
    for (let p of this.putings) {
      if (!p.alreadyResumed && p.puter.finished) p.notOk()
    }
    this.putings.filter(p => p.alreadyResumed || !p.puter.finished)
  }
}
pogo.chan = buf => new Channel(buf)

class Buffer {
  constructor(capacity) {
    this.capacity = capacity
    this.buf = []
  }
  empty() { return this.buf.length === 0 }
  underCapacity() { return this.buf.length < this.capacity }
  push(x) { this.buf.push(x) }
  shift() { return this.buf.shift() }
  filter(p) { this.buf = this.buf.filter(p) }
  [Symbol.iterator]() { return this.buf[Symbol.iterator]() }
}
pogo.strictBuffer = capacity => new Buffer(capacity)

class SlidingBuffer extends Buffer {
  underCapacity() { return true }
  push(x) {
    if (this.buf.length >= this.capacity) this.buf.shift()
    this.buf.push(x)
  }
}
pogo.slidingBuffer = capacity => new SlidingBuffer(capacity)

const isPromise = x => typeof x.then === 'function'
const isGen = x => typeof x.next === 'function' && typeof x.throw === 'function'
const noOp = () => {}
<commit_msg>Fix a few eslint errors.<commit_after>'use strict'

/*
 * pogo : *r -> promise r
 * pogo : ((...args -> *r), ...args) -> promise r
 */
export default function pogo(genOrStar, ...args) {
  const gen = isGen(genOrStar) ? genOrStar : genOrStar(...args)
  const cachedPromisifications = new WeakMap
  return new Promise((ok, notOk) => {
    bounce()

    function bounce(input) {
      let output
      try { output = gen.next(input) }
      catch (e) { notOk(e); return }
      decode(output)
    }
    function toss(error) {
      let output
      try { output = gen.throw(error) }
      catch (e) { notOk(e); return }
      decode(output)
    }

    function decode(output) {
      if (output.done) return ok(output.value)

      const instr = output.value
      if (isPromise(instr)) return instr.then(bounce, toss)
      if (instr instanceof Channel) return instr.take(gen).then(bounce)
      if (instr instanceof Put) return instr.ch.put(gen, instr.val).then(bounce)
      if (instr instanceof Race) {
        const race = { finished: false }
        return instr.ops.forEach(op => {
          if (isPromise(op)) {
            op.then(i => { if (!race.finished) { race.finished = true; bounce(i) } },
                    e => { if (!race.finished) { race.finished = true; toss(e) } })
          }
          if (op instanceof Channel) {
            op.take(race).then(i => bounce({ value: i, channel: op }))
          }
          if (op instanceof Put) {
            op.ch.put(race, op.val).then(() => bounce({ channel: op }))
          }
          if (isGen(op)) {
            if (!cachedPromisifications.has(op)) cachedPromisifications.set(op, pogo(op))
            cachedPromisifications.get(op).then(i => {
              if (!race.finished) { race.finished = true; bounce(i) }
            }, e => {
              if (!race.finished) { race.finished = true; toss(e) }
            })
          }
        })
      }
      if (isGen(instr)) {
        if (!cachedPromisifications.has(instr)) cachedPromisifications.set(instr, pogo(instr))
        return cachedPromisifications.get(instr).then(bounce, toss)
      }

      notOk(new Error("Invalid yield instruction: " + instr + "."))
    }
  })
}

class Put {
  constructor(ch, val) {
    this.ch = ch
    this.val = val
  }
}
pogo.put = (ch, val) => new Put(ch, val)

class Race {
  constructor(ops) {
    this.ops = ops
  }
}
pogo.race = ops => new Race(ops)

class Channel {
  constructor(buf) {
    this.takings = []
    this.putings = buf || new Buffer(0)
  }

  _take(taker, ok, notOk) {
    if (taker.finished) return notOk()

    this._disqualifySlowRacers()
    if (!this.putings.empty()) {
      const puting = this.putings.shift()
      if (puting.alreadyResumed) return ok(puting.value)
      if (puting.puter.finished !== undefined) puting.puter.finished = true
      puting.ok()

      if (taker.finished !== undefined) taker.finished = true
      ok(puting.value)
    } else {
      this.takings.push({taker, ok, notOk})
    }
  }

  _put(puter, value, ok, notOk) {
    if (puter.finished) return notOk()

    this._disqualifySlowRacers()
    if (this.takings.length) {
      const taking = this.takings.shift()
      if (taking.taker.finished !== undefined) taking.taker.finished = true
      taking.ok(value)
      if (puter.finished !== undefined) puter.finished = true
      ok()
    } else if (this.putings.underCapacity()) {
      this.putings.push({value, alreadyResumed: true})
      ok()
    } else {
      this.putings.push({puter, ok, notOk, value})
    }
  }

  put(puter, value) { return new Promise(this._put.bind(this, puter, value)) }
  putAsync(value, ok = noOp) { this._put('async', value, ok) }

  take(taker) { return new Promise(this._take.bind(this, taker)) }
  takeAsync(ok = noOp) { return this._take('async', ok) }

  _disqualifySlowRacers() {
    for (let t of this.takings) {
      if (t.taker.finished) t.notOk()
    }
    this.takings = this.takings.filter(t => !t.taker.finished)
    for (let p of this.putings) {
      if (!p.alreadyResumed && p.puter.finished) p.notOk()
    }
    this.putings.filter(p => p.alreadyResumed || !p.puter.finished)
  }
}
pogo.chan = buf => new Channel(buf)

class Buffer {
  constructor(capacity) {
    this.capacity = capacity
    this.buf = []
  }
  empty() { return this.buf.length === 0 }
  underCapacity() { return this.buf.length < this.capacity }
  push(x) { this.buf.push(x) }
  shift() { return this.buf.shift() }
  filter(p) { this.buf = this.buf.filter(p) }
  [Symbol.iterator]() { return this.buf[Symbol.iterator]() }
}
pogo.strictBuffer = capacity => new Buffer(capacity)

class SlidingBuffer extends Buffer {
  underCapacity() { return true }
  push(x) {
    if (this.buf.length >= this.capacity) this.buf.shift()
    this.buf.push(x)
  }
}
pogo.slidingBuffer = capacity => new SlidingBuffer(capacity)

const isPromise = x => typeof x.then === 'function'
const isGen = x => typeof x.next === 'function' && typeof x.throw === 'function'
const noOp = () => {}
<|endoftext|>