Пример #1
0
    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get(
                'X-Real-Ip',
                request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip )

        self.trade_client = None
        self.user_response = None
        self.last_message_datetime = [datetime.now()]
        self.open_orders = {}
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}
        self.honey_pot_connection = False

        if self.application.is_tor_node( self.remote_ip ):
            self.honey_pot_connection = True
            application.log('INFO', 'BLOCKED_TOR_NODE', self.remote_ip )
            return

        self.trade_client = TradeClient(
            self.application.zmq_context,
            self.application.trade_in_socket,
            self.application.options.trade_pub)
Пример #2
0
    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get(
                'X-Real-Ip',
                request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip )

        self.trade_client = None
        self.user_response = None
        self.last_message_datetime = [datetime.now()]
        self.open_orders = {}
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}
        self.honey_pot_connection = False

        if self.application.is_tor_node( self.remote_ip ):
            self.honey_pot_connection = True
            application.log('INFO', 'BLOCKED_TOR_NODE', self.remote_ip )
            return

        self.trade_client = TradeClient(
            self.application.zmq_context,
            self.application.trade_in_socket,
            self.application.options.trade_pub)
Пример #3
0
    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get('X-Real-Ip', request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip)

        self.trade_client = TradeClient(self.application.zmq_context,
                                        self.application.trade_in_socket,
                                        self.application.options.trade_pub)
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}

        self.user_response = None
        self.last_order_datetime = datetime.now()
        self.open_orders = {}
Пример #4
0
    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get(
                'X-Real-Ip',
                request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip )

        self.trade_client = TradeClient(
            self.application.zmq_context,
            self.application.trade_in_socket,
            self.application.options.trade_pub)
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}

        self.user_response = None
Пример #5
0
class WebSocketHandler(websocket.WebSocketHandler):

    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get(
                'X-Real-Ip',
                request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip )

        self.trade_client = TradeClient(
            self.application.zmq_context,
            self.application.trade_in_socket,
            self.application.options.trade_pub)
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}

        self.user_response = None

    def on_trade_publish(self, message):
        self.write_message(str(message[1]))

    def check_origin(self, origin):
      self.application.log('INFO', 'ORIGIN', origin)
      return self.application.is_origin_allowed(origin)

    def open(self):
        try:
            self.trade_client.connect()
            self.trade_client.on_trade_publish = self.on_trade_publish
            self.application.register_connection(self)

        except TradeClientException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Error establishing connection with trade", "Detail": "' +
                str(e) +
                '"}')
            self.trade_client.close()
            self.close()

    def write_message(self, message, binary=False):
        self.application.log('OUT', self.trade_client.connection_id, message )
        super(WebSocketHandler, self).write_message(message, binary)

    def close(self):
      self.application.log('DEBUG', self.remote_ip, 'WebSocketHandler.close() invoked' )
      super(WebSocketHandler, self).close()

    def on_message(self, raw_message):
        if not self.trade_client.isConnected():
            return

        try:
            req_msg = JsonMessage(raw_message)
        except InvalidMessageException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Invalid message", "Detail": "' +
                str(e) +
                '"}')
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return


        if req_msg.isUserRequest():
            if req_msg.has('Password'):
                raw_message = raw_message.replace(req_msg.get('Password'), '*')
            if req_msg.has('NewPassword'):
                raw_message = raw_message.replace(req_msg.get('NewPassword'), '*')

            self.application.log('IN', self.trade_client.connection_id ,raw_message )
        else:
            self.application.log('IN', self.trade_client.connection_id, raw_message )


        if req_msg.isTestRequest() or req_msg.isHeartbeat():
            dt = datetime.datetime.now()
            response_msg = {
                'MsgType'           : '0',
                'TestReqID'         : req_msg.get('TestReqID'),
                'ServerTimestamp'   : int(mktime(dt.timetuple()) + dt.microsecond/1000.0 )
            }

            sendTime = req_msg.get('SendTime')
            if sendTime:
                response_msg['SendTime'] = sendTime


            self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))
            return


        if req_msg.isTradeHistoryRequest():  # Trade History request
            self.on_trade_history_request(req_msg)
            return

        if req_msg.isMarketDataRequest():  # Market Data Request
            self.on_market_data_request(req_msg)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id, 'not self.trade_client.isConnected()' )
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
            return

        if req_msg.isSecurityStatusRequest():
            self.on_security_status_request(req_msg)
            return

        if req_msg.isDepositRequest():
            if not req_msg.get('DepositMethodID') and not req_msg.get('DepositID'):

                currency = req_msg.get('Currency')

                secret = uuid.uuid4().hex
                callback_url = self.application.options.callback_url + secret

                hot_wallet  = self.get_broker_wallet('hot', currency)
                cold_wallet = self.get_broker_wallet('cold', currency)
                if not hot_wallet and not cold_wallet:
                    return

                if not hot_wallet and cold_wallet:
                    dest_wallet = cold_wallet
                elif hot_wallet and not cold_wallet:
                    dest_wallet = hot_wallet
                else:
                    # 62.5% of all deposits go to the cold wallet, and 37.5% go to the hot wallet
                    dest_wallet = hot_wallet
                    if secret[0] in ('0','1','2','3','4','5','6','7','8','9'):
                        dest_wallet = cold_wallet


                if not dest_wallet:
                    return

                parameters = urllib.urlencode({
                    'method': 'create',
                    'address': dest_wallet,
                    'callback': callback_url,
                    'currency': currency
                })


                try:
                    url_payment_processor = self.application.options.url_payment_processor + '?' + parameters
                    self.application.log('DEBUG', self.trade_client.connection_id, "invoking..."  + url_payment_processor )
                    response = urllib2.urlopen(url_payment_processor)
                    data = json.load(response)
                    self.application.log('DEBUG', self.trade_client.connection_id, str(data) )

                    req_msg.set('InputAddress', data['input_address'])
                    req_msg.set('Destination', data['destination'])
                    req_msg.set('Secret', secret)
                except urllib2.HTTPError as e:
                    out_message = json.dumps({
                      'MsgType': 'ERROR',
                      'ReqID': req_msg.get('DepositReqID'),
                      'Description': 'Blockchain.info is not available at this moment, please try again within few minutes',
                      'Detail': str(e)
                    })
                    self.write_message(out_message)
                    return
                except Exception as e:
                    out_message = json.dumps({
                      'MsgType': 'ERROR',
                      'ReqID': req_msg.get('DepositReqID'),
                      'Description': 'Error retrieving a new deposit address from Blockchain.info. Please, try again',
                      'Detail': str(e)
                    })
                    self.write_message(out_message)
                    return

        try:
            resp_message = self.trade_client.sendMessage(req_msg)
            if resp_message:
                self.write_message(resp_message.raw_message)

            if resp_message and resp_message.isUserResponse():
                self.user_response = resp_message

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id, 'not self.trade_client.isConnected()' )
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
        except TradeClientException as e:
            exception_message = {
                'MsgType': 'ERROR',
                'Description': 'Invalid message',
                'Detail': str(e)
            }
            self.write_message(json.dumps(exception_message))
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()

    def is_user_logged(self):
        if not self.user_response:
            return False
        return self.user_response.get('UserStatus') == 1

    def is_broker(self):
      if not self.is_user_logged():
        return False
      return self.user_response.get('IsBroker') == 1


    def get_broker_wallet(self, type, currency):
        if not self.user_response:
            return

        broker = self.user_response.get('Broker')
        if not broker:
            return

        if 'CryptoCurrencies' not in broker:
            return

        broker_crypto_currencies = broker['CryptoCurrencies']
        for crypto_currency in broker_crypto_currencies:
            if crypto_currency['CurrencyCode'] == currency:
                for wallet in crypto_currency['Wallets']:
                    if wallet['type'] == type:
                        return wallet['address']

    def on_close(self):
        self.application.log('DEBUG', self.trade_client.connection_id, 'WebSocketHandler.on_close' )
        self.application.unregister_connection(self)
        self.trade_client.close()

    def on_trade_history_request(self, msg):
        since       = msg.get('Since') 
        page        = msg.get('Page', 0)
        page_size   = msg.get('PageSize', 100)
        filter      = msg.get('Filter')

        offset      = page * page_size

        if self.is_broker():
          columns = [ 'TradeID' , 'Market',  'Side', 'Price', 'Size',
                      'Buyer'   , 'Seller', 'Created', 'BuyerUsername' ,'SellerUsername' ]
        else:
          columns = [ 'TradeID' , 'Market',  'Side', 'Price', 'Size',
                      'Buyer'   , 'Seller', 'Created' ]


        trade_list = generate_trade_history(self.application.db_session, page_size, offset, show_username=self.is_broker(), since=since)

        response_msg = {
            'MsgType'           : 'U33', # TradeHistoryResponse
            'TradeHistoryReqID' : msg.get('TradeHistoryReqID'),
            'Page'              : page,
            'PageSize'          : page_size,
            'Columns'           : columns,
            'TradeHistoryGrp'   : trade_list
        }
        if since:
          response_msg['Since'] = since

        self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))

    def on_security_status_request(self, msg):
        # Generate a FullRefresh
        req_id = msg.get('SecurityStatusReqID')

        # Disable previous Snapshot + Update Request
        if int(msg.get('SubscriptionRequestType')) == 2:
            if req_id in self.sec_status_subscriptions:
                del self.sec_status_subscriptions[req_id]
            return

        instruments = msg.get('Instruments')

        if int(msg.get('SubscriptionRequestType')) == 1:  # Snapshot + Updates
            if req_id not in self.sec_status_subscriptions:
                self.sec_status_subscriptions[req_id] = []

        for instrument in instruments:
            ss = generate_security_status(
                instrument,
                req_id)
            self.write_message(str(json.dumps(ss, cls=JsonEncoder)))

            # Snapshot + Updates
            if int(msg.get('SubscriptionRequestType')) == 1:
                self.sec_status_subscriptions[req_id].append(
                    SecurityStatusPublisher(
                        req_id,
                        instrument,
                        self.on_send_json_msg_to_user))


    def on_market_data_request(self, msg):
        # Generate a FullRefresh
        req_id = msg.get('MDReqID')

        # Disable previous Snapshot + Update Request
        if int(msg.get('SubscriptionRequestType')) == 2:
            if req_id in self.md_subscriptions:
                del self.md_subscriptions[req_id]
            return

        market_depth = msg.get('MarketDepth')
        instruments = msg.get('Instruments')
        entries = msg.get('MDEntryTypes')

        if int(msg.get('SubscriptionRequestType')) == 1:  # Snapshot + Updates
            if req_id not in self.md_subscriptions:
                self.md_subscriptions[req_id] = []

        for instrument in instruments:
            md = generate_md_full_refresh(
                instrument,
                market_depth,
                entries,
                req_id,
                self.is_broker())
            self.write_message(str(json.dumps(md, cls=JsonEncoder)))

            # Snapshot + Updates
            if int(msg.get('SubscriptionRequestType')) == 1:
                self.md_subscriptions[req_id].append(
                    MarketDataPublisher(
                        req_id,
                        market_depth,
                        entries,
                        instrument,
                        self.on_send_json_msg_to_user,
                        self.is_broker()))

    def on_send_json_msg_to_user(self, sender, json_msg):
        s = json.dumps(json_msg, cls=JsonEncoder)
        self.write_message(s)
