Example #1
0
    def on_message(self, message):
        entity = Message.from_dict(json.loads(message))
        self.application.db.messages.insert_one(entity.__dict__)

        conn = ToRedisClient()
        conn.connect(host="redis")

        def publish_message(channel,message):
            conn.publish(channel,message)

        self.io_loop.add_timeout(time.time(), partial(publish_message,self.channel,format_entity(entity.__dict__)))
Example #2
0
class Handler(RequestHandler):
    @asynchronous
    def get(self):
        self.client = Client()
        self.client.connect()
        self.client.subscribe("foo", callback=self.on_receive)

    def on_receive(self, msg):
        """ New message, close out connection. """
        msg_type, msg_channel, msg = msg
        if msg_type == b"message":
            self.finish({"message": msg.decode()})
Example #3
0
class Handler(RequestHandler):
    @asynchronous
    def get(self):
        self.client = Client()
        self.client.connect()
        self.client.subscribe("foo", callback=self.on_receive)

    def on_receive(self, msg):
        """ New message, close out connection. """
        msg_type, msg_channel, msg = msg
        if msg_type == "message":
            self.finish({"message": msg})
Example #4
0
async def get_grouped_count(group_type, content_id):
    """ Sends document id and group type to redis and returns page view count as response. """

    group_value = get_group_value(group_type)
    if group_value is None:
        return 0

    redis = Client()
    redis.connect(config.HOST, config.PORT)
    response = await gen.Task(redis.zcard,
                              "{0}:{1}".format(group_value, content_id))
    return response
Example #5
0
    def test_subscribe(self):
        """ Tests a subscription message """

        # conn = redis.Redis()
        conn = Client()
        conn.connect()

        def publish_message():
            conn.publish("foo", "bar")

        self.io_loop.add_timeout(time.time() + 0.5, publish_message)
        response = self.fetch("/")
        # blocks
        self.assertEqual(response.code, 200)
Example #6
0
class RedisWebSocket(tornado.websocket.WebSocketHandler):

    client = None
    user = None
    channel = None
    io_loop = tornado.ioloop.IOLoop.instance()

    def open(self):
        # Get user and channel
        self.user = self.get_argument('user', None)
        self.channel = self.get_argument('channel', None)

        # new access
        self.application.db.access.insert_one(Access.connect(self.user,self.channel).__dict__)

        # get all messages
        messages = self.application.db.messages.find({"channel" : self.channel}).sort("$natural",pymongo.DESCENDING)

        output = [format_entity(msg) for msg in messages]

        for message in reversed(output):
            self.write_message(message)

        # subscribe to channel
        self.client = ToRedisClient()
        self.client.connect(host="redis")
        self.client.subscribe(self.channel, callback=self.on_receive)

    def on_receive(self,msg):
        msg_type, msg_channel, msg = msg
        if msg_type == b"message":
            self.write_message(eval(msg))
        # client.write_message(message)

    def on_message(self, message):
        entity = Message.from_dict(json.loads(message))
        self.application.db.messages.insert_one(entity.__dict__)

        conn = ToRedisClient()
        conn.connect(host="redis")

        def publish_message(channel,message):
            conn.publish(channel,message)

        self.io_loop.add_timeout(time.time(), partial(publish_message,self.channel,format_entity(entity.__dict__)))
        # self.application.manager.notify(entity.channel,format_entity(entity.__dict__))

    def on_close(self):
        self.application.db.access.insert_one(Access.disconnect(self.user, self.channel).__dict__)
        self.client.unsubscribe(self.channel)
