<commit_before>/*
 * Copyright (c) 2012-2015 Netforce Co. Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 */

var FieldSelection=NFView.extend({
    _name: "field_selection",
    className: "form-group nf-field",
    events: {
        "change select": "onchange",
        "blur select": "blur"
    },

    initialize: function(options) {
        NFView.prototype.initialize.call(this,options);
        var name=this.options.name;
        var model=this.context.model;
        model.on("change:"+name,this.render,this);
        model.on("error",this.render,this);
        this.listen_selection();
        this.listen_attrs();
    },

    render: function() {
        //log("field_selection.render",this);
        var name=this.options.name;
        this.$el.addClass("field-"+name);
        var model=this.context.model;
        var value=translate(model.get(name));
        this.data.value=value;
        var field=model.get_field(name);
        if (!this.selection) {
            this.selection=field.selection;
            if (this.options.selection) {
                this.update_selection();
            }
        }
        //log("selection",this.selection);
        this.data.string=field.string;
        this.data.readonly=field.readonly||this.options.readonly||this.context.readonly;
        var attrs=this.eval_attrs();
        if (attrs.readonly!==undefined) {
            this.data.readonly=attrs.readonly;
        }
        var perms=get_field_permissions(model.name,name);
        if (!perms.perm_write) {
            this.data.readonly=true;
        }
        //log("readonly",this.data.readonly);
        var required=field.required||this.options.required;
        if (required && !this.data.readonly) {
            this.$el.addClass("nf-required-field");
        }
        if (required) {
            model.set_required(name);
        }
        if (this.options.inline) {
            this.$el.css({display: "inline"});
        }
        var that=this;
        var sel_group_vals={};
        var sel_groups=[];
        var sel_options=[];
        var group;
        for (var i in that.selection) {
            var v=that.selection[i];
            if (v[0]=="_group") {
                var label=v[1];
                group=sel_group_vals[label];
                if (!group) {
                    group={
                        "label": label,
                        "sel_options": []
                    }
                    sel_groups.push(group);
                    sel_group_vals[label]=group;
                }
            } else {
                var opt={
                    "value": v[0],
                    "string": v[1],
                    "selected": v[0]==value
                }
                if (group) {
                    group.sel_options.push(opt);
                } else {
                    sel_options.push(opt);
                }
                if (v[0]==value) that.data.value_string=v[1];
            }
        }
        if (sel_groups.length>0) {
            //log("sel_groups",sel_groups);
            that.data.sel_groups=sel_groups;
        } else {
            //log("sel_options",sel_options);
            that.data.sel_options=sel_options;
        }
        that.data.sel_options=sel_options;
        var form_layout=this.options.form_layout||"stacked";
        this.data.horizontal=form_layout=="horizontal";
        var pkg=this.options.pkg||field.pkg;
        if (!check_package(pkg)) {
            this.data.disabled=true;
        }
        NFView.prototype.render.call(that);
        var err=model.get_field_error(name);
        if (err) {
            that.$el.addClass("error");
        } else {
            that.$el.removeClass("error");
        }
        if (this.options.span && !this.options.span_input_only) { // XXX
            that.$el.addClass("col-sm-"+that.options.span);
        }
        if (that.options.invisible || attrs.invisible) {
            that.$el.hide();
        } else {
            that.$el.show();
        }
        if (this.options.width) {
            this.$el.find("select").css("width",this.options.width+"px");
            this.$el.css("width",this.options.width+"px");
        }
        this.$el.find("a.help").tooltip();
    },

    listen_selection: function() {
        var str=this.options.selection;
        if (!str) return;
        log("listen_selection",this,str);
        var re=/\w+\((.*)\)/;
        var m=re.exec(str);
        if (!m) return;
        var depends=m[1].split(",");
        log("==> depends",depends);
        var model=this.context.model;
        for (var i in depends) {
            var n=depends[i];
            log("...listen "+n);
            model.on("change:"+n,this.update_selection,this);
        }
    },

    update_selection: function() {
        var str=this.options.selection;
        if (!str) return;
        log("update_selection",this,str);
        var re=/(\w+)(\((.*)\))?/;
        var m=re.exec(str);
        var func=m[1];
        var arg_vals=[];
        var model=this.context.model;
        if (m[3]) {
            var args=m[3].split(",");
            var vals=model.get_vals();
            for (var i in args) {
                var n=args[i];
                var v=vals[n];
                arg_vals.push(v);
            }
        }
        var that=this;
        var ctx=clean_context(this.options.context);
        rpc_execute(model.name,func,arg_vals,{context:ctx},function(err,data) {
            that.selection=data;
            that.render();
        });
    },

    onchange: function() {
        var val=this.$el.find("select").val();
        var name=this.options.name;
        var model=this.context.model;
        model.set(name,val);
        this.$el.find("select").focus();
        var form=this.context.form;
        if (this.options.onchange) {
            var path=model.get_path(name);
            form.do_onchange(this.options.onchange,path);
        }
    },

    eval_attrs: function() {
        var str=this.options.attrs;
        //log("eval_attrs",this,str);
        if (!str) return {};
        var expr=JSON.parse(str);
        var model=this.context.model;
        var attrs={};
        for (var attr in expr) {
            var conds=expr[attr];
            var attr_val=true;
            for (var i in conds) {
                var clause=conds[i];
                var n=clause[0];
                var op=clause[1];
                var cons=clause[2];
                var v=model.get(n);
                var clause_v;
                if (op=="=") {
                    clause_v=v==cons;
                } else if (op=="!=") {
                    clause_v=v!=cons;
                } else if (op=="in") {
                    clause_v=_.contains(cons,v);
                } else if (op=="not in") {
                    clause_v=!_.contains(cons,v);
                } else {
                    throw "Invalid operator: "+op;
                }
                if (!clause_v) {
                    attr_val=false;
                    break;
                }
            }
            attrs[attr]=attr_val;
        }
        //log("==>",attrs);
        return attrs;
    },

    listen_attrs: function() {
        var str=this.options.attrs;
        //log("listen_attrs",this,str);
        if (!str) return;
        var expr=JSON.parse(str);
        var attrs={};
        var depends=[];
        for (var attr in expr) {
            var conds=expr[attr];
            for (var i in conds) {
                var clause=conds[i];
                var n=clause[0];
                depends.push(n);
            }
        }
        //log("==> depends",depends);
        var model=this.context.model;
        for (var i in depends) {
            var n=depends[i];
            //log("...listen "+n);
            model.on("change:"+n,this.render,this);
        }
    },

    focus: function() {
        log("field_selection.focus",this);
        this.$el.find("select").focus();
    },

    blur: function() {
        this.trigger("blur");
    }
});

FieldSelection.register();
<commit_msg>after select some value , the result show empty<commit_after>/*
 * Copyright (c) 2012-2015 Netforce Co. Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 */