Пример #6
0
    def __init__(self, opt, instance_name):
        self.options = opt
        self.instance_name = instance_name

        handlers = [
            (r'/', WebSocketHandler),
            (r'/get_deposit(.*)', DepositHandler),
            (r'/_webhook/verification_form', VerificationWebHookHandler),
            (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler),
            (r'/process_deposit(.*)', ProcessDepositHandler),
            (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler)
        ]
        settings = dict(
            cookie_secret='cookie_secret'
        )
        tornado.web.Application.__init__(self, handlers, **settings)


        self.allowed_origins = json.loads(self.options.allowed_origins)
        self.allow_all_origins = self.allowed_origins[0] == '*'

        input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
          os.path.expanduser(self.options.gateway_log), when='MIDNIGHT')
        formatter = logging.Formatter('%(asctime)s - %(message)s')
        input_log_file_handler.setFormatter(formatter)

        self.replay_logger = logging.getLogger(self.instance_name)
        self.replay_logger.setLevel(logging.INFO)
        self.replay_logger.addHandler(input_log_file_handler)

        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
        self.replay_logger.addHandler(ch)

        self.replay_logger.info('START')
        self.log_start_data()

        from models import Base, db_bootstrap
        db_engine = self.options.sqlalchemy_engine + ':///' +\
                    os.path.expanduser(self.options.sqlalchemy_connection_string)
        engine = create_engine( db_engine, echo=self.options.db_echo)
        Base.metadata.create_all(engine)
        self.db_session = scoped_session(sessionmaker(bind=engine))
        db_bootstrap(self.db_session)


        self.zmq_context = zmq.Context()

        self.trade_in_socket = self.zmq_context.socket(zmq.REQ)
        self.trade_in_socket.connect(self.options.trade_in)

        self.application_trade_client = TradeClient(
            self.zmq_context,
            self.trade_in_socket)
        self.application_trade_client.connect()

        self.security_list = self.application_trade_client.getSecurityList()
        self.md_subscriber = {}

        for instrument in self.security_list.get('Instruments'):
            symbol = instrument['Symbol']
            self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self)
            self.md_subscriber[symbol].subscribe(
                self.zmq_context,
                self.options.trade_pub,
                self.application_trade_client)

        last_trade_id = Trade.get_last_trade_id(self.db_session)
        trade_list = self.application_trade_client.getLastTrades(last_trade_id)

        for trade in trade_list:
            msg = dict()
            msg['id']               = trade[0]
            msg['symbol']           = trade[1]
            msg['side']             = trade[2]
            msg['price']            = trade[3]
            msg['size']             = trade[4]
            msg['buyer_id']         = trade[5]
            msg['seller_id']        = trade[6]
            msg['buyer_username']   = trade[7]
            msg['seller_username']  = trade[8]
            msg['created']          = trade[9]
            msg['trade_date']       = trade[9][:10]
            msg['trade_time']       = trade[9][11:]
            msg['order_id']         = trade[10]
            msg['counter_order_id'] = trade[11]
            Trade.create( self.db_session, msg)

        all_trades = Trade.get_all_trades(self.db_session)
        for t in all_trades:
          trade_info = dict()
          trade_info['price'] = t.price
          trade_info['size'] = t.size
          trade_info['trade_date'] = t.created.strftime('%Y-%m-%d')
          trade_info['trade_time'] = t.created.strftime('%H:%M:%S')
          self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info)

        for symbol, subscriber in self.md_subscriber.iteritems():
            subscriber.ready()

        self.connections = {}

        self.heart_beat_timer = tornado.ioloop.PeriodicCallback(
            self.send_heartbeat_to_trade,
            30000)
        self.heart_beat_timer.start()
