<commit_before>import PercyClient from 'percy-client';
import Environment from 'percy-client/dist/environment';

import { version } from '../package.json';

import FileSystemAssetLoader from './fileSystemAssetLoader';

function parseMissingResources(response) {
  return (
    (response.body.data &&
      response.body.data.relationships &&
      response.body.data.relationships['missing-resources'] &&
      response.body.data.relationships['missing-resources'].data) ||
    []
  );
}

function gatherBuildResources(assetLoaders, percyClient) {
  return new Promise((resolve, reject) => {
    Promise.all(assetLoaders.map(loader => loader.findBuildResources(percyClient)))
      .then(listOfResources => {
        resolve([].concat(...listOfResources));
      })
      .catch(err => {
        // eslint-disable-next-line no-console
        console.log('[percy webdriverio] gatherBuildResources.XXX.reject', err);
        reject(err);
      });
  });
}

function uploadMissingResources(percyClient, buildId, response, shaToResource) {
  const missingResources = parseMissingResources(response);
  const promises = [];
  if (missingResources.length > 0) {
    for (const missingResource of missingResources) {
      promises.push(
        percyClient
          .uploadResource(buildId, shaToResource[missingResource.id].content)
          .then(() => {})
          // eslint-disable-next-line no-console
          .catch(err => console.log('[percy webdriverio] uploadMissingResources', err)),
      );
    }
  }
  return Promise.all(promises);
}

class WebdriverPercy {
  constructor(browser) {
    if (!browser) {
      throw new Error('A WebdriverIO instance is needed to initialise percy-webdriverio');
    }
    browser.percy = { assetLoaders: [] };

    const enabled = isEnabled();
    const token = process.env.PERCY_TOKEN;
    const apiUrl = process.env.PERCY_API;
    const clientInfo = `percy-webdriverio ${version}`;
    browser.percy.environment = new Environment(process.env);
    browser.percy.percyClient = new PercyClient({ token, apiUrl, clientInfo });

    // adding `async` as function name disables the synchronous behavior of WebdriverIO commands
    // eslint-disable-next-line prefer-arrow-callback
    browser.addCommand('__percyReinit', function async() {
      browser.percy = { assetLoaders: [] };
      browser.percy.environment = new Environment(process.env);
      browser.percy.percyClient = new PercyClient({ token, apiUrl, clientInfo });
    });

    browser.addCommand('percyFinalizeBuild', () => {
      throw new Error(
        '[percy] browser.percyFinalizeBuild is deprecated, see https://github.com/percy/percy-webdriverio/pull/19',
      );
    });

    browser.addCommand('percyUseAssetLoader', () => {
      throw new Error(
        '[percy] browser.percyUseAssetLoader is deprecated, see https://github.com/percy/percy-webdriverio/pull/19',
      );
    });

    browser.addCommand('percySnapshot', function async(name, options = {}) {
      if (!enabled) {
        browser.logger.info('Percy is disabled, skipping screenshot: ' + name);
        return;
      }
      const percy = browser.percy;
      const browserInstance = this;
      const percyClient = percy.percyClient;
      return new Promise((resolve, reject) => {
        Promise.resolve(browserInstance.getSource())
          .then(source => {
            percyBuildId('percySnapshot')
              .then(buildId => {
                const rootResource = percyClient.makeResource({
                  resourceUrl: '/',
                  content: source,
                  isRoot: true,
                  mimetype: 'text/html',
                });
                percyClient
                  .createSnapshot(buildId, [rootResource], {
                    name,
                    widths: options.widths,
                    enableJavaScript: options.enableJavaScript,
                    minimumHeight: options.minimumHeight,
                  })
                  .then(snapshotResponse => {
                    const snapshotId = snapshotResponse.body.data.id;
                    const shaToResource = {};
                    shaToResource[rootResource.sha] = rootResource;
                    uploadMissingResources(percyClient, buildId, snapshotResponse, shaToResource)
                      .then(() => {
                        percyClient
                          .finalizeSnapshot(snapshotId)
                          .then(() => {
                            browser.logger.info('percy finalizeSnapshot');
                            resolve();
                          })
                          .catch(err => {
                            browser.logger.error(`percy finalizeSnapshot failed: ${err}`);
                            reject(err);
                          });
                      })
                      .catch(err => {
                        browser.logger.error(`percy uploadMissingResources failed: ${err}`);
                        reject(err);
                      });
                  })
                  .catch(err => {
                    browser.logger.error(`percy createSnapshot failed: ${err}`);
                    resolve();
                  });
              })
              .catch(err => {
                browser.logger.error(`percy snapshot failed to createBuild: ${err}`);
                reject(err);
              });
          })
          .catch(err => {
            browser.logger.error(`percy snapshot failed to get source from browser: ${err}`);
            reject(err);
          });
      });
    });
  }
}

export function init(webdriverInstance, options) {
  return new WebdriverPercy(webdriverInstance, options);
}

export function assetLoader(type, options) {
  switch (type) {
    case 'filesystem':
      return new FileSystemAssetLoader(options);
    default:
      throw new Error(`Unexpected asset loader type: ${type}`);
  }
}

function createPercyClient() {
  const token = process.env.PERCY_TOKEN;
  const apiUrl = process.env.PERCY_API;
  const clientInfo = `percy-webdriverio ${version}`;
  return new PercyClient({ token, apiUrl, clientInfo });
}

function isEnabled() {
  const hasRequiredVars = Boolean(process.env.PERCY_TOKEN) && Boolean(process.env.PERCY_PROJECT);
  const hasDisableVar = parseInt(process.env.PERCY_ENABLE) === 0;
  return hasRequiredVars && !hasDisableVar;
}

function logError(message) {
  console.log(`[percy] ${message}`); // eslint-disable-line no-console
}

function logInfo(message) {
  console.log(`[percy] ${message}`); // eslint-disable-line no-console
}

function percyBuildId(caller) {
  return new Promise((resolve, reject) => {
    if (process.env.PERCY_WEBDRIVERIO_BUILD === undefined) {
      reject(new Error(`[percy] ${caller}: createBuild needs to be called in onPrepare`));
    } else {
      resolve(process.env.PERCY_WEBDRIVERIO_BUILD);
    }
  });
}

export function finalizeBuild() {
  if (!isEnabled()) {
    return;
  }
  let percyClient = createPercyClient();
  return new Promise((resolve, reject) => {
    percyBuildId('finalizeBuild')
      .then(buildId => {
        percyClient
          .finalizeBuild(buildId)
          .then(() => {
            logInfo(`finalizedBuild[${buildId}]: ok`);
            resolve(true);
          })
          .catch(err => {
            logError(`finalizedBuild[${buildId}]: ${err}`);
            reject(err);
          });
      })
      .catch(err => {
        logError('finalizedBuild failed to get build id');
        reject(err);
      });
  });
}

export function __reinit(browser) {
  browser.__percyReinit();
  delete process.env.PERCY_WEBDRIVERIO_BUILD;
}

export function createBuild(assetLoaders) {
  if (!isEnabled()) {
    logInfo(
      'Percy disabled. Set the PERCY_TOKEN and PERCY_PROJECT and unset PERCY_ENABLE to re-enable Percy.',
    );
    return new Promise(resolve => {
      resolve(null);
    });
  }
  return new Promise((resolve, reject) => {
    let percyClient = createPercyClient();
    let environment = new Environment(process.env);
    gatherBuildResources(assetLoaders || [], percyClient)
      .then(resources => {
        percyClient
          .createBuild(environment.repo, { resources })
          .then(buildResponse => {
            const buildId = buildResponse.body.data.id;
            const shaToResource = {};
            for (const resource of resources) {
              shaToResource[resource.sha] = resource;
            }
            uploadMissingResources(percyClient, buildId, buildResponse, shaToResource)
              .then(() => {
                process.env.PERCY_WEBDRIVERIO_BUILD = buildId;
                resolve(buildId);
              })
              .catch(err => {
                logError(`createBuild: failed to upload resources: ${err}`);
                reject(err);
              });
          })
          .catch(err => {
            logError(`createBuild: createBuild failed: ${err}`);
            reject(err);
          });
      })
      .catch(err => {
        logError(`createBuild: gatherBuildResources failed: ${err}`);
        reject(err);
      });
  });
}
<commit_msg>Update disabled log message<commit_after>import PercyClient from 'percy-client';
import Environment from 'percy-client/dist/environment';

import { version } from '../package.json';

import FileSystemAssetLoader from './fileSystemAssetLoader';

function parseMissingResources(response) {
  return (
    (response.body.data &&
      response.body.data.relationships &&
      response.body.data.relationships['missing-resources'] &&
      response.body.data.relationships['missing-resources'].data) ||
    []
  );
}

function gatherBuildResources(assetLoaders, percyClient) {
  return new Promise((resolve, reject) => {
    Promise.all(assetLoaders.map(loader => loader.findBuildResources(percyClient)))
      .then(listOfResources => {
        resolve([].concat(...listOfResources));
      })
      .catch(err => {
        // eslint-disable-next-line no-console
        console.log('[percy webdriverio] gatherBuildResources.XXX.reject', err);
        reject(err);
      });
  });
}

function uploadMissingResources(percyClient, buildId, response, shaToResource) {
  const missingResources = parseMissingResources(response);
  const promises = [];
  if (missingResources.length > 0) {
    for (const missingResource of missingResources) {
      promises.push(
        percyClient
          .uploadResource(buildId, shaToResource[missingResource.id].content)
          .then(() => {})
          // eslint-disable-next-line no-console
          .catch(err => console.log('[percy webdriverio] uploadMissingResources', err)),
      );
    }
  }
  return Promise.all(promises);
}