var FieldSelection=NFView.extend({
    _name: "field_selection",
    className: "form-group nf-field",
    events: {
        "change select": "onchange",
        "blur select": "blur"
    },

    initialize: function(options) {
        NFView.prototype.initialize.call(this,options);
        var name=this.options.name;
        var model=this.context.model;
        model.on("change:"+name,this.render,this);
        model.on("error",this.render,this);
        this.listen_selection();
        this.listen_attrs();
    },

    render: function() {
        //log("field_selection.render",this);
        var name=this.options.name;
        this.$el.addClass("field-"+name);
        var model=this.context.model;
        var value=model.get(name);
        this.data.value=value;
        var field=model.get_field(name);
        if (!this.selection) {
            this.selection=field.selection;
            if (this.options.selection) {
                this.update_selection();
            }
        }
        //log("selection",this.selection);
        this.data.string=field.string;
        this.data.readonly=field.readonly||this.options.readonly||this.context.readonly;
        var attrs=this.eval_attrs();
        if (attrs.readonly!==undefined) {
            this.data.readonly=attrs.readonly;
        }
        var perms=get_field_permissions(model.name,name);
        if (!perms.perm_write) {
            this.data.readonly=true;
        }
        //log("readonly",this.data.readonly);
        var required=field.required||this.options.required;
        if (required && !this.data.readonly) {
            this.$el.addClass("nf-required-field");
        }
        if (required) {
            model.set_required(name);
        }
        if (this.options.inline) {
            this.$el.css({display: "inline"});
        }
        var that=this;
        var sel_group_vals={};
        var sel_groups=[];
        var sel_options=[];
        var group;
        for (var i in that.selection) {
            var v=that.selection[i];
            if (v[0]=="_group") {
                var label=v[1];
                group=sel_group_vals[label];
                if (!group) {
                    group={
                        "label": label,
                        "sel_options": []
                    }
                    sel_groups.push(group);
                    sel_group_vals[label]=group;
                }
            } else {
                var opt={
                    "value": v[0],
                    "string": v[1],
                    "selected": v[0]==value
                }
                if (group) {
                    group.sel_options.push(opt);
                } else {
                    sel_options.push(opt);
                }
                if (v[0]==value) that.data.value_string=v[1];
            }
        }
        if (sel_groups.length>0) {
            //log("sel_groups",sel_groups);
            that.data.sel_groups=sel_groups;
        } else {
            //log("sel_options",sel_options);
            that.data.sel_options=sel_options;
        }
        that.data.sel_options=sel_options;
        var form_layout=this.options.form_layout||"stacked";
        this.data.horizontal=form_layout=="horizontal";
        var pkg=this.options.pkg||field.pkg;
        if (!check_package(pkg)) {
            this.data.disabled=true;
        }
        NFView.prototype.render.call(that);
        var err=model.get_field_error(name);
        if (err) {
            that.$el.addClass("error");
        } else {
            that.$el.removeClass("error");
        }
        if (this.options.span && !this.options.span_input_only) { // XXX
            that.$el.addClass("col-sm-"+that.options.span);
        }
        if (that.options.invisible || attrs.invisible) {
            that.$el.hide();
        } else {
            that.$el.show();
        }
        if (this.options.width) {
            this.$el.find("select").css("width",this.options.width+"px");
            this.$el.css("width",this.options.width+"px");
        }
        this.$el.find("a.help").tooltip();
    },

    listen_selection: function() {
        var str=this.options.selection;
        if (!str) return;
        log("listen_selection",this,str);
        var re=/\w+\((.*)\)/;
        var m=re.exec(str);
        if (!m) return;
        var depends=m[1].split(",");
        log("==> depends",depends);
        var model=this.context.model;
        for (var i in depends) {
            var n=depends[i];
            log("...listen "+n);
            model.on("change:"+n,this.update_selection,this);
        }
    },

    update_selection: function() {
        var str=this.options.selection;
        if (!str) return;
        log("update_selection",this,str);
        var re=/(\w+)(\((.*)\))?/;
        var m=re.exec(str);
        var func=m[1];
        var arg_vals=[];
        var model=this.context.model;
        if (m[3]) {
            var args=m[3].split(",");
            var vals=model.get_vals();
            for (var i in args) {
                var n=args[i];
                var v=vals[n];
                arg_vals.push(v);
            }
        }
        var that=this;
        var ctx=clean_context(this.options.context);
        rpc_execute(model.name,func,arg_vals,{context:ctx},function(err,data) {
            that.selection=data;
            that.render();
        });
    },

    onchange: function() {
        var val=this.$el.find("select").val();
        var name=this.options.name;
        var model=this.context.model;
        model.set(name,val);
        this.$el.find("select").focus();
        var form=this.context.form;
        if (this.options.onchange) {
            var path=model.get_path(name);
            form.do_onchange(this.options.onchange,path);
        }
    },

    eval_attrs: function() {
        var str=this.options.attrs;
        //log("eval_attrs",this,str);
        if (!str) return {};
        var expr=JSON.parse(str);
        var model=this.context.model;
        var attrs={};
        for (var attr in expr) {
            var conds=expr[attr];
            var attr_val=true;
            for (var i in conds) {
                var clause=conds[i];
                var n=clause[0];
                var op=clause[1];
                var cons=clause[2];
                var v=model.get(n);
                var clause_v;
                if (op=="=") {
                    clause_v=v==cons;
                } else if (op=="!=") {
                    clause_v=v!=cons;
                } else if (op=="in") {
                    clause_v=_.contains(cons,v);
                } else if (op=="not in") {
                    clause_v=!_.contains(cons,v);
                } else {
                    throw "Invalid operator: "+op;
                }
                if (!clause_v) {
                    attr_val=false;
                    break;
                }
            }
            attrs[attr]=attr_val;
        }
        //log("==>",attrs);
        return attrs;
    },

    listen_attrs: function() {
        var str=this.options.attrs;
        //log("listen_attrs",this,str);
        if (!str) return;
        var expr=JSON.parse(str);
        var attrs={};
        var depends=[];
        for (var attr in expr) {
            var conds=expr[attr];
            for (var i in conds) {
                var clause=conds[i];
                var n=clause[0];
                depends.push(n);
            }
        }
        //log("==> depends",depends);
        var model=this.context.model;
        for (var i in depends) {
            var n=depends[i];
            //log("...listen "+n);
            model.on("change:"+n,this.render,this);
        }
    },

    focus: function() {
        log("field_selection.focus",this);
        this.$el.find("select").focus();
    },

    blur: function() {
        this.trigger("blur");
    }
});

FieldSelection.register();
<|endoftext|>


<commit_before>import {Resource} from 'react-admin';
import resourceFactory from './resourceFactory';

describe('makes Resource component', () => {
  const resource = {
    name: 'name',
    props: {custom: 'props'},
  };
  const api = {
    name: 'api',
  };

  const fieldFactory = jest.fn();
  const inputFactory = jest.fn();
  const parameterFactory = jest.fn();

  describe('makes default Resource component', () => {
    const resourceComponent = resourceFactory(
      resource,
      api,
      fieldFactory,
      inputFactory,
      parameterFactory,
    );

    test('is Resource component', () => {
      expect(resourceComponent.type.prototype).toEqual(Resource.prototype);
    });

    test('have props defined', () => {
      expect(resourceComponent.props).toBeDefined();
    });

    test('have proper name prop set', () => {
      expect(resourceComponent.props.name).toEqual(resource.name);
    });

    test('have proper icon prop set', () => {
      expect(resourceComponent.props.icon).toEqual(resource.icon);
    });

    test('have default actions: create, edit, list, show set', () => {
      expect(resourceComponent.props.create).toBeInstanceOf(Function);
      expect(resourceComponent.props.edit).toBeInstanceOf(Function);
      expect(resourceComponent.props.list).toBeInstanceOf(Function);
      expect(resourceComponent.props.show).toBeInstanceOf(Function);
    });

    test('have proper custom props set', () => {
      Object.keys(resource.props).forEach(key => {
        expect(resourceComponent.props[key]).toEqual(resource.props[key]);
      });
    });

    test('have proper options prop set', () => {
      expect(resourceComponent.props.options).toEqual({
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
        resource,
      });
    });
  });

  describe('makes Resource component with custom actions', () => {
    test('have custom create action', () => {
      const customCreate = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          create: customCreate,
        }),
        api,
        fieldFactory,
        inputFactory,
      );

      expect(resourceComponent.props.create).toEqual(customCreate);
    });

    test('have custom create action', () => {
      const customCreate = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          create: customCreate,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.create).toEqual(customCreate);
    });

    test('have custom icon action', () => {
      const customIcon = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          icon: customIcon,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.icon).toEqual(customIcon);
    });

    test('have custom list action', () => {
      const customList = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          list: customList,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.list).toEqual(customList);
    });

    test('have custom show action', () => {
      const customShow = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          show: customShow,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.show).toEqual(customShow);
    });

    test('have custom edit action', () => {
      const customEdit = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          edit: customEdit,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.edit).toEqual(customEdit);
    });
  });
});
<commit_msg>lint fix for resource-custom-icon<commit_after>import {Resource} from 'react-admin';
import resourceFactory from './resourceFactory';