Пример #7
0
class WebSocketGatewayApplication(tornado.web.Application):

    def __init__(self, opt, instance_name):
        self.options = opt
        self.instance_name = instance_name

        handlers = [
            (r'/', WebSocketHandler),
            (r'/get_deposit(.*)', DepositHandler),
            (r'/_webhook/verification_form', VerificationWebHookHandler),
            (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler),
            (r'/process_deposit(.*)', ProcessDepositHandler),
            (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler)
        ]
        settings = dict(
            cookie_secret='cookie_secret'
        )
        tornado.web.Application.__init__(self, handlers, **settings)


        self.allowed_origins = json.loads(self.options.allowed_origins)
        self.allow_all_origins = self.allowed_origins[0] == '*'

        input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
          os.path.expanduser(self.options.gateway_log), when='MIDNIGHT')
        formatter = logging.Formatter('%(asctime)s - %(message)s')
        input_log_file_handler.setFormatter(formatter)

        self.replay_logger = logging.getLogger(self.instance_name)
        self.replay_logger.setLevel(logging.INFO)
        self.replay_logger.addHandler(input_log_file_handler)

        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
        self.replay_logger.addHandler(ch)

        self.replay_logger.info('START')
        self.log_start_data()

        from models import Base, db_bootstrap
        db_engine = self.options.sqlalchemy_engine + ':///' +\
                    os.path.expanduser(self.options.sqlalchemy_connection_string)
        engine = create_engine( db_engine, echo=self.options.db_echo)
        Base.metadata.create_all(engine)
        self.db_session = scoped_session(sessionmaker(bind=engine))
        db_bootstrap(self.db_session)


        self.zmq_context = zmq.Context()

        self.trade_in_socket = self.zmq_context.socket(zmq.REQ)
        self.trade_in_socket.connect(self.options.trade_in)

        self.application_trade_client = TradeClient(
            self.zmq_context,
            self.trade_in_socket)
        self.application_trade_client.connect()

        self.security_list = self.application_trade_client.getSecurityList()
        self.md_subscriber = {}

        for instrument in self.security_list.get('Instruments'):
            symbol = instrument['Symbol']
            self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self)
            self.md_subscriber[symbol].subscribe(
                self.zmq_context,
                self.options.trade_pub,
                self.application_trade_client)

        last_trade_id = Trade.get_last_trade_id(self.db_session)
        trade_list = self.application_trade_client.getLastTrades(last_trade_id)

        for trade in trade_list:
            msg = dict()
            msg['id']               = trade[0]
            msg['symbol']           = trade[1]
            msg['side']             = trade[2]
            msg['price']            = trade[3]
            msg['size']             = trade[4]
            msg['buyer_id']         = trade[5]
            msg['seller_id']        = trade[6]
            msg['buyer_username']   = trade[7]
            msg['seller_username']  = trade[8]
            msg['created']          = trade[9]
            msg['trade_date']       = trade[9][:10]
            msg['trade_time']       = trade[9][11:]
            msg['order_id']         = trade[10]
            msg['counter_order_id'] = trade[11]
            Trade.create( self.db_session, msg)

        all_trades = Trade.get_all_trades(self.db_session)
        for t in all_trades:
          trade_info = dict()
          trade_info['price'] = t.price
          trade_info['size'] = t.size
          trade_info['trade_date'] = t.created.strftime('%Y-%m-%d')
          trade_info['trade_time'] = t.created.strftime('%H:%M:%S')
          self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info)

        for symbol, subscriber in self.md_subscriber.iteritems():
            subscriber.ready()

        self.connections = {}

        self.heart_beat_timer = tornado.ioloop.PeriodicCallback(
            self.send_heartbeat_to_trade,
            30000)
        self.heart_beat_timer.start()

    def format_currency(self, currency_code, value, is_value_in_satoshis=True):
      currencies = self.security_list.get('Currencies')
      for currency_obj in currencies:
        if currency_obj['Code'] == currency_code:
          if is_value_in_satoshis:
            return currency_obj['FormatPython'].format(value/1e8)
          else:
            return currency_obj['FormatPython'].format(value)
      return value

    def is_origin_allowed(self, origin):
      if self.allow_all_origins:
        return  True

      if origin in self.allowed_origins:
        return True
      return False


    def log_start_data(self):
        self.log('PARAM','BEGIN')
        self.log('PARAM','callback_url'                 ,self.options.callback_url)
        self.log('PARAM','port'                         ,self.options.port)
        self.log('PARAM','trade_in'                     ,self.options.trade_in)
        self.log('PARAM','trade_pub'                    ,self.options.trade_pub)
        self.log('PARAM','url_payment_processor'        ,self.options.url_payment_processor)
        self.log('PARAM','session_timeout_limit'        ,self.options.session_timeout_limit)
        self.log('PARAM','db_echo'                      ,self.options.db_echo)
        self.log('PARAM','sqlalchemy_engine'            ,self.options.sqlalchemy_engine)
        self.log('PARAM','sqlalchemy_connection_string' ,self.options.sqlalchemy_connection_string)
        self.log('PARAM','allowed_origins'              ,self.options.allowed_origins)
        self.log('PARAM','END')


    def log(self, command, key, value=None):
        log_msg = command + ',' + key
        if value:
            try:
                log_msg += ',' + value
            except Exception,e :
                try:
                    log_msg += ',' + str(value)
                except Exception,e :
                    try:
                        log_msg += ',' + unicode(value)
                    except Exception,e :
                        log_msg += ', [object]'
