<commit_before>'use strict';

var sf = require('sf');
var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
var Redis = require('ioredis');
var express = require('express');
var browserify = require('browserify-middleware');
var myUtils = require('./util');
var methodOverride = require('method-override');
var bodyParser = require('body-parser');
var partials = require('express-partials');
var flash = require('express-flash');
var bcrypt;
try {
  bcrypt = require('bcrypt');
} catch (e) {
  bcrypt = require('bcryptjs');
}

process.chdir( path.join(__dirname, '..') );    // fix the cwd

var viewsPath = path.join(__dirname, '../web/views');
var staticPath = path.join(__dirname, '../web/static');
var redisConnections = [];
redisConnections.getLast = myUtils.getLast;

module.exports = function (httpServerOptions, _redisConnections, nosave, rootPattern) {
  redisConnections = _redisConnections;
  var app = express();
  app.use(partials());
  app.use(flash());
  app.use(function(req, res, next) {
    res.locals.sf = sf;
    res.locals.getFlashes = function() {
      return req.flash();
    };
    res.locals.getConnections = function() {
      return req.redisConnections;
    };
    next();
  });
  app.getConfig = myUtils.getConfig;
  if (!nosave) {
     app.saveConfig = myUtils.saveConfig;
  } else {
     app.saveConfig = function (config, callback) { callback(null) };
  }

  app.login = login;
  app.logout = logout;
  app.layoutFilename = path.join(__dirname, '../web/views/layout.ejs');
  app.rootPattern = rootPattern;
  app.set('views', viewsPath);
  app.set('view engine', 'ejs');
  app.use(httpAuth(httpServerOptions.username, httpServerOptions.passwordHash || httpServerOptions.password, !!httpServerOptions.passwordHash));
  app.use(bodyParser.urlencoded({ extended: false }))
  app.use(bodyParser.json())
  app.use(methodOverride());
  app.use(express.query());
  app.use(express.cookieParser());
  app.use(express.session({ secret: "rediscommander" }));
  app.use(addConnectionsToRequest);
  app.get('/browserify.js', browserify(['cmdparser','readline-browserify']));
  app.use(app.router);
  app.use(express.static(staticPath));
  require('./routes')(app);
  return app;
};

function httpAuth (username, password, isPasswordHashed) {
  if (username && password) {
    return express.basicAuth(function (user, pass) {
      return (username === user && (isPasswordHashed ? bcrypt.compareSync(pass, password) : (pass === password)));
    });
  } else {
    return function (req, res, next) {
      next()
    }
  }
}

function logout (hostname, port, db, callback) {
  var notRemoved = true;
  redisConnections.forEach(function (instance, index) {
    if (notRemoved && instance.options.host == hostname && instance.options.port == port && instance.options.db == db) {
      notRemoved = false;
      var connectionToClose = redisConnections.splice(index, 1);
      connectionToClose[0].quit();
    }
  });
  if (notRemoved) {
    return callback(new Error("Could not remove ", hostname, port, "."));
  } else {
    return callback(null);
  }
}

function login (label, hostname, port, password, dbIndex, callback) {
  console.log('connecting... ', hostname, port);
  var client = new Redis(port, hostname);
  client.label = label;
  redisConnections.push(client);
  redisConnections.getLast().on("error", function (err) {
    console.error("Redis error", err.stack);
  });
  redisConnections.getLast().on("end", function () {
    console.log("Connection closed. Attempting to Reconnect...");
  });
  if (password) {
    return redisConnections.getLast().auth(password, function (err) {
      if (err) {
        console.error("Could not authenticate", err.stack);
        if (callback) {
          callback(err);
          callback = null;
        }
        return;
      }
      redisConnections.getLast().on("connect", selectDatabase);
    });
  } else {
    return redisConnections.getLast().on("connect", selectDatabase);
  }

  function selectDatabase () {
    try {
      dbIndex = parseInt(dbIndex || 0);
    } catch (e) {
      return callback(e);
    }

    return redisConnections.getLast().select(dbIndex, function (err) {
      if (err) {
        console.log("could not select database", err.stack);
        if (callback) {
          callback(err);
          callback = null;
        }
        return;
      }
      console.log("Using Redis DB #" + dbIndex);
      return callback();
    });
  }
}

function addConnectionsToRequest (req, res, next) {
  req.redisConnections = redisConnections;
  return next();
}
<commit_msg>do not change dir<commit_after>'use strict';

var sf = require('sf');
var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
var Redis = require('ioredis');
var express = require('express');
var browserify = require('browserify-middleware');
var myUtils = require('./util');
var methodOverride = require('method-override');
var bodyParser = require('body-parser');
var partials = require('express-partials');
var flash = require('express-flash');
var bcrypt;
try {
  bcrypt = require('bcrypt');
} catch (e) {
  bcrypt = require('bcryptjs');
}

// process.chdir( path.join(__dirname, '..') );    // fix the cwd

var viewsPath = path.join(__dirname, '../web/views');
var staticPath = path.join(__dirname, '../web/static');
var redisConnections = [];
redisConnections.getLast = myUtils.getLast;

module.exports = function (httpServerOptions, _redisConnections, nosave, rootPattern) {
  redisConnections = _redisConnections;
  var app = express();
  app.use(partials());
  app.use(flash());
  app.use(function(req, res, next) {
    res.locals.sf = sf;
    res.locals.getFlashes = function() {
      return req.flash();
    };
    res.locals.getConnections = function() {
      return req.redisConnections;
    };
    next();
  });
  app.getConfig = myUtils.getConfig;
  if (!nosave) {
     app.saveConfig = myUtils.saveConfig;
  } else {
     app.saveConfig = function (config, callback) { callback(null) };
  }

  app.login = login;
  app.logout = logout;
  app.layoutFilename = path.join(__dirname, '../web/views/layout.ejs');
  app.rootPattern = rootPattern;
  app.set('views', viewsPath);
  app.set('view engine', 'ejs');
  app.use(httpAuth(httpServerOptions.username, httpServerOptions.passwordHash || httpServerOptions.password, !!httpServerOptions.passwordHash));
  app.use(bodyParser.urlencoded({ extended: false }))
  app.use(bodyParser.json())
  app.use(methodOverride());
  app.use(express.query());
  app.use(express.cookieParser());
  app.use(express.session({ secret: "rediscommander" }));
  app.use(addConnectionsToRequest);
  app.get('/browserify.js', browserify(['cmdparser','readline-browserify']));
  app.use(app.router);
  app.use(express.static(staticPath));
  require('./routes')(app);
  return app;
};

function httpAuth (username, password, isPasswordHashed) {
  if (username && password) {
    return express.basicAuth(function (user, pass) {
      return (username === user && (isPasswordHashed ? bcrypt.compareSync(pass, password) : (pass === password)));
    });
  } else {
    return function (req, res, next) {
      next()
    }
  }
}

function logout (hostname, port, db, callback) {
  var notRemoved = true;
  redisConnections.forEach(function (instance, index) {
    if (notRemoved && instance.options.host == hostname && instance.options.port == port && instance.options.db == db) {
      notRemoved = false;
      var connectionToClose = redisConnections.splice(index, 1);
      connectionToClose[0].quit();
    }
  });
  if (notRemoved) {
    return callback(new Error("Could not remove ", hostname, port, "."));
  } else {
    return callback(null);
  }
}

function login (label, hostname, port, password, dbIndex, callback) {
  console.log('connecting... ', hostname, port);
  var client = new Redis(port, hostname);
  client.label = label;
  redisConnections.push(client);
  redisConnections.getLast().on("error", function (err) {
    console.error("Redis error", err.stack);
  });
  redisConnections.getLast().on("end", function () {
    console.log("Connection closed. Attempting to Reconnect...");
  });
  if (password) {
    return redisConnections.getLast().auth(password, function (err) {
      if (err) {
        console.error("Could not authenticate", err.stack);
        if (callback) {
          callback(err);
          callback = null;
        }
        return;
      }
      redisConnections.getLast().on("connect", selectDatabase);
    });
  } else {
    return redisConnections.getLast().on("connect", selectDatabase);
  }

  function selectDatabase () {
    try {
      dbIndex = parseInt(dbIndex || 0);
    } catch (e) {
      return callback(e);
    }

    return redisConnections.getLast().select(dbIndex, function (err) {
      if (err) {
        console.log("could not select database", err.stack);
        if (callback) {
          callback(err);
          callback = null;
        }
        return;
      }
      console.log("Using Redis DB #" + dbIndex);
      return callback();
    });
  }
}