Example #7
0
class MessageHandler(WebSocketHandler):
    def __init__(self, *args, **kwargs):
        super(MessageHandler, self).__init__(*args, **kwargs)
        self.r_server = Redis()
        self.redis = Client()
        self.redis.connect()

    def get_current_user(self):
        user = self.get_secure_cookie("user")
        if user is None:
            return ''
        else:
            return user.strip('" ')

    def on_message(self, msg):
        msginfo = loads(msg)
        # listens for handshake from page
        self.channel = msginfo['user']
        # need to split the rest off to new func so it can be asynchronous
        self.listen()

    def listen(self):
        # runs task given, with the yield required to get returned value
        # equivalent of callback/wait pairing from tornado.gen
        self.redis.subscribe(self.channel, callback=self.callback)
        # fight race condition by loading from redis after listen started
        oldmessages = self.r_server.lrange('%s:messages' % self.channel, 0, -1)
        if oldmessages is not None:
            for message in oldmessages:
                self.write_message(message)

    def callback(self, msg):
        if msg[0] == 'message':
            self.write_message(msg[2])

    @engine
    def on_close(self):
        yield Task(self.redis.unsubscribe, self.channel)
        self.redis.disconnect()
Example #8
0
# -*- coding: utf-8 -*-

from tornado import httpclient
from toredis import Client


redis_client = Client()
redis_client.connect('localhost')

http_client = httpclient.AsyncHTTPClient()
Example #9
0
import logging
import tornado.ioloop
from toredis import Client


def test_auth():
    # Assuming that 12345 is your redis pasword
    redis.auth('12345', after_auth)


def after_auth(status):
    print 'Authentication status:', status
    assert status == 'OK'
    io_loop.stop()


if __name__ == "__main__":
    logging.basicConfig()

    io_loop = tornado.ioloop.IOLoop.instance()

    redis = Client()
    redis.connect('localhost', callback=test_auth)
    io_loop.start()