Пример #8
0
class WebSocketHandler(websocket.WebSocketHandler):
    def __init__(self, application, request, **kwargs):
        super(WebSocketHandler, self).__init__(application, request, **kwargs)
        self.remote_ip = request.headers.get(
            'X-Forwarded-For',
            request.headers.get('X-Real-Ip', request.remote_ip))
        application.log('INFO', 'CONNECTION_OPEN', self.remote_ip)

        self.trade_client = None
        self.user_response = None
        self.last_message_datetime = [datetime.now()]
        self.open_orders = {}
        self.md_subscriptions = {}
        self.sec_status_subscriptions = {}
        self.honey_pot_connection = False

        if self.application.is_tor_node(self.remote_ip):
            self.honey_pot_connection = True
            application.log('INFO', 'BLOCKED_TOR_NODE', self.remote_ip)
            return

        self.trade_client = TradeClient(self.application.zmq_context,
                                        self.application.trade_in_socket,
                                        self.application.options.trade_pub)

    def process_execution_report(self):
        pass

    def on_close(self):
        self.application.log('INFO', 'CONNECTION_CLOSE', self.remote_ip)

        for req_id, md_publisher_list in self.md_subscriptions.items():
            for md_publisher in md_publisher_list:
                md_publisher.cleanup()
            self.md_subscriptions[req_id] = []
        self.md_subscriptions = {}

        for req_id, sec_status_publisher_list in self.sec_status_subscriptions.items(
        ):
            for sec_status_publisher in sec_status_publisher_list:
                sec_status_publisher.cleanup()
            self.sec_status_subscriptions[req_id] = []
        self.sec_status_subscriptions = {}

        self.application.unregister_connection(self)
        if self.trade_client:
            self.trade_client.close()
        self.trade_client = None

    def on_trade_publish(self, message):
        self.write_message(str(message[1]))

    def check_origin(self, origin):
        self.application.log('INFO', 'ORIGIN', origin)
        return self.application.is_origin_allowed(origin)

    def open(self):
        self.set_nodelay(True)
        try:
            if self.trade_client:
                self.trade_client.connect()
                self.trade_client.on_trade_publish = self.on_trade_publish
                self.application.register_connection(self)

        except TradeClientException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Error establishing connection with trade", "Detail": "'
                + str(e) + '"}')
            if self.trade_client:
                self.trade_client.close()
            self.close()

    def write_message(self, message, binary=False):
        super(WebSocketHandler, self).write_message(message, binary)

    def close(self, code=None, reason=None):
        self.application.log('DEBUG', self.remote_ip,
                             'WebSocketHandler.close() invoked')
        super(WebSocketHandler, self).close()

    def on_message(self, raw_message):
        if self.honey_pot_connection:
            self.application.log('INFO', "HONEY_POT", raw_message)

        if self.trade_client is None or not self.trade_client.isConnected():
            return

        self.last_message_datetime.append(datetime.now())
        message_time_last_second = self.last_message_datetime[-1] - timedelta(
            seconds=1)
        for x in xrange(0, len(self.last_message_datetime)):
            if self.last_message_datetime[x] > message_time_last_second:
                self.last_message_datetime = self.last_message_datetime[x:]
                break
        if len(self.last_message_datetime
               ) > 15:  # higher than 15 messages per second
            self.application.log(
                "ERROR", "TOO_MANY_MESSAGES",
                "Exceed 15 messages per second. [ip=" + self.remote_ip + ",'" +
                raw_message + "']")
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Too many messages per second", "Detail": "16 messages in the last second"}'
            )
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return

        try:
            req_msg = JsonMessage(raw_message)
        except InvalidMessageException as e:
            self.write_message(
                '{"MsgType":"ERROR", "Description":"Invalid message", "Detail": "'
                + str(e) + '"}')
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()
            return

        req_msg.set('RemoteIP', self.remote_ip)

        if req_msg.isUserRequest():
            if req_msg.has('Password'):
                raw_message = raw_message.replace(req_msg.get('Password'), '*')
            if req_msg.has('NewPassword'):
                raw_message = raw_message.replace(req_msg.get('NewPassword'),
                                                  '*')
            self.application.log('IN', self.trade_client.connection_id,
                                 raw_message)

        if req_msg.isTestRequest() or req_msg.isHeartbeat():
            dt = datetime.now()
            response_msg = {
                'MsgType':
                '0',
                'TestReqID':
                req_msg.get('TestReqID'),
                'ServerTimestamp':
                int(mktime(dt.timetuple()) + dt.microsecond / 1000.0)
            }

            sendTime = req_msg.get('SendTime')
            if sendTime:
                response_msg['SendTime'] = sendTime

            self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))
            return

        if req_msg.isTradeHistoryRequest():  # Trade History request
            self.on_trade_history_request(req_msg)
            return

        if req_msg.isMarketDataRequest():  # Market Data Request
            self.on_market_data_request(req_msg)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
            return

        if req_msg.isSecurityStatusRequest():
            self.on_security_status_request(req_msg)
            return

        if req_msg.isDepositRequest():
            if not req_msg.get('DepositMethodID') and not req_msg.get(
                    'DepositID'):

                currency = req_msg.get('Currency')

                secret = uuid.uuid4().hex
                callback_url = self.application.options.callback_url + secret

                hot_wallet = self.get_broker_wallet('hot', currency)
                cold_wallet = self.get_broker_wallet('cold', currency)
                if not hot_wallet and not cold_wallet:
                    return

                if not hot_wallet and cold_wallet:
                    dest_wallet = cold_wallet
                elif hot_wallet and not cold_wallet:
                    dest_wallet = hot_wallet
                else:
                    # 62.5% of all deposits go to the cold wallet, and 37.5% go to the hot wallet
                    dest_wallet = hot_wallet
                    if secret[0] in ('0', '1', '2', '3', '4', '5', '6', '7',
                                     '8', '9'):
                        dest_wallet = cold_wallet

                if not dest_wallet:
                    return

                parameters = urllib.urlencode({
                    'method': 'create',
                    'address': dest_wallet,
                    'callback': callback_url,
                    'currency': currency
                })

                try:
                    url_payment_processor = self.application.options.url_payment_processor + '?' + parameters
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         "invoking..." + url_payment_processor)
                    response = urllib2.urlopen(url_payment_processor)
                    data = json.load(response)
                    self.application.log('DEBUG',
                                         self.trade_client.connection_id,
                                         str(data))

                    req_msg.set('InputAddress', data['input_address'])
                    req_msg.set('Destination', data['destination'])
                    req_msg.set('Secret', secret)
                except urllib2.HTTPError as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Blockchain.info is not available at this moment, please try again within few minutes',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return
                except Exception as e:
                    out_message = json.dumps({
                        'MsgType':
                        'ERROR',
                        'ReqID':
                        req_msg.get('DepositReqID'),
                        'Description':
                        'Error retrieving a new deposit address from Blockchain.info. Please, try again',
                        'Detail':
                        str(e)
                    })
                    self.write_message(out_message)
                    return

        try:
            resp_message = self.trade_client.sendMessage(req_msg)
            if resp_message:
                self.write_message(resp_message.raw_message)

            if resp_message and resp_message.isUserResponse():
                self.user_response = resp_message
                if self.is_user_logged():
                    self.application.log('LOGIN_OK',
                                         self.trade_client.connection_id,
                                         raw_message)
                    #TODO: Request open order list
                    #self.trade_client.

                else:
                    self.application.log('LOGIN_FAILED',
                                         self.trade_client.connection_id,
                                         raw_message)

            if not self.trade_client.isConnected():
                self.application.log('DEBUG', self.trade_client.connection_id,
                                     'not self.trade_client.isConnected()')
                self.application.unregister_connection(self)
                self.trade_client.close()
                self.close()
        except TradeClientException as e:
            exception_message = {
                'MsgType': 'ERROR',
                'Description': 'Invalid message',
                'Detail': str(e)
            }
            self.write_message(json.dumps(exception_message))
            self.application.unregister_connection(self)
            self.trade_client.close()
            self.close()

    def is_user_logged(self):
        if not self.user_response:
            return False
        return self.user_response.get('UserStatus') == 1

    def is_broker(self):
        if not self.is_user_logged():
            return False
        return self.user_response.get('IsBroker') == 1

    def get_broker_wallet(self, type, currency):
        if not self.user_response:
            return

        broker = self.user_response.get('Broker')
        if not broker:
            return

        if 'CryptoCurrencies' not in broker:
            return

        broker_crypto_currencies = broker['CryptoCurrencies']
        for crypto_currency in broker_crypto_currencies:
            if crypto_currency['CurrencyCode'] == currency:
                for wallet in crypto_currency['Wallets']:
                    if wallet['type'] == type:
                        return wallet['address']

    def on_trade_history_request(self, msg):
        since = msg.get('Since')
        page = msg.get('Page', 0)
        page_size = msg.get('PageSize', 100)
        filter = msg.get('Filter')

        offset = page * page_size

        if self.is_broker():
            columns = [
                'TradeID', 'Market', 'Side', 'Price', 'Size', 'Buyer',
                'Seller', 'Created', 'BuyerUsername', 'SellerUsername'
            ]
        else:
            columns = [
                'TradeID', 'Market', 'Side', 'Price', 'Size', 'Buyer',
                'Seller', 'Created'
            ]

        trade_list = generate_trade_history(self.application.db_session,
                                            page_size,
                                            offset,
                                            show_username=self.is_broker(),
                                            since=since)

        response_msg = {
            'MsgType': 'U33',  # TradeHistoryResponse
            'TradeHistoryReqID': msg.get('TradeHistoryReqID'),
            'Page': page,
            'PageSize': page_size,
            'Columns': columns,
            'TradeHistoryGrp': trade_list
        }
        if since:
            response_msg['Since'] = since

        self.write_message(str(json.dumps(response_msg, cls=JsonEncoder)))

    def on_security_status_request(self, msg):
        # Generate a FullRefresh
        req_id = msg.get('SecurityStatusReqID')

        # Disable previous Snapshot + Update Request
        if int(msg.get('SubscriptionRequestType')) == 2:
            if req_id in self.sec_status_subscriptions:
                for sec_status_publisher in self.sec_status_subscriptions[
                        req_id]:
                    sec_status_publisher.cleanup()
                self.sec_status_subscriptions[req_id] = []
                del self.sec_status_subscriptions[req_id]
            return

        instruments = msg.get('Instruments')

        if int(msg.get('SubscriptionRequestType')) == 1:  # Snapshot + Updates
            if req_id not in self.sec_status_subscriptions:
                self.sec_status_subscriptions[req_id] = []

        for instrument in instruments:
            ss = generate_security_status(instrument, req_id)
            self.write_message(str(json.dumps(ss, cls=JsonEncoder)))

            # Snapshot + Updates
            if int(msg.get('SubscriptionRequestType')) == 1:
                self.sec_status_subscriptions[req_id].append(
                    SecurityStatusPublisher(req_id, instrument,
                                            self.on_send_json_msg_to_user))

    def on_market_data_request(self, msg):
        # Generate a FullRefresh
        req_id = msg.get('MDReqID')

        # Disable previous Snapshot + Update Request
        if int(msg.get('SubscriptionRequestType')) == 2:
            if req_id in self.md_subscriptions:
                for md_publisher in self.md_subscriptions[req_id]:
                    md_publisher.cleanup()
                self.md_subscriptions[req_id] = []
                del self.md_subscriptions[req_id]
            return

        market_depth = msg.get('MarketDepth')
        instruments = msg.get('Instruments')
        entries = msg.get('MDEntryTypes')

        if int(msg.get('SubscriptionRequestType')) == 1:  # Snapshot + Updates
            if req_id not in self.md_subscriptions:
                self.md_subscriptions[req_id] = []

        for instrument in instruments:
            md = generate_md_full_refresh(instrument, market_depth, entries,
                                          req_id, self.is_broker())
            self.write_message(str(json.dumps(md, cls=JsonEncoder)))

            # Snapshot + Updates
            if int(msg.get('SubscriptionRequestType')) == 1:
                self.md_subscriptions[req_id].append(
                    MarketDataPublisher(req_id, market_depth, entries,
                                        instrument,
                                        self.on_send_json_msg_to_user,
                                        self.is_broker()))

    def on_send_json_msg_to_user(self, sender, json_msg):
        s = json.dumps(json_msg, cls=JsonEncoder)
        self.write_message(s)