describe('makes Resource component', () => {
  const resource = {
    name: 'name',
    props: {custom: 'props'},
  };
  const api = {
    name: 'api',
  };

  const fieldFactory = jest.fn();
  const inputFactory = jest.fn();
  const parameterFactory = jest.fn();

  describe('makes default Resource component', () => {
    const resourceComponent = resourceFactory(
      resource,
      api,
      fieldFactory,
      inputFactory,
      parameterFactory,
    );

    test('is Resource component', () => {
      expect(resourceComponent.type.prototype).toEqual(Resource.prototype);
    });

    test('have props defined', () => {
      expect(resourceComponent.props).toBeDefined();
    });

    test('have proper name prop set', () => {
      expect(resourceComponent.props.name).toEqual(resource.name);
    });

    test('have proper icon prop set', () => {
      expect(resourceComponent.props.icon).toEqual(resource.icon);
    });

    test('have default actions: create, edit, list, show set', () => {
      expect(resourceComponent.props.create).toBeInstanceOf(Function);
      expect(resourceComponent.props.edit).toBeInstanceOf(Function);
      expect(resourceComponent.props.list).toBeInstanceOf(Function);
      expect(resourceComponent.props.show).toBeInstanceOf(Function);
    });

    test('have proper custom props set', () => {
      Object.keys(resource.props).forEach(key => {
        expect(resourceComponent.props[key]).toEqual(resource.props[key]);
      });
    });

    test('have proper options prop set', () => {
      expect(resourceComponent.props.options).toEqual({
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
        resource,
      });
    });
  });

  describe('makes Resource component with custom actions', () => {
    test('have custom create action', () => {
      const customCreate = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          create: customCreate,
        }),
        api,
        fieldFactory,
        inputFactory,
      );

      expect(resourceComponent.props.create).toEqual(customCreate);
    });

    test('have custom create action', () => {
      const customCreate = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          create: customCreate,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.create).toEqual(customCreate);
    });

    test('have custom icon action', () => {
      const customIcon = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          icon: customIcon,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.icon).toEqual(customIcon);
    });

    test('have custom list action', () => {
      const customList = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          list: customList,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.list).toEqual(customList);
    });

    test('have custom show action', () => {
      const customShow = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          show: customShow,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.show).toEqual(customShow);
    });

    test('have custom edit action', () => {
      const customEdit = jest.fn();
      const resourceComponent = resourceFactory(
        Object.assign({}, resource, {
          edit: customEdit,
        }),
        api,
        fieldFactory,
        inputFactory,
        parameterFactory,
      );

      expect(resourceComponent.props.edit).toEqual(customEdit);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @title Detect Ecommerce Fraud Users
 * @overview Get the signifyd score from signfyd.com and store it on app_metadata.
 * @gallery true
 * @category enrich profile
 *
 *
 * This rule gets the signifyd score and status from signifyd.com and stored it in app_metadata.
 *
 */

function getSignifydScore(user, context, callback) {

    user.app_metadata = user.app_metadata || {};
    if (!user.app_metadata.caseId) return callback(null, user, context);

    if(!user.email) {
      // the profile doesn't have email so we can't query their api.
      return callback(null, user, context);
    }

    const request = require('request');

    request({
      url: `https://api.signifyd.com/v2/cases/${user.app_metadata.caseId}`,
      headers: {
          "Authorization": "Basic YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo6"
        }

    }, function (err, resp, body) {
      if (err) return callback(null, user, context);
      if (resp.statusCode !== 200) return callback(null, user, context);
      const signifyd = JSON.parse(body);
      if (signifyd.status !== 'Ok') return callback(null, user, context);

      user.app_metadata = user.app_metadata || {};
      user.app_metadata.guaranteeEligible = signifyd.data.status;
      user.app_metadata.signifyd = signifyd.data.score;
      // "attributes":[
      //      "guaranteeEligible":true,
      //      "status": "open",
      //      "caseId": caseId.
      //      "score": 785, (A value from 0-1000 indicating the likelihood that the order/transaction is fraud. 0 indicates the highest risk, 1000 inidicates the lowest risk)
      //      "uuid": 97c56c86-7984-44fa-9a3e-7d5f34d1bead
      //      "headline": Maxine Trycia
      //      "orderId": 19418
      //      "orderAmount": 48
      //      "associatedTeam": 1
      // ]
      user.app_metadata.signifyd_details = signifyd.data.details;

      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          context.idToken['https://example.com/signifyd_status'] = user.app_metadata.signifyd_status;
          context.idToken['https://example.com/signifyd_score'] = user.app_metadata.signifyd_score;
          callback(null, user, context);
        })
        .catch(function(err){
          callback(null, user, context);
        });
    });
  }<commit_msg>updated code with errors that were noted in the repo - typo on comments and making sure i declared signify status<commit_after>/**
 * @title Detect Ecommerce Fraud Users
 * @overview Get the signifyd score from signfyd.com and store it on app_metadata.
 * @gallery true
 * @category enrich profile
 *
 *
 * This rule gets the signifyd score and status from signifyd.com and stores it in app_metadata.
 *
 */

function getSignifydScore(user, context, callback) {

    user.app_metadata = user.app_metadata || {};
    if (!user.app_metadata.caseId) return callback(null, user, context);

    if(!user.email) {
      // the profile doesn't have email so we can't query their api.
      return callback(null, user, context);
    }

    const request = require('request');

    request({
      url: `https://api.signifyd.com/v2/cases/${user.app_metadata.caseId}`,
      headers: {
          "Authorization": "Basic YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo6"
        }

    }, function (err, resp, body) {
      if (err) return callback(null, user, context);
      if (resp.statusCode !== 200) return callback(null, user, context);
      const signifyd = JSON.parse(body);
      if (signifyd.status !== 'Ok') return callback(null, user, context);

      user.app_metadata = user.app_metadata || {};
      user.app_metadata.signifyd_status = signifyd.data.status;
      user.app_metadata.signifyd_score = signifyd.data.score;
      // "attributes":[
      //      "guaranteeEligible":true,
      //      "status": "open",
      //      "caseId": caseId.
      //      "score": 785, (A value from 0-1000 indicating the likelihood that the order/transaction is fraud. 0 indicates the highest risk, 1000 inidicates the lowest risk)
      //      "uuid": 97c56c86-7984-44fa-9a3e-7d5f34d1bead
      //      "headline": Maxine Trycia
      //      "orderId": 19418
      //      "orderAmount": 48
      //      "associatedTeam": 1
      // ]
      user.app_metadata.signifyd_details = signifyd.data.details;

      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          context.idToken['https://example.com/signifyd_status'] = user.app_metadata.signifyd_status;
          context.idToken['https://example.com/signifyd_score'] = user.app_metadata.signifyd_score;
          callback(null, user, context);
        })
        .catch(function(err){
          callback(null, user, context);
        });
    });
  }<|endoftext|>


