'use strict'; const _ = require('lodash'); const EventEmitter = require('events').EventEmitter; const inherits = require('util').inherits; const request = require('co-request'); const defer = require('co-defer') const socketio = require('socket.io-client'); const debug = require('debug')('instant:client'); const https = require('https'); const logger = require('winston') https.globalAgent.options.rejectUnauthorized = false; module.exports = JdClient; function JdClient(username, password) { EventEmitter.call(this); let self = this; // Save configuration and stuff. (async () => { self.username = null; self.name = null; self.balance = null; self.csrf = null; self.inits = null; self.uid = null; self.invested = null; self.balance = null; self.max_profit = null; self.cookie = null; self.version = '0.1.5' self.url = 'https://just-dice.com' self.last_idle_time; self.pong_count = 0; self.credentials = { hash: '', username: username, password: password, code: '' } try { self.cookie = await login(self.credentials, self.url) } catch (e) { logger.error("jd login error", e) throw new Error('error connecting to just-dice') } logger.info('JD - Received cookie: ' + self.cookie); logger.info('JD - Setting up connection to %s', self.url); self.socket = socketio(self.url, { multiplex: false, agent: https.globalAgent, extraHeaders: { origin: self.url, cookie: self.cookie } }); self.socket.on('error', self.onError.bind(self)); self.socket.on('login_error', self.onError.bind(self)); self.socket.on('invest_error', self.onError.bind(self)); self.socket.on('divest_error', self.onError.bind(self)); self.socket.on('getver', self.onGetVer.bind(self)); self.socket.on('tip', self.onTip.bind(self)); self.socket.on('init', self.onInit.bind(self)); self.socket.on('set_hash', self.onSetHash.bind(self)); self.socket.on('balance', self.onBalance.bind(self)); self.socket.on('pong', self.onPong.bind(self)); self.socket.on('chat', self.onMsg.bind(self)); self.socket.on('reload', self.connect.bind(self)); self.socket.on('timeout', self.reconnect.bind(self)); //socket.emit("withdraw", csrf, address.val(), amount.val(), code.val(), speech.val()) defer.setTimeout(self.heartbeat.bind(self), 5000) })() } inherits(JdClient, EventEmitter); JdClient.prototype.reconnect = async function() { this.socket.emit("reconnect", this.csrf); } JdClient.prototype.connect = async function() { this.csrf = null; this.inits = null; this.cookie = null; try { this.cookie = await login(this.credentials, this.url) } catch (e) { logger.error("jd heartbeat login error", e) throw new Error('error connecting to just-dice') } logger.info('JD - Received cookie: ' + this.cookie); logger.info('JD - Setting up connection to %s', this.url); this.socket = socketio(this.url, { multiplex: false, agent: https.globalAgent, extraHeaders: { origin: this.url, cookie: this.cookie } }); } JdClient.prototype.heartbeat = async function() { // if idle time hasn't been updated in 5 minutes, reconnected if(Date.now() - this.last_idle_time > 1000 * 60 * 5 ) await this.connect() defer.setTimeout(this.heartbeat.bind(this), 5000) } JdClient.prototype.onPong = function() { this.pong_count++ if ( this.pong_count > 7 ) { this.last_idle_time = new Date().getTime(); this.pong_count = 0; } }; JdClient.prototype.onBalance = function(data) { this.last_idle_time = new Date().getTime(); this.balance = data; logger.info('JD - onBalance: ', data); this.emit('balance', this.balance) }; JdClient.prototype.onGetVer = function(key) { this.last_idle_time = new Date().getTime(); socket.emit('version', this.csrf, key, "jdbot:" + this.version); logger.info('JD - onGetVer: ', key); }; JdClient.prototype.onSetHash = function(hash) { logger.info('JD - onSetHash: ', hash); }; JdClient.prototype.onTip = function(from, name, amount, comment, ignored) { this.last_idle_time = new Date().getTime(); if (amount < 2) { return socket.emit("chat", csrf, '/tip noconf ' + from + ' ' + Number(amount).toFixed(8) + ' "Please send 2 or more clam with your withdraw address in the comment, eg: /tip 18 1.0 \'1ADDRESS\'"') } logger.info('JD - onTip: ', from, name, amount, comment, ignored); }; JdClient.prototype.onInit = function(data) { this.invested = data.investment; this.uid = data.uid; this.name = data.name; this.username = data.username; this.last_idle_time = new Date().getTime(); if (!this.inits++) { this.csrf = data.csrf; this.balance = data.balance; this.emit('balance', this.balance) logger.info('JD - connected as (' + this.uid + ') <' + this.name + '>'); } else { logger.info('JD - reconnected'); this.csrf = data.csrf; } }; JdClient.prototype.onError = function(err) { logger.info('JD - onError: ', err); }; JdClient.prototype.onErr = function(err) { logger.info('JD - onErr: ', err); }; JdClient.prototype.onDisconnect = function(data) { logger.info('JD - Client disconnected |', data, '|', typeof data); this.emit('disconnect'); }; JdClient.prototype.onMsg = function(message) { this.last_idle_time = new Date().getTime(); let msg = {} msg.site = 'JD' console.log(message) //setup message format for Instant and determine if message if private or public to // determine how to respond to the user if (message.match(/\[ \((.*?)\) <(.*?)> → \(18\) \] (.*)/)) { let isPrivateRegMatch = message.match(/\[ \((.*?)\) <(.*?)> → \(18\) \] (.*)/) msg.type = 'private' msg.uid = Number(isPrivateRegMatch[1]) msg.name = isPrivateRegMatch[2] msg.message = isPrivateRegMatch[3].trim() } else { if (!message.match(/\((.*?)\) <(.*?)> (.*)/)) return let isPublicRegMatch = message.match(/\((.*?)\) <(.*?)> (.*)/) msg.type = 'public' msg.uid = Number(isPublicRegMatch[1]) msg.name = isPublicRegMatch[2] msg.message = isPublicRegMatch[3].trim() } this.emit('msg', msg); }; JdClient.prototype.say = function(msg) { if (msg.type === "private") this.sayPrivate(msg.uid, msg) else this.sayPublic(msg) }; JdClient.prototype.sayPrivate = function(uid, msg) { this.socket.emit('chat', this.csrf, '/msg ' + uid + ' ' + msg.message); }; JdClient.prototype.sayPublic = function(msg) { this.socket.emit("chat", this.csrf, msg.message) }; async function login(credentials, url) { try { let jar = request.jar(); let req = { url: url, jar: jar, form: {} } if (credentials.username) req.form.username = credentials.username; if (credentials.password) req.form.password = credentials.password; if (credentials.code) req.form.code = credentials.code; let res = await request.post(req); let cookie = jar.getCookieString(url); return cookie } catch (e) { logger.error('[JD][login]', e) throw new Error('error connecting to just-dice', e) } }