Пример #9
0
    def __init__(self, opt, instance_name):
        self.options = opt
        self.instance_name = instance_name

        handlers = [
            (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler),
            (r'/_webhook/verification_form', VerificationWebHookHandler),
            (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler),
            (r'/process_deposit(.*)', ProcessDepositHandler),
            (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)',
             RestApiHandler)
        ]
        settings = dict(cookie_secret='cookie_secret')
        tornado.web.Application.__init__(self, handlers, **settings)

        self.allowed_origins = json.loads(self.options.allowed_origins)
        self.allow_all_origins = self.allowed_origins[0] == '*'

        input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
            os.path.expanduser(self.options.gateway_log), when='MIDNIGHT')
        formatter = logging.Formatter('%(asctime)s - %(message)s')
        input_log_file_handler.setFormatter(formatter)

        self.replay_logger = logging.getLogger(self.instance_name)
        self.replay_logger.setLevel(logging.INFO)
        self.replay_logger.addHandler(input_log_file_handler)

        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(
            logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
        self.replay_logger.addHandler(ch)

        self.replay_logger.info('START')
        self.log_start_data()

        self.update_tor_nodes()

        from models import Base, db_bootstrap
        db_engine = self.options.sqlalchemy_engine + ':///' +\
                    os.path.expanduser(self.options.sqlalchemy_connection_string)
        engine = create_engine(db_engine, echo=self.options.db_echo)
        Base.metadata.create_all(engine)
        self.db_session = scoped_session(sessionmaker(bind=engine))
        db_bootstrap(self.db_session)

        self.zmq_context = zmq.Context()

        self.trade_in_socket = self.zmq_context.socket(zmq.REQ)
        self.trade_in_socket.connect(self.options.trade_in)

        self.application_trade_client = TradeClient(self.zmq_context,
                                                    self.trade_in_socket)
        self.application_trade_client.connect()

        self.security_list = self.application_trade_client.getSecurityList()
        self.md_subscriber = {}

        for instrument in self.security_list.get('Instruments'):
            symbol = instrument['Symbol']
            self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self)
            self.md_subscriber[symbol].subscribe(self.zmq_context,
                                                 self.options.trade_pub,
                                                 self.application_trade_client)

        last_trade_id = Trade.get_last_trade_id(self.db_session)
        trade_list = self.application_trade_client.getLastTrades(last_trade_id)

        for trade in trade_list:
            msg = dict()
            msg['id'] = trade[0]
            msg['symbol'] = trade[1]
            msg['side'] = trade[2]
            msg['price'] = trade[3]
            msg['size'] = trade[4]
            msg['buyer_id'] = trade[5]
            msg['seller_id'] = trade[6]
            msg['buyer_username'] = trade[7]
            msg['seller_username'] = trade[8]
            msg['created'] = trade[9]
            msg['trade_date'] = trade[9][:10]
            msg['trade_time'] = trade[9][11:]
            msg['order_id'] = trade[10]
            msg['counter_order_id'] = trade[11]
            Trade.create(self.db_session, msg)

        all_trades = Trade.get_all_trades(self.db_session)
        for t in all_trades:
            trade_info = dict()
            trade_info['price'] = t.price
            trade_info['size'] = t.size
            trade_info['trade_date'] = t.created.strftime('%Y-%m-%d')
            trade_info['trade_time'] = t.created.strftime('%H:%M:%S')
            self.md_subscriber[t.symbol].inst_status.push_trade(trade_info)

        for symbol, subscriber in self.md_subscriber.iteritems():
            subscriber.ready()

        self.connections = {}

        self.heart_beat_timer = tornado.ioloop.PeriodicCallback(
            self.send_heartbeat_to_trade, 30000)
        self.heart_beat_timer.start()

        self.update_tor_nodes_timer = tornado.ioloop.PeriodicCallback(
            self.update_tor_nodes, 3600000)
        self.update_tor_nodes_timer.start()