<commit_before>function embed360(selectors) {
  var embed360 = {};
  var elementList = document.querySelectorAll(selectors);
  for (var i = 0; i < elementList.length; ++i) {
    var el = elementList[i];
    var img = el.querySelector('img');
    if (img) {
      makeIframe(el, img);
    }
  }

  function makeIframe(el, img) {
    var imgsrc = img.src;
    el.removeChild(img);
    var iframe = document.createElement('iframe');
    var content = '<!DOCTYPE html>' +
      '<title>A photo in aframe in an iframe</title>' +
      '


<commit_before>angular.module('ot.view.validationStamp', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('validationStamp', {
            url: '/validationStamp/{validationStampId}',
            templateUrl: 'app/view/view.validationStamp.tpl.html',
            controller: 'ValidationStampCtrl'
        });
    })
    .controller('ValidationStampCtrl', function ($q, $state, $scope, $stateParams, $http, ot, otStructureService, otAlertService, otGraphqlService) {
        const view = ot.view();
        let viewInitialised = false;
        // ValidationStamp's id
        const validationStampId = $stateParams.validationStampId;

        // Initial query parameters
        const pageSize = 20;
        const queryVariables = {
            validationStampId: validationStampId,
            offset: 0,
            size: pageSize
        };

        // Range of validation runs
        $scope.selectedValidationRuns = {};

        // Query for the validation stamp
        const query = `
            query PaginatedValidationRuns($validationStampId: Int!, $offset: Int = 0, $size: Int = 20) {
                validationStamp(id: $validationStampId) {
                    id
                    name
                    description
                    annotatedDescription
                    image
                    _image
                    decorations {
                      decorationType
                      data
                      error
                      feature {
                        id
                      }
                    }
                    dataType {
                      descriptor {
                        id
                        displayName
                        feature {
                          id
                        }
                      }
                      config
                    }
                    branch {
                      id
                      name
                      project {
                        id
                        name
                      }
                      buildDiffActions {
                        id
                        name
                        type
                        uri
                      }
                    }
                    links {
                      _self
                      _bulkUpdate
                      _update
                      _delete
                      _properties
                      _events
                      _actions
                    }
                    validationRunsPaginated(offset: $offset, size: $size) {
                      pageInfo {
                        totalSize
                        currentOffset
                        currentSize
                        previousPage {
                          offset
                          size
                        }
                        nextPage {
                          offset
                          size
                        }
                        pageIndex
                        pageTotal
                      }
                      pageItems {
                        id
                        runOrder
                        build {
                          id
                          name
                        }
                        creation {
                          user
                          time
                        }
                        runInfo {
                          sourceType
                          sourceUri
                          triggerType
                          triggerData
                          runTime
                        }
                        data {
                          descriptor {
                            id
                            feature {
                              id
                            }
                          }
                          data
                        }
                        validationRunStatuses {
                          creation {
                            user
                            time
                          }
                          statusID {
                            id
                            name
                          }
                          description
                          annotatedDescription
                        }
                      }
                    }
                }
            }`;

        // Loading the validation stamp
        function loadValidationStamp() {
            otGraphqlService.pageGraphQLCall(query, queryVariables).then(function (data) {
                const validationStamp = data.validationStamp;
                $scope.validationStamp = validationStamp;
                // View setup
                if (!viewInitialised) {
                    // View title
                    view.breadcrumbs = ot.branchBreadcrumbs(validationStamp.branch);
                    // Commands
                    view.commands = [
                        {
                            condition: function () {
                                return validationStamp.links._update;
                            },
                            id: 'updateValidationStampImage',
                            name: "Change image",
                            cls: 'ot-command-validation-stamp-image',
                            action: changeImage
                        },
                        {
                            condition: function () {
                                return validationStamp.links._update;
                            },
                            id: 'updateValidationStamp',
                            name: "Update validation stamp",
                            cls: 'ot-command-validation-stamp-update',
                            action: function () {
                                otStructureService.update(
                                    validationStamp.links._update,
                                    "Update validation stamp"
                                ).then(loadValidationStamp);
                            }
                        },
                        {
                            condition: function () {
                                return validationStamp.links._delete;
                            },
                            id: 'deleteValidationStamp',
                            name: "Delete validation stamp",
                            cls: 'ot-command-validation-stamp-delete',
                            action: function () {
                                otAlertService.confirm({
                                    title: "Deleting a validation stamp",
                                    message: "Do you really want to delete the validation stamp " + validationStamp.name +
                                    " and all its associated data?"
                                }).then(function () {
                                    return ot.call($http.delete(validationStamp.links._delete));
                                }).then(function () {
                                    $state.go('branch', {branchId: validationStamp.branch.id});
                                });
                            }
                        },
                        {
                            condition: function () {
                                return validationStamp.links._bulkUpdate;
                            },
                            id: 'bulkUpdateValidationStamp',
                            name: "Bulk update",
                            cls: 'ot-command-update',
                            action: function () {
                                otAlertService.confirm({
                                    title: "Validation stamps bulk update",
                                    message: "Updates all other validation stamps with the same name?"
                                }).then(function () {
                                    return ot.call($http.put(validationStamp.links._bulkUpdate, {}));
                                }).then(loadValidationStamp);
                            }
                        },
                        ot.viewActionsCommand($scope.validationStamp.links._actions),
                        ot.viewCloseCommand('/branch/' + $scope.validationStamp.branch.id)
                    ];
                    // View OK now
                    viewInitialised = true;
                }
            });
        }

        // Initialisation
        loadValidationStamp();

        // Changing the image
        function changeImage() {
            otStructureService.changeValidationStampImage($scope.validationStamp).then(loadValidationStamp);
        }

        // Switching the page
        $scope.switchPage = function (pageRequest) {
            $scope.selectedValidationRuns.first = undefined;
            $scope.selectedValidationRuns.second = undefined;
            queryVariables.offset = pageRequest.offset;
            queryVariables.size = pageSize;
            loadValidationStamp();
        };

        // Diff between two validation runs
        $scope.validationRunDiff = function (action) {
            if ($scope.selectedValidationRuns.first && $scope.selectedValidationRuns.second) {
                $state.go(action.id, {
                    branch: $scope.validationStamp.branch.id,
                    from: $scope.selectedValidationRuns.first.build.id,
                    to: $scope.selectedValidationRuns.second.build.id
                });
            }
        };

        // Duration graph
        $scope.durationOptions = () => {
            // Graph data to inject into the options
            const chartData = {
                categories: [],
                dates: [],
                data: {
                    mean: [],
                    percentile90: [],
                    maximum: []
                }
            };

            // Base options
            const options = {
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        crossStyle: {
                            color: '#999'
                        }
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: true },
                        // magicType: { show: true, type: ['line', 'bar'] },
                        // restore: { show: true },
                        saveAsImage: { show: true }
                    }
                },
                legend: {
                    data: chartData.categories
                },
                xAxis: [
                    {
                        type: 'category',
                        data: chartData.dates,
                        axisPointer: {
                            type: 'shadow'
                        },
                        axisLabel: {
                            rotate: 45
                        }
                    }
                ],
                yAxis: [
                    {
                        type: 'value',
                        name: 'Duration',
                        min: 0,
                        axisLabel: {
                            formatter: '{value} s'
                        }
                    }
                ],
                series: [
                    {
                        name: 'Mean',
                        type: 'bar',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.mean
                    },
                    {
                        name: '90th Percentile',
                        type: 'line',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.percentile90
                    },
                    {
                        name: 'Maximum',
                        type: 'line',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.maximum
                    }
                ]
            };

            const d = $q.defer();

            chartData.categories.length = 0;
            chartData.categories.push(...['Mean', '90th Percentile', 'Maximum']);

            chartData.dates.length = 0;
            chartData.dates.push(...[
                '2022-02-28',
                '2022-03-07',
                '2022-03-14',
                '2022-03-21',
                '2022-03-28',
                '2022-04-04',
                '2022-04-11',
                '2022-04-18',
                '2022-04-25',
                '2022-05-02',
                '2022-05-09',
                '2022-05-16'
            ]);

            chartData.data.mean.length = 0;
            chartData.data.mean.push(...[
                2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3
            ]);

            chartData.data.percentile90.length = 0;
            chartData.data.percentile90.push(...[
                2.6, 5.9, 9.0, 26.4, 28.7, 78.7, 175.6, 182.2, 48.7, 24.8, 7.0, 5.3
            ]);

            chartData.data.maximum.length = 0;
            chartData.data.maximum.push(...[
                3.0, 6.2, 9.3, 34.5, 36.3, 80.2, 220.3, 223.4, 53.0, 36.5, 12.0, 6.2
            ]);

            d.resolve(options);
            return d.promise;
        };

        // Stability graph
        $scope.stabilityOptions = () => {
            // Graph data to inject into the options
            const chartData = {
                dates: [],
                data: {
                    value: []
                }
            };

            // Base options
            const options = {
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        crossStyle: {
                            color: '#999'
                        }
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: true },
                        // magicType: { show: true, type: ['line', 'bar'] },
                        // restore: { show: true },
                        saveAsImage: { show: true }
                    }
                },
                xAxis: [
                    {
                        type: 'category',
                        data: chartData.dates,
                        axisPointer: {
                            type: 'shadow'
                        },
                        axisLabel: {
                            rotate: 45
                        }
                    }
                ],
                yAxis: [
                    {
                        type: 'value',
                        name: '% of success',
                        min: 0,
                        max: 100
                    }
                ],
                series: [
                    {
                        name: 'Value',
                        type: 'bar',
                        data: chartData.data.value
                    }
                ]
            };

            const d = $q.defer();

            chartData.dates.length = 0;
            chartData.dates.push(...[
                '2022-02-28',
                '2022-03-07',
                '2022-03-14',
                '2022-03-21',
                '2022-03-28',
                '2022-04-04',
                '2022-04-11',
                '2022-04-18',
                '2022-04-25',
                '2022-05-02',
                '2022-05-09',
                '2022-05-16'
            ]);

            chartData.data.value.length = 0;
            chartData.data.value.push(...[
                1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 100, 100
            ]);

            d.resolve(options);
            return d.promise;
        };

    })