Example #10
0
class SessionHandler(object):
    """
    Manage complete flight session.
    """
    def __init__(self,
                 session_id,
                 vehicle_id,
                 api_key,
                 namespace,
                 name,
                 poi,
                 height,
                 clearance,
                 wait_time=10.,
                 url=None):
        self.session_id = session_id
        self.vehicle_id = vehicle_id
        self.api_key = api_key
        self.ns = namespace
        self.name = name
        self.poi = poi  # point of interest information. e.g. {'lat':45.,'long':65., 'alt':10.0}
        self.height = height  # height at which the drone should fly
        self.clearance = clearance  # distance away from PPOI
        self.wait_time = wait_time  # drone will wait at users;s location for these many seconds
        self.url = url  # stream endpoint

        # setup environment variables.
        self.api_base_url = 'https://dev.flytbase.com/rest/ros/' + self.ns
        self.header = {
            'Authorization': 'Token ' + self.api_key,
            'VehicleID': self.vehicle_id
        }
        self.status = -1  # set session status flag to 'initilized state'
        self.fuse = True  # if fuse is false then the session will stay on hold. No call backs should execute.
        self.home = None
        self.target_loc = self.poi.copy(
        )  # later change this to 'clearance' meter distance away from POI in straight line path.
        #  Initialize redis client
        self.redis = RedisClient()
        self.redis.connect('localhost')

        # instance of non blocking http client
        self.http_client = AsyncHTTPClient()
        self.init_redis_structs()

    @gen.engine
    def init_redis_structs(self):
        #  initialize session structure and upload to redis server. No need to update this later
        session_struct = json.dumps({
            "vehicle_id": self.vehicle_id,
            "session_key": "removed_key",
            "api_key": self.api_key,
            "ns": self.ns
        })
        yield gen.Task(self.redis.set, self.session_id + "_info",
                       session_struct)

        # initialize status structure for session on redis. This should be updated after state change.
        yield gen.Task(self.redis.set, self.session_id + "_status",
                       self.status)

        #  update sessions structure. No need to update this.
        cur_sessions = yield gen.Task(self.redis.get, "sessions")
        try:
            cur_sessions = json.loads(cur_sessions)
            updated_sessions = cur_sessions.copy()
            updated_sessions[self.session_id] = {"session_key": "removed"}
            yield gen.Task(self.redis.set, "sessions", updated_sessions)
        except ValueError:
            print "session JSON decode error"

    @gen.coroutine
    def run_mission(self):
        # todo "make sure app is initialized"
        yield gen.sleep(5.0)
        if self.status == -1 and self.fuse:
            print "Session Handler: Initialized, starting stream"
            success, resp = yield self.start_stream()
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
            self.status = 0
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 0 and self.fuse:
            # save home location.
            self.home = yield self.get_drone_state()

            # Update the target clearance distance away from POI
            offset_loc = get_offset_location(self.home['lat'],
                                             self.home['long'],
                                             self.poi['lat'], self.poi['long'],
                                             self.clearance)
            self.target_loc = {
                'lat': offset_loc[0],
                'long': offset_loc[1],
                'alt': self.poi['alt']
            }

            print "Session Handler: taking off"
            success, resp = yield self.take_off(3.0)
            if success:
                print "Request success: ", resp
            else:
                print "Request failed: ", resp
                # todo handle takeoff failure
            self.status = 1
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 1 and self.fuse:
            print "Session Handler: Attaining mission height and correcting heading"
            # todo check that self.home is populated
            success, resp = yield self.attain_global_setpoint(
                self.home['lat'], self.home['long'], self.height, 3)
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
                # todo handle this case
            dist, ang = dist_ang_betn_coordinates(self.home['lat'],
                                                  self.home['long'],
                                                  self.poi['lat'],
                                                  self.poi['long'])
            delta_ang = ang - self.home['yaw']
            success, resp = yield self.attain_yaw_sp(delta_ang)
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
                # todo handle this case
            self.status = 2
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 2 and self.fuse:
            print "Session Handler: Moving to goal"
            success, resp = yield self.attain_global_setpoint(
                self.target_loc['lat'], self.target_loc['long'], self.height,
                3)
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
            self.status = 3
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 3 and self.fuse:
            # print "Session Handler: pointing towards user"
            # Nothing here
            self.status = 4
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
            # don't change mission number now, 4 will be used to allow 3rd party access.
        if self.status == 4 and self.fuse:
            print "Session Handler: Waiting at goal", self.wait_time
            yield gen.sleep(self.wait_time)
            print "Session Handler: confirming lock"
            access_lock = yield self.check_access_lock(4, 100)
            print "Session Handler: acquired lock"
            if not access_lock:
                print "FATAL!"
            self.status = 5
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
            # continue only if status code is 5 in database. If it is 100 (foreign access)
            # then wait for 10 more seconds before checking
        if self.status == 5 and self.fuse:
            print "Session Handler: Moving back to home"
            # success, resp = yield self.global_sp(self.home['lat'], self.home['long'], self.height, 0., False, False)
            success, resp = yield self.attain_global_setpoint(
                self.home['lat'], self.home['long'], self.height, 3)
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
            self.status = 6
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 6 and self.fuse:
            print "Session Handler: landing"
            success, resp = yield self.land()
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
            self.status = 7
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        if self.status == 7 and self.fuse:
            print "Session Handler: stopping stream"
            success, resp = yield self.stop_stream()
            if success:
                print "Session Handler: Request success: ", resp
            else:
                print "Session Handler: Request failed: ", resp
            self.status = 8
            yield gen.Task(self.redis.set, self.session_id + "_status",
                           self.status)
        # set_drone free
        yield self.close_session()

    @gen.coroutine
    def check_access_lock(self, wait_case, foreign_case):
        """return True when access lock is released"""
        # TOdo repeat only 3 times.
        current_state = yield gen.Task(self.redis.get,
                                       self.session_id + "_status")
        if current_state == str(wait_case):
            raise gen.Return(True)
        if current_state == str(foreign_case):
            print "Session Handler: will try to acquire lock again in 10 secs."
            yield gen.sleep(10.)
            res = yield self.check_access_lock(wait_case, foreign_case)
            raise gen.Return(res)

    @gen.coroutine
    def attain_global_setpoint(self,
                               lat,
                               long,
                               height,
                               max_retries=3,
                               max_error_retries=3,
                               r_count=0,
                               re_count=0):
        success, resp = yield self.global_sp(lat, long, height, 0., False,
                                             False)
        if success:
            # print "Request success: ", resp
            max_error_retries = 0
            try:
                resp_dec = json.loads(resp)
                if not resp_dec['success']:
                    if r_count <= max_retries:
                        r_count += 1
                        print "Session Handler: Target not achieved, retrying: retry no. ", r_count
                        success, resp = yield self.attain_global_setpoint(
                            lat, long, height, max_retries, max_error_retries,
                            r_count, re_count)
                        raise gen.Return((success, resp))
                    else:
                        raise gen.Return((False, resp))
                raise gen.Return((True, resp))
            except ValueError, KeyError:
                print "drone GPOS sp API json response decode failed", success, resp
                raise gen.Return((False, resp))
        else:
Example #11
0
            return None

        key = custom_vars["1"][0]
        value = custom_vars["1"][1]

        if value == "":
            return None

        return value



def make_app():
    return tornado.web.Application([
        (r"/capture", MainHandler),

        # serve pikik tag
        (r"/static/(.*)", tornado.web.StaticFileHandler, {'path': STATIC_DIR}),
    ])

def set_database():
    redis.select(config.getint('redis','index'))


if __name__ == "__main__":
    app = make_app()
    app.listen(config.getint('server','port'))
    redis = Client()
    redis.connect(host=config.get('redis','hostname'), port=config.getint('redis','port'), callback=set_database)
    tornado.ioloop.IOLoop.current().start()
Example #12
0
    if message_type == 'landing:track:change':
        for participant in RouterConnection.participants:
            if participant.user_id == 'anonymous':
                participant.send(message_data)

    elif message_type == 'admin:':
        user_id = data.get('user_id', None)
        for participant in RouterConnection.participants:
            if participant.user_id == user_id:
                participant.send(message_data)

application = tornado.web.Application(
    sockjs.tornado.SockJSRouter(RouterConnection, '/sock').urls
)


if __name__ == '__main__':
    parse_command_line()
    import logging
    logging.getLogger().setLevel(logging.DEBUG)

    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port, address=options.host)

    client = Client()
    client.connect()
    client.subscribe('tornado_events', callback=tornado_events)

    tornado.ioloop.IOLoop.instance().start()
Example #13
0
import logging
import tornado.ioloop
from tornado import gen
from toredis import Client


@gen.engine
def test():
    # Authenticate first
    status = yield gen.Task(redis.auth, "12345")
    assert status == "OK"

    # Select database
    status = yield gen.Task(redis.select, "0")
    assert status == "OK"

    print "Success"

    io_loop.stop()


if __name__ == "__main__":
    logging.basicConfig()

    io_loop = tornado.ioloop.IOLoop.instance()

    redis = Client()
    redis.connect("localhost", callback=test)
    io_loop.start()
Example #14
0
import logging
import tornado.ioloop
from tornado import gen
from toredis import Client


@gen.engine
def test():
    # Authenticate first
    status = yield gen.Task(redis.auth, '12345')
    assert status == 'OK'

    # Select database
    status = yield gen.Task(redis.select, '0')
    assert status == 'OK'

    print('Success')

    io_loop.stop()


if __name__ == "__main__":
    logging.basicConfig()

    io_loop = tornado.ioloop.IOLoop.instance()

    redis = Client()
    redis.connect('localhost', callback=test)
    io_loop.start()