Пример #10
0
class WebSocketGatewayApplication(tornado.web.Application):
    def __init__(self, opt, instance_name):
        self.options = opt
        self.instance_name = instance_name

        handlers = [
            (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler),
            (r'/_webhook/verification_form', VerificationWebHookHandler),
            (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler),
            (r'/process_deposit(.*)', ProcessDepositHandler),
            (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)',
             RestApiHandler)
        ]
        settings = dict(cookie_secret='cookie_secret')
        tornado.web.Application.__init__(self, handlers, **settings)

        self.allowed_origins = json.loads(self.options.allowed_origins)
        self.allow_all_origins = self.allowed_origins[0] == '*'

        input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
            os.path.expanduser(self.options.gateway_log), when='MIDNIGHT')
        formatter = logging.Formatter('%(asctime)s - %(message)s')
        input_log_file_handler.setFormatter(formatter)

        self.replay_logger = logging.getLogger(self.instance_name)
        self.replay_logger.setLevel(logging.INFO)
        self.replay_logger.addHandler(input_log_file_handler)

        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(
            logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
        self.replay_logger.addHandler(ch)

        self.replay_logger.info('START')
        self.log_start_data()

        self.update_tor_nodes()

        from models import Base, db_bootstrap
        db_engine = self.options.sqlalchemy_engine + ':///' +\
                    os.path.expanduser(self.options.sqlalchemy_connection_string)
        engine = create_engine(db_engine, echo=self.options.db_echo)
        Base.metadata.create_all(engine)
        self.db_session = scoped_session(sessionmaker(bind=engine))
        db_bootstrap(self.db_session)

        self.zmq_context = zmq.Context()

        self.trade_in_socket = self.zmq_context.socket(zmq.REQ)
        self.trade_in_socket.connect(self.options.trade_in)

        self.application_trade_client = TradeClient(self.zmq_context,
                                                    self.trade_in_socket)
        self.application_trade_client.connect()

        self.security_list = self.application_trade_client.getSecurityList()
        self.md_subscriber = {}

        for instrument in self.security_list.get('Instruments'):
            symbol = instrument['Symbol']
            self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self)
            self.md_subscriber[symbol].subscribe(self.zmq_context,
                                                 self.options.trade_pub,
                                                 self.application_trade_client)

        last_trade_id = Trade.get_last_trade_id(self.db_session)
        trade_list = self.application_trade_client.getLastTrades(last_trade_id)

        for trade in trade_list:
            msg = dict()
            msg['id'] = trade[0]
            msg['symbol'] = trade[1]
            msg['side'] = trade[2]
            msg['price'] = trade[3]
            msg['size'] = trade[4]
            msg['buyer_id'] = trade[5]
            msg['seller_id'] = trade[6]
            msg['buyer_username'] = trade[7]
            msg['seller_username'] = trade[8]
            msg['created'] = trade[9]
            msg['trade_date'] = trade[9][:10]
            msg['trade_time'] = trade[9][11:]
            msg['order_id'] = trade[10]
            msg['counter_order_id'] = trade[11]
            Trade.create(self.db_session, msg)

        all_trades = Trade.get_all_trades(self.db_session)
        for t in all_trades:
            trade_info = dict()
            trade_info['price'] = t.price
            trade_info['size'] = t.size
            trade_info['trade_date'] = t.created.strftime('%Y-%m-%d')
            trade_info['trade_time'] = t.created.strftime('%H:%M:%S')
            self.md_subscriber[t.symbol].inst_status.push_trade(trade_info)

        for symbol, subscriber in self.md_subscriber.iteritems():
            subscriber.ready()

        self.connections = {}

        self.heart_beat_timer = tornado.ioloop.PeriodicCallback(
            self.send_heartbeat_to_trade, 30000)
        self.heart_beat_timer.start()

        self.update_tor_nodes_timer = tornado.ioloop.PeriodicCallback(
            self.update_tor_nodes, 3600000)
        self.update_tor_nodes_timer.start()

    def format_currency(self, currency_code, value, is_value_in_satoshis=True):
        currencies = self.security_list.get('Currencies')
        for currency_obj in currencies:
            if currency_obj['Code'] == currency_code:
                if is_value_in_satoshis:
                    return currency_obj['FormatPython'].format(value / 1e8)
                else:
                    return currency_obj['FormatPython'].format(value)
        return value

    def is_origin_allowed(self, origin):
        if self.allow_all_origins:
            return True

        if origin in self.allowed_origins:
            return True
        return False

    def is_tor_node(self, ip):
        self.log('DEBUG', 'TOR_CHECK', ip)
        return ip in self.tor_ip_list_

    def log_start_data(self):
        self.log('PARAM', 'BEGIN')
        self.log('PARAM', 'callback_url', self.options.callback_url)
        self.log('PARAM', 'port', self.options.port)
        self.log('PARAM', 'trade_in', self.options.trade_in)
        self.log('PARAM', 'trade_pub', self.options.trade_pub)
        self.log('PARAM', 'url_payment_processor',
                 self.options.url_payment_processor)
        self.log('PARAM', 'session_timeout_limit',
                 self.options.session_timeout_limit)
        self.log('PARAM', 'db_echo', self.options.db_echo)
        self.log('PARAM', 'sqlalchemy_engine', self.options.sqlalchemy_engine)
        self.log('PARAM', 'sqlalchemy_connection_string',
                 self.options.sqlalchemy_connection_string)
        self.log('PARAM', 'allowed_origins', self.options.allowed_origins)
        self.log('PARAM', 'END')

    def log(self, command, key, value=None):
        log_msg = command + ',' + key
        if value:
            try:
                log_msg += ',' + value
            except Exception, e:
                try:
                    log_msg += ',' + str(value)
                except Exception, e:
                    try:
                        log_msg += ',' + unicode(value)
                    except Exception, e:
                        log_msg += ', [object]'
Пример #11
0
def run_application(options, instance_name):
  input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
    os.path.expanduser(options.mailer_log), when='MIDNIGHT')
  input_log_file_handler.setFormatter(logging.Formatter(u"%(asctime)s - %(message)s"))

  app_logger = logging.getLogger(instance_name)
  app_logger.setLevel(logging.INFO)
  app_logger.addHandler(input_log_file_handler)

  ch = logging.StreamHandler(sys.stdout)
  ch.setLevel(logging.DEBUG)
  ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
  app_logger.addHandler(ch)

  app_logger.info('START')
  def log(command, key, value=None):
    log_msg = u'%s, %s, %s' %(command, key, value if value else None)
    app_logger.info(unicode(log_msg))


  log('PARAM', 'BEGIN')
  log('PARAM', 'trade_in',                      options.trade_in)
  log('PARAM', 'trade_pub',                     options.trade_pub)
  log('PARAM', 'app_log',                       options.app_log)
  log('PARAM', 'maxmind_license_key',           options.maxmind_license_key)
  log('PARAM', 'END')

  context = zmq.Context()
  socket = context.socket(zmq.SUB)
  socket.connect(options.trade_pub)
  socket.setsockopt(zmq.SUBSCRIBE, "^FRAUDER$")

  trade_in_socket = context.socket(zmq.REQ)
  trade_in_socket.connect(options.trade_in)

  application_trade_client = TradeClient( context, trade_in_socket)
  application_trade_client.connect()

  login_response = application_trade_client.sendJSON( MessageBuilder.login( 8999999,
                                                                            options.frauder_username,
                                                                            options.frauder_password))
  if login_response.get('UserStatus') != 1:
    raise RuntimeError("Invalid user id")

  brokers = {}
  broker_list, broker_list_columns = application_trade_client.getBrokerList(['1'])
  for b in  broker_list:
    brokers[b[0]] = { "params": b }


  while True:
    try:
      raw_email_message = socket.recv()
      log('IN', 'TRADE_IN_PUB', raw_email_message)

      msg = JsonMessage(raw_email_message)

      if not msg.isAccessLog():
        continue

      try:
        broker_id = msg.get('BrokerID')

      except Exception as ex:
        traceback.print_exc()
        log('ERROR', 'EXCEPTION', str(ex))
        time.sleep(1)

    except KeyboardInterrupt:
      app_logger.info('END')
      break

    except Exception as ex:
      time.sleep(1)