function addConnectionsToRequest (req, res, next) {
  req.redisConnections = redisConnections;
  return next();
}
<|endoftext|>


<commit_before>Package.describe({
	name: 'nathantreid:css-modules-import-path-helpers',
	version: '0.0.1',
	// Brief, one-line summary of the package.
	summary: 'Helper Library for package file paths',
	// URL to the Git repository containing the source code for this package.
	git: '',
	// By default, Meteor will default to using README.md for documentation.
	// To avoid submitting documentation, set this field to null.
	documentation: 'README.md'
});

Package.onUse(function (api) {
	api.versionsFrom('1.2.0.1');

	api.use('ecmascript');
	api.addFiles('import-path-helpers.js');
	api.export('ImportPathHelpers');
});
<commit_msg>Added reference to git repository<commit_after>Package.describe({
	name: 'nathantreid:css-modules-import-path-helpers',
	version: '0.0.1',
	// Brief, one-line summary of the package.
	summary: 'Helper Library for package file paths',
	// URL to the Git repository containing the source code for this package.
	git: 'https://github.com/nathantreid/meteor-css-modules-import-path-helpers.git',
	// By default, Meteor will default to using README.md for documentation.
	// To avoid submitting documentation, set this field to null.
	documentation: 'README.md'
});

Package.onUse(function (api) {
	api.versionsFrom('1.2.0.1');

	api.use('ecmascript');
	api.addFiles('import-path-helpers.js');
	api.export('ImportPathHelpers');
});
<|endoftext|>


<commit_before>Package.describe({
  name: 'iron:router',
  summary: 'Routing specifically designed for Meteor',
  version: "1.0.9",
  git: "https://github.com/eventedmind/iron-router"
});

Npm.depends({
  'body-parser': '1.12.4'
});

Package.on_use(function (api) {
  api.versionsFrom('METEOR@0.9.2');
  // meteor dependencies
  api.use('underscore');
  api.use('webapp', 'server');
  api.use('deps', 'client');
  api.use('ui');
  api.use('templating');

  // for cloning
  api.use('ejson');

  // for dynamic scoping with environment variables
  api.use('meteor')

  // main namespace and utils
  api.use('iron:core@1.0.8');
  api.imply('iron:core');

  // ui layout
  api.use('iron:layout@1.0.8');

  // connect like middleware stack for client/server
  api.use('iron:middleware-stack@1.0.8');

  // client and server side url utilities and compiling
  api.use('iron:url@1.0.9');

  // for reactive urls and pushState in the browser
  api.use('iron:location@1.0.8');

  // for RouteController which inherits from this
  api.use('iron:controller@1.0.8');

  api.add_files('lib/current_options.js');
  api.add_files('lib/http_methods.js');
  api.add_files('lib/route_controller.js');
  api.add_files('lib/route_controller_server.js', 'server');
  api.add_files('lib/route_controller_client.js', 'client');
  api.add_files('lib/route.js');
  api.add_files('lib/router.js');
  api.add_files('lib/hooks.js');
  api.add_files('lib/helpers.js');
  api.add_files('lib/router_client.js', 'client');
  api.add_files('lib/body_parser_server.js', 'server');
  api.add_files('lib/router_server.js', 'server');
  api.add_files('lib/plugins.js');
  api.add_files('lib/global_router.js');
  api.add_files('lib/templates.html');

  // symbol exports
  api.export('Router');
  api.export('RouteController');
});

Package.on_test(function (api) {
  api.use('iron:router');
  api.use('tinytest');
  api.use('test-helpers');

  api.add_files('test/helpers.js');
  api.add_files('test/route_test.js');
  api.add_files('test/router_test.js');
  api.add_files('test/route_controller_test.js');
});
<commit_msg>update middleware and location deps<commit_after>Package.describe({
  name: 'iron:router',
  summary: 'Routing specifically designed for Meteor',
  version: "1.0.9",
  git: "https://github.com/eventedmind/iron-router"
});

Npm.depends({
  'body-parser': '1.12.4'
});

Package.on_use(function (api) {
  api.versionsFrom('METEOR@0.9.2');
  // meteor dependencies
  api.use('underscore');
  api.use('webapp', 'server');
  api.use('deps', 'client');
  api.use('ui');
  api.use('templating');

  // for cloning
  api.use('ejson');

  // for dynamic scoping with environment variables
  api.use('meteor')

  // main namespace and utils
  api.use('iron:core@1.0.8');
  api.imply('iron:core');

  // ui layout
  api.use('iron:layout@1.0.8');

  // connect like middleware stack for client/server
  api.use('iron:middleware-stack@1.0.9');

  // client and server side url utilities and compiling
  api.use('iron:url@1.0.9');

  // for reactive urls and pushState in the browser
  api.use('iron:location@1.0.9');

  // for RouteController which inherits from this
  api.use('iron:controller@1.0.8');

  api.add_files('lib/current_options.js');
  api.add_files('lib/http_methods.js');
  api.add_files('lib/route_controller.js');
  api.add_files('lib/route_controller_server.js', 'server');
  api.add_files('lib/route_controller_client.js', 'client');
  api.add_files('lib/route.js');
  api.add_files('lib/router.js');
  api.add_files('lib/hooks.js');
  api.add_files('lib/helpers.js');
  api.add_files('lib/router_client.js', 'client');
  api.add_files('lib/body_parser_server.js', 'server');
  api.add_files('lib/router_server.js', 'server');
  api.add_files('lib/plugins.js');
  api.add_files('lib/global_router.js');
  api.add_files('lib/templates.html');

  // symbol exports
  api.export('Router');
  api.export('RouteController');
});