Example #15
0
class WebSocketClient(WebSocketClientBase):
    def __init__(self, drone_info, drone_vec, sub_topics, throttle_rate=6000):
        self.api_key = drone_info["api_key"]  # API key to talk with drone.
        self.vehicle_id = drone_info["vehicle_id"]  # vehicle ID of the drone.
        self.namespace = drone_info["namespace"]  # namespace of the drone
        self.topics_subscribed = []
        self.drone_vec = drone_vec  # drone status vector that will be updated.
        self.topics_to_subscribe = sub_topics
        self.msglib = MsgStructs(self.namespace, throttle_rate)
        self.redis = RedisClient()
        self.redis.connect('localhost')
        super(WebSocketClient, self).__init__()

    def _on_message(self, msg):
        try:
            res = json.loads(msg)
            ioloop.IOLoop.instance().add_callback(partial(self.parse_msg, res))
        except ValueError:
            print "json decoding failed"

    def _on_connection_success(self):
        print('Drone Connected! ', self.vehicle_id)
        deadline = time.time() + 1
        ioloop.IOLoop().instance().add_timeout(
            deadline, functools.partial(self.subscribe_to_topics))

    def _on_connection_close(self):
        print('Connection closed!')

    def _on_connection_error(self, exception):
        print('Connection error: %s', exception)

    def subscribe_to_topics(self):
        for topic in self.topics_to_subscribe:
            self.topics_subscribed.append(topic)
            ioloop.IOLoop.instance().add_callback(
                partial(self.send, json.dumps(self.msglib.sub_msg(topic))))
            # TODO remove debug statement
            # ioloop.IOLoop().instance().add_timeout(time.time()+10, functools.partial(self.stop_client))

    def stop_client(self):
        #  unsubscribe from the data.
        for topic in self.topics_subscribed:
            self.send(json.dumps(self.msglib.get_unsub_msg(topic)))
        # call close method
        self.close()

    def parse_msg(self, msg):
        if isinstance(msg, dict):
            if 'op' in msg.keys():
                if msg['op'] == 'publish':
                    # print msg
                    word6 = msg['topic'][-6:]
                    if word6 == "global":
                        lat = msg['msg']['latitude']
                        lon = msg['msg']['longitude']
                        alt = msg['msg']['altitude']
                        # print lat, lon, "global"
                        self.redis.set(
                            self.vehicle_id + '_gpos',
                            json.dumps({
                                "lat": lat,
                                "long": lon,
                                "alt": alt
                            }))
                    if word6 == "/local":
                        x = msg['msg']['twist']['linear']['x']
                        y = msg['msg']['twist']['linear']['y']
                        z = msg['msg']['twist']['linear']['z']
                        yaw = msg['msg']['twist']['angular']['z']
                        # print x,y,z, "local"
                        self.redis.set(
                            self.vehicle_id + '_lpos',
                            json.dumps({
                                "x": x,
                                "y": y,
                                "z": z,
                                "yaw": yaw
                            }))
                    if word6 == "attery":
                        percent = msg['msg']['percentage']
                        # print percent*100, " % battery"
                        self.redis.set(self.vehicle_id + '_batt',
                                       json.dumps({"percent": percent}))
                    if word6 == "_euler":
                        yaw = msg['msg']['twist']['linear']['z']
                        # print percent*100, " % battery"
                        self.redis.set(self.vehicle_id + '_imu',
                                       json.dumps({"yaw": yaw}))
import operator
from tornado import gen
from toredis import Client as RedisClient
from tornado.web import Application, RequestHandler, asynchronous
import sys
from tornado import ioloop
import json
import time
import requests

from helper import WebSocketClient, dist_bet_coordinates, DroneRemoteAccess
from session import SessionHandler

### Initialize redis client
redis_main = RedisClient()
redis_main.connect('localhost')

### set parameters
drone_status_update_rate = 4000  # data will be updated every T mili seconds.
sub_topics = ["gpos", "lpos", 'imu', "battery"]  # topics to be subscribed


def init_redis_structures(drone_list):
    """ update initial structures on redis server
    """
    counter = 0
    drone_dict = {}
    for drone in drone_list:
        counter += 1
        name = "SFRD00" + str(counter)