Пример #12
0
def run_application(options, instance_name):
  input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
    os.path.expanduser(options.mailer_log), when='MIDNIGHT')
  input_log_file_handler.setFormatter(logging.Formatter(u"%(asctime)s - %(message)s"))

  mail_logger = logging.getLogger(instance_name)
  mail_logger.setLevel(logging.INFO)
  mail_logger.addHandler(input_log_file_handler)

  ch = logging.StreamHandler(sys.stdout)
  ch.setLevel(logging.DEBUG)
  ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
  mail_logger.addHandler(ch)

  mail_logger.info('START')
  def log(command, key, value=None):
    log_msg = u'%s, %s, %s' %(command, key, value if value else None)
    mail_logger.info(unicode(log_msg))


  log('PARAM', 'BEGIN')
  log('PARAM', 'trade_in',                      options.trade_in)
  log('PARAM', 'trade_pub',                     options.trade_pub)
  log('PARAM', 'mailer_log',                    options.mailer_log)
  log('PARAM', 'mailchimp_apikey',              options.mailchimp_apikey)
  log('PARAM', 'mandrill_apikey',               options.mandrill_apikey)
  log('PARAM', 'mailer_username',               options.mailer_username)
  log('PARAM', 'mailchimp_newsletter_list_id',  options.mailchimp_newsletter_list_id)
  log('PARAM', 'END')

  context = zmq.Context()
  socket = context.socket(zmq.SUB)
  socket.connect(options.trade_pub)
  socket.setsockopt(zmq.SUBSCRIBE, "^EMAIL$")

  trade_in_socket = context.socket(zmq.REQ)
  trade_in_socket.connect(options.trade_in)

  application_trade_client = TradeClient( context, trade_in_socket)
  application_trade_client.connect()

  login_response = application_trade_client.sendJSON( MessageBuilder.login( 8999999,
                                                                            options.mailer_username,
                                                                            options.mailer_password))
  if login_response.get('UserStatus') != 1:
    raise RuntimeError("Invalid user id")

  brokers = {}
  broker_list, broker_list_columns = application_trade_client.getBrokerList(['1'])
  for b in  broker_list:
    brokers[b[0]] = { "params": b }

  broker_mandrill_column_index = None
  try:
    broker_mandrill_column_index = broker_list_columns.index('MandrillApiKey')
  except ValueError:
    pass


  for broker_id, broker_data  in brokers.iteritems():
    if broker_mandrill_column_index and broker_data['params'][ broker_mandrill_column_index ]:
      broker_data['MandrillApiKey'] =  broker_data['params'][ broker_mandrill_column_index ]
    else:
      broker_data['MandrillApiKey'] = options.mandrill_apikey

  for broker_id, broker_data  in brokers.iteritems():
    print broker_id, broker_data['MandrillApiKey']

  # [u'BrokerID', u'ShortName', u'BusinessName', u'Address', u'City', u'State',
  #  u'ZipCode', u'Country', u'PhoneNumber1', u'PhoneNumber2', u'Skype', u'Currencies',
  #  u'TosUrl', u'FeeStructure', u'TransactionFeeBuy', u'TransactionFeeSell', u'Status',
  #  u'ranking', u'Email', u'CountryCode', u'CryptoCurrencies', u'WithdrawStructure',
  #  u'SupportURL', u'SignupLabel', u'AcceptCustomersFrom', u'IsBrokerHub']

  mailchimp_api =  mailchimp.Mailchimp(options.mailchimp_apikey)
  try:
    mailchimp_api.helper.ping()
  except mailchimp.Error:
    raise RuntimeError("Invalid MailChimp API key")

  mandrill_api = mandrill.Mandrill(options.mandrill_apikey)
  try:
    mandrill_api.users.ping()
  except mandrill.Error:
    raise RuntimeError("Invalid Mandrill API key")

  while True:
    try:
      raw_email_message = socket.recv()
      log('IN', 'TRADE_IN_PUB', raw_email_message)

      msg = JsonMessage(raw_email_message)

      if not msg.isEmail():
        log('ERROR',
            'EXCEPTION',
            'Received message is not an email message')
        continue

      try:
        broker_id = msg.get('BrokerID')
        sender =  brokers[broker_id]['params'][broker_list_columns.index('MailerFromName')]  + \
                  '<' + brokers[broker_id]['params'][broker_list_columns.index('MailerFromEmail')] + '>'
        body = ""
        msg_to    = msg.get('To')
        subject   = msg.get('Subject')
        language  = msg.get('Language')
        content_type = 'plain'

        if msg.has('Template') and msg.get('Template'):
          params = {}
          if msg.has('Params') and msg.get('Params'):
            params = json.loads(msg.get('Params'))

          template_name = msg.get('Template')


          if template_name  == 'welcome':
            # user signup .... let's register him on mailchimp newsletter
            try:
              mailchimp_api.lists.subscribe(
                id =  brokers[broker_id]['params'][broker_list_columns.index('MailchimpListID')],
                email = {'email': params['email'] },
                merge_vars = {'EMAIL' : params['email'], 'FNAME': params['username'] } )

            except mailchimp.ListAlreadySubscribedError:
              log('ERROR', 'EXCEPTION', params['email'] + ' mailchimp.ListAlreadySubscribedError' )
            except mailchimp.Error, e:
              log('ERROR', 'EXCEPTION', str(e))


          template_content = []
          for k,v in params.iteritems():
            template_content.append( { 'name': k, 'content': v  } )

          for broker_column_key in broker_list_columns:
            broker_column_value  = brokers[broker_id]['params'][broker_list_columns.index(broker_column_key)]
            template_content.append( { 'name': 'broker_' + convertCamelCase2Underscore(broker_column_key),
                                       'content': broker_column_value  } )


          message = {
            'from_email': brokers[broker_id]['params'][broker_list_columns.index('MailerFromEmail')],
            'from_name': brokers[broker_id]['params'][broker_list_columns.index('MailerFromName')],
            'to': [{'email': msg_to, 'name': params['username'],'type': 'to' }],
            'metadata': {'website': 'www.blinktrade.com'},
            'global_merge_vars': template_content
          }

          result = mandrill_api.messages.send_template(
            template_name= (template_name + '-' + language.replace('_','-') ).lower(),
            template_content=template_content,
            message=message)

          log('INFO', 'SUCCESS', str(result))
          continue

        elif msg.has('RawData') and msg.get('RawData'):
          body = msg.get('RawData')

          log('DEBUG', 'EMAIL',
              u'{"Sender":"%s","To":"%s","Subject":"%s", "Body":"%s" }' % (sender,
                                                                           msg_to,
                                                                           subject,
                                                                           body))
          send_email(sender, msg_to, subject, body, content_type)
          log('IN', 'SENT', "")

          log('INFO', 'SUCCESS', msg.get('EmailThreadID'))
      except Exception as ex:
        traceback.print_exc()
        log('ERROR', 'EXCEPTION', str(ex))
        time.sleep(1)

    except KeyboardInterrupt:
      mail_logger.info('END')
      break