;<commit_msg>#979 Getting the chart data from a GraphQL call<commit_after>angular.module('ot.view.validationStamp', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('validationStamp', {
            url: '/validationStamp/{validationStampId}',
            templateUrl: 'app/view/view.validationStamp.tpl.html',
            controller: 'ValidationStampCtrl'
        });
    })
    .controller('ValidationStampCtrl', function ($q, $state, $scope, $stateParams, $http, ot, otStructureService, otAlertService, otGraphqlService) {
        const view = ot.view();
        let viewInitialised = false;
        // ValidationStamp's id
        const validationStampId = $stateParams.validationStampId;

        // Initial query parameters
        const pageSize = 20;
        const queryVariables = {
            validationStampId: validationStampId,
            offset: 0,
            size: pageSize
        };

        // Range of validation runs
        $scope.selectedValidationRuns = {};

        // Query for the validation stamp
        const query = `
            query PaginatedValidationRuns($validationStampId: Int!, $offset: Int = 0, $size: Int = 20) {
                validationStamp(id: $validationStampId) {
                    id
                    name
                    description
                    annotatedDescription
                    image
                    _image
                    decorations {
                      decorationType
                      data
                      error
                      feature {
                        id
                      }
                    }
                    dataType {
                      descriptor {
                        id
                        displayName
                        feature {
                          id
                        }
                      }
                      config
                    }
                    branch {
                      id
                      name
                      project {
                        id
                        name
                      }
                      buildDiffActions {
                        id
                        name
                        type
                        uri
                      }
                    }
                    links {
                      _self
                      _bulkUpdate
                      _update
                      _delete
                      _properties
                      _events
                      _actions
                    }
                    validationRunsPaginated(offset: $offset, size: $size) {
                      pageInfo {
                        totalSize
                        currentOffset
                        currentSize
                        previousPage {
                          offset
                          size
                        }
                        nextPage {
                          offset
                          size
                        }
                        pageIndex
                        pageTotal
                      }
                      pageItems {
                        id
                        runOrder
                        build {
                          id
                          name
                        }
                        creation {
                          user
                          time
                        }
                        runInfo {
                          sourceType
                          sourceUri
                          triggerType
                          triggerData
                          runTime
                        }
                        data {
                          descriptor {
                            id
                            feature {
                              id
                            }
                          }
                          data
                        }
                        validationRunStatuses {
                          creation {
                            user
                            time
                          }
                          statusID {
                            id
                            name
                          }
                          description
                          annotatedDescription
                        }
                      }
                    }
                }
            }`;

        // Loading the validation stamp
        function loadValidationStamp() {
            otGraphqlService.pageGraphQLCall(query, queryVariables).then(function (data) {
                const validationStamp = data.validationStamp;
                $scope.validationStamp = validationStamp;
                // View setup
                if (!viewInitialised) {
                    // View title
                    view.breadcrumbs = ot.branchBreadcrumbs(validationStamp.branch);
                    // Commands
                    view.commands = [
                        {
                            condition: function () {
                                return validationStamp.links._update;
                            },
                            id: 'updateValidationStampImage',
                            name: "Change image",
                            cls: 'ot-command-validation-stamp-image',
                            action: changeImage
                        },
                        {
                            condition: function () {
                                return validationStamp.links._update;
                            },
                            id: 'updateValidationStamp',
                            name: "Update validation stamp",
                            cls: 'ot-command-validation-stamp-update',
                            action: function () {
                                otStructureService.update(
                                    validationStamp.links._update,
                                    "Update validation stamp"
                                ).then(loadValidationStamp);
                            }
                        },
                        {
                            condition: function () {
                                return validationStamp.links._delete;
                            },
                            id: 'deleteValidationStamp',
                            name: "Delete validation stamp",
                            cls: 'ot-command-validation-stamp-delete',
                            action: function () {
                                otAlertService.confirm({
                                    title: "Deleting a validation stamp",
                                    message: "Do you really want to delete the validation stamp " + validationStamp.name +
                                    " and all its associated data?"
                                }).then(function () {
                                    return ot.call($http.delete(validationStamp.links._delete));
                                }).then(function () {
                                    $state.go('branch', {branchId: validationStamp.branch.id});
                                });
                            }
                        },
                        {
                            condition: function () {
                                return validationStamp.links._bulkUpdate;
                            },
                            id: 'bulkUpdateValidationStamp',
                            name: "Bulk update",
                            cls: 'ot-command-update',
                            action: function () {
                                otAlertService.confirm({
                                    title: "Validation stamps bulk update",
                                    message: "Updates all other validation stamps with the same name?"
                                }).then(function () {
                                    return ot.call($http.put(validationStamp.links._bulkUpdate, {}));
                                }).then(loadValidationStamp);
                            }
                        },
                        ot.viewActionsCommand($scope.validationStamp.links._actions),
                        ot.viewCloseCommand('/branch/' + $scope.validationStamp.branch.id)
                    ];
                    // View OK now
                    viewInitialised = true;
                }
            });
        }

        // Initialisation
        loadValidationStamp();

        // Changing the image
        function changeImage() {
            otStructureService.changeValidationStampImage($scope.validationStamp).then(loadValidationStamp);
        }

        // Switching the page
        $scope.switchPage = function (pageRequest) {
            $scope.selectedValidationRuns.first = undefined;
            $scope.selectedValidationRuns.second = undefined;
            queryVariables.offset = pageRequest.offset;
            queryVariables.size = pageSize;
            loadValidationStamp();
        };

        // Diff between two validation runs
        $scope.validationRunDiff = function (action) {
            if ($scope.selectedValidationRuns.first && $scope.selectedValidationRuns.second) {
                $state.go(action.id, {
                    branch: $scope.validationStamp.branch.id,
                    from: $scope.selectedValidationRuns.first.build.id,
                    to: $scope.selectedValidationRuns.second.build.id
                });
            }
        };

        // Duration graph
        $scope.durationOptions = () => {
            // Graph data to inject into the options
            const chartData = {
                categories: [],
                dates: [],
                data: {
                    mean: [],
                    percentile90: [],
                    maximum: []
                }
            };

            // Base options
            const options = {
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        crossStyle: {
                            color: '#999'
                        }
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: true },
                        // magicType: { show: true, type: ['line', 'bar'] },
                        // restore: { show: true },
                        saveAsImage: { show: true }
                    }
                },
                legend: {
                    data: chartData.categories
                },
                xAxis: [
                    {
                        type: 'category',
                        data: chartData.dates,
                        axisPointer: {
                            type: 'shadow'
                        },
                        axisLabel: {
                            rotate: 45
                        }
                    }
                ],
                yAxis: [
                    {
                        type: 'value',
                        name: 'Duration',
                        min: 0,
                        axisLabel: {
                            formatter: '{value} s'
                        }
                    }
                ],
                series: [
                    {
                        name: 'Mean',
                        type: 'bar',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.mean
                    },
                    {
                        name: '90th Percentile',
                        type: 'line',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.percentile90
                    },
                    {
                        name: 'Maximum',
                        type: 'line',
                        tooltip: {
                            valueFormatter: function (value) {
                                return value + ' s';
                            }
                        },
                        data: chartData.data.maximum
                    }
                ]
            };

            return otGraphqlService.pageGraphQLCall(`
                query ValidationStampDuration(
                    $validationStampId: Int!,
                ) {
                    getChart(input: {
                        name: "validation-stamp-durations",
                        options: {
                            period: "1w",
                            interval: "1m"
                        },
                        parameters: {
                            id: $validationStampId,
                        }
                    })
                }
            `, {
                validationStampId: validationStampId
            }).then(data => {
                const chart = data.getChart;

                chartData.categories.length = 0;
                chartData.categories.push(...chart.categories);

                chartData.dates.length = 0;
                chartData.dates.push(...chart.dates);

                chartData.data.mean.length = 0;
                chartData.data.mean.push(...chart.data.mean);

                chartData.data.percentile90.length = 0;
                chartData.data.percentile90.push(...chart.data.percentile90);

                chartData.data.maximum.length = 0;
                chartData.data.maximum.push(...chart.data.maximum);
            });
        };

        // Stability graph
        $scope.stabilityOptions = () => {
            // Graph data to inject into the options
            const chartData = {
                dates: [],
                data: {
                    value: []
                }
            };

            // Base options
            const options = {
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        crossStyle: {
                            color: '#999'
                        }
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: true },
                        // magicType: { show: true, type: ['line', 'bar'] },
                        // restore: { show: true },
                        saveAsImage: { show: true }
                    }
                },
                xAxis: [
                    {
                        type: 'category',
                        data: chartData.dates,
                        axisPointer: {
                            type: 'shadow'
                        },
                        axisLabel: {
                            rotate: 45
                        }
                    }
                ],
                yAxis: [
                    {
                        type: 'value',
                        name: '% of success',
                        min: 0,
                        max: 100
                    }
                ],
                series: [
                    {
                        name: 'Value',
                        type: 'bar',
                        data: chartData.data.value
                    }
                ]
            };

            const d = $q.defer();

            chartData.dates.length = 0;
            chartData.dates.push(...[
                '2022-02-28',
                '2022-03-07',
                '2022-03-14',
                '2022-03-21',
                '2022-03-28',
                '2022-04-04',
                '2022-04-11',
                '2022-04-18',
                '2022-04-25',
                '2022-05-02',
                '2022-05-09',
                '2022-05-16'
            ]);

            chartData.data.value.length = 0;
            chartData.data.value.push(...[
                1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 100, 100
            ]);

            d.resolve(options);
            return d.promise;
        };

    })