class WebdriverPercy {
  constructor(browser) {
    if (!browser) {
      throw new Error('A WebdriverIO instance is needed to initialise percy-webdriverio');
    }
    browser.percy = { assetLoaders: [] };

    const enabled = isEnabled();
    const token = process.env.PERCY_TOKEN;
    const apiUrl = process.env.PERCY_API;
    const clientInfo = `percy-webdriverio ${version}`;
    browser.percy.environment = new Environment(process.env);
    browser.percy.percyClient = new PercyClient({ token, apiUrl, clientInfo });

    // adding `async` as function name disables the synchronous behavior of WebdriverIO commands
    // eslint-disable-next-line prefer-arrow-callback
    browser.addCommand('__percyReinit', function async() {
      browser.percy = { assetLoaders: [] };
      browser.percy.environment = new Environment(process.env);
      browser.percy.percyClient = new PercyClient({ token, apiUrl, clientInfo });
    });

    browser.addCommand('percyFinalizeBuild', () => {
      throw new Error(
        '[percy] browser.percyFinalizeBuild is deprecated, see https://github.com/percy/percy-webdriverio/pull/19',
      );
    });

    browser.addCommand('percyUseAssetLoader', () => {
      throw new Error(
        '[percy] browser.percyUseAssetLoader is deprecated, see https://github.com/percy/percy-webdriverio/pull/19',
      );
    });

    browser.addCommand('percySnapshot', function async(name, options = {}) {
      if (!enabled) {
        browser.logger.info('Percy is disabled, skipping screenshot: ' + name);
        return;
      }
      const percy = browser.percy;
      const browserInstance = this;
      const percyClient = percy.percyClient;
      return new Promise((resolve, reject) => {
        Promise.resolve(browserInstance.getSource())
          .then(source => {
            percyBuildId('percySnapshot')
              .then(buildId => {
                const rootResource = percyClient.makeResource({
                  resourceUrl: '/',
                  content: source,
                  isRoot: true,
                  mimetype: 'text/html',
                });
                percyClient
                  .createSnapshot(buildId, [rootResource], {
                    name,
                    widths: options.widths,
                    enableJavaScript: options.enableJavaScript,
                    minimumHeight: options.minimumHeight,
                  })
                  .then(snapshotResponse => {
                    const snapshotId = snapshotResponse.body.data.id;
                    const shaToResource = {};
                    shaToResource[rootResource.sha] = rootResource;
                    uploadMissingResources(percyClient, buildId, snapshotResponse, shaToResource)
                      .then(() => {
                        percyClient
                          .finalizeSnapshot(snapshotId)
                          .then(() => {
                            browser.logger.info('percy finalizeSnapshot');
                            resolve();
                          })
                          .catch(err => {
                            browser.logger.error(`percy finalizeSnapshot failed: ${err}`);
                            reject(err);
                          });
                      })
                      .catch(err => {
                        browser.logger.error(`percy uploadMissingResources failed: ${err}`);
                        reject(err);
                      });
                  })
                  .catch(err => {
                    browser.logger.error(`percy createSnapshot failed: ${err}`);
                    resolve();
                  });
              })
              .catch(err => {
                browser.logger.error(`percy snapshot failed to createBuild: ${err}`);
                reject(err);
              });
          })
          .catch(err => {
            browser.logger.error(`percy snapshot failed to get source from browser: ${err}`);
            reject(err);
          });
      });
    });
  }
}

export function init(webdriverInstance, options) {
  return new WebdriverPercy(webdriverInstance, options);
}

export function assetLoader(type, options) {
  switch (type) {
    case 'filesystem':
      return new FileSystemAssetLoader(options);
    default:
      throw new Error(`Unexpected asset loader type: ${type}`);
  }
}

function createPercyClient() {
  const token = process.env.PERCY_TOKEN;
  const apiUrl = process.env.PERCY_API;
  const clientInfo = `percy-webdriverio ${version}`;
  return new PercyClient({ token, apiUrl, clientInfo });
}

function isEnabled() {
  const hasRequiredVars = Boolean(process.env.PERCY_TOKEN) && Boolean(process.env.PERCY_PROJECT);
  const hasDisableVar = parseInt(process.env.PERCY_ENABLE) === 0;
  return hasRequiredVars && !hasDisableVar;
}

function logError(message) {
  console.log(`[percy] ${message}`); // eslint-disable-line no-console
}

function logInfo(message) {
  console.log(`[percy] ${message}`); // eslint-disable-line no-console
}

function percyBuildId(caller) {
  return new Promise((resolve, reject) => {
    if (process.env.PERCY_WEBDRIVERIO_BUILD === undefined) {
      reject(new Error(`[percy] ${caller}: createBuild needs to be called in onPrepare`));
    } else {
      resolve(process.env.PERCY_WEBDRIVERIO_BUILD);
    }
  });
}

export function finalizeBuild() {
  if (!isEnabled()) {
    return;
  }
  let percyClient = createPercyClient();
  return new Promise((resolve, reject) => {
    percyBuildId('finalizeBuild')
      .then(buildId => {
        percyClient
          .finalizeBuild(buildId)
          .then(() => {
            logInfo(`finalizedBuild[${buildId}]: ok`);
            resolve(true);
          })
          .catch(err => {
            logError(`finalizedBuild[${buildId}]: ${err}`);
            reject(err);
          });
      })
      .catch(err => {
        logError('finalizedBuild failed to get build id');
        reject(err);
      });
  });
}

export function __reinit(browser) {
  browser.__percyReinit();
  delete process.env.PERCY_WEBDRIVERIO_BUILD;
}

export function createBuild(assetLoaders) {
  if (!isEnabled()) {
    logInfo(
      'Percy disabled. Set PERCY_TOKEN and PERCY_PROJECT, and ensure PERCY_ENABLE is not set to 0 to re-enable Percy.',
    );
    return new Promise(resolve => {
      resolve(null);
    });
  }
  return new Promise((resolve, reject) => {
    let percyClient = createPercyClient();
    let environment = new Environment(process.env);
    gatherBuildResources(assetLoaders || [], percyClient)
      .then(resources => {
        percyClient
          .createBuild(environment.repo, { resources })
          .then(buildResponse => {
            const buildId = buildResponse.body.data.id;
            const shaToResource = {};
            for (const resource of resources) {
              shaToResource[resource.sha] = resource;
            }
            uploadMissingResources(percyClient, buildId, buildResponse, shaToResource)
              .then(() => {
                process.env.PERCY_WEBDRIVERIO_BUILD = buildId;
                resolve(buildId);
              })
              .catch(err => {
                logError(`createBuild: failed to upload resources: ${err}`);
                reject(err);
              });
          })
          .catch(err => {
            logError(`createBuild: createBuild failed: ${err}`);
            reject(err);
          });
      })
      .catch(err => {
        logError(`createBuild: gatherBuildResources failed: ${err}`);
        reject(err);
      });
  });
}
<|endoftext|>


<commit_before>/* eslint new-cap: ["error", { "capIsNewExceptions": "Router" }] */
const router = require('express').Router();
const userController = require('../controllers/userController.js');

module.exports = (app, passport) => {
  app.route('/api/v1/users').post((req, res, next) => {
    passport.authenticate('local-signup', (err, user, info) => {
      if (err) {
        return next(err)
      };
      if (user) {
        // user was created in the database
        // Manually establish the session...
        req.login(user, function(err) {
            if (err) return next(err);
            return res.json(info)
        });
      };
      if (!user) {
        return res.json(info)
      }

    })(req, res, next);
  });

  app.route('/api/v1/session').post((req, res, next) => {
    passport.authenticate('local-login', (err, user, info) => {
      if (err) {
        console.log('error in session post: ', err)
        return next(err)
      };
      if (user) {
        console.log('Wait, what?? The user was validated: ', user);
        // user was validated
        // Manually establish the session...
        req.login(user, function(err) {
            if (err) return next(err);
            return res.json(info)
        });
      };
      if (!user) {
        console.log('No user, cannot login');
        return res.json(info)
      }

    })(req, res, next);
  });
};
<commit_msg>(fix) remove console.logs<commit_after>/* eslint new-cap: ["error", { "capIsNewExceptions": "Router" }] */
const router = require('express').Router();
const userController = require('../controllers/userController.js');

module.exports = (app, passport) => {
  app.route('/api/v1/users').post((req, res, next) => {
    passport.authenticate('local-signup', (err, user, info) => {
      if (err) {
        return next(err)
      };
      if (user) {
        // user was created in the database
        // Manually establish the session...
        req.login(user, function(err) {
            if (err) return next(err);
            return res.json(info)
        });
      };
      if (!user) {
        return res.json(info)
      }

    })(req, res, next);
  });

  app.route('/api/v1/session').post((req, res, next) => {
    passport.authenticate('local-login', (err, user, info) => {
      if (err) {
        return next(err)
      };
      if (user) {
        // user was validated
        // Manually establish the session...
        req.login(user, function(err) {
            if (err) return next(err);
            return res.json(info)
        });
      };
      if (!user) {
        return res.json(info)
      }

    })(req, res, next);
  });
};
<|endoftext|>


<commit_before>/*
  base.js - Javascript wrapper for REST Interface to socialfarm.org and other js that should probably go elsewhere

*/

var revision_cache = {};
var do_nothing = function(){};
var user = null;
var DEBUG = true;

function LOG(msg) {
    if (DEBUG)
        console.log(msg);
}

//needs to be fixed, currently returning a global var
function get_user() {
    return user
}

function set_user(val) {
    user = val;
}

function set_user_access_token(token) {
    if (user != null){
        user.AccessToken = token;
    } else {
        sf_login();
    }
}

function warn(msg){
    $('#alert_content').text(msg);
    $('#alert').show();
    $('#alert').focus();
}

function build_readonly_li(label, for_attr, name_attr, type_attr, value_attr){
    return '
' +
           '' + label + '' +
           '<input type="' + type_attr + '" name="' + name_attr + '" id="' + for_attr + '" value = "' + value_attr + '"readonly/>' +
           '
';
}

function build_task_json(){
	var task = Object();
	var data_items = Object();

	$.each($('#task_form #data_items li'), function(item) {
		$.each(this.children, function (child) {
			if (! $(this).is('label') && (! $(this).is('button')) ){
				data_items[jQuery.trim(''+this.id)] = jQuery.trim(''+ this.value) ;
			}
		});
	});

	$.each($('#task_form #task_info li'), function(item) {
		$.each(this.children, function (child) {
			if (! $(this).is('label') && (! $(this).is('button')) ){
				task[jQuery.trim(''+this.id)] = jQuery.trim(''+ this.value) ;
			}
		});
	});
	task.data_items = data_items;
	LOG(task);
	return task;

}

function save_task(){
	var task = build_task_json();
	var url = $('#task_form').attr("action")
	var data = JSON.stringify(task);
	post_json(url, data, null, null);
}

function forward_task(){
	var task = build_task_json();
	var url = $('#task_form').attr("action");
	task.state = 'finished';
	var data = JSON.stringify(task);
	post_json(url, data, null, null);
}

function setHeader(xhr) {
    if (user != null){
        xhr.setRequestHeader('AccessToken', user.accessToken);
    }
}

function get_json(url, successcb, failurecb){
    //if (! url in revision_cache) {
        $.ajax({
            url: url,
            type: 'GET',
            dataType: 'json',
            success: function (response){
                LOG('GET response: ' + JSON.stringify(response));
                revision_cache[url] = JSON.stringify(response);
                successcb(response);
            },
            error: failurecb,
            beforeSend: setHeader
        });
    /*} else {
        LOG('returning cached data...');
        successcb();
    }   */
}

function put_json(url, data, successcb, failurecb){
        if (url in revision_cache && data == revision_cache[url]){
            // trying to put the same object
            LOG('trying to put the same object...');
        } else {
        $.ajax({
            url: url,
            type: 'PUT',
            dataType: 'json',
            data : data,
            success: function (response){
                LOG('PUT response: ' + JSON.stringify(response));
                //should update cache rev
                //revision_cache[url] = response;
                successcb();
            },
            error: failurecb,
            beforeSend: setHeader
        });
    }
}