def run_application(options, instance_name):
    input_log_file_handler = logging.handlers.TimedRotatingFileHandler(
        os.path.expanduser(options.mailer_log), when='MIDNIGHT')
    input_log_file_handler.setFormatter(
        logging.Formatter(u"%(asctime)s - %(message)s"))

    mail_logger = logging.getLogger(instance_name)
    mail_logger.setLevel(logging.INFO)
    mail_logger.addHandler(input_log_file_handler)

    ch = logging.StreamHandler(sys.stdout)
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(
        logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    mail_logger.addHandler(ch)

    mail_logger.info('START')

    def log(command, key, value=None):
        log_msg = u'%s, %s, %s' % (command, key, value if value else None)
        mail_logger.info(unicode(log_msg))

    log('PARAM', 'BEGIN')
    log('PARAM', 'trade_in', options.trade_in)
    log('PARAM', 'trade_pub', options.trade_pub)
    log('PARAM', 'mailer_log', options.mailer_log)
    log('PARAM', 'mailchimp_apikey', options.mailchimp_apikey)
    log('PARAM', 'mandrill_apikey', options.mandrill_apikey)
    log('PARAM', 'mailer_username', options.mailer_username)
    log('PARAM', 'mailchimp_newsletter_list_id',
        options.mailchimp_newsletter_list_id)
    log('PARAM', 'END')

    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.connect(options.trade_pub)
    socket.setsockopt(zmq.SUBSCRIBE, "^EMAIL$")

    trade_in_socket = context.socket(zmq.REQ)
    trade_in_socket.connect(options.trade_in)

    application_trade_client = TradeClient(context, trade_in_socket)
    application_trade_client.connect()

    login_response = application_trade_client.sendJSON(
        MessageBuilder.login(8999999, options.mailer_username,
                             options.mailer_password))
    if login_response.get('UserStatus') != 1:
        raise RuntimeError("Invalid user id")

    brokers = {}
    broker_list, broker_list_columns = application_trade_client.getBrokerList(
        ['1'])
    for b in broker_list:
        brokers[b[0]] = {"params": b}

    broker_mandrill_column_index = None
    try:
        broker_mandrill_column_index = broker_list_columns.index(
            'MandrillApiKey')
    except ValueError:
        pass

    for broker_id, broker_data in brokers.iteritems():
        if broker_mandrill_column_index and broker_data['params'][
                broker_mandrill_column_index]:
            broker_data['MandrillApiKey'] = broker_data['params'][
                broker_mandrill_column_index]
        else:
            broker_data['MandrillApiKey'] = options.mandrill_apikey

    for broker_id, broker_data in brokers.iteritems():
        print broker_id, broker_data['MandrillApiKey']

    # [u'BrokerID', u'ShortName', u'BusinessName', u'Address', u'City', u'State',
    #  u'ZipCode', u'Country', u'PhoneNumber1', u'PhoneNumber2', u'Skype', u'Currencies',
    #  u'TosUrl', u'FeeStructure', u'TransactionFeeBuy', u'TransactionFeeSell', u'Status',
    #  u'ranking', u'Email', u'CountryCode', u'CryptoCurrencies', u'WithdrawStructure',
    #  u'SupportURL', u'SignupLabel', u'AcceptCustomersFrom', u'IsBrokerHub']

    mailchimp_api = mailchimp.Mailchimp(options.mailchimp_apikey)
    try:
        mailchimp_api.helper.ping()
    except mailchimp.Error:
        raise RuntimeError("Invalid MailChimp API key")

    mandrill_api = mandrill.Mandrill(options.mandrill_apikey)
    try:
        mandrill_api.users.ping()
    except mandrill.Error:
        raise RuntimeError("Invalid Mandrill API key")

    while True:
        try:
            raw_email_message = socket.recv()
            log('IN', 'TRADE_IN_PUB', raw_email_message)

            msg = JsonMessage(raw_email_message)

            if not msg.isEmail():
                log('ERROR', 'EXCEPTION',
                    'Received message is not an email message')
                continue

            try:
                broker_id = msg.get('BrokerID')
                sender =  brokers[broker_id]['params'][broker_list_columns.index('MailerFromName')]  + \
                          '<' + brokers[broker_id]['params'][broker_list_columns.index('MailerFromEmail')] + '>'
                body = ""
                msg_to = msg.get('To')
                subject = msg.get('Subject')
                language = msg.get('Language')
                content_type = 'plain'

                if msg.has('Template') and msg.get('Template'):
                    params = {}
                    if msg.has('Params') and msg.get('Params'):
                        params = json.loads(msg.get('Params'))

                    template_name = msg.get('Template')

                    if template_name == 'welcome':
                        # user signup .... let's register him on mailchimp newsletter
                        try:
                            mailchimp_api.lists.subscribe(
                                id=brokers[broker_id]['params']
                                [broker_list_columns.index('MailchimpListID')],
                                email={'email': params['email']},
                                merge_vars={
                                    'EMAIL': params['email'],
                                    'FNAME': params['username']
                                })

                        except mailchimp.ListAlreadySubscribedError:
                            log(
                                'ERROR', 'EXCEPTION', params['email'] +
                                ' mailchimp.ListAlreadySubscribedError')
                        except mailchimp.Error, e:
                            log('ERROR', 'EXCEPTION', str(e))

                    template_content = []
                    for k, v in params.iteritems():
                        template_content.append({'name': k, 'content': v})

                    for broker_column_key in broker_list_columns:
                        broker_column_value = brokers[broker_id]['params'][
                            broker_list_columns.index(broker_column_key)]
                        template_content.append({
                            'name':
                            'broker_' +
                            convertCamelCase2Underscore(broker_column_key),
                            'content':
                            broker_column_value
                        })

                    message = {
                        'from_email':
                        brokers[broker_id]['params'][broker_list_columns.index(
                            'MailerFromEmail')],
                        'from_name':
                        brokers[broker_id]['params'][broker_list_columns.index(
                            'MailerFromName')],
                        'to': [{
                            'email': msg_to,
                            'name': params['username'],
                            'type': 'to'
                        }],
                        'metadata': {
                            'website': 'www.blinktrade.com'
                        },
                        'global_merge_vars':
                        template_content
                    }

                    result = mandrill_api.messages.send_template(
                        template_name=(template_name + '-' +
                                       language.replace('_', '-')).lower(),
                        template_content=template_content,
                        message=message)

                    log('INFO', 'SUCCESS', str(result))
                    continue

                elif msg.has('RawData') and msg.get('RawData'):
                    body = msg.get('RawData')

                    log(
                        'DEBUG', 'EMAIL',
                        u'{"Sender":"%s","To":"%s","Subject":"%s", "Body":"%s" }'
                        % (sender, msg_to, subject, body))
                    send_email(sender, msg_to, subject, body, content_type)
                    log('IN', 'SENT', "")

                    log('INFO', 'SUCCESS', msg.get('EmailThreadID'))
            except Exception as ex:
                traceback.print_exc()
                log('ERROR', 'EXCEPTION', str(ex))
                time.sleep(1)

        except KeyboardInterrupt:
            mail_logger.info('END')
            break