Example #17
0
class ChatSocketHandler(UserMixin, tornado.websocket.WebSocketHandler):
    cache_size = 30
    commands_client = Client()
    pub_client = Client()

    def open(self):
        # FIXME: make chat_channel dynamic
        self.chat_channel = "chat"

        self.chat_userset = chat_userset_key(self.chat_channel)
        self.from_user = self.get_current_user()['name']

        host, port = options.redis.split(":")
        self.sub_client = Client()
        self.sub_client.connect(host, int(port))
        logging.debug("Opened subscribe connection to redis for user=%s", self.from_user)

        # first add entered user in user_set, then subscribe to notifications
        def sadd_finished(resp):
            self.sub_client.subscribe(self.chat_channel, callback=self.on_redis_message)
        self.sub_client.sadd(self.chat_userset, self.from_user, callback=sadd_finished)

        logging.info("%s joined the chat", self.from_user)
        ChatSocketHandler.send_message(self.chat_channel, self.from_user, "joined the chat", system=True)

    def on_redis_message(self, msg):
        msg_type, msg_channel, msg = msg
        logging.debug("Got message from Redis: type=%s, channel=%s, msg=%s", msg_type, msg_channel, msg)
        if msg_type == b"message":
            # write message back to websocket
            self.write_message(json.loads(msg.decode()))

    def on_close(self):
        logging.info("%s left the chat", self.from_user)

        self.sub_client.srem(self.chat_userset, self.from_user)
        ChatSocketHandler.send_message(self.chat_channel, self.from_user, "left the chat", system=True)

    def on_message(self, message):
        logging.info("got message %r", message)
        ChatSocketHandler.send_message(self.chat_channel, self.from_user, message)

    @classmethod
    def update_lastmessages(cls, chat_channel, chat):
        cls.pub_client.lpush(chat_lastmessages_key(chat_channel), json.dumps(chat))
        cls.pub_client.ltrim(chat_lastmessages_key(chat_channel), 0, cls.cache_size)

    @classmethod
    def last_messages(cls, chat_channel, callback):
        """get last messages"""
        if not cls.commands_client.is_connected():
            host, port = options.redis.split(":")
            cls.commands_client.connect(host, int(port))
            logging.debug("Opened commands connection to redis")

        def transform(response):
            json_resp = [json.loads(x.decode("utf8")) for x in response]
            callback(json_resp[::-1])

        cls.commands_client.lrange(chat_lastmessages_key(chat_channel), 0, cls.cache_size, callback=transform)

    @classmethod
    def current_users(cls, chat_channel, callback):
        """get last messages"""
        if not cls.commands_client.is_connected():
            host, port = options.redis.split(":")
            cls.commands_client.connect(host, int(port))
            logging.debug("Opened commands connection to redis")

        def transform(response):
            json_resp = [x.decode("utf8") for x in response]
            callback(json_resp)

        cls.commands_client.smembers(chat_userset_key(chat_channel), callback=transform)

    @classmethod
    def send_message(cls, chat_channel, from_user, body, system=False):
        if not cls.pub_client.is_connected():
            host, port = options.redis.split(":")
            cls.pub_client.connect(host, int(port))
            logging.debug("Opened publish connection to redis")

        if not system:
            body = message_beautify(body)

        chat_msg = {
            "id": str(uuid.uuid4()),
            "from": from_user,
            "when": datetime.now().strftime("%Y-%m-%d %H:%M"),
            "body": body,
            "system": system,
            }

        cls.update_lastmessages(chat_channel, chat_msg)
        logging.debug("Broadcasting message %s", chat_msg)
        cls.pub_client.publish(chat_channel, json.dumps(chat_msg))
Example #18
0
    redis.get('test_key', callback=after_get)


@gen.engine
def test_gen():
    """
        ``gen.engine`` example
    """
    # Set test_key2 with 10
    result = yield gen.Task(redis.set, 'test_key2', 10)
    assert result == 'OK'

    # Increment test_key2.
    result = yield gen.Task(redis.incr, 'test_key2')
    assert result == 11

    # Get test_key2 value. Redis will return string instead of number.
    result = yield gen.Task(redis.get, 'test_key2')
    assert result == '11'

    finish()


if __name__ == "__main__":
    logging.basicConfig()

    redis = Client()
    redis.connect('localhost', callback=test_set)
    tornado.ioloop.IOLoop.instance().start()