function post_json(url, data, successcb, failurecb){
    if (url in revision_cache && data == revision_cache[url]){
        // trying to post the same object
        LOG('trying to post the same object...');
    } else {
        $.ajax({
        url: url,
        type: 'POST',
        dataType: 'json',
        data : data,
        success: function (response){
                LOG('POST response: ' + JSON.stringify(response));
                //should update cache rev
                //revision_cache[url] = response;
                successcb();
            },
        error: failurecb,
        beforeSend: setHeader
        });
    }
}

function load_my_tasks(){
    if (user != null){
        id = user.id

        var business_tasks;
        var success = function(tasks) {
            $.each(tasks.rows, function(task){
                $(business_tasks).append('
' +  this.id + '
');
            });
        };
        var failure = function(tasks) {};

        //asynchronously load tasks via api
        $.each( $('.business_tasks') , function(index, value) {
            business_tasks = this;
            var url = "/api/business/" + this.id + "/tasks/" + id ;
            get_json(url, success, failure);
        });
    }
}

function add_user_to_socialfarm(){
    if (get_user() != null){
        var url = "/api/person/" + get_user().id

        var person = Object();
        person.type = 'person';
        person.businesses =  Array()

        var data = JSON.stringify(person) ;

        //add person to socialfarm db

        var update_id = function (response){
            LOG('add user response: ' + response);
            revision_cache[ur].rev = response.rev;
        };
        put_json(url, data, do_nothing, do_nothing);
    }

}

<commit_msg>fixing join business form<commit_after>/*
  base.js - Javascript wrapper for REST Interface to socialfarm.org and other js that should probably go elsewhere

*/

var revision_cache = {};
var do_nothing = function(){};
var user = null;
var DEBUG = true;

function LOG(msg) {
    if (DEBUG)
        console.log(msg);
}

//needs to be fixed, currently returning a global var
function get_user() {
    return user
}

function set_user(val) {
    user = val;
}

function set_user_access_token(token) {
    if (user != null){
        user.AccessToken = token;
    } else {
        sf_login();
    }
}

function warn(msg){
    $('#alert_content').text(msg);
    $('#alert').show();
    $('#alert').focus();
}

function build_readonly_li(label, for_attr, name_attr, type_attr, value_attr){
    return '
' +
           '' + label + '' +
           '<input type="' + type_attr + '" name="' + name_attr + '" id="' + for_attr + '" value = "' + value_attr + '"readonly/>' +
           '
';
}

function build_task_json(){
	var task = Object();
	var data_items = Object();

	$.each($('#task_form #data_items li'), function(item) {
		$.each(this.children, function (child) {
			if (! $(this).is('label') && (! $(this).is('button')) ){
				data_items[jQuery.trim(''+this.id)] = jQuery.trim(''+ this.value) ;
			}
		});
	});

	$.each($('#task_form #task_info li'), function(item) {
		$.each(this.children, function (child) {
			if (! $(this).is('label') && (! $(this).is('button')) ){
				task[jQuery.trim(''+this.id)] = jQuery.trim(''+ this.value) ;
			}
		});
	});
	task.data_items = data_items;
	LOG(task);
	return task;

}

function save_task(){
	var task = build_task_json();
	var url = $('#task_form').attr("action")
	var data = JSON.stringify(task);
	post_json(url, data, null, null);
}

function forward_task(){
	var task = build_task_json();
	var url = $('#task_form').attr("action");
	task.state = 'finished';
	var data = JSON.stringify(task);
	post_json(url, data, null, null);
}

function setHeader(xhr) {
    if (user != null){
        xhr.setRequestHeader('AccessToken', user.accessToken);
    }
}

function get_json(url, successcb, failurecb){
    if (! url in revision_cache) {
        $.ajax({
            url: url,
            type: 'GET',
            dataType: 'json',
            success: function (response){
                LOG('GET response: ' + JSON.stringify(response));
                revision_cache[url] = JSON.stringify(response);
                successcb(response);
            },
            error: failurecb,
            beforeSend: setHeader
        });
    } else {
        LOG('returning cached data...');
        successcb();
    }
}

function put_json(url, data, successcb, failurecb){
        if (url in revision_cache && data == revision_cache[url]){
            // trying to put the same object
            LOG('trying to put the same object...');
        } else {
        $.ajax({
            url: url,
            type: 'PUT',
            dataType: 'json',
            data : data,
            success: function (response){
                LOG('PUT response: ' + JSON.stringify(response));
                //should update cache rev
                //revision_cache[url] = response;
                successcb();
            },
            error: failurecb,
            beforeSend: setHeader
        });
    }
}

function post_json(url, data, successcb, failurecb){
    if (url in revision_cache && data == revision_cache[url]){
        // trying to post the same object
        LOG('trying to post the same object...');
    } else {
        $.ajax({
        url: url,
        type: 'POST',
        dataType: 'json',
        data : data,
        success: function (response){
                LOG('POST response: ' + JSON.stringify(response));
                //should update cache rev
                //revision_cache[url] = response;
                successcb();
            },
        error: failurecb,
        beforeSend: setHeader
        });
    }
}

function load_my_tasks(){
    if (user != null){
        id = user.id

        var business_tasks;
        var success = function(tasks) {
            $.each(tasks.rows, function(task){
                $(business_tasks).append('
' +  this.id + '
');
            });
        };
        var failure = function(tasks) {};

        //asynchronously load tasks via api
        $.each( $('.business_tasks') , function(index, value) {
            business_tasks = this;
            var url = "/api/business/" + this.id + "/tasks/" + id ;
            get_json(url, success, failure);
        });
    }
}

function add_user_to_socialfarm(){
    if (get_user() != null){
        var url = "/api/person/" + get_user().id

        var person = Object();
        person.type = 'person';
        person.businesses =  Array()

        var data = JSON.stringify(person) ;

        //add person to socialfarm db

        var update_id = function (response){
            LOG('add user response: ' + response);
            revision_cache[ur].rev = response.rev;
        };
        put_json(url, data, do_nothing, do_nothing);
    }

}

<|endoftext|>


<commit_before>var events = require('events')
var	net = require('net')
var	os = require('os')

var mem, store = {}

var cmd = {
	sync : '\u0016',
	update : '\u0006'
}

function init() {
	if(!mem)
		setup()
	return mem
}

function log(line, id) {
	var who = id >= 0 ? mem.conf[id].host +':'+ mem.conf[id].port : ''
	mem.emit('log', '[AMNESIA] '+ line +' '+ who)
}

function setup() {
	mem = new events.EventEmitter()
	mem.updated = 0
	mem.remote = false

	Object.defineProperty(mem, 'conf', {
		set : conf,
		get : function() {
			return store.conf
		}
	})

	Object.defineProperty(mem, 'data', {
		set : data,
		get : function() {
			return store.data
		}
	})
}

function conf(value) {
	store.conf = value
	server()
}

function data(value) {
	if(value === undefined
		|| value == Infinity
		|| Number.isNaN(value)
		|| typeof value == 'function')
		return log('Skipping invalid value: '+ value)

	log('Value changed from '+ store.data +' to '
		+ value +' '+ (mem.remote ? 'remotely' : 'locally'))

	mem.updated = Date.now()
	mem.emit('change', store.data, value, mem.remote)
	store.data = value

	if(mem.remote === false) { // new value was set locally, send to other peers
		for(var id = 0; id < mem.conf.length; id++) {
			send(value, id)
		}
	}
	else {
		mem.remote = false
	}
}

function send(value, id, callback) {
	var cid = mem.conf[id]
	if(cid.self) // do not send to itself
		return

	if(!cid.client)
		cid.client = connect(id)

	if(callback)
		cid.callback = callback

	cid.client.write(JSON.stringify(value))
}

function connect(id) {
	var cid = mem.conf[id]
	var client = net.connect(cid.port, cid.host)

	log('Connecting to peer', id)

	client.on('data', function(data) {
		if(cid.callback)
			cid.callback(data.toString(), id)
	})

	client.on('close', function() {
		cid.client = null
		log('Peer connection closed', id)
	})

	client.on('error', function(error) {
		cid.client = null
		log('Peer connection error ('+ error.message +')', id)
	})

	return client
}

function sync() { // on init, SYNC with other peers
	var fresh = 0, id = null
	var callback = function(result, i) {
		var updated = result.split(':')[1]
		if(updated > fresh) {
			fresh = updated
			id = i
		}
	}

	for(var i = 0; i < mem.conf.length; i++) {
		send(cmd.sync, i, callback)
	}

	setTimeout(function() { // wait 1 sec for any sync responses from all peers
		if (id !== null && fresh > mem.updated) // no update needed, all peers have nothing
			update(id)
	}, 1000)

	log('Requesting SYNC to all peers')
}

function update(id) { // on SYNC a peer has an updated value, request it.
	send(cmd.update, id, function(val) {
		mem.remote = true
		mem.data = parse(val)
	})

	log('Requesting UPDATE to', id)
}

function server() {
	var tcpserver = net.createServer(function(socket) {
		var peer = socket.remoteAddress

		socket.on('data', function(value) {
			router(socket, parse(value), peer)
		})

		socket.on('error', function(error) {
			if(error.code == 'ECONNRESET')
		    	log('Peer disconnected '+ peer)
		    else
		    	log('Error ('+ error.message +') connecting to peer '+ peer)
		})

		log('Peer connected '+ peer)
	})

	tcpserver.on('listening', function() {
		mem.conf[mem.conf.id].self = true
		log('Amnesia tcp server running on ', mem.conf.id)
		sync()
	})

	tcpserver.on('error', function(error) {
		if(error.code == 'EADDRINUSE') {
			log('Port already in use. Trying another one')
			mem.conf[mem.conf.id].self = false
			listen(tcpserver)
		}
		else {
			log('Amnesia server error '+ error.message)
		}
	})

	listen(tcpserver)
}

function listen(server) { // find the correct ip and port to bind
	var nifs = JSON.stringify(os.networkInterfaces())

	for (var i in mem.conf) { // loop over conf ips
		if(nifs.indexOf(mem.conf[i].host) != -1 && mem.conf[i].self === undefined) {
			mem.conf.id = i
			return server.listen(mem.conf[i].port, mem.conf[i].host)
		}
	}

	console.error('No configuration found for this machine. '
		+ 'Edit conf.json and add this machine\'s ip/port')

	process.exit(1)
}

function router(socket, data, peer) { // route request to the server
	if(data == cmd.sync) {
		log('Sending SYNC response to peer '+ peer)
		socket.write(cmd.sync +':'+ mem.updated)
	}
	else if(data == cmd.update) {
		log('Sending UPDATE response to peer '+ peer)
		socket.write(JSON.stringify(mem.data))
	}
	else {
		log('Received new value from peer '+ peer)
		mem.remote = true
		mem.data = data
	}
}

function parse(value) {
	try {
		return JSON.parse(value)
	}
	catch(e) {
		return value.toString()
	}
}

// export and init
module.exports = init()
<commit_msg>changing tabs to 2 spaces<commit_after>var events = require('events')
var net = require('net')
var os = require('os')

var mem, store = {}

var cmd = {
  sync : '\u0016',
  update : '\u0006'
}

function init() {
  if(!mem)
    setup()
  return mem
}

function log(line, id) {
  var who = id >= 0 ? mem.conf[id].host +':'+ mem.conf[id].port : ''
  mem.emit('log', '[AMNESIA] '+ line +' '+ who)
}

function setup() {
  mem = new events.EventEmitter()
  mem.updated = 0
  mem.remote = false

  Object.defineProperty(mem, 'conf', {
    set : conf,
    get : function() {
      return store.conf
    }
  })

  Object.defineProperty(mem, 'data', {
    set : data,
    get : function() {
      return store.data
    }
  })
}

function conf(value) {
  store.conf = value
  server()
}

function data(value) {
  if(value === undefined
    || value == Infinity
    || Number.isNaN(value)
    || typeof value == 'function')
    return log('Skipping invalid value: '+ value)

  log('Value changed from '+ store.data +' to '
    + value +' '+ (mem.remote ? 'remotely' : 'locally'))

  mem.updated = Date.now()
  mem.emit('change', store.data, value, mem.remote)
  store.data = value

  if(mem.remote === false) { // new value was set locally, send to other peers
    for(var id = 0; id < mem.conf.length; id++) {
      send(value, id)
    }
  }
  else {
    mem.remote = false
  }
}

function send(value, id, callback) {
  var cid = mem.conf[id]
  if(cid.self) // do not send to itself
    return

  if(!cid.client)
    cid.client = connect(id)

  if(callback)
    cid.callback = callback

  cid.client.write(JSON.stringify(value))
}

function connect(id) {
  var cid = mem.conf[id]
  var client = net.connect(cid.port, cid.host)

  log('Connecting to peer', id)

  client.on('data', function(data) {
    if(cid.callback)
      cid.callback(data.toString(), id)
  })

  client.on('close', function() {
    cid.client = null
    log('Peer connection closed', id)
  })

  client.on('error', function(error) {
    cid.client = null
    log('Peer connection error ('+ error.message +')', id)
  })

  return client
}

function sync() { // on init, SYNC with other peers
  var fresh = 0, id = null
  var callback = function(result, i) {
    var updated = result.split(':')[1]
    if(updated > fresh) {
      fresh = updated
      id = i
    }
  }

  for(var i = 0; i < mem.conf.length; i++) {
    send(cmd.sync, i, callback)
  }

  setTimeout(function() { // wait 1 sec for any sync responses from all peers
    if (id !== null && fresh > mem.updated) // no update needed
      update(id)
  }, 1000)

  log('Requesting SYNC to all peers')
}

function update(id) { // on SYNC a peer has an updated value, request it.
  send(cmd.update, id, function(val) {
    mem.remote = true
    mem.data = parse(val)
  })

  log('Requesting UPDATE to', id)
}

function server() {
  var tcpserver = net.createServer(function(socket) {
    var peer = socket.remoteAddress

    socket.on('data', function(value) {
      router(socket, parse(value), peer)
    })

    socket.on('error', function(error) {
      if(error.code == 'ECONNRESET')
        log('Peer disconnected '+ peer)
      else
        log('Error ('+ error.message +') connecting to peer '+ peer)
    })

    log('Peer connected '+ peer)
  })

  tcpserver.on('listening', function() {
    mem.conf[mem.conf.id].self = true
    log('Amnesia tcp server running on', mem.conf.id)
    sync()
  })

  tcpserver.on('error', function(error) {
    if(error.code == 'EADDRINUSE') {
      log('Port already in use. Trying another one')
      mem.conf[mem.conf.id].self = false
      listen(tcpserver)
    }
    else {
      log('Amnesia server error '+ error.message)
    }
  })

  listen(tcpserver)
}

function listen(server) { // find the correct ip and port to bind
  var nifs = JSON.stringify(os.networkInterfaces())

  for(var i in mem.conf) { // loop over conf ips
    if(nifs.indexOf(mem.conf[i].host) != -1 && mem.conf[i].self === undefined) {
      mem.conf.id = i
      return server.listen(mem.conf[i].port, mem.conf[i].host)
    }
  }

  console.error('No configuration found for this machine. '
    + 'Edit conf.json and add this machine\'s ip/port')

  process.exit(1)
}

function router(socket, data, peer) { // route request to the server
  if(data == cmd.sync) {
    log('Sending SYNC response to peer '+ peer)
    socket.write(cmd.sync +':'+ mem.updated)
  }
  else if(data == cmd.update) {
    log('Sending UPDATE response to peer '+ peer)
    socket.write(JSON.stringify(mem.data))
  }
  else {
    log('Received new value from peer '+ peer)
    mem.remote = true
    mem.data = data
  }
}

function parse(value) {
  try {
    return JSON.parse(value)
  }
  catch(e) {
    return value.toString()
  }
}

// export and init
module.exports = init()
<|endoftext|>


<commit_before>const crc = require('crc')
const moment = require('moment')

function throwParseError (message) {
  throw new Error(`${message}`)
}

function stripParentheses (value) {
  if (value.length < 2 || value[0] !== '(' || value[value.length - 1] !== ')') {
    throwParseError(`Value is not enclosed in parentheses: ${value}`)
  }
  return value.substring(1, value.length - 1)
}

function string (value) {
  value = stripParentheses(value)
  if (value.length % 2 !== 0) {
    throwParseError(`Hex string has odd length: ${value}`)
  }
  const chars = []
  for (let i = 0; i < value.length; i += 2) {
    const substr = value.substr(i, 2)
    const charCode = parseInt(substr, 16)
    if (isNaN(charCode)) {
      throwParseError(`Invalid hex sequence: ${substr}`)
    }
    chars.push(String.fromCharCode(charCode))
  }
  return chars.join('')
}

function timestamp (value) {
  value = stripParentheses(value)
  if (value.length < 1) {
    throwParseError(`Timestamp is too short: ${value}`)
  }

  const dateTimeStr = value.substring(0, value.length - 1)
  const dstFlag = value[value.length - 1]
  // Assuming Dutch timezone. The standard makes no mention of time zones.
  const timezoneOffset = {
    'S': '+02:00',
    'W': '+01:00'
  }[dstFlag]
  if (!timezoneOffset) {
    throwParseError(`Invalid DST flag in timestamp: ${value}`)
  }

  const dateTime = moment(dateTimeStr + timezoneOffset, 'YYMMDDHHmmssZZ')
  if (!dateTime.isValid()) {
    throwParseError(`Could not parse timestamp: ${value}`)
  }
  return dateTime.toDate()
}

function floatWithUnit (expectedUnit) {
  return function parseFloatWithUnit (value) {
    value = stripParentheses(value)

    const parts = value.split('*')
    if (parts.length !== 2) {
      throwParseError(`Value must contain exactly one *: ${value}`)
    }

    const unit = parts[1]
    if (unit !== expectedUnit) {
      throwParseError(`Expected unit ${expectedUnit}, but got ${parts[1]}`)
    }

    const float = parseFloat(parts[0])
    if (isNaN(float)) {
      throwParseError(`Could not parse value as float: ${parts[0]}`)
    }

    return float
  }
}

function singleField (field, parser) {
  return function handle (output, value) {
    output[field] = parser(value)
  }
}

function multipleFields (handlers) {
  return function handle (output, value) {
    const fieldRe = /\([^)]*\)/g
    let match
    let expectedIndex = 0
    let handlerIndex = 0
    while ((match = fieldRe.exec(value)) !== null) {
      if (handlerIndex > handlers.length) {
        throwParseError(`Found more than the expected ${handlers.length} fields in ${value}`)
      }
      if (match.index !== expectedIndex) {
        throwParseError(`Garbage between fields in multi-valued field ${value}`)
      }
      expectedIndex = match.index + match[0].length
      handlers[handlerIndex](output, match[0])
      handlerIndex++
    }
    if (handlerIndex !== handlers.length) {
      throwParseError(`Found fewer than the expected ${handlers.length} fields in ${value}`)
    }
  }
}

function ObisCode ({ a, b, c, d, e, f }) {
  this.a = parseInt(a)
  this.b = parseInt(b)
  this.c = parseInt(c)
  this.d = parseInt(d)
  this.e = parseInt(e)
  this.f = parseInt(f)
}

ObisCode.prototype.matchesPattern = function (pattern) {
  return (
    (pattern.a === undefined || this.a === pattern.a) &&
    (pattern.b === undefined || this.b === pattern.b) &&
    (pattern.c === undefined || this.c === pattern.c) &&
    (pattern.d === undefined || this.d === pattern.d) &&
    (pattern.e === undefined || this.e === pattern.e) &&
    (pattern.f === undefined || this.f === pattern.f)
  )
}

// Mapping from OBIS numbers to parsers. OBIS notation:
// A- B: C. D .E *F
// The parts "C." and "D" are required, the rest are optional. The character
// before F can vary.
//
// Part ("value group") B is the channel number. This distinguishes the
// electricity meter (channel 0) from any gas meters (channels 1-...).
//
// Part F is unused in DSMR and defaults to 255 in that case.
const KNOWN_COSEM_OBJECTS = [
  {obisCode: {a: 0, c: 96, d: 1}, parse: singleField('meterId', string)},
  {obisCode: {a: 0, c: 1, d: 0, e: 0}, parse: singleField('electricityDateTime', timestamp)},
  {obisCode: {a: 1, c: 1, d: 8, e: 1}, parse: singleField('totalElectricityConsumptionKwhLow', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 1, d: 8, e: 2}, parse: singleField('totalElectricityConsumptionKwhHigh', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 2, d: 8, e: 1}, parse: singleField('totalElectricityProductionKwhLow', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 2, d: 8, e: 2}, parse: singleField('totalElectricityProductionKwhHigh', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 1, d: 7, e: 0}, parse: singleField('currentElectricityConsumptionKw', floatWithUnit('kW'))},
  {obisCode: {a: 1, c: 2, d: 7, e: 0}, parse: singleField('currentElectricityProductionKw', floatWithUnit('kW'))},
  {obisCode: {a: 0, c: 24, d: 2, e: 1}, parse: multipleFields([singleField('gasDateTime', timestamp), singleField('totalGasConsumptionM3', floatWithUnit('m3'))])}
  // eslint-disable: object-curly-spacing
]

module.exports = {

  isCrcValid: function checkCrc (data) {
    // [^], unlike ., matches any character _including_ \r and \n.
    const match = /^([^]*!)([a-fA-F0-9]{4})\s*$/.exec(data)
    if (!match) {
      const snippet = (data.length > 12 ? '...' : '') + data.substring(data.length - 12).replace(/\r/g, '\\r').replace(/\n/g, '\\n')
      console.warn(`No CRC found at end of telegram: "${snippet}"`)
      return false
    }

    const expectedCrc = parseInt(match[2], 16)
    if (isNaN(expectedCrc)) {
      console.warn(`Could not parse expected CRC ${match[2]}`)
      return false
    }

    const actualCrc = crc.crc16(match[1])

    if (actualCrc !== expectedCrc) {
      console.warn(`CRC mismatch: expected ${expectedCrc.toString(16)}, got ${actualCrc.toString(16)}`)
      return false
    }

    return true
  },

  parse: function parse (data) {
    const lines = data.split('\r\n').map(line => line.trim()).filter((line) => line.length > 0)
    if (lines.length === 0) {
      throwParseError('No non-blank lines found in telegram')
    }

    const meters = []

    const dataItemRe = /^(?:(\d+)-|)(?:(\d+):|)(\d+)\.(\d+)(?:\.(\d+)|)(?:[^(](\d+)|)(.*)\r\n/mg
    let match
    while ((match = dataItemRe.exec(data)) !== null) {
      let [, a, b, c, d, e, f, value] = match
      if (!a || !b || !e) {
        throwParseError(`Current implementation cannot handle missing value groups A, B or E: ${match[0]}`)
      }
      const obisCode = new ObisCode({ a, b, c, d, e, f })
      const channel = obisCode.b
      const meter = meters[channel] = meters[channel] || {}

      for (const obj of KNOWN_COSEM_OBJECTS) {
        if (obisCode.matchesPattern(obj.obisCode)) {
          obj.parse(meter, value)
          break
        }
      }
    }

    return meters
  }
}
<commit_msg>Require that all meters have an ID<commit_after>const crc = require('crc')
const moment = require('moment')

function throwParseError (message) {
  throw new Error(`${message}`)
}

function stripParentheses (value) {
  if (value.length < 2 || value[0] !== '(' || value[value.length - 1] !== ')') {
    throwParseError(`Value is not enclosed in parentheses: ${value}`)
  }
  return value.substring(1, value.length - 1)
}

function string (value) {
  value = stripParentheses(value)
  if (value.length % 2 !== 0) {
    throwParseError(`Hex string has odd length: ${value}`)
  }
  const chars = []
  for (let i = 0; i < value.length; i += 2) {
    const substr = value.substr(i, 2)
    const charCode = parseInt(substr, 16)
    if (isNaN(charCode)) {
      throwParseError(`Invalid hex sequence: ${substr}`)
    }
    chars.push(String.fromCharCode(charCode))
  }
  return chars.join('')
}

function timestamp (value) {
  value = stripParentheses(value)
  if (value.length < 1) {
    throwParseError(`Timestamp is too short: ${value}`)
  }

  const dateTimeStr = value.substring(0, value.length - 1)
  const dstFlag = value[value.length - 1]
  // Assuming Dutch timezone. The standard makes no mention of time zones.
  const timezoneOffset = {
    'S': '+02:00',
    'W': '+01:00'
  }[dstFlag]
  if (!timezoneOffset) {
    throwParseError(`Invalid DST flag in timestamp: ${value}`)
  }

  const dateTime = moment(dateTimeStr + timezoneOffset, 'YYMMDDHHmmssZZ')
  if (!dateTime.isValid()) {
    throwParseError(`Could not parse timestamp: ${value}`)
  }
  return dateTime.toDate()
}

function floatWithUnit (expectedUnit) {
  return function parseFloatWithUnit (value) {
    value = stripParentheses(value)

    const parts = value.split('*')
    if (parts.length !== 2) {
      throwParseError(`Value must contain exactly one *: ${value}`)
    }

    const unit = parts[1]
    if (unit !== expectedUnit) {
      throwParseError(`Expected unit ${expectedUnit}, but got ${parts[1]}`)
    }

    const float = parseFloat(parts[0])
    if (isNaN(float)) {
      throwParseError(`Could not parse value as float: ${parts[0]}`)
    }

    return float
  }
}

function singleField (field, parser) {
  return function handle (output, value) {
    output[field] = parser(value)
  }
}

function multipleFields (handlers) {
  return function handle (output, value) {
    const fieldRe = /\([^)]*\)/g
    let match
    let expectedIndex = 0
    let handlerIndex = 0
    while ((match = fieldRe.exec(value)) !== null) {
      if (handlerIndex > handlers.length) {
        throwParseError(`Found more than the expected ${handlers.length} fields in ${value}`)
      }
      if (match.index !== expectedIndex) {
        throwParseError(`Garbage between fields in multi-valued field ${value}`)
      }
      expectedIndex = match.index + match[0].length
      handlers[handlerIndex](output, match[0])
      handlerIndex++
    }
    if (handlerIndex !== handlers.length) {
      throwParseError(`Found fewer than the expected ${handlers.length} fields in ${value}`)
    }
  }
}

function ObisCode ({ a, b, c, d, e, f }) {
  this.a = parseInt(a)
  this.b = parseInt(b)
  this.c = parseInt(c)
  this.d = parseInt(d)
  this.e = parseInt(e)
  this.f = parseInt(f)
}

ObisCode.prototype.matchesPattern = function (pattern) {
  return (
    (pattern.a === undefined || this.a === pattern.a) &&
    (pattern.b === undefined || this.b === pattern.b) &&
    (pattern.c === undefined || this.c === pattern.c) &&
    (pattern.d === undefined || this.d === pattern.d) &&
    (pattern.e === undefined || this.e === pattern.e) &&
    (pattern.f === undefined || this.f === pattern.f)
  )
}

// Mapping from OBIS numbers to parsers. OBIS notation:
// A- B: C. D .E *F
// The parts "C." and "D" are required, the rest are optional. The character
// before F can vary.
//
// Part ("value group") B is the channel number. This distinguishes the
// electricity meter (channel 0) from any gas meters (channels 1-...).
//
// Part F is unused in DSMR and defaults to 255 in that case.
const KNOWN_COSEM_OBJECTS = [
  {obisCode: {a: 0, c: 96, d: 1}, parse: singleField('meterId', string)},
  {obisCode: {a: 0, c: 1, d: 0, e: 0}, parse: singleField('electricityDateTime', timestamp)},
  {obisCode: {a: 1, c: 1, d: 8, e: 1}, parse: singleField('totalElectricityConsumptionKwhLow', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 1, d: 8, e: 2}, parse: singleField('totalElectricityConsumptionKwhHigh', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 2, d: 8, e: 1}, parse: singleField('totalElectricityProductionKwhLow', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 2, d: 8, e: 2}, parse: singleField('totalElectricityProductionKwhHigh', floatWithUnit('kWh'))},
  {obisCode: {a: 1, c: 1, d: 7, e: 0}, parse: singleField('currentElectricityConsumptionKw', floatWithUnit('kW'))},
  {obisCode: {a: 1, c: 2, d: 7, e: 0}, parse: singleField('currentElectricityProductionKw', floatWithUnit('kW'))},
  {obisCode: {a: 0, c: 24, d: 2, e: 1}, parse: multipleFields([singleField('gasDateTime', timestamp), singleField('totalGasConsumptionM3', floatWithUnit('m3'))])}
  // eslint-disable: object-curly-spacing
]

module.exports = {

  isCrcValid: function checkCrc (data) {
    // [^], unlike ., matches any character _including_ \r and \n.
    const match = /^([^]*!)([a-fA-F0-9]{4})\s*$/.exec(data)
    if (!match) {
      const snippet = (data.length > 12 ? '...' : '') + data.substring(data.length - 12).replace(/\r/g, '\\r').replace(/\n/g, '\\n')
      console.warn(`No CRC found at end of telegram: "${snippet}"`)
      return false
    }

    const expectedCrc = parseInt(match[2], 16)
    if (isNaN(expectedCrc)) {
      console.warn(`Could not parse expected CRC ${match[2]}`)
      return false
    }

    const actualCrc = crc.crc16(match[1])

    if (actualCrc !== expectedCrc) {
      console.warn(`CRC mismatch: expected ${expectedCrc.toString(16)}, got ${actualCrc.toString(16)}`)
      return false
    }

    return true
  },

  parse: function parse (data) {
    const lines = data.split('\r\n').map(line => line.trim()).filter((line) => line.length > 0)
    if (lines.length === 0) {
      throwParseError('No non-blank lines found in telegram')
    }

    const meters = []

    const dataItemRe = /^(?:(\d+)-|)(?:(\d+):|)(\d+)\.(\d+)(?:\.(\d+)|)(?:[^(](\d+)|)(.*)\r\n/mg
    let match
    while ((match = dataItemRe.exec(data)) !== null) {
      let [, a, b, c, d, e, f, value] = match
      if (!a || !b || !e) {
        throwParseError(`Current implementation cannot handle missing value groups A, B or E: ${match[0]}`)
      }
      const obisCode = new ObisCode({ a, b, c, d, e, f })
      const channel = obisCode.b
      const meter = meters[channel] = meters[channel] || {}

      for (const obj of KNOWN_COSEM_OBJECTS) {
        if (obisCode.matchesPattern(obj.obisCode)) {
          obj.parse(meter, value)
          break
        }
      }
    }

    return meters.filter(({ meterId }) => !!meterId)
  }
}
<|endoftext|>


<commit_before>var mysql = require('mysql');
var async = require('async');
var exec = require('child_process').exec;

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '',
  database : 'wedding'
});