;<|endoftext|>


<commit_before>// Description:
//   Allows hubot query ethereum blockchain and few ethereum api
//
// Dependencies:
//   hubot-brain-redis
//
// Configuration:
//   none
//
// Commands:
//   ethereum balance
//   ethereum check <address>
//
// Author:
//   Edouard SCHWEISGUTH <edznux@gmail.com> (https://edouard.schweisguth.fr)
//

var https = require("https");

var DEFAULT_PRICE_CURRENCY = "eur";
var SECOND_PRICE_CURRENCY = "usd";

function main(robot){

	var UNIT = 1000000000000000000;

	var hu = require("./lib/hubot_utils.js");
	hu.setRobot(robot);
	var eu = require("./lib/ethereum_utils.js");
	eu.setRobot(robot);
	var nanopool = require("./lib/nanopool.js");

	robot.hear(/(?:ethereum|eth)( .*)?/i, function(res){
		if(res.message.rawText.match(/^(?:ethereum|eth)/i)){

			res.match[1] = res.match[1].trim();
			switch(true){
				case /check/.test(res.match[1]):
					if(/\$|\€/.test(res.match[1])){
						console.info("€ or $ found");
						_checkByCurrency(res);
					}else{
						console.info("€ or $ NOT found");
						_check(res);
					}
					break;
				case /add/.test(res.match[1]):
					_addAddr(res);
					break;
				case /(rm)|(delete)|(remove)/.test(res.match[1]):
					_deleteAddr(res);
					break;
				case res.match[1] == "list":
					_getList(res);
					break;
				case /transaction (.*)/.test(res.match[1]):
					_getTransactionByAddr(res);
					break;
				case res.match[1] == "transaction":
					_getTransaction(res);
					break;
				case /nanopool (.*)/.test(res.match[1]):
					_getNanopoolBalanceByCurrency(res);
					break;
				case res.match[1] == "nanopool":
				case res.match[1] == "nanopool balance":
					_getNanopoolBalance(res);
					break;

				case /balance (.*)/.test(res.match[1]) :
					_getBalanceByCurrency(res);
					break;

				case res.match[1] == "balance" :
					_getBalance(res);
					break;

				case res.match[1] == "price":
					_getPrice(res);
					break;
				case res.match[1] == "version":
						res.send(require("./package.json").version);
					break;

				case res.match[1] == "?":
				case res.match[1] == "help":
					res.send(getHelp());
					break;
				case /convert (.*)/.test(res.match[1]):
					_getConvertion(res);
					break;

				default:
					res.send(getHelp());
					break;
			}
		}
	});

	function getHelp(){
		return [
			"Ethereum commands",
				" - add <address> : Attach address to your user",
				" - delete <address> : Delete address from your user",
				" - remove <address> : Alias for delete",
				" - rm <address> : Alias for delete",
				" - list : list addresses from the current user",
				" - balance : Get the balance of the current user",
				" - balance <€ or $> : Get the balance of the current user in the provided currency",
				" - nanopool [balance] : Get nanopool balance of the current user (if the miner has mined something)",
				" - nanopool <€ or $> : Get nanopool balance of the current user in the provided currency",
				" - transaction : List latest transaction of the current user",
				" - check <address> : Get balance from the address provided",
				" - price : value of ethereum",
				" - convert <value> <from> <to> : convert value from currency to another (<to> default = eth)",
				" - p : alias for price",
				" - version : Print current version of hubot-ethereum",
				" - help : Print this help",
				" - ? : Alias for help"
				].join("\n\t");
	}

	function _getBalance(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var total = 0;
		eu.getBalanceByUser(user, function(err,balances){
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			console.error("======", balances);
			data = balances.data;
			for(var i=0; i < data.length; i++){
				tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ data[i].balance/UNIT + " ETH`] \n";
				total += data[i].balance;
			}
			tmp += "-------\n";
			tmp += "Total : `" + parseFloat(total/UNIT).toFixed(3) + "` ETH over " + data.length + " account(s)";
			res.send(tmp);
		});
	}

	function _getBalanceByCurrency(res){
		var currency = res.match[1].split(" ")[1];

		var user = res.message.user.name.toLowerCase();
		eu.getBalanceByUser(user, function(err,balances){
			var tmp = "";
			var data = balances.data;
			var total = 0;
			var value;

			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			try{
				for(var i=0; i < data.length; i++){
					value = hu.ethToCurrency(data[i].balance/UNIT, currency);
					tmp += "Adress : [`" + data[i].addr + "`] balance : [`" + value+ "`] \n";
					total += data[i].balance;
				}
				tmp += "-------\n";
				tmp += "Total : `" + parseFloat(hu.ethToCurrency(total/UNIT, currency)).toFixed(3) + currency + "` over " + data.length + " account(s)";

				res.send(tmp);

			}catch(e){
				res.send("Cannot get balance by currency : " + e);
			}

		});
	}

	function _getTransaction(res){
		var user = res.message.user.name.toLowerCase();
		eu.getTransactionByUser(user, function(err,data){
			if(err){
				console.error(err);
				res.send("Can't  get transation for the user :" + user);
				return;
			}
			tmp = "";
			console.log(data);
			var m, dateString;

			for(var i = 0; i< data.length && i < 10; i++){
				m = new Date(data[i].time);
				dateString = m.getUTCFullYear() +"/"+
					("0" + (m.getUTCMonth()+1)).slice(-2) +"/"+
					("0" + m.getUTCDate()).slice(-2) + " " +
					("0" + m.getUTCHours()).slice(-2) + ":" +
					("0" + m.getUTCMinutes()).slice(-2) + ":" +
					("0" + m.getUTCSeconds()).slice(-2);
				tmp += "From : [`" + data[i].sender + "`] to [`" + data[i].recipient + "`] amount : `" + data[i].amount/UNIT + " ETH` Date " + dateString +"\n";
			}
			res.send("List of latest transactions \n" + tmp);

		});
	}

	function _getTransactionByAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");
		var addr = tmp[2];
		eu.getTransactionByAddr(addr, function(err,data){
			if(err){
				console.error(err);
			}
			res.send(data);
		});
	}

	function _getNanopoolBalance(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var total = 0;
		nanopool.getBalanceByUser(user, function(err, balances){
			console.log(err,balances);
			if(err){
				console.error(err);
				res.send(err);
				return;
			}
			data = balances.data;
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			for(var i = 0; i < data.length; i++){
				tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ data[i].balance + " ETH`] \n";
				total += data[i].balance;
			}
			tmp += "-------\n";
			tmp += "Total : `" + total + " ETH` over " + data.length + " account(s)";
			res.send(tmp);

		});
	}

	function _getNanopoolBalanceByCurrency(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var currency = res.match[1].split(" ")[1];
		var total = 0;
		nanopool.getBalanceByUser(user, function(err, balances){
			console.log(err,balances);
			if(err){
				console.error(err);
				res.send(err);
				return;
			}
			data = balances.data;
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}

			try{
				for(var i = 0; i < data.length; i++){
					tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ parseFloat(hu.ethToCurrency(data[i].balance, currency)).toFixed(3) + " "+ currency +"`] \n";
					total += data[i].balance;
				}
				tmp += "-------\n";
				tmp += "Total : `" + parseFloat(total*currencyMult).toFixed(3) + " "+ currency+ "` over " + data.length + " account(s)";
				res.send(tmp);

			}catch(e){
				res.send("Cannot get nanopool balance by currency : " +e);
				return;
			}

		});
	}

	function _getList(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		hu.listAddrFromUser(user, function(err, data){
			if(err){
				res.send(err);
			}else{
				for(var i =0; i<data.length; i++){
					tmp += data[i]+"\n";
				}
				res.send(tmp);
			}
		});
	}

	function _deleteAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");

		console.log("remove address :", tmp[1], "from user :", user,"[",new Date(), "]");

		if(tmp.length < 2){
			res.send("Syntax error");
			return;
		}
		hu.deleteAddrToUser(tmp[1], user, function(err, data){
			if(err){
				res.send(err);
			}else{
				res.send(data);
			}
		});
	}

	function _addAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");

		console.log("Add address :", tmp[1], "to user :", user, "[", new Date(), "]");

		if(tmp.length < 2){
			res.send("Syntax error");
			return;
		}
		hu.addAddrToUser(tmp[1], user, function(err, data){
			if(err){
				res.send(err);
			}else{
				res.send(data);
			}
		});
	}

	function _check(res){
		var tmp = res.match[1].split(" ");
		var addr = tmp[1];
		eu.getBalanceByAddr(addr, function(err, data){
			if(err){
				res.send("Cannot get balance of " + addr);
				return;
			}
			console.log(data.data[0].balance);
			res.send("Balance : `" + data.data[0].balance/UNIT + " ETH`");
		});
	}

	function _checkByCurrency(res){
		var tmp = res.match[1].split(" ");
		var addr = tmp[1];
		var currency = tmp[2];
		eu.getBalanceByAddr(addr, function(err, data){
			if(err){
				res.send("Cannot get balance of " + addr);
				return;
			}
			console.log(data.data[0].balance);
			try{
				res.send("Balance : `" + parseFloat(hu.ethToCurrency(data.data[0].balance/UNIT, currency)).toFixed(3) + " " +currency + "`");
			}catch(e){
				res.send("Cannot check address by currency : " + e);
			}
		});
	}

	function _getPrice(res){
		eu.getPrice(function(err, data){
			if(err){
				console.error("Error" + err);
				res.send("Can't get price");
				return;
			}
			res.send("Current value of ether : `"+ parseFloat(data[0]["price_"+DEFAULT_PRICE_CURRENCY]).toFixed(3) + DEFAULT_PRICE_CURRENCY + " (" + parseFloat(data[0]["price_"+SECOND_PRICE_CURRENCY]).toFixed(3) + SECOND_PRICE_CURRENCY + ")`");
		});
	}

	function _getConvertion(res){
		var split = res.match[1].split(" ");
		//split 0 == "convert"
		var value = split[1];
		var base = split[2];
		var dest = split[3] || "eth"; // "eth" not required
		console.log("Value :", value);
		console.log("base :", base);
		console.log("dest :", dest);

		if(dest == "€" || dest == "$"){
			res.send(value + " " + base + " = " + parseFloat( hu.ethToCurrency(value, dest) ).toFixed(3) + " "+ dest);
		}else if(dest == "eth"){
			res.send(value + " " + base + " = " + parseFloat( hu.currencyToEth(value, base) ).toFixed(3) + " "+ dest);
		}

	}
}