Example #19
0
class ChatSocketHandler(UserMixin, tornado.websocket.WebSocketHandler):
    cache_size = 30
    commands_client = Client()
    pub_client = Client()

    def open(self):
        # FIXME: make chat_channel dynamic
        self.chat_channel = "chat"

        self.chat_userset = chat_userset_key(self.chat_channel)
        self.from_user = self.get_current_user()['name']

        host, port = options.redis.split(":")
        self.sub_client = Client()
        self.sub_client.connect(host, int(port))
        logging.debug("Opened subscribe connection to redis for user=%s",
                      self.from_user)

        # first add entered user in user_set, then subscribe to notifications
        def sadd_finished(resp):
            self.sub_client.subscribe(self.chat_channel,
                                      callback=self.on_redis_message)

        self.sub_client.sadd(self.chat_userset,
                             self.from_user,
                             callback=sadd_finished)

        logging.info("%s joined the chat", self.from_user)
        ChatSocketHandler.send_message(self.chat_channel,
                                       self.from_user,
                                       "joined the chat",
                                       system=True)

    def on_redis_message(self, msg):
        msg_type, msg_channel, msg = msg
        logging.debug("Got message from Redis: type=%s, channel=%s, msg=%s",
                      msg_type, msg_channel, msg)
        if msg_type == b"message":
            # write message back to websocket
            self.write_message(json.loads(msg.decode()))

    def on_close(self):
        logging.info("%s left the chat", self.from_user)

        self.sub_client.srem(self.chat_userset, self.from_user)
        ChatSocketHandler.send_message(self.chat_channel,
                                       self.from_user,
                                       "left the chat",
                                       system=True)

    def on_message(self, message):
        logging.info("got message %r", message)
        ChatSocketHandler.send_message(self.chat_channel, self.from_user,
                                       message)

    @classmethod
    def update_lastmessages(cls, chat_channel, chat):
        cls.pub_client.lpush(chat_lastmessages_key(chat_channel),
                             json.dumps(chat))
        cls.pub_client.ltrim(chat_lastmessages_key(chat_channel), 0,
                             cls.cache_size)

    @classmethod
    def last_messages(cls, chat_channel, callback):
        """get last messages"""
        if not cls.commands_client.is_connected():
            host, port = options.redis.split(":")
            cls.commands_client.connect(host, int(port))
            logging.debug("Opened commands connection to redis")

        def transform(response):
            json_resp = [json.loads(x.decode("utf8")) for x in response]
            callback(json_resp[::-1])

        cls.commands_client.lrange(chat_lastmessages_key(chat_channel),
                                   0,
                                   cls.cache_size,
                                   callback=transform)

    @classmethod
    def current_users(cls, chat_channel, callback):
        """get last messages"""
        if not cls.commands_client.is_connected():
            host, port = options.redis.split(":")
            cls.commands_client.connect(host, int(port))
            logging.debug("Opened commands connection to redis")

        def transform(response):
            json_resp = [x.decode("utf8") for x in response]
            callback(json_resp)

        cls.commands_client.smembers(chat_userset_key(chat_channel),
                                     callback=transform)

    @classmethod
    def send_message(cls, chat_channel, from_user, body, system=False):
        if not cls.pub_client.is_connected():
            host, port = options.redis.split(":")
            cls.pub_client.connect(host, int(port))
            logging.debug("Opened publish connection to redis")

        if not system:
            body = message_beautify(body)

        chat_msg = {
            "id": str(uuid.uuid4()),
            "from": from_user,
            "when": datetime.now().strftime("%Y-%m-%d %H:%M"),
            "body": body,
            "system": system,
        }

        cls.update_lastmessages(chat_channel, chat_msg)
        logging.debug("Broadcasting message %s", chat_msg)
        cls.pub_client.publish(chat_channel, json.dumps(chat_msg))
Example #20
0
# -*- coding: utf-8 -*-

from tornado import httpclient
from toredis import Client

redis_client = Client()
redis_client.connect('localhost')

http_client = httpclient.AsyncHTTPClient()