connection.connect();

connection.query('SELECT * from invitation', function(err, rows, fields) {
  if (!err) {
    var pdfs = [];
    async.forEach(rows, function(row, callback){
      console.log(row['title']);
      if(row['language'] === 'English') {
        generateInvitation("invitation_en.svg", "tmp/" + row['id'], {
          title: ['tspan4678', row['title']],
          code: ['tspan4682', row['key']],
          link: ['image232', "https://www.married.dk/#?key=" + row['key']]
        }, callback);

      } else if(row['language'] === 'Latvian') {
        if(row['conjugation'] === 'Plural') {
          generateInvitation("invitation_lv_plural.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image254', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Plural Female') {
          generateInvitation("invitation_lv_plural_female.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image254', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Singular Female') {
          generateInvitation("invitation_lv_singular_female.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image256', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Singular Male') {
          generateInvitation("invitation_lv_singular_male.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image256', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else {
          console.log("did not match template conjugation: " + row['conjugation']);
        }
        //return false;
      } else {
        console.log("did not match template language: " + row['language']);
      }
      pdfs.push("tmp/" + row['id'] + ".pdf");

    }, function(err){
      if (err) return;
      exec("pdftk " + pdfs.join(" ") + " cat output tmp/invitations.pdf", function (error, stdout, stderr) {
        console.log(stdout);
        console.log(stderr);
        console.log("done");
      });
    });

  } else {
    console.log('Error while performing Query.');
  }
});

connection.end();

function generateInvitation(template, outfile, fields, callback) {
  var DOMParser = require('xmldom').DOMParser;
  var XMLSerializer = require('xmldom').XMLSerializer;
  var xmls = new XMLSerializer();
  var qr = require('qr-image');
  var fs = require('fs');
  var base64 = require('base64-stream');
  var data = fs.readFileSync(template, 'utf8');
  var doc = new DOMParser().parseFromString(data);

  var te = doc.getElementById(fields['title'][0]);
  //console.log(d);
  te.textContent = fields['title'][1];

  var ce = doc.getElementById(fields['code'][0]);
  ce.textContent = fields['code'][1];

  var qe = doc.getElementById(fields['link'][0]);
  var qrcode_stream = qr.image(fields['link'][1], {
    type: 'png', ec_level: 'H', margin: 0, parse_url: false, size: 100,
    customize: function(bitmap) {
      //console.log(bitmap.data.length);
      for(var i = 0; i < bitmap.data.length; i++) {
        if(bitmap.data[i] === 0) {
          bitmap.data[i] = 160;
        }
      }
    }
  }).pipe(base64.encode());
  var qrcode_base64 = '';
  qrcode_stream.on('data', function(data) { qrcode_base64 += data })
  qrcode_stream.on('end', function() {
    //console.log(template + "\n");
    qe.setAttribute("xlink:href", "data:" + "image/png" + ";base64," + qrcode_base64);
    // Save the new svg
    fs.writeFileSync(outfile + ".svg", xmls.serializeToString(doc), "utf8");
    exec('inkscape -z --export-dpi=300 --export-text-to-path -f ' + outfile + '.svg --export-pdf=' + outfile + ".pdf", function (error, stdout, stderr) {
      //fs.unlinkSync(outfile + ".svg");
      callback();
    });
  });
}<commit_msg>Make sure we dont start to many conversions at a time<commit_after>var mysql = require('mysql');
var async = require('async');
var exec = require('child_process').exec;

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '',
  database : 'wedding'
});

connection.connect();

connection.query('SELECT * from invitation', function(err, rows, fields) {
  if (!err) {
    var pdfs = [];
    async.eachLimit(rows, 4, function(row, callback){
      console.log(row['title']);
      if(row['language'] === 'English') {
        generateInvitation("invitation_en.svg", "tmp/" + row['id'], {
          title: ['tspan4678', row['title']],
          code: ['tspan4682', row['key']],
          link: ['image232', "https://www.married.dk/#?key=" + row['key']]
        }, callback);

      } else if(row['language'] === 'Latvian') {
        if(row['conjugation'] === 'Plural') {
          generateInvitation("invitation_lv_plural.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image254', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Plural Female') {
          generateInvitation("invitation_lv_plural_female.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image254', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Singular Female') {
          generateInvitation("invitation_lv_singular_female.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image256', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else if(row['conjugation'] === 'Singular Male') {
          generateInvitation("invitation_lv_singular_male.svg", "tmp/" + row['id'], {
            title: ['tspan4678', row['title']],
            code: ['tspan4682', row['key']],
            link: ['image256', "https://www.married.dk/#?key=" + row['key']]
          }, callback);
        } else {
          console.log("did not match template conjugation: " + row['conjugation']);
        }
        //return false;
      } else {
        console.log("did not match template language: " + row['language']);
      }
      pdfs.push("tmp/" + row['id'] + ".pdf");

    }, function(err){
      if (err) return;
      exec("pdftk " + pdfs.join(" ") + " cat output tmp/invitations.pdf", function (error, stdout, stderr) {
        console.log(stdout);
        console.log(stderr);
        console.log("done");
      });
    });

  } else {
    console.log('Error while performing Query.');
  }
});

connection.end();

function generateInvitation(template, outfile, fields, callback) {
  var DOMParser = require('xmldom').DOMParser;
  var XMLSerializer = require('xmldom').XMLSerializer;
  var xmls = new XMLSerializer();
  var qr = require('qr-image');
  var fs = require('fs');
  var base64 = require('base64-stream');
  var data = fs.readFileSync(template, 'utf8');
  var doc = new DOMParser().parseFromString(data);

  var te = doc.getElementById(fields['title'][0]);
  //console.log(d);
  te.textContent = fields['title'][1];

  var ce = doc.getElementById(fields['code'][0]);
  ce.textContent = fields['code'][1];

  var qe = doc.getElementById(fields['link'][0]);
  var qrcode_stream = qr.image(fields['link'][1], {
    type: 'png', ec_level: 'H', margin: 0, parse_url: false, size: 100,
    customize: function(bitmap) {
      //console.log(bitmap.data.length);
      for(var i = 0; i < bitmap.data.length; i++) {
        if(bitmap.data[i] === 0) {
          bitmap.data[i] = 160;
        }
      }
    }
  }).pipe(base64.encode());
  var qrcode_base64 = '';
  qrcode_stream.on('data', function(data) { qrcode_base64 += data })
  qrcode_stream.on('end', function() {
    //console.log(template + "\n");
    qe.setAttribute("xlink:href", "data:" + "image/png" + ";base64," + qrcode_base64);
    // Save the new svg
    fs.writeFileSync(outfile + ".svg", xmls.serializeToString(doc), "utf8");
    exec('inkscape -z --export-dpi=300 --export-text-to-path -f ' + outfile + '.svg --export-pdf=' + outfile + ".pdf", function (error, stdout, stderr) {
      //fs.unlinkSync(outfile + ".svg");
      callback();
    });
  });
}<|endoftext|>


<commit_before>define([
    'jquery',
    'ko',
    'uiComponent',
    'uiRegistry',
    'Magento_Ui/js/modal/modal',
    'mage/template',
    'text!Praxigento_Accounting/templates/customer/accounting/slider.html'
], function ($, ko, Component, uiRegistry, Modal, mageTemplate, innerHtml) {

    /**
     * Collect working data into the local context (scope).
     */
    /* component constants */
    const TYPE_DIRECT = 'direct';
    /* pin globals into UI component scope */
    const baseUrl = BASE_URL;
    const formKey = '?form_key=' + FORM_KEY;
    /* define local working data */
    const urlAdminBase = baseUrl.replace('/customer/', '/');
    const urlAssetGet = urlAdminBase + 'account/asset/get/' + formKey;
    const urlCustomerGet = urlAdminBase + 'prxgt/customer/get_byId/' + formKey;
    const urlCustomerSearch = urlAdminBase + 'prxgt/customer/search_byKey/' + formKey;
    const urlTransfer = urlAdminBase + 'account/asset/transfer/' + formKey;
    /* slider itself */
    var popup;
    /* View Model for slider */
    const viewModel = {
        amount: ko.observable(0),
        assets: undefined,
        counterparty: ko.observable(),
        customer: undefined,
        operationId: 0,
        selectedAsset: ko.observable(),
        selectedCounterparty: undefined,
        transferType: ko.observable(TYPE_DIRECT)
    };

    /**
     * Get current customer ID data from uiRegistry (loaded asynchronously).
     *
     * @returns {*|Integer|string}
     */
    function getCustomerId() {
        /* */
        const customerDs = uiRegistry.get('customer_form.customer_form_data_source');
        const customerData = customerDs.data;
        const customer = customerData.customer;
        const result = customer.entity_id;
        return result;
    }

    /**
     * Front-back communication functions
     */
    /* get initial data to fill in slider (customer info, assets balances, etc.) */
    var fnAjaxGetInitData = function () {
        /* flags for ajax requests - 'true' means that requests is done. */
        var isAjaxGetCustDone = false;
        var isAjaxGetAssetsDone = false;
        /* containers for customer & assets data loaded by AJAX */
        var customer, assets;

        /**
         * Definitions.
         */
        var options = {
            type: 'slide',
            responsive: true,
            innerScroll: true,
            clickableOverlay: true,
            title: $.mage.__('Accounting'),
            buttons: [{
                text: $.mage.__('Cancel'),
                class: '',
                click: function () {
                    this.closeModal();
                }
            }, {
                text: $.mage.__('Process'),
                class: '',
                click: fnAjaxProcessData
            }]
        };
        /* populate template with initial data then open slider */
        var fnModalOpen = function () {
            /* switch off loader */
            $('body').trigger('processStop');
            /* set parsed HTML as content for modal placeholder create modal slider */
            $('#modal_panel_placeholder').html(innerHtml);
            popup = Modal(options, $('#modal_panel_placeholder'));

            /* open modal slider, populate knockout view-model and bind it to template */
            popup.openModal();
            viewModel.amount = ko.observable(0);
            viewModel.assets = assets;
            viewModel.counterparty = ko.observable();
            viewModel.customer = customer;
            viewModel.operationId = 0;
            viewModel.transferType = ko.observable(TYPE_DIRECT);
            var elm = document.getElementById('modal_panel_placeholder');
            ko.cleanNode(elm);
            ko.applyBindings(viewModel, elm);

            /* add JQuery auto complete widget to the slider */
            $('#prxgtCustomerSearch').autocomplete({
                source: fnAjaxCustomerSearch,
                select: fnAutocompleteSelected,
                minLength: 2,
                /* disable auto-complete helper text */
                messages: {
                    noResults: '',
                    results: function () {
                    }
                }
            });
        };
        /* success responses handlers for 2 requests */
        var fnGetCustSuccess = function (response) {
            customer = response.data;
            isAjaxGetCustDone = true;
            if (isAjaxGetCustDone && isAjaxGetAssetsDone) {
                /* open slider */
                fnModalOpen();
            }
        };
        var fnGetAssetsSuccess = function (response) {
            assets = response.data.items;
            isAjaxGetAssetsDone = true;
            if (isAjaxGetCustDone && isAjaxGetAssetsDone) {
                /* open slider */
                fnModalOpen();
            }
        };

        /**
         * Processing
         */
        /* switch on ajax loader */
        $('body').trigger('processStart');

        /* compose and perform ajax request to get customer data */
        const customerId = getCustomerId();
        var request = {data: {customerId: customerId}};
        var json = JSON.stringify(request);
        var opts = {
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: fnGetCustSuccess
        };
        $.ajax(urlCustomerGet, opts);
        /* compose and perform ajax request to get assets data */
        const customerId = getCustomerId();
        request = {data: {customerId: customerId}};
        json = JSON.stringify(request);
        opts = {
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: fnGetAssetsSuccess
        };
        $.ajax(urlAssetGet, opts);
    };

    /**
     * Search counterparty customers on the server and prepare data for UI.
     *
     * @param request
     * @param response
     */
    var fnAjaxCustomerSearch = function (request, response) {
        var data = {data: {search_key: request.term}};
        var json = JSON.stringify(data);
        $.ajax({
            url: urlCustomerSearch,
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: function (resp) {
                /* convert API data into JQuery widget data */
                var data = resp.data;
                var found = [];
                for (var i in data.items) {
                    var one = data.items[i];
                    var nameFirst = one.name_first;
                    var nameLast = one.name_last;
                    var email = one.email;
                    var mlmId = one.mlm_id;
                    var label = nameFirst + ' ' + nameLast + ' <' + email + '> / ' + mlmId;
                    var foundOne = {
                        label: label,
                        value: label,
                        data: one
                    };
                    found.push(foundOne);
                }
                response(found);
            }
        });
    };

    var fnAjaxProcessData = function () {
        var asset = viewModel.selectedAsset();
        var assetId = asset.asset_id;
        var amount = viewModel.amount();
        var customerId = viewModel.customer.id;
        var counterPartyId = viewModel.selectedCounterparty;
        var type = viewModel.transferType();
        var isDirect = (type == TYPE_DIRECT);

        /* see: \Praxigento\Accounting\Controller\Adminhtml\Asset\Transfer */
        var data = {
            amount: amount,
            assetId: assetId,
            counterPartyId: counterPartyId,
            customerId: customerId,
            isDirect: isDirect,
        };
        var json = JSON.stringify({data: data});

        /* process response from server: create modal slider and populate with data */
        var fnSuccess = function (response) {
            /* switch off ajax loader */
            $('body').trigger('processStop');
            viewModel.operationId = response.data.oper_id;
            var elm = document.getElementById('modal_panel_placeholder');
            ko.cleanNode(elm);
            ko.applyBindings(viewModel, elm);
            /* wait 3 sec. & close modal */
            setTimeout(function () {
                popup.closeModal();
            }, 3000);
        };

        var opts = {
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: fnSuccess
        };

        $.ajax(urlTransfer, opts);
        /* switch on ajax loader */
        $('body').trigger('processStart');
    };

    var fnAutocompleteSelected = function (event, ui) {
        viewModel.selectedCounterparty = ui.item.data.id;
    };

    /* bind modal opening to 'Accounting' button on the form */
    /* (see \Praxigento\Accounting\Block\Customer\Adminhtml\Edit\AccountingButton) */
    $('#customer-edit-prxgt-accounting').on('click', fnAjaxGetInitData);

    /* this is required return to prevent Magento parsing errors */
    var result = Component.extend({});
    return result;
});<commit_msg>MOBI-1197 Fix admin/customer/accounting<commit_after>define([
    'jquery',
    'ko',
    'uiComponent',
    'uiRegistry',
    'Magento_Ui/js/modal/modal',
    'mage/template',
    'text!Praxigento_Accounting/templates/customer/accounting/slider.html'
], function ($, ko, Component, uiRegistry, Modal, mageTemplate, innerHtml) {

    /**
     * Collect working data into the local context (scope).
     */
    /* component constants */
    const TYPE_DIRECT = 'direct';
    /* pin globals into UI component scope */
    const baseUrl = BASE_URL;
    const formKey = '?form_key=' + FORM_KEY;
    /* define local working data */
    const urlAdminBase = baseUrl.replace('/customer/', '/');
    const urlAssetGet = urlAdminBase + 'account/asset/get/' + formKey;
    const urlCustomerGet = urlAdminBase + 'prxgt/customer/get_byId/' + formKey;
    const urlCustomerSearch = urlAdminBase + 'prxgt/customer/search_byKey/' + formKey;
    const urlTransfer = urlAdminBase + 'account/asset/transfer/' + formKey;
    /* slider itself */
    var popup;
    /* View Model for slider */
    const viewModel = {
        amount: ko.observable(0),
        assets: undefined,
        counterparty: ko.observable(),
        customer: undefined,
        operationId: 0,
        selectedAsset: ko.observable(),
        selectedCounterparty: undefined,
        transferType: ko.observable(TYPE_DIRECT)
    };

    /**
     * Get current customer ID data from uiRegistry (loaded asynchronously).
     *
     * @returns {*|Integer|string}
     */
    function getCustomerId() {
        /* */
        const customerDs = uiRegistry.get('customer_form.customer_form_data_source');
        const customerData = customerDs.data;
        const customer = customerData.customer;
        const result = customer.entity_id;
        return result;
    }

    /**
     * Front-back communication functions
     */
    /* get initial data to fill in slider (customer info, assets balances, etc.) */
    var fnAjaxGetInitData = function () {
        /* flags for ajax requests - 'true' means that requests is done. */
        var isAjaxGetCustDone = false;
        var isAjaxGetAssetsDone = false;
        /* containers for customer & assets data loaded by AJAX */
        var customer, assets;

        /**
         * Definitions.
         */
        var options = {
            type: 'slide',
            responsive: true,
            innerScroll: true,
            clickableOverlay: true,
            title: $.mage.__('Accounting'),
            buttons: [{
                text: $.mage.__('Cancel'),
                class: '',
                click: function () {
                    this.closeModal();
                }
            }, {
                text: $.mage.__('Process'),
                class: '',
                click: fnAjaxProcessData
            }]
        };
        /* populate template with initial data then open slider */
        var fnModalOpen = function () {
            /* switch off loader */
            $('body').trigger('processStop');
            /* set parsed HTML as content for modal placeholder create modal slider */
            $('#modal_panel_placeholder').html(innerHtml);
            popup = Modal(options, $('#modal_panel_placeholder'));

            /* open modal slider, populate knockout view-model and bind it to template */
            popup.openModal();
            viewModel.amount = ko.observable(0);
            viewModel.assets = assets;
            viewModel.counterparty = ko.observable();
            viewModel.customer = customer;
            viewModel.operationId = 0;
            viewModel.transferType = ko.observable(TYPE_DIRECT);
            var elm = document.getElementById('modal_panel_placeholder');
            ko.cleanNode(elm);
            ko.applyBindings(viewModel, elm);

            /* add JQuery auto complete widget to the slider */
            $('#prxgtCustomerSearch').autocomplete({
                source: fnAjaxCustomerSearch,
                select: fnAutocompleteSelected,
                minLength: 2,
                /* disable auto-complete helper text */
                messages: {
                    noResults: '',
                    results: function () {
                    }
                }
            });
        };
        /* success responses handlers for 2 requests */
        var fnGetCustSuccess = function (response) {
            customer = response.data;
            isAjaxGetCustDone = true;
            if (isAjaxGetCustDone && isAjaxGetAssetsDone) {
                /* open slider */
                fnModalOpen();
            }
        };
        var fnGetAssetsSuccess = function (response) {
            assets = response.data.items;
            isAjaxGetAssetsDone = true;
            if (isAjaxGetCustDone && isAjaxGetAssetsDone) {
                /* open slider */
                fnModalOpen();
            }
        };

        /**
         * Processing
         */
        /* switch on ajax loader */
        $('body').trigger('processStart');

        /* compose common parts for async requests */
        const customerId = getCustomerId();
        var request = {data: {customerId: customerId}};
        var json = JSON.stringify(request);
        var opts = {
            data: json,
            contentType: 'application/json',
            type: 'post'
        };
        /* perform ajax request to get customer data */
        opts.success = fnGetCustSuccess;
        $.ajax(urlCustomerGet, opts);
        /* perform ajax request to get assets data */
        opts.success = fnGetAssetsSuccess;
        $.ajax(urlAssetGet, opts);
    };

    /**
     * Search counterparty customers on the server and prepare data for UI.
     *
     * @param request
     * @param response
     */
    var fnAjaxCustomerSearch = function (request, response) {
        var data = {data: {search_key: request.term}};
        var json = JSON.stringify(data);
        $.ajax({
            url: urlCustomerSearch,
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: function (resp) {
                /* convert API data into JQuery widget data */
                var data = resp.data;
                var found = [];
                for (var i in data.items) {
                    var one = data.items[i];
                    var nameFirst = one.name_first;
                    var nameLast = one.name_last;
                    var email = one.email;
                    var mlmId = one.mlm_id;
                    var label = nameFirst + ' ' + nameLast + ' <' + email + '> / ' + mlmId;
                    var foundOne = {
                        label: label,
                        value: label,
                        data: one
                    };
                    found.push(foundOne);
                }
                response(found);
            }
        });
    };

    var fnAjaxProcessData = function () {
        var asset = viewModel.selectedAsset();
        var assetId = asset.asset_id;
        var amount = viewModel.amount();
        var customerId = viewModel.customer.id;
        var counterPartyId = viewModel.selectedCounterparty;
        var type = viewModel.transferType();
        var isDirect = (type == TYPE_DIRECT);

        /* see: \Praxigento\Accounting\Controller\Adminhtml\Asset\Transfer */
        var data = {
            amount: amount,
            assetId: assetId,
            counterPartyId: counterPartyId,
            customerId: customerId,
            isDirect: isDirect,
        };
        var json = JSON.stringify({data: data});

        /* process response from server: create modal slider and populate with data */
        var fnSuccess = function (response) {
            /* switch off ajax loader */
            $('body').trigger('processStop');
            viewModel.operationId = response.data.oper_id;
            var elm = document.getElementById('modal_panel_placeholder');
            ko.cleanNode(elm);
            ko.applyBindings(viewModel, elm);
            /* wait 3 sec. & close modal */
            setTimeout(function () {
                popup.closeModal();
            }, 3000);
        };

        var opts = {
            data: json,
            contentType: 'application/json',
            type: 'post',
            success: fnSuccess
        };

        $.ajax(urlTransfer, opts);
        /* switch on ajax loader */
        $('body').trigger('processStart');
    };

    var fnAutocompleteSelected = function (event, ui) {
        viewModel.selectedCounterparty = ui.item.data.id;
    };

    /* bind modal opening to 'Accounting' button on the form */
    /* (see \Praxigento\Accounting\Block\Customer\Adminhtml\Edit\AccountingButton) */
    $('#customer-edit-prxgt-accounting').on('click', fnAjaxGetInitData);

    /* this is required return to prevent Magento parsing errors */
    var result = Component.extend({});
    return result;
});<|endoftext|>


<commit_before>// Use the web-push library to hide the implementation details of the communication
// between the application server and the push service.
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
const webPush = require('web-push');

if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
  console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
    "environment variables. You can use the following ones:");
  console.log(webPush.generateVAPIDKeys());
  return;
}
// Set the keys used for encrypting the push messages.
webPush.setVapidDetails(
  'https://serviceworke.rs/',
  process.env.VAPID_PUBLIC_KEY,
  process.env.VAPID_PRIVATE_KEY,
);

const payloads = {};

module.exports = function(app, route) {
  app.get(route + 'vapidPublicKey', function(req, res) {
    res.send(process.env.VAPID_PUBLIC_KEY);
  });

  app.post(route + 'register', function(req, res) {
    // A real world application would store the subscription info.
    res.sendStatus(201);
  });

  app.post(route + 'sendNotification', function(req, res) {
    const subscription = req.body.subscription;
    const payload = req.body.payload;
    const options = {
      TTL: req.body.ttl
    };

    setTimeout(function() {
      payloads[req.body.endpoint] = payload;
      webPush.sendNotification(subscription, null, options)
      .then(function() {
        res.sendStatus(201);
      })
      .catch(function(error) {
        res.sendStatus(500);
        console.log(error);
      });
    }, req.body.delay * 1000);
  });

  app.get(route + 'getPayload', function(req, res) {
    res.send(payloads[req.query.endpoint]);
  });
};
<commit_msg>Fix push-get-payload The client sends the endpoint as a property of the subscription object<commit_after>// Use the web-push library to hide the implementation details of the communication
// between the application server and the push service.
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
const webPush = require('web-push');

if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
  console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
    "environment variables. You can use the following ones:");
  console.log(webPush.generateVAPIDKeys());
  return;
}
// Set the keys used for encrypting the push messages.
webPush.setVapidDetails(
  'https://serviceworke.rs/',
  process.env.VAPID_PUBLIC_KEY,
  process.env.VAPID_PRIVATE_KEY,
);

const payloads = {};

module.exports = function(app, route) {
  app.get(route + 'vapidPublicKey', function(req, res) {
    res.send(process.env.VAPID_PUBLIC_KEY);
  });

  app.post(route + 'register', function(req, res) {
    // A real world application would store the subscription info.
    res.sendStatus(201);
  });

  app.post(route + 'sendNotification', function(req, res) {
    const subscription = req.body.subscription;
    const payload = req.body.payload;
    const options = {
      TTL: req.body.ttl
    };

    setTimeout(function() {
      payloads[req.body.subscription.endpoint] = payload;
      webPush.sendNotification(subscription, null, options)
      .then(function() {
        res.sendStatus(201);
      })
      .catch(function(error) {
        res.sendStatus(500);
        console.log(error);
      });
    }, req.body.delay * 1000);
  });

  app.get(route + 'getPayload', function(req, res) {
    res.send(payloads[req.query.endpoint]);
  });
};
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/* More information about these options at jshint.com/docs/options */

/* jshint browser: true, camelcase: true, curly: true, devel: true,
eqeqeq: true, forin: false, globalstrict: true, quotmark: single,
undef: true, unused: strict */

/* global mozRTCIceCandidate, mozRTCPeerConnection,
mozRTCSessionDescription, webkitRTCPeerConnection */

/* exported trace */

'use strict';

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

function trace(text) {
  // This function is used for logging.
  if (text[text.length - 1] === '\n') {
    text = text.substring(0, text.length - 1);
  }
  console.log((window.performance.now() / 1000).toFixed(3) + ': ' + text);
}

function maybeFixConfiguration(pcConfig) {
  if (!pcConfig) {
    return;
  }
  for (var i = 0; i < pcConfig.iceServers.length; i++) {
    if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
      pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
      delete pcConfig.iceServers[i].urls;
    }
  }
}