Package.on_test(function (api) {
  api.use('iron:router');
  api.use('tinytest');
  api.use('test-helpers');

  api.add_files('test/helpers.js');
  api.add_files('test/route_test.js');
  api.add_files('test/router_test.js');
  api.add_files('test/route_controller_test.js');
});
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitflyer extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitflyer',
            'name': 'bitFlyer',
            'countries': [ 'JP' ],
            'version': 'v1',
            'rateLimit': 1000, // their nonce-timestamp is in seconds...
            'has': {
                'CORS': false,
                'withdraw': true,
                'fetchMyTrades': true,
                'fetchOrders': true,
                'fetchOrder': 'emulated',
                'fetchOpenOrders': 'emulated',
                'fetchClosedOrders': 'emulated',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28051642-56154182-660e-11e7-9b0d-6042d1e6edd8.jpg',
                'api': 'https://api.bitflyer.jp',
                'www': 'https://bitflyer.jp',
                'doc': 'https://lightning.bitflyer.com/docs?lang=en',
            },
            'api': {
                'public': {
                    'get': [
                        'getmarkets/usa', // new (wip)
                        'getmarkets/eu',  // new (wip)
                        'getmarkets',     // or 'markets'
                        'getboard',       // ...
                        'getticker',
                        'getexecutions',
                        'gethealth',
                        'getboardstate',
                        'getchats',
                    ],
                },
                'private': {
                    'get': [
                        'getpermissions',
                        'getbalance',
                        'getbalancehistory',
                        'getcollateral',
                        'getcollateralhistory',
                        'getcollateralaccounts',
                        'getaddresses',
                        'getcoinins',
                        'getcoinouts',
                        'getbankaccounts',
                        'getdeposits',
                        'getwithdrawals',
                        'getchildorders',
                        'getparentorders',
                        'getparentorder',
                        'getexecutions',
                        'getpositions',
                        'gettradingcommission',
                    ],
                    'post': [
                        'sendcoin',
                        'withdraw',
                        'sendchildorder',
                        'cancelchildorder',
                        'sendparentorder',
                        'cancelparentorder',
                        'cancelallchildorders',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.25 / 100,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets (params = {}) {
        const jp_markets = await this.publicGetGetmarkets (params);
        const us_markets = await this.publicGetGetmarketsUsa (params);
        const eu_markets = await this.publicGetGetmarketsEu (params);
        let markets = this.arrayConcat (jp_markets, us_markets);
        markets = this.arrayConcat (markets, eu_markets);
        const result = [];
        for (let i = 0; i < markets.length; i++) {
            const market = markets[i];
            const id = this.safeString (market, 'product_code');
            let spot = true;
            let future = false;
            let type = 'spot';
            if ('alias' in market) {
                type = 'future';
                future = true;
                spot = false;
            }
            const currencies = id.split ('_');
            let baseId = undefined;
            let quoteId = undefined;
            let base = undefined;
            let quote = undefined;
            const numCurrencies = currencies.length;
            if (numCurrencies === 1) {
                baseId = id.slice (0, 3);
                quoteId = id.slice (3, 6);
            } else if (numCurrencies === 2) {
                baseId = currencies[0];
                quoteId = currencies[1];
            } else {
                baseId = currencies[1];
                quoteId = currencies[2];
            }
            base = this.commonCurrencyCode (baseId);
            quote = this.commonCurrencyCode (quoteId);
            const symbol = (numCurrencies === 2) ? (base + '/' + quote) : id;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'type': type,
                'spot': spot,
                'future': future,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const response = await this.privateGetGetbalance (params);
        //
        //     [
        //         {
        //             "currency_code": "JPY",
        //             "amount": 1024078,
        //             "available": 508000
        //         },
        //         {
        //             "currency_code": "BTC",
        //             "amount": 10.24,
        //             "available": 4.12
        //         },
        //         {
        //             "currency_code": "ETH",
        //             "amount": 20.48,
        //             "available": 16.38
        //         }
        //     ]
        //
        const result = { 'info': response };
        const balances = {};
        for (let i = 0; i < response.length; i++) {
            const balance = response[i];
            const currencyId = this.safeString (balance, 'currency_code');
            const code = this.commonCurrencyCode (currencyId);
            const account = this.account ();
            account['total'] = this.safeFloat (balance, 'amount');
            account['free'] = this.safeFloat (balance, 'available');
            balances[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
        };
        const orderbook = await this.publicGetGetboard (this.extend (request, params));
        return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'size');
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
        };
        const ticker = await this.publicGetGetticker (this.extend (request, params));
        const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp'));
        const last = this.safeFloat (ticker, 'ltp');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': this.safeFloat (ticker, 'best_bid'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'best_ask'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_by_product'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let side = this.safeString (trade, 'side');
        if (side !== undefined) {
            if (side.length < 1) {
                side = undefined;
            } else {
                side = side.toLowerCase ();
            }
        }
        let order = undefined;
        if (side !== undefined) {
            side = trade['side'].toLowerCase ();
            const id = side + '_child_order_acceptance_id';
            if (id in trade) {
                order = trade[id];
            }
        }
        if (order === undefined) {
            order = this.safeString (trade, 'child_order_acceptance_id');
        }
        const timestamp = this.parse8601 (this.safeString (trade, 'exec_date'));
        const price = this.safeFloat (trade, 'price');
        const amount = this.safeFloat (trade, 'size');
        let cost = undefined;
        if (amount !== undefined) {
            if (price !== undefined) {
                cost = price * amount;
            }
        }
        const id = this.safeString (trade, 'id');
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        return {
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'order': order,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
        };
        const response = await this.publicGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
            'child_order_type': type.toUpperCase (),
            'side': side.toUpperCase (),
            'price': price,
            'size': amount,
        };
        const result = await this.privatePostSendchildorder (this.extend (request, params));
        // { "status": - 200, "error_message": "Insufficient funds", "data": null }
        const id = this.safeString (result, 'child_order_acceptance_id');
        return {
            'info': result,
            'id': id,
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' cancelOrder() requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
            'child_order_acceptance_id': id,
        };
        return await this.privatePostCancelchildorder (this.extend (request, params));
    }

    parseOrderStatus (status) {
        const statuses = {
            'ACTIVE': 'open',
            'COMPLETED': 'closed',
            'CANCELED': 'canceled',
            'EXPIRED': 'canceled',
            'REJECTED': 'canceled',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        const timestamp = this.parse8601 (this.safeString (order, 'child_order_date'));
        const amount = this.safeFloat (order, 'size');
        const remaining = this.safeFloat (order, 'outstanding_size');
        const filled = this.safeFloat (order, 'executed_size');
        const price = this.safeFloat (order, 'price');
        const cost = price * filled;
        const status = this.parseOrderStatus (this.safeString (order, 'child_order_state'));
        let type = this.safeString (order, 'child_order_type');
        if (type !== undefined) {
            type = type.toLowerCase ();
        }
        let side = this.safeString (order, 'side');
        if (side !== undefined) {
            side = side.toLowerCase ();
        }
        let symbol = undefined;
        if (market === undefined) {
            const marketId = this.safeString (order, 'product_code');
            if (marketId in this.markets_by_id) {
                market = this.markets_by_id[marketId];
            }
        }
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        let fee = undefined;
        const feeCost = this.safeFloat (order, 'total_commission');
        if (feeCost !== undefined) {
            fee = {
                'cost': feeCost,
                'currency': undefined,
                'rate': undefined,
            };
        }
        const id = this.safeString (order, 'child_order_acceptance_id');
        return {
            'id': id,
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': fee,
        };
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrders() requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
            'count': limit,
        };
        const response = await this.privateGetGetchildorders (this.extend (request, params));
        let orders = this.parseOrders (response, market, since, limit);
        if (symbol !== undefined) {
            orders = this.filterBy (orders, 'symbol', symbol);
        }
        return orders;
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        const request = {
            'child_order_state': 'ACTIVE',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        const request = {
            'child_order_state': 'COMPLETED',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrder() requires a `symbol` argument');
        }
        const orders = await this.fetchOrders (symbol);
        const ordersById = this.indexBy (orders, 'id');
        if (id in ordersById) {
            return ordersById[id];
        }
        throw new OrderNotFound (this.id + ' No order found with id ' + id);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
        };
        if (limit !== undefined) {
            request['count'] = limit;
        }
        const response = await this.privateGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        if (code !== 'JPY' && code !== 'USD' && code !== 'EUR') {
            throw new ExchangeError (this.id + ' allows withdrawing JPY, USD, EUR only, ' + code + ' is not supported');
        }
        const currency = this.currency (code);
        const request = {
            'currency_code': currency['id'],
            'amount': amount,
            // 'bank_account_id': 1234,
        };
        const response = await this.privatePostWithdraw (this.extend (request, params));
        const id = this.safeString (response, 'message_id');
        return {
            'info': response,
            'id': id,
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.version + '/';
        if (api === 'private') {
            request += 'me/';
        }
        request += path;
        if (method === 'GET') {
            if (Object.keys (params).length) {
                request += '?' + this.urlencode (params);
            }
        }
        const url = this.urls['api'] + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            const nonce = this.nonce ().toString ();
            let auth = [ nonce, method, request ].join ('');
            if (Object.keys (params).length) {
                if (method !== 'GET') {
                    body = this.json (params);
                    auth += body;
                }
            }
            headers = {
                'ACCESS-KEY': this.apiKey,
                'ACCESS-TIMESTAMP': nonce,
                'ACCESS-SIGN': this.hmac (this.encode (auth), this.encode (this.secret)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>bitflyer fetchBalance bug<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitflyer extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitflyer',
            'name': 'bitFlyer',
            'countries': [ 'JP' ],
            'version': 'v1',
            'rateLimit': 1000, // their nonce-timestamp is in seconds...
            'has': {
                'CORS': false,
                'withdraw': true,
                'fetchMyTrades': true,
                'fetchOrders': true,
                'fetchOrder': 'emulated',
                'fetchOpenOrders': 'emulated',
                'fetchClosedOrders': 'emulated',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28051642-56154182-660e-11e7-9b0d-6042d1e6edd8.jpg',
                'api': 'https://api.bitflyer.jp',
                'www': 'https://bitflyer.jp',
                'doc': 'https://lightning.bitflyer.com/docs?lang=en',
            },
            'api': {
                'public': {
                    'get': [
                        'getmarkets/usa', // new (wip)
                        'getmarkets/eu',  // new (wip)
                        'getmarkets',     // or 'markets'
                        'getboard',       // ...
                        'getticker',
                        'getexecutions',
                        'gethealth',
                        'getboardstate',
                        'getchats',
                    ],
                },
                'private': {
                    'get': [
                        'getpermissions',
                        'getbalance',
                        'getbalancehistory',
                        'getcollateral',
                        'getcollateralhistory',
                        'getcollateralaccounts',
                        'getaddresses',
                        'getcoinins',
                        'getcoinouts',
                        'getbankaccounts',
                        'getdeposits',
                        'getwithdrawals',
                        'getchildorders',
                        'getparentorders',
                        'getparentorder',
                        'getexecutions',
                        'getpositions',
                        'gettradingcommission',
                    ],
                    'post': [
                        'sendcoin',
                        'withdraw',
                        'sendchildorder',
                        'cancelchildorder',
                        'sendparentorder',
                        'cancelparentorder',
                        'cancelallchildorders',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.25 / 100,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets (params = {}) {
        const jp_markets = await this.publicGetGetmarkets (params);
        const us_markets = await this.publicGetGetmarketsUsa (params);
        const eu_markets = await this.publicGetGetmarketsEu (params);
        let markets = this.arrayConcat (jp_markets, us_markets);
        markets = this.arrayConcat (markets, eu_markets);
        const result = [];
        for (let i = 0; i < markets.length; i++) {
            const market = markets[i];
            const id = this.safeString (market, 'product_code');
            let spot = true;
            let future = false;
            let type = 'spot';
            if ('alias' in market) {
                type = 'future';
                future = true;
                spot = false;
            }
            const currencies = id.split ('_');
            let baseId = undefined;
            let quoteId = undefined;
            let base = undefined;
            let quote = undefined;
            const numCurrencies = currencies.length;
            if (numCurrencies === 1) {
                baseId = id.slice (0, 3);
                quoteId = id.slice (3, 6);
            } else if (numCurrencies === 2) {
                baseId = currencies[0];
                quoteId = currencies[1];
            } else {
                baseId = currencies[1];
                quoteId = currencies[2];
            }
            base = this.commonCurrencyCode (baseId);
            quote = this.commonCurrencyCode (quoteId);
            const symbol = (numCurrencies === 2) ? (base + '/' + quote) : id;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'type': type,
                'spot': spot,
                'future': future,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const response = await this.privateGetGetbalance (params);
        //
        //     [
        //         {
        //             "currency_code": "JPY",
        //             "amount": 1024078,
        //             "available": 508000
        //         },
        //         {
        //             "currency_code": "BTC",
        //             "amount": 10.24,
        //             "available": 4.12
        //         },
        //         {
        //             "currency_code": "ETH",
        //             "amount": 20.48,
        //             "available": 16.38
        //         }
        //     ]
        //
        const result = { 'info': response };
        for (let i = 0; i < response.length; i++) {
            const balance = response[i];
            const currencyId = this.safeString (balance, 'currency_code');
            let code = currencyId;
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            } else {
                code = this.commonCurrencyCode (currencyId);
            }
            const account = this.account ();
            account['total'] = this.safeFloat (balance, 'amount');
            account['free'] = this.safeFloat (balance, 'available');
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
        };
        const orderbook = await this.publicGetGetboard (this.extend (request, params));
        return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'size');
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
        };
        const ticker = await this.publicGetGetticker (this.extend (request, params));
        const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp'));
        const last = this.safeFloat (ticker, 'ltp');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': this.safeFloat (ticker, 'best_bid'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'best_ask'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_by_product'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let side = this.safeString (trade, 'side');
        if (side !== undefined) {
            if (side.length < 1) {
                side = undefined;
            } else {
                side = side.toLowerCase ();
            }
        }
        let order = undefined;
        if (side !== undefined) {
            side = trade['side'].toLowerCase ();
            const id = side + '_child_order_acceptance_id';
            if (id in trade) {
                order = trade[id];
            }
        }
        if (order === undefined) {
            order = this.safeString (trade, 'child_order_acceptance_id');
        }
        const timestamp = this.parse8601 (this.safeString (trade, 'exec_date'));
        const price = this.safeFloat (trade, 'price');
        const amount = this.safeFloat (trade, 'size');
        let cost = undefined;
        if (amount !== undefined) {
            if (price !== undefined) {
                cost = price * amount;
            }
        }
        const id = this.safeString (trade, 'id');
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        return {
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'order': order,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
        };
        const response = await this.publicGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
            'child_order_type': type.toUpperCase (),
            'side': side.toUpperCase (),
            'price': price,
            'size': amount,
        };
        const result = await this.privatePostSendchildorder (this.extend (request, params));
        // { "status": - 200, "error_message": "Insufficient funds", "data": null }
        const id = this.safeString (result, 'child_order_acceptance_id');
        return {
            'info': result,
            'id': id,
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' cancelOrder() requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const request = {
            'product_code': this.marketId (symbol),
            'child_order_acceptance_id': id,
        };
        return await this.privatePostCancelchildorder (this.extend (request, params));
    }

    parseOrderStatus (status) {
        const statuses = {
            'ACTIVE': 'open',
            'COMPLETED': 'closed',
            'CANCELED': 'canceled',
            'EXPIRED': 'canceled',
            'REJECTED': 'canceled',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        const timestamp = this.parse8601 (this.safeString (order, 'child_order_date'));
        const amount = this.safeFloat (order, 'size');
        const remaining = this.safeFloat (order, 'outstanding_size');
        const filled = this.safeFloat (order, 'executed_size');
        const price = this.safeFloat (order, 'price');
        const cost = price * filled;
        const status = this.parseOrderStatus (this.safeString (order, 'child_order_state'));
        let type = this.safeString (order, 'child_order_type');
        if (type !== undefined) {
            type = type.toLowerCase ();
        }
        let side = this.safeString (order, 'side');
        if (side !== undefined) {
            side = side.toLowerCase ();
        }
        let symbol = undefined;
        if (market === undefined) {
            const marketId = this.safeString (order, 'product_code');
            if (marketId in this.markets_by_id) {
                market = this.markets_by_id[marketId];
            }
        }
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        let fee = undefined;
        const feeCost = this.safeFloat (order, 'total_commission');
        if (feeCost !== undefined) {
            fee = {
                'cost': feeCost,
                'currency': undefined,
                'rate': undefined,
            };
        }
        const id = this.safeString (order, 'child_order_acceptance_id');
        return {
            'id': id,
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': fee,
        };
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrders() requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
            'count': limit,
        };
        const response = await this.privateGetGetchildorders (this.extend (request, params));
        let orders = this.parseOrders (response, market, since, limit);
        if (symbol !== undefined) {
            orders = this.filterBy (orders, 'symbol', symbol);
        }
        return orders;
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        const request = {
            'child_order_state': 'ACTIVE',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        const request = {
            'child_order_state': 'COMPLETED',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrder() requires a `symbol` argument');
        }
        const orders = await this.fetchOrders (symbol);
        const ordersById = this.indexBy (orders, 'id');
        if (id in ordersById) {
            return ordersById[id];
        }
        throw new OrderNotFound (this.id + ' No order found with id ' + id);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a `symbol` argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'product_code': market['id'],
        };
        if (limit !== undefined) {
            request['count'] = limit;
        }
        const response = await this.privateGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        if (code !== 'JPY' && code !== 'USD' && code !== 'EUR') {
            throw new ExchangeError (this.id + ' allows withdrawing JPY, USD, EUR only, ' + code + ' is not supported');
        }
        const currency = this.currency (code);
        const request = {
            'currency_code': currency['id'],
            'amount': amount,
            // 'bank_account_id': 1234,
        };
        const response = await this.privatePostWithdraw (this.extend (request, params));
        const id = this.safeString (response, 'message_id');
        return {
            'info': response,
            'id': id,
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.version + '/';
        if (api === 'private') {
            request += 'me/';
        }
        request += path;
        if (method === 'GET') {
            if (Object.keys (params).length) {
                request += '?' + this.urlencode (params);
            }
        }
        const url = this.urls['api'] + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            const nonce = this.nonce ().toString ();
            let auth = [ nonce, method, request ].join ('');
            if (Object.keys (params).length) {
                if (method !== 'GET') {
                    body = this.json (params);
                    auth += body;
                }
            }
            headers = {
                'ACCESS-KEY': this.apiKey,
                'ACCESS-TIMESTAMP': nonce,
                'ACCESS-SIGN': this.hmac (this.encode (auth), this.encode (this.secret)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>import _ from 'lodash';
import Client from './api';

class Bot {
  constructor() {
    this.client = new Client({
        app: 'YjED2JGsO9'
      , secret: 'oNiF8V3Yfw'
      , account: 't3FB3XyoPeH3EGkLyVsI'
    });
    this.badWords = [
        /[qk]u?r[wf][ao]/i // kurwa
      , /qwa/i
      , /jprdl/i
      , /pierdo\w+/i // pierdolić
      , /szmat[ao]/i // szmata
      , /cwel/i
      , /pi[zź]d[ayz]i?e?/i
      , /testmanderigona/i
      , /penis/i
      , /pines/i
      , /cipk?a/i
      , /c?h[u|ó]j/i
      , /zajebi/i
      , /zapier/i
    ];
    this.templates = [
        'Użytkowniku @<%= nick %>, brzydko się wyrażasz! Wzywam Cię do porządku i informuję, że w dniu dzisiejszym składam zawiadomienie do Moderacji Wykop.pl! Wołam @moderacja'
      , 'Panie, @<%= nick %>, pan w domu też tak się brzydko wyrażasz? Uspokój się Pan i wołam @moderacja!'
      , '@<%= nick %> Używanie wulgaryzmów w serwisie Wykop.pl jest zabronione. Zgłaszam Pana do @moderacja'
      , '@<%= nick %> ale z Ciebie śmieszek, za te złe wyrażanie się zgłaszam Ciebie do @moderacja'
    ];
    this.cache = [];
  }

  verifyString(str, patterns) {
    return !_.some(patterns, (word) => str.match(word));
  }

  parseEntry(data) {
    let checkBlock = (entry, comments=[]) => {
      if(!this.verifyString(entry['body'], this.badWords)) {
        let cacheKey = `${data['id']}${entry['author']}`;
        if(~this.cache.indexOf(cacheKey))
          return;

        let body = _.template(this.templates[Math.floor(this.templates.length * Math.random())])({nick: entry['author']})
        if(!_.find(comments, (comment) => comment['author'] === 'Mati365' && !~comment['body'].indexOf(entry['author']))) {
          console.log('Niegrzeczny ', entry['author'], '! Wiadomosc:', entry['body']);
          this.cache.push(cacheKey);
          this.client
            .request('entries/addcomment', {body}, {method: [data['id']]})
            .then((res) => console.log(res));
        }
      }
    };
    if(data['body'].indexOf('#bekazlewactwa') > -1)
      this.client.request('entries/index', null, {method: [data['id']]}).then(({comments}) => {
        comments = comments.concat([data]);
        _.each(comments, (entry) => checkBlock(entry, comments));
      });
    else
      checkBlock(data);
  }
  run() {
    let search = () => {
      this.client
        .request('stream/index')
        .then((data) => {
          _.each(data, (entry) => this.parseEntry(entry));
        });
    }

    search();
    setInterval(() => search.bind(this), 300000);
  }
};

export default new Bot;<commit_msg>Better texts<commit_after>import _ from 'lodash';
import Client from './api';

class Bot {
  constructor() {
    this.client = new Client({
        app: 'YjED2JGsO9'
      , secret: 'oNiF8V3Yfw'
      , account: 't3FB3XyoPeH3EGkLyVsI'
    });
    this.badWords = [
        /[qk]u?r[wf][ao]/i // kurwa
      , /qwa/i
      , /jprdl/i
      , /pierdo\w+/i // pierdolić
      , /szmat[ao]/i // szmata
      , /cwel/i
      , /pi[zź]d[ayz]i?e?/i
      , /testmanderigona/i
      , /penis/i
      , /pines/i
      , /cipk?a/i
      , /c?h[u|ó]j/i
      , /zajebi/i
      , /zapier/i
    ];
    this.templates = [
        'Użytkowniku @<%= nick %>, Jestem oburzony Twoim wpisem, mógłbyś go usunąć? ( ͡° ʖ̯ ͡°)'
      , 'Panie, @<%= nick %>, pan weź to usuń bo Cie zgłosze!'
      , '@<%= nick %>, ... usuń konto'
      , '@<%= nick %> baaardzo interesujące, usuń się'
      , '@<%= nick %> nie klnij tak bo Cie zglosze'
    ];
    this.cache = [];
  }

  verifyString(str, patterns) {
    return !_.some(patterns, (word) => str.match(word));
  }

  parseEntry(data) {
    let checkBlock = (entry, comments=[]) => {
      if(!this.verifyString(entry['body'], this.badWords)) {
        let cacheKey = `${data['id']}${entry['author']}`;
        if(this.cache.indexOf(cacheKey) > -1)
          return;
        let body = _.template(this.templates[Math.floor(this.templates.length * Math.random())])({nick: entry['author']})
        if(!_.find(comments, (comment) => comment['author'] === 'Mati365' && !~comment['body'].indexOf(entry['author']))) {
          console.log('Niegrzeczny ', entry['author'], '! Wiadomosc:', entry['body']);
          this.cache.push(cacheKey);
          this.client
            .request('entries/addcomment', {body}, {method: [data['id']]})
            .then((res) => console.log(res));
        }
      }
    };
    if(data['body'].indexOf('#bekazlewactwa') > -1)
      this.client.request('entries/index', null, {method: [data['id']]}).then(({comments}) => {
        comments = comments.concat([data]);
        _.each(comments, (entry) => checkBlock(entry, comments));
      });
    else
      checkBlock(data);
  }
  run() {
    let search = () => {
      console.log('Szukam mirko...');
      this.client
        .request('stream/index')
        .then((data) => {
          _.each(data, (entry) => this.parseEntry(entry));
        });
    }

    search();
    setInterval(() => search.bind(this), 300000);
  }
};

export default new Bot;<|endoftext|>


<commit_before>Package.describe({
  summary: 'Dynamically create and update templates and their data contexts.',
  version: "1.0.0-pre3",
  git: "https://github.com/eventedmind/iron-dynamic-template",
  name: 'iron:dynamic-template'
});

Package.on_use(function (api) {
  api.versionsFrom('METEOR@0.9.2');

  api.use('blaze');
  api.use('underscore');
  api.use('ui');
  api.use('jquery');
  api.use('tracker');
  api.use('reactive-var');
  api.use('templating');

  api.use('iron:core@1.0.0-pre3');
  api.imply('iron:core');

  api.add_files('version_conflict_error.js');
  api.add_files('dynamic_template.html');
  api.add_files('dynamic_template.js');
  api.add_files('blaze_overrides.js');
});

Package.on_test(function (api) {
  api.versionsFrom('METEOR@0.9.2');

  api.use('iron:dynamic-template');
  api.use('templating');
  api.use('tinytest');
  api.use('test-helpers');
  api.use('blaze');
  api.use('deps');

  api.add_files('dynamic_template_test.html', 'client');
  api.add_files('dynamic_template_test.js', 'client');
});
<commit_msg>bump version<commit_after>Package.describe({
  summary: 'Dynamically create and update templates and their data contexts.',
  version: "1.0.8",
  git: "https://github.com/eventedmind/iron-dynamic-template",
  name: 'iron:dynamic-template'
});

Package.on_use(function (api) {
  api.versionsFrom('METEOR@0.9.2');

  api.use('blaze');
  api.use('underscore');
  api.use('ui');
  api.use('jquery');
  api.use('tracker');
  api.use('reactive-var');
  api.use('templating');

  api.use('iron:core@1.0.8');
  api.imply('iron:core');

  api.add_files('version_conflict_error.js');
  api.add_files('dynamic_template.html');
  api.add_files('dynamic_template.js');
  api.add_files('blaze_overrides.js');
});

Package.on_test(function (api) {
  api.versionsFrom('METEOR@0.9.2');

  api.use('iron:dynamic-template');
  api.use('templating');
  api.use('tinytest');
  api.use('test-helpers');
  api.use('blaze');
  api.use('deps');

  api.add_files('dynamic_template_test.html', 'client');
  api.add_files('dynamic_template_test.js', 'client');
});
<|endoftext|>


<commit_before>'use strict'

exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray

var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array

function init () {
  var i
  var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

  for (i = 0; i < code.length; i++) {
    lookup[i] = code[i]
  }

  for (i = 0; i < code.length; ++i) {
    revLookup[code.charCodeAt(i)] = i
  }
  revLookup['-'.charCodeAt(0)] = 62
  revLookup['_'.charCodeAt(0)] = 63
}

init()

function toByteArray (b64) {
  var i, j, l, tmp, placeHolders, arr
  var len = b64.length

  if (len % 4 > 0) {
    throw new Error('Invalid string. Length must be a multiple of 4')
  }

  // the number of equal signs (place holders)
  // if there are two placeholders, than the two characters before it
  // represent one byte
  // if there is only one, then the three characters before it represent 2 bytes
  // this is just a cheap hack to not do indexOf twice
  placeHolders = b64.charAt(len - 2) === '=' ? 2 : b64.charAt(len - 1) === '=' ? 1 : 0

  // base64 is 4/3 + up to two characters of the original data
  arr = new Arr(len * 3 / 4 - placeHolders)

  // if there are placeholders, only get up to the last complete 4 chars
  l = placeHolders > 0 ? len - 4 : len

  var L = 0

  for (i = 0, j = 0; i < l; i += 4, j += 3) {
    tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
    arr[L++] = (tmp & 0xFF0000) >> 16
    arr[L++] = (tmp & 0xFF00) >> 8
    arr[L++] = tmp & 0xFF
  }

  if (placeHolders === 2) {
    tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
    arr[L++] = tmp & 0xFF
  } else if (placeHolders === 1) {
    tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
    arr[L++] = (tmp >> 8) & 0xFF
    arr[L++] = tmp & 0xFF
  }

  return arr
}

function tripletToBase64 (num) {
  return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
}

function encodeChunk (uint8, start, end) {
  var temp
  var output = []
  for (var i = start; i < end; i += 3) {
    temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
    output.push(tripletToBase64(temp))
  }
  return output.join('')
}

function fromByteArray (uint8) {
  var i
  var extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes
  var output = ''
  var parts = []
  var temp, length
  var maxChunkLength = 16383 // must be multiple of 3

  // go through the array every three bytes, we'll deal with trailing stuff later

  for (i = 0, length = uint8.length - extraBytes; i < length; i += maxChunkLength) {
    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > length ? length : (i + maxChunkLength)))
  }

  // pad the end with zeros, but make sure to not forget the extra bytes
  switch (extraBytes) {
    case 1:
      temp = uint8[uint8.length - 1]
      output += lookup[temp >> 2]
      output += lookup[(temp << 4) & 0x3F]
      output += '=='
      break
    case 2:
      temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
      output += lookup[temp >> 10]
      output += lookup[(temp >> 4) & 0x3F]
      output += lookup[(temp << 2) & 0x3F]
      output += '='
      break
    default:
      break
  }

  parts.push(output)

  return parts.join('')
}
<commit_msg>replace str.charAt() with str[]<commit_after>'use strict'

exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray

var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array

function init () {
  var i
  var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

  for (i = 0; i < code.length; i++) {
    lookup[i] = code[i]
  }

  for (i = 0; i < code.length; ++i) {
    revLookup[code.charCodeAt(i)] = i
  }
  revLookup['-'.charCodeAt(0)] = 62
  revLookup['_'.charCodeAt(0)] = 63
}

init()

function toByteArray (b64) {
  var i, j, l, tmp, placeHolders, arr
  var len = b64.length

  if (len % 4 > 0) {
    throw new Error('Invalid string. Length must be a multiple of 4')
  }

  // the number of equal signs (place holders)
  // if there are two placeholders, than the two characters before it
  // represent one byte
  // if there is only one, then the three characters before it represent 2 bytes
  // this is just a cheap hack to not do indexOf twice
  placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0

  // base64 is 4/3 + up to two characters of the original data
  arr = new Arr(len * 3 / 4 - placeHolders)

  // if there are placeholders, only get up to the last complete 4 chars
  l = placeHolders > 0 ? len - 4 : len

  var L = 0

  for (i = 0, j = 0; i < l; i += 4, j += 3) {
    tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
    arr[L++] = (tmp & 0xFF0000) >> 16
    arr[L++] = (tmp & 0xFF00) >> 8
    arr[L++] = tmp & 0xFF
  }

  if (placeHolders === 2) {
    tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
    arr[L++] = tmp & 0xFF
  } else if (placeHolders === 1) {
    tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
    arr[L++] = (tmp >> 8) & 0xFF
    arr[L++] = tmp & 0xFF
  }

  return arr
}

function tripletToBase64 (num) {
  return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
}

function encodeChunk (uint8, start, end) {
  var temp
  var output = []
  for (var i = start; i < end; i += 3) {
    temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
    output.push(tripletToBase64(temp))
  }
  return output.join('')
}

function fromByteArray (uint8) {
  var i
  var extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes
  var output = ''
  var parts = []
  var temp, length
  var maxChunkLength = 16383 // must be multiple of 3

  // go through the array every three bytes, we'll deal with trailing stuff later

  for (i = 0, length = uint8.length - extraBytes; i < length; i += maxChunkLength) {
    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > length ? length : (i + maxChunkLength)))
  }

  // pad the end with zeros, but make sure to not forget the extra bytes
  switch (extraBytes) {
    case 1:
      temp = uint8[uint8.length - 1]
      output += lookup[temp >> 2]
      output += lookup[(temp << 4) & 0x3F]
      output += '=='
      break
    case 2:
      temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
      output += lookup[temp >> 10]
      output += lookup[(temp >> 4) & 0x3F]
      output += lookup[(temp << 2) & 0x3F]
      output += '='
      break
    default:
      break
  }

  parts.push(output)

  return parts.join('')
}
<|endoftext|>


<commit_before>Package.describe({
  name: 'zodern:pure-admin',
  version: '0.9.0-beta.4',
  summary: 'Isolated, customizable admin panel for Meteor',
  git: 'https://github.com/zodern/meteor-pure-admin.git',
  documentation: 'README.md'
});

Package.onUse(function(api) {
  api.versionsFrom('1.8.2');
  api.use(['typescript@3.7.0||4.0.0', 'ecmascript', 'dynamic-import']);
  api.use('zodern:melte@1.6.1');
  api.use('zodern:types@1.0.7');

  api.mainModule('./src/main.ts', 'client');
  api.mainModule('./src/server.js', 'server');
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.addFiles('pureadmin-tests.js');
});
<commit_msg>v0.9.0<commit_after>Package.describe({
  name: 'zodern:pure-admin',
  version: '0.9.0',
  summary: 'Isolated, customizable admin panel for Meteor',
  git: 'https://github.com/zodern/meteor-pure-admin.git',
  documentation: 'README.md'
});

Package.onUse(function(api) {
  api.versionsFrom('1.8.2');
  api.use(['typescript@3.7.0||4.0.0', 'ecmascript', 'dynamic-import']);
  api.use('zodern:melte@1.6.1');
  api.use('zodern:types@1.0.7');

  api.mainModule('./src/main.ts', 'client');
  api.mainModule('./src/server.js', 'server');
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.addFiles('pureadmin-tests.js');
});
<|endoftext|>


<commit_before>// Credits: ScriptSafe, LetMeOut.
function getVersion() {
  var request = new XMLHTTPRequest();
  request.open("GET", chrome.extension.getURL("../manifest.json"), false);
  request.send(null);
  return JSON.parse(request.responseText).version;
}

var version = getVersion();

chrome.webRequest.onBeforeRequest.addListener(function(e) {

});
chrome.webRequest.onBeforeRedirect.addListener(function(e) {

});
<commit_msg>Added a console.log<commit_after>// Credits: ScriptSafe, LetMeOut.
function getVersion() {
  var request = new XMLHTTPRequest();
  request.open("GET", chrome.extension.getURL("../manifest.json"), false);
  request.send(null);
  return JSON.parse(request.responseText).version;
}

var version = getVersion();

chrome.webRequest.onBeforeRequest.addListener(function(e) {
  console.log("onBeforeRequest found~!");
});
chrome.webRequest.onBeforeRedirect.addListener(function(e) {
  console.log("onBeforeRedirect found!");
});
<|endoftext|>


<commit_before>Package.describe({
  name: "brylie:api-umbrella",
  summary: "Wrapper for API Umbrella Admin API.",
  version: "0.1.0",
  git: "https://github.com/brylie/meteor-api-umbrella"
});

Package.onUse(function(api) {
  api.versionsFrom("1.0.1");
  api.use(["meteor", "ddp", "jquery"]);

  api.addFiles("shared/index.js", ["client", "server"]);

  api.export("apiUmbrella");
});

Package.onTest(function (api) {
  api.use("tinytest");
  api.use("brylie:api-umbrella");

  api.addFiles("tests/shared/index.js", ["client", "server"]);
});
<commit_msg>Changed file includes.<commit_after>Package.describe({
  name: "brylie:api-umbrella",
  summary: "Wrapper for API Umbrella Admin API.",
  version: "0.1.0",
  git: "https://github.com/brylie/meteor-api-umbrella"
});

Package.onUse(function(api) {
  api.versionsFrom("1.0.1");
  api.use(["meteor", "ddp", "jquery"]);

  api.addFiles("server/admin-api.js", ["server"]);

  api.export("apiUmbrella");
});

Package.onTest(function (api) {
  api.use("tinytest");
  api.use("brylie:api-umbrella");

  api.addFiles("tests/server/admin-api.js", ["server"]);
});
<|endoftext|>


<commit_before>// dependencies
var _ = require('lomath');
var emoji = require('node-emoji');

// API as superclass that bot inherits methods from
var API = require('telegram-bot-bootstrap')
var TradingAPI = require(__dirname + '/trading_api.js')
var AccountsAPI = require(__dirname + '/accounts_api.js')

var authCommands = ["/auth", "Log In", "Sign Up"];
var defaultSymbolName = "EURUSD";
var defaultVolume = "1k";

// The bot object prototype
// bot extends and inherits methods of API
var bot = function(params) {
    var self = this;
    API.apply(this, [params.token]);
    this.app = params.app;
    this.redisClient = params.redisClient;
    // set webhook on construction: override the old webhook
    this.setWebhook(params.webhookUrl);
    var tradingApiParams = {
        host: 'tradeapi.spotware.com',
        port: 5032,
        clientId: params.clientId,
        clientSecret: params.clientSecret
    };
    this.tradingAPI = new TradingAPI(tradingApiParams);
    this.accountsAPI = new AccountsAPI();
    this.tradingAPI.onSpotEvent(function (msg) {
        self.redisClient.get("subscriptions:" + msg.subscriptionId, function (err, chatId) {
            self.sendMessage(chatId, msg.symbolName + ', Bid: ' + msg.bidPrice + ', Ask: ' + msg.askPrice, undefined, undefined, createBuySellKeyboard(msg));
        });
    });
    this.tradingAPI.start();
}

// set prototype to API
bot.prototype = API.prototype;
// set constructor back to bot
bot.prototype.constructor = bot;

/**
 * Handles a Telegram Update object sent from the server. Extend this method for your bot.
 *
 * @category Bot
 * @param {Object} req The incoming HTTP request.
 * @param {Object} res The HTTP response in return.
 * @returns {Promise} promise A promise returned from calling Telegram API method(s) for chaining.
 *
 * @example
 * var bot1 = new bot('yourtokenhere');
 * ...express server setup
 * app.route('/')
 * // robot API as middleware
 * .post(function(req, res) {
 *     bot1.handle(req, res)
 * })
 * // Then bot will handle the incoming Update from you, routed from Telegram!
 *
 */
bot.prototype.handle = function(req, res) {
    var self = this;
    // the Telegram Update object. Useful shits
    var Update = req.body,
        // the telegram Message object
        Message = Update.message,
        // the user who sent it
        userId = Message.from.id,
        // id of the chat(room)
        chatId = Message.chat.id,
        // Message text
        text = Message.text;
    if (text) {
        text = trimMessage(text);
        self.sendMessage(chatId, "You said " + text);
        this.redisClient.get("tokens:" + chatId, function (err, token) {
            if (authCommands.indexOf(text) == -1) {
                if (!token) {
                    self.sendMessage(chatId, "Please log in with cTrader ID or sign up", undefined, undefined, createAuthKeyboard());
                    return;
                } else {
                    try {
                        token = JSON.parse(token);
                    } catch(e) {
                        self.redisClient.del("tokens:" + chatId);
                        text = "/auth";
                    }
                }
            }
            switch (text) {
                case "/start":
                    self.redisClient.get("accountId:" + chatId,  function (err, accountId) {
                        self.tradingAPI.sendSubscribeForSpotsRequest(accountId, defaultSymbolName, token.token.access_token)
                            .then(function(respond) {
                                self.redisClient.set("subscriptions:" + respond.subscriptionId, chatId);
                        });
                    });
                    break;
                case "/stop":
                    self.tradingAPI.sendUnsubscribeFromSpotsRes();
                    break;
                case "/auth":
                case "Log In":
                case "Sign Up":
                    self.sendMessage(chatId, "Open this link to authorize the bot: https://ctrader-telegram-bot.herokuapp.com/auth?state=" + chatId);
                    break;
                case "/accounts":
                    self.accountsAPI.getTradingAccounts(token.token.access_token,
                        function (error, result) {
                            if (error) {
                                console.log('Get Trading Accounts Error', error.message);
                            } else {
                                self.app.render('accounts', result.body, function(err, message) {
                                    self.sendMessage(chatId, message);
                                });
                            }
                        });
                    break;
                case "/clean":
                    self.redisClient.keys("*", function(err, key) {
                        self.redisClient.del(key, function(err) {});
                    });
                    self.sendMessage(chatId, "Storage is cleaned");
                    break;
                case "/buy":
                case "/sell":
                default:
                    self.sendMessage(chatId, "Sorry, unknown command: " + Message.text);
            }
        });
    }
}

bot.prototype.saveToken = function(token, chatId) {
    var self = this;
    this.redisClient.set("tokens:" + chatId, JSON.stringify(token));
    this.accountsAPI.getProfile(token.token.access_token,
        function (error, result) {
            if (error) {
                console.log('Get Profile Error', error.message);
            } else {
                var profile = result.body.data;
                //self.redisClient.set("profile:" + token.token.access_token, profile);
                //self.redisClient.set("profile:" + chatId, profile);
                self.accountsAPI.getTradingAccounts(token.token.access_token,
                    function (error, result) {
                        if (error) {
                            console.log('Get Trading Accounts Error', error.message);
                        } else {
                            var accounts = result.body.data;
                            var account = accounts[0];
                            self.redisClient.set("accountId:" + chatId, account.accountId);
                            var params = {
                                symbolName: defaultSymbolName,
                                volume: defaultVolume,
                                accountNumber: account.accountNumber,
                                positionsCount: 0,
                                ordersCount: 0
                            };
                            self.sendMessage(chatId, "Hello, " + profile.nickname + "! Let's trade!", undefined, undefined, createTradeKeyboard(params));
                        }
                    });
            }
        });
}

bot.prototype.setDefaultAccount = function(chatId, account) {
    this.redisClient.set("account:" + chatId, JSON.stringify(token));
}

function trimMessage(msg) {
    return msg.replace(/([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])/g, '').trim();
}

function createTradeKeyboard(params) {
    return {
        keyboard: [
            ['Sell', 'Buy'],
            [params.symbolName, params.volume],
            [params.accountNumber, 'Positions ' + params.positionsCount, 'Orders ' + params.ordersCount]
        ],
        one_time_keyboard: false
    }
}

function createAuthKeyboard() {
    return {
        keyboard: [
            [emoji.emojify(':key: Log In')],
            [emoji.emojify(':bust_in_silhouette: Sign Up')],
            [emoji.emojify(':question: Help')]
        ],
        one_time_keyboard: false
    }
}

// export the bot class
module.exports = bot;

// sample keyboard
var kb = {
    keyboard: [
        ['one', 'two'],
        ['three'],
        ['four']
    ],
    one_time_keyboard: true
}
<commit_msg>Added trading keyboard<commit_after>// dependencies
var _ = require('lomath');
var emoji = require('node-emoji');

// API as superclass that bot inherits methods from
var API = require('telegram-bot-bootstrap')
var TradingAPI = require(__dirname + '/trading_api.js')
var AccountsAPI = require(__dirname + '/accounts_api.js')

var authCommands = ["/auth", "Log In", "Sign Up"];
var defaultSymbolName = "EURUSD";
var defaultVolume = "1k";

// The bot object prototype
// bot extends and inherits methods of API
var bot = function(params) {
    var self = this;
    API.apply(this, [params.token]);
    this.app = params.app;
    this.redisClient = params.redisClient;
    // set webhook on construction: override the old webhook
    this.setWebhook(params.webhookUrl);
    var tradingApiParams = {
        host: 'tradeapi.spotware.com',
        port: 5032,
        clientId: params.clientId,
        clientSecret: params.clientSecret
    };
    this.tradingAPI = new TradingAPI(tradingApiParams);
    this.accountsAPI = new AccountsAPI();
    this.tradingAPI.onSpotEvent(function (msg) {
        self.redisClient.get("subscriptions:" + msg.subscriptionId, function (err, chatId) {
            self.sendMessage(chatId, msg.symbolName + ', Bid: ' + msg.bidPrice + ', Ask: ' + msg.askPrice);
        });
    });
    this.tradingAPI.start();
}

// set prototype to API
bot.prototype = API.prototype;
// set constructor back to bot
bot.prototype.constructor = bot;

/**
 * Handles a Telegram Update object sent from the server. Extend this method for your bot.
 *
 * @category Bot
 * @param {Object} req The incoming HTTP request.
 * @param {Object} res The HTTP response in return.
 * @returns {Promise} promise A promise returned from calling Telegram API method(s) for chaining.
 *
 * @example
 * var bot1 = new bot('yourtokenhere');
 * ...express server setup
 * app.route('/')
 * // robot API as middleware
 * .post(function(req, res) {
 *     bot1.handle(req, res)
 * })
 * // Then bot will handle the incoming Update from you, routed from Telegram!
 *
 */
bot.prototype.handle = function(req, res) {
    var self = this;
    // the Telegram Update object. Useful shits
    var Update = req.body,
        // the telegram Message object
        Message = Update.message,
        // the user who sent it
        userId = Message.from.id,
        // id of the chat(room)
        chatId = Message.chat.id,
        // Message text
        text = Message.text;
    if (text) {
        text = trimMessage(text);
        self.sendMessage(chatId, "You said " + text);
        this.redisClient.get("tokens:" + chatId, function (err, token) {
            if (authCommands.indexOf(text) == -1) {
                if (!token) {
                    self.sendMessage(chatId, "Please log in with cTrader ID or sign up", undefined, undefined, createAuthKeyboard());
                    return;
                } else {
                    try {
                        token = JSON.parse(token);
                    } catch(e) {
                        self.redisClient.del("tokens:" + chatId);
                        text = "/auth";
                    }
                }
            }
            switch (text) {
                case "/start":
                    self.redisClient.get("accountId:" + chatId,  function (err, accountId) {
                        self.tradingAPI.sendSubscribeForSpotsRequest(accountId, defaultSymbolName, token.token.access_token)
                            .then(function(respond) {
                                self.redisClient.set("subscriptions:" + respond.subscriptionId, chatId);
                        });
                    });
                    break;
                case "/stop":
                    self.tradingAPI.sendUnsubscribeFromSpotsRes();
                    break;
                case "/auth":
                case "Log In":
                case "Sign Up":
                    self.sendMessage(chatId, "Open this link to authorize the bot: https://ctrader-telegram-bot.herokuapp.com/auth?state=" + chatId);
                    break;
                case "/accounts":
                    self.accountsAPI.getTradingAccounts(token.token.access_token,
                        function (error, result) {
                            if (error) {
                                console.log('Get Trading Accounts Error', error.message);
                            } else {
                                self.app.render('accounts', result.body, function(err, message) {
                                    self.sendMessage(chatId, message);
                                });
                            }
                        });
                    break;
                case "/clean":
                    self.redisClient.keys("*", function(err, key) {
                        self.redisClient.del(key, function(err) {});
                    });
                    self.sendMessage(chatId, "Storage is cleaned");
                    break;
                case "/buy":
                case "/sell":
                default:
                    self.sendMessage(chatId, "Sorry, unknown command: " + Message.text);
            }
        });
    }
}

bot.prototype.saveToken = function(token, chatId) {
    var self = this;
    this.redisClient.set("tokens:" + chatId, JSON.stringify(token));
    this.accountsAPI.getProfile(token.token.access_token,
        function (error, result) {
            if (error) {
                console.log('Get Profile Error', error.message);
            } else {
                var profile = result.body.data;
                //self.redisClient.set("profile:" + token.token.access_token, profile);
                //self.redisClient.set("profile:" + chatId, profile);
                self.accountsAPI.getTradingAccounts(token.token.access_token,
                    function (error, result) {
                        if (error) {
                            console.log('Get Trading Accounts Error', error.message);
                        } else {
                            var accounts = result.body.data;
                            var account = accounts[0];
                            self.redisClient.set("accountId:" + chatId, account.accountId);
                            var params = {
                                symbolName: defaultSymbolName,
                                volume: defaultVolume,
                                accountNumber: account.accountNumber,
                                positionsCount: 0,
                                ordersCount: 0
                            };
                            console.log(params);
                            self.sendMessage(chatId, "Hello, " + profile.nickname + "! Let's trade!", undefined, undefined, createTradeKeyboard(params));
                        }
                    });
            }
        });
}

bot.prototype.setDefaultAccount = function(chatId, account) {
    this.redisClient.set("account:" + chatId, JSON.stringify(token));
}

function trimMessage(msg) {
    return msg.replace(/([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])/g, '').trim();
}

function createTradeKeyboard(params) {
    return {
        keyboard: [
            ['Sell', 'Buy'],
            [params.symbolName, params.volume],
            [params.accountNumber, 'Positions ' + params.positionsCount, 'Orders ' + params.ordersCount]
        ]
    }
}

function createAuthKeyboard() {
    return {
        keyboard: [
            [emoji.emojify(':key: Log In')],
            [emoji.emojify(':bust_in_silhouette: Sign Up')],
            [emoji.emojify(':question: Help')]
        ]
    }
}

// export the bot class
module.exports = bot;

// sample keyboard
var kb = {
    keyboard: [
        ['one', 'two'],
        ['three'],
        ['four']
    ],
    one_time_keyboard: true
}
<|endoftext|>