module.exports = main;
<commit_msg>Add graph preview<commit_after>// Description:
//   Allows hubot query ethereum blockchain and few ethereum api
//
// Dependencies:
//   hubot-brain-redis
//
// Configuration:
//   none
//
// Commands:
//   ethereum balance
//   ethereum check <address>
//
// Author:
//   Edouard SCHWEISGUTH <edznux@gmail.com> (https://edouard.schweisguth.fr)
//

var https = require("https");

var DEFAULT_PRICE_CURRENCY = "eur";
var SECOND_PRICE_CURRENCY = "usd";

function main(robot){

	var UNIT = 1000000000000000000;

	var hu = require("./lib/hubot_utils.js");
	hu.setRobot(robot);
	var eu = require("./lib/ethereum_utils.js");
	eu.setRobot(robot);
	var nanopool = require("./lib/nanopool.js");

	robot.hear(/(?:ethereum|eth)( .*)?/i, function(res){
		if(res.message.rawText.match(/^(?:ethereum|eth)/i)){

			res.match[1] = res.match[1].trim();
			switch(true){
				case /check/.test(res.match[1]):
					if(/\$|\€/.test(res.match[1])){
						console.info("€ or $ found");
						_checkByCurrency(res);
					}else{
						console.info("€ or $ NOT found");
						_check(res);
					}
					break;
				case /add/.test(res.match[1]):
					_addAddr(res);
					break;
				case /(rm)|(delete)|(remove)/.test(res.match[1]):
					_deleteAddr(res);
					break;
				case res.match[1] == "list":
					_getList(res);
					break;
				case /graph(.*)/.test(res.match[1]):
					_printGraph(res);
					break;
				case /transaction (.*)/.test(res.match[1]):
					_getTransactionByAddr(res);
					break;
				case res.match[1] == "transaction":
					_getTransaction(res);
					break;
				case /nanopool (.*)/.test(res.match[1]):
					_getNanopoolBalanceByCurrency(res);
					break;
				case res.match[1] == "nanopool":
				case res.match[1] == "nanopool balance":
					_getNanopoolBalance(res);
					break;

				case /balance (.*)/.test(res.match[1]) :
					_getBalanceByCurrency(res);
					break;

				case res.match[1] == "balance" :
					_getBalance(res);
					break;

				case res.match[1] == "price":
					_getPrice(res);
					break;
				case res.match[1] == "version":
						res.send(require("./package.json").version);
					break;

				case res.match[1] == "?":
				case res.match[1] == "help":
					res.send(getHelp());
					break;
				case /convert (.*)/.test(res.match[1]):
					_getConvertion(res);
					break;

				default:
					res.send(getHelp());
					break;
			}
		}
	});

	function getHelp(){
		return [
			"Ethereum commands",
				" - add <address> : Attach address to your user",
				" - delete <address> : Delete address from your user",
				" - remove <address> : Alias for delete",
				" - rm <address> : Alias for delete",
				" - list : list addresses from the current user",
				" - balance : Get the balance of the current user",
				" - balance <€ or $> : Get the balance of the current user in the provided currency",
				" - nanopool [balance] : Get nanopool balance of the current user (if the miner has mined something)",
				" - nanopool <€ or $> : Get nanopool balance of the current user in the provided currency",
				" - transaction : List latest transaction of the current user",
				" - check <address> : Get balance from the address provided",
				" - price : value of ethereum",
				" - convert <value> <from> <to> : convert value from currency to another (<to> default = eth)",
				" - p : alias for price",
				" - graph [<period> <format>]",
				" - version : Print current version of hubot-ethereum",
				" - help : Print this help",
				" - ? : Alias for help"
				].join("\n\t");
	}

	/*
	* eth graph [<period> <format>]
	* period in [24h, 7d, 30d, 1y]
	* Format in [png,svg]
	* Send the graph link in response
	*
	* Print the btc graph for the period giver
	* @params :
	*       - res : response from robot
	*/

	function _printGraph(res){

		var user = res.message.user.name.toLowerCase();
		var split = res.match[1].split(" ");
		var period = split[1] || "24h";
		var format = split[2] || "png";

		if( !(format == "svg" || format == "png")){
			return res.send("Unsupported format");
		}

		if( !(period == "24h" || period == "7d" || period == "30d" || period == "1y") ){
			return res.send("Format not in 24h, 7d, 30d, 1y");
		}

		var url = "https://cryptohistory.org/charts/dark/eth-usdt/"+period+"/"+format+"?nonce="+Math.floor(Math.random()*10000);

		res.send("Graph : ETH / usdt over " + period+ "\n"+ url )
	}

	function _getBalance(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var total = 0;
		eu.getBalanceByUser(user, function(err,balances){
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			console.error("======", balances);
			data = balances.data;
			for(var i=0; i < data.length; i++){
				tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ data[i].balance/UNIT + " ETH`] \n";
				total += data[i].balance;
			}
			tmp += "-------\n";
			tmp += "Total : `" + parseFloat(total/UNIT).toFixed(3) + "` ETH over " + data.length + " account(s)";
			res.send(tmp);
		});
	}

	function _getBalanceByCurrency(res){
		var currency = res.match[1].split(" ")[1];

		var user = res.message.user.name.toLowerCase();
		eu.getBalanceByUser(user, function(err,balances){
			var tmp = "";
			var data;
			var total = 0;
			var value;

			if(balances.data){
				data = balances.data;
			}else{
				err = "Empty balances"
			}

			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			try{
				for(var i=0; i < data.length; i++){
					value = hu.ethToCurrency(data[i].balance/UNIT, currency);
					tmp += "Adress : [`" + data[i].addr + "`] balance : [`" + value+ "`] \n";
					total += data[i].balance;
				}
				tmp += "-------\n";
				tmp += "Total : `" + parseFloat(hu.ethToCurrency(total/UNIT, currency)).toFixed(3) + currency + "` over " + data.length + " account(s)";

				res.send(tmp);

			}catch(e){
				res.send("Cannot get balance by currency : " + e);
			}

		});
	}

	function _getTransaction(res){
		var user = res.message.user.name.toLowerCase();
		eu.getTransactionByUser(user, function(err,data){
			if(err){
				console.error(err);
				res.send("Can't  get transation for the user :" + user);
				return;
			}
			tmp = "";
			console.log(data);
			var m, dateString;

			for(var i = 0; i< data.length && i < 10; i++){
				m = new Date(data[i].time);
				dateString = m.getUTCFullYear() +"/"+
					("0" + (m.getUTCMonth()+1)).slice(-2) +"/"+
					("0" + m.getUTCDate()).slice(-2) + " " +
					("0" + m.getUTCHours()).slice(-2) + ":" +
					("0" + m.getUTCMinutes()).slice(-2) + ":" +
					("0" + m.getUTCSeconds()).slice(-2);
				tmp += "From : [`" + data[i].sender + "`] to [`" + data[i].recipient + "`] amount : `" + data[i].amount/UNIT + " ETH` Date " + dateString +"\n";
			}
			res.send("List of latest transactions \n" + tmp);

		});
	}

	function _getTransactionByAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");
		var addr = tmp[2];
		eu.getTransactionByAddr(addr, function(err,data){
			if(err){
				console.error(err);
			}
			res.send(data);
		});
	}

	function _getNanopoolBalance(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var total = 0;
		nanopool.getBalanceByUser(user, function(err, balances){
			console.log(err,balances);
			if(err){
				console.error(err);
				res.send(err);
				return;
			}
			data = balances.data;
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}
			for(var i = 0; i < data.length; i++){
				tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ data[i].balance + " ETH`] \n";
				total += data[i].balance;
			}
			tmp += "-------\n";
			tmp += "Total : `" + total + " ETH` over " + data.length + " account(s)";
			res.send(tmp);

		});
	}

	function _getNanopoolBalanceByCurrency(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		var currency = res.match[1].split(" ")[1];
		var total = 0;
		nanopool.getBalanceByUser(user, function(err, balances){
			console.log(err,balances);
			if(err){
				console.error(err);
				res.send(err);
				return;
			}
			data = balances.data;
			if(err){
				res.send("Cannot get balance for user :", user);
				return;
			}

			try{
				for(var i = 0; i < data.length; i++){
					tmp += "Adress : [`" + data[i].addr + "`] balance : [`"+ parseFloat(hu.ethToCurrency(data[i].balance, currency)).toFixed(3) + " "+ currency +"`] \n";
					total += data[i].balance;
				}
				tmp += "-------\n";
				tmp += "Total : `" + parseFloat(total*currencyMult).toFixed(3) + " "+ currency+ "` over " + data.length + " account(s)";
				res.send(tmp);

			}catch(e){
				res.send("Cannot get nanopool balance by currency : " +e);
				return;
			}

		});
	}

	function _getList(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = "";
		hu.listAddrFromUser(user, function(err, data){
			if(err){
				res.send(err);
			}else{
				for(var i =0; i<data.length; i++){
					tmp += data[i]+"\n";
				}
				res.send(tmp);
			}
		});
	}

	function _deleteAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");

		console.log("remove address :", tmp[1], "from user :", user,"[",new Date(), "]");

		if(tmp.length < 2){
			res.send("Syntax error");
			return;
		}
		hu.deleteAddrToUser(tmp[1], user, function(err, data){
			if(err){
				res.send(err);
			}else{
				res.send(data);
			}
		});
	}

	function _addAddr(res){
		var user = res.message.user.name.toLowerCase();
		var tmp = res.match[1].split(" ");

		console.log("Add address :", tmp[1], "to user :", user, "[", new Date(), "]");

		if(tmp.length < 2){
			res.send("Syntax error");
			return;
		}
		hu.addAddrToUser(tmp[1], user, function(err, data){
			if(err){
				res.send(err);
			}else{
				res.send(data);
			}
		});
	}

	function _check(res){
		var tmp = res.match[1].split(" ");
		var addr = tmp[1];
		eu.getBalanceByAddr(addr, function(err, data){
			if(err){
				res.send("Cannot get balance of " + addr);
				return;
			}
			console.log(data.data[0].balance);
			res.send("Balance : `" + data.data[0].balance/UNIT + " ETH`");
		});
	}

	function _checkByCurrency(res){
		var tmp = res.match[1].split(" ");
		var addr = tmp[1];
		var currency = tmp[2];
		eu.getBalanceByAddr(addr, function(err, data){
			if(err){
				res.send("Cannot get balance of " + addr);
				return;
			}
			console.log(data.data[0].balance);
			try{
				res.send("Balance : `" + parseFloat(hu.ethToCurrency(data.data[0].balance/UNIT, currency)).toFixed(3) + " " +currency + "`");
			}catch(e){
				res.send("Cannot check address by currency : " + e);
			}
		});
	}

	function _getPrice(res){
		eu.getPrice(function(err, data){
			if(err){
				console.error("Error" + err);
				res.send("Can't get price");
				return;
			}
			res.send("Current value of ether : `"+ parseFloat(data[0]["price_"+DEFAULT_PRICE_CURRENCY]).toFixed(3) + DEFAULT_PRICE_CURRENCY + " (" + parseFloat(data[0]["price_"+SECOND_PRICE_CURRENCY]).toFixed(3) + SECOND_PRICE_CURRENCY + ")`");
		});
	}

	function _getConvertion(res){
		var split = res.match[1].split(" ");
		//split 0 == "convert"
		var value = split[1];
		var base = split[2];
		var dest = split[3] || "eth"; // "eth" not required
		console.log("Value :", value);
		console.log("base :", base);
		console.log("dest :", dest);

		if(dest == "€" || dest == "$"){
			res.send(value + " " + base + " = " + parseFloat( hu.ethToCurrency(value, dest) ).toFixed(3) + " "+ dest);
		}else if(dest == "eth"){
			res.send(value + " " + base + " = " + parseFloat( hu.currencyToEth(value, base) ).toFixed(3) + " "+ dest);
		}

	}
}

module.exports = main;
<|endoftext|>