if (navigator.mozGetUserMedia) {
  console.log('This appears to be Firefox');

  webrtcDetectedBrowser = 'firefox';

  webrtcDetectedVersion =
    parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);

  // The RTCPeerConnection object.
  RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is not supported in FF yet.
    maybeFixConfiguration(pcConfig);
    return new mozRTCPeerConnection(pcConfig, pcConstraints);
  };

  // The RTCSessionDescription object.
  window.RTCSessionDescription = mozRTCSessionDescription;

  // The RTCIceCandidate object.
  window.RTCIceCandidate = mozRTCIceCandidate;

  // getUserMedia shim (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Creates ICE server from the URL for FF.
  window.createIceServer = function(url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create ICE server with STUN URL.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      if (webrtcDetectedVersion < 27) {
        // Create iceServer with turn url.
        // Ignore the transport parameter from TURN url for FF version <=27.
        var turnUrlParts = url.split('?');
        // Return null for createIceServer if transport=tcp.
        if (turnUrlParts.length === 1 ||
          turnUrlParts[1].indexOf('transport=udp') === 0) {
          iceServer = {
            'url': turnUrlParts[0],
            'credential': password,
            'username': username
          };
        }
      } else {
        // FF 27 and above supports transport parameters in TURN url,
        // So passing in the full url to create iceServer.
        iceServer = {
          'url': url,
          'credential': password,
          'username': username
        };
      }
    }
    return iceServer;
  };

  window.createIceServers = function(urls, username, password) {
    var iceServers = [];
    // Use .url for FireFox.
    for (var i = 0; i < urls.length; i++) {
      var iceServer =
        window.createIceServer(urls[i], username, password);
      if (iceServer !== null) {
        iceServers.push(iceServer);
      }
    }
    return iceServers;
  };

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    console.log('Attaching media stream');
    element.mozSrcObject = stream;
  };

  reattachMediaStream = function(to, from) {
    console.log('Reattaching media stream');
    to.mozSrcObject = from.mozSrcObject;
  };

} else if (navigator.webkitGetUserMedia) {
  console.log('This appears to be Chrome');

  webrtcDetectedBrowser = 'chrome';
  // Temporary fix until crbug/374263 is fixed.
  // Setting Chrome version to 999, if version is unavailable.
  var result = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
  if (result !== null) {
    webrtcDetectedVersion = parseInt(result[2], 10);
  } else {
    webrtcDetectedVersion = 999;
  }

  // Creates iceServer from the url for Chrome M33 and earlier.
  window.createIceServer = function(url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      // Chrome M28 & above uses below TURN format.
      iceServer = {
        'url': url,
        'credential': password,
        'username': username
      };
    }
    return iceServer;
  };

  // Creates iceServers from the urls for Chrome M34 and above.
  window.createIceServers = function(urls, username, password) {
    var iceServers = [];
    if (webrtcDetectedVersion >= 34) {
      // .urls is supported since Chrome M34.
      iceServers = {
        'urls': urls,
        'credential': password,
        'username': username
      };
    } else {
      for (var i = 0; i < urls.length; i++) {
        var iceServer =
          window.createIceServer(urls[i], username, password);
        if (iceServer !== null) {
          iceServers.push(iceServer);
        }
      }
    }
    return iceServers;
  };

  // The RTCPeerConnection object.
  RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is supported since Chrome M34.
    if (webrtcDetectedVersion < 34) {
      maybeFixConfiguration(pcConfig);
    }
    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
  };

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    if (typeof element.srcObject !== 'undefined') {
      element.srcObject = stream;
    } else if (typeof element.mozSrcObject !== 'undefined') {
      element.mozSrcObject = stream;
    } else if (typeof element.src !== 'undefined') {
      element.src = URL.createObjectURL(stream);
    } else {
      console.log('Error attaching stream to element.');
    }
  };

  reattachMediaStream = function(to, from) {
    to.src = from.src;
  };
} else {
  console.log('Browser does not appear to be WebRTC-capable');
}
<commit_msg>set global variables for webRTC detection<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/* More information about these options at jshint.com/docs/options */

/* jshint browser: true, camelcase: true, curly: true, devel: true,
eqeqeq: true, forin: false, globalstrict: true, quotmark: single,
undef: true, unused: strict */

/* global mozRTCIceCandidate, mozRTCPeerConnection,
mozRTCSessionDescription, webkitRTCPeerConnection */

/* exported trace */

'use strict';

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

function trace(text) {
  // This function is used for logging.
  if (text[text.length - 1] === '\n') {
    text = text.substring(0, text.length - 1);
  }
  console.log((window.performance.now() / 1000).toFixed(3) + ': ' + text);
}

function maybeFixConfiguration(pcConfig) {
  if (!pcConfig) {
    return;
  }
  for (var i = 0; i < pcConfig.iceServers.length; i++) {
    if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
      pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
      delete pcConfig.iceServers[i].urls;
    }
  }
}

if (navigator.mozGetUserMedia) {
  console.log('This appears to be Firefox');

  webrtcDetectedBrowser = 'firefox';

  webrtcDetectedVersion =
    parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);

  // The RTCPeerConnection object.
  RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is not supported in FF yet.
    maybeFixConfiguration(pcConfig);
    return new mozRTCPeerConnection(pcConfig, pcConstraints);
  };

  // The RTCSessionDescription object.
  window.RTCSessionDescription = mozRTCSessionDescription;

  // The RTCIceCandidate object.
  window.RTCIceCandidate = mozRTCIceCandidate;

  // getUserMedia shim (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Creates ICE server from the URL for FF.
  window.createIceServer = function(url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create ICE server with STUN URL.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      if (webrtcDetectedVersion < 27) {
        // Create iceServer with turn url.
        // Ignore the transport parameter from TURN url for FF version <=27.
        var turnUrlParts = url.split('?');
        // Return null for createIceServer if transport=tcp.
        if (turnUrlParts.length === 1 ||
          turnUrlParts[1].indexOf('transport=udp') === 0) {
          iceServer = {
            'url': turnUrlParts[0],
            'credential': password,
            'username': username
          };
        }
      } else {
        // FF 27 and above supports transport parameters in TURN url,
        // So passing in the full url to create iceServer.
        iceServer = {
          'url': url,
          'credential': password,
          'username': username
        };
      }
    }
    return iceServer;
  };

  window.createIceServers = function(urls, username, password) {
    var iceServers = [];
    // Use .url for FireFox.
    for (var i = 0; i < urls.length; i++) {
      var iceServer =
        window.createIceServer(urls[i], username, password);
      if (iceServer !== null) {
        iceServers.push(iceServer);
      }
    }
    return iceServers;
  };

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    console.log('Attaching media stream');
    element.mozSrcObject = stream;
  };

  reattachMediaStream = function(to, from) {
    console.log('Reattaching media stream');
    to.mozSrcObject = from.mozSrcObject;
  };

} else if (navigator.webkitGetUserMedia) {
  console.log('This appears to be Chrome');

  webrtcDetectedBrowser = 'chrome';
  // Temporary fix until crbug/374263 is fixed.
  // Setting Chrome version to 999, if version is unavailable.
  var result = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
  if (result !== null) {
    webrtcDetectedVersion = parseInt(result[2], 10);
  } else {
    webrtcDetectedVersion = 999;
  }

  // Creates iceServer from the url for Chrome M33 and earlier.
  window.createIceServer = function(url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      // Chrome M28 & above uses below TURN format.
      iceServer = {
        'url': url,
        'credential': password,
        'username': username
      };
    }
    return iceServer;
  };

  // Creates iceServers from the urls for Chrome M34 and above.
  window.createIceServers = function(urls, username, password) {
    var iceServers = [];
    if (webrtcDetectedVersion >= 34) {
      // .urls is supported since Chrome M34.
      iceServers = {
        'urls': urls,
        'credential': password,
        'username': username
      };
    } else {
      for (var i = 0; i < urls.length; i++) {
        var iceServer =
          window.createIceServer(urls[i], username, password);
        if (iceServer !== null) {
          iceServers.push(iceServer);
        }
      }
    }
    return iceServers;
  };

  // The RTCPeerConnection object.
  RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is supported since Chrome M34.
    if (webrtcDetectedVersion < 34) {
      maybeFixConfiguration(pcConfig);
    }
    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
  };

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    if (typeof element.srcObject !== 'undefined') {
      element.srcObject = stream;
    } else if (typeof element.mozSrcObject !== 'undefined') {
      element.mozSrcObject = stream;
    } else if (typeof element.src !== 'undefined') {
      element.src = URL.createObjectURL(stream);
    } else {
      console.log('Error attaching stream to element.');
    }
  };

  reattachMediaStream = function(to, from) {
    to.src = from.src;
  };
} else {
  console.log('Browser does not appear to be WebRTC-capable');
}

window.RTCPeerConnection = RTCPeerConnection;
window.getUserMedia = getUserMedia;
window.attachMediaStream = attachMediaStream;
window.reattachMediaStream = reattachMediaStream;
window.webrtcDetectedBrowser = webrtcDetectedBrowser;
window.webrtcDetectedVersion = webrtcDetectedVersion;
<|endoftext|>