예제 #1
0
def lambda_handler(event, context):
    news = get_news()
    if len(news) > 0:
        news = news[0]
        room_id = '45'
        room_type = 'room'

        chat_message = {
            "id": str(uuid.uuid4()),
            "roomId": room_id,
            "roomType": room_type,
            "user": {
                'id': 3,
                'name': "news",
                'about': "新闻推送",
                'avatarSrc': "https://dnsofx4sf31ab.cloudfront.net/3.jpg"
            },
            "content": {
                "type": "url",
                "dataSrc": get_content(news['url']),
                "htmlContent": '<h1>please update your extension</h1>',
                "url": news['constructed_url'],
                "title": news['title']
            }
        }

        save_msg(chat_message, room_id)

        room = get_room(room_id)
        if room:
            payload = {"name": "chat message", "data": chat_message}
            send_msg_to_room('https://chat-v6.yiyechat.com/prod', payload,
                             room['id'])
예제 #2
0
def lambda_handler(event, context):
    user_id = event.get("queryStringParameters", {}).get('userId')
    params = {}
    if user_id:
        params['userId'] = user_id

    resp = requests.get(f"{API_URL}/api/v1/rooms", params=params)
    if resp.ok:

        rooms = resp.json()

        for room in rooms:
            realtime_room_data = get_room(room['id'])
            if realtime_room_data:
                room['userCount'] = len(realtime_room_data['users'])
            else:
                room['userCount'] = 0

        return {
            'statusCode': 200,
            'body': json.dumps(rooms),
            'headers': {
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Headers': 'token'
            },
        }
예제 #3
0
def lambda_handler(event, context):

    connection_id = event["requestContext"].get("connectionId")
    data = json.loads(event['body'])['data']

    # This is only called by chatbox not injection script
    # And chatbox always getChatHistory
    get_chat_history = data.get('getChatHistory')
    rooms = data.get('rooms', [])
    res = {}
    if len(rooms) == 0:
        # If client doesn't specify which room
        # return room info of all rooms this connection is in
        connection = get_connection(connection_id)
        if connection:
            rooms = connection['rooms']

    for room_id in rooms:

        room = get_room(room_id) or {}
        if get_chat_history:
            room['chatHistory'] = get_room_messages(room_id)
            if room.get('users'):
                # client shouldn't see other user's connections
                for u in room["users"]:
                    del u['connections']
        res[room_id] = room

    payload = {"name": "room info", "data": res, "query": data}
    return {'statusCode': 200, 'body': json.dumps(payload)}
예제 #4
0
def handle(connection, data):
    """
    Client tell room id,
    broadcast to that room
    """
    user = connection.user
    message_id = data['id']
    room_id = data['roomId']
    room = get_room(room_id)

    if room:
        # Check user is in room or not, might be kicked or blacklisted
        user_ids_in_room = [u['id'] for u in room['users']]
        if user['id'] not in user_ids_in_room:
            return {
                'error': 'user_not_in_room',
                'roomId': room_id
            }

         # TODO: sanitize input!!!!!!
        content = get_content(data['content'])

        sender = get_sender_basic_info(user)

        # sometimes sender's connection isn't in the room
        # add it to room first? Better to fix the source of bug then patching here..

        chat_message = {
            "id": message_id,
            # "roomId": room_id,
            "user": sender,
            "content": content,
            'created_at': datetime.datetime.utcnow().isoformat()

        }
        payload = {
            "name": "chat_message",
            "roomId": room_id,
            "data": chat_message,
            "connectionId": connection.id
        }

        logger.info(f"[{room_id}] {sender['name']}: {content['value']}")

        # exclude sender's connectionId id so they don't receive twice
        redis_client.publish('sp', json.dumps(payload))

        save_msg(chat_message, room_id)
        return payload

    return {
        'error': 'no room'
    }
예제 #5
0
def handle(connection, data):
    """
    Check permission
    Check if target user is in room
    Remove target user
    Retrun if kick is successful
    Broadcast user is gone/kicked
    """

    room_id = data['roomId']
    userId = data['userId']
    check_permission(ACTION_NAME, connection.token, room_id)

    room = get_room(room_id)

    res = {
        "name": ACTION_NAME,
        "roomId": room_id,
    }

    if room:
        users_in_room = room['users']
        user_in_room = [u for u in room['users'] if u['id'] == userId]
        if len(user_in_room) > 0:
            users_in_room[:] = [u for u in room['users'] if u['id'] != userId]
            upsert_room(room)
            target_user = user_in_room[0]
            # broadcast user kicked
            user_kicked_msg_payload = {
                'name': 'user_kicked',
                "roomId": room_id,
                'user': target_user
            }
            redis_client.publish('sp', json.dumps(user_kicked_msg_payload))

            # tell user himself he's kicked
            self_kicked_msg_payload = {
                "name": "self_kicked",
                "roomId": room_id,
                "connectionIds": [c['id'] for c in target_user['connections']]
            }
            redis_client.publish('sp', json.dumps(self_kicked_msg_payload))

            res['success']: True
        else:
            res['error'] = 'user_not_in_room'
    else:
        res['error'] = 'room_not_exist'

    return res
예제 #6
0
def join_room(connection, user, room_id):

    # check if room already exists
    # check if connection already joined this room
    # TODO: check if user is allowed to join this room
    # need to check room data from db

    room = get_room(room_id)

    if room:

        existing_users_in_room = room['users']
        existing_user = [
            u for u in existing_users_in_room if u['id'] == user['id']
        ]
        if len(existing_user) > 0:
            existing_user = existing_user[0]
        else:
            existing_user = None

        if existing_user:
            user_connections = existing_user['connections']
            existing_connection = [
                c for c in user_connections if c['id'] == connection.id
            ]
            if len(existing_connection) > 0:
                # return directly if connection already in
                # TODO: should tell client about this
                return room
            user_connections.append(build_room_connection(connection.id))
            if len(user_connections) > MAX_USER_CONNECTION:
                logger.info(
                    f"[{room_id}] {user['id']}'s connection has reached limit")
                user_connections[:] = user_connections[-MAX_USER_CONNECTION:]
                # TODO: tell the connection client it's removed due to max connection limit
                # so UI would show disconnected
        else:
            new_user = build_room_user_from_user_data(user, connection.id)

            broadcast_new_join(connection.id, room_id, new_user)
            # broadcast to users already in the room
            # then join the new user
            room['users'].append(new_user)

        upsert_room(room)
    else:
        new_user = build_room_user_from_user_data(user, connection.id)
        room = {'id': room_id, 'users': [new_user]}
        upsert_room(room)
    return room
예제 #7
0
def handle(connection, data):
    """
    Heartbeat is used to let server know this connection is alive
    and still connected to the room

    Meanwhile, it tells client that the connection is fine, if server
    doesn't see this connection in the room, this handler should not
    try to join user. Let client handle it. Maybe client is kicked out
    on purpose.

    TODO: may need non-room heartbeat too
    """

    room_id = data['roomId']
    room = get_room(room_id)
    user = connection.user
    # user object is already attached to the connection object
    # when joining the room

    res = {"name": "heartbeat", "success": False, "roomId": room_id}
    if room:
        user_in_room = [u for u in room['users'] if u['id'] == user['id']]
        if len(user_in_room) > 0:
            user_in_room = user_in_room[0]
            connection_in_room = [
                c for c in user_in_room['connections']
                if c['id'] == connection.id
            ]

            if len(connection_in_room) > 0:
                connection_in_room = connection_in_room[0]
                connection_in_room['heartbeat'] = time.time()
                res['success'] = True
                upsert_room(room)
            else:
                res['error'] = 'user is in room but connection not found'
        else:
            res['error'] = 'user is not in room'
    else:
        res['error'] = 'room not exist!'

    return res
예제 #8
0
def join_room(connection, user, room_id):

    # check if room already exists
    # check if connection already joined this room
    room = get_room(room_id)

    if room:

        existing_users_in_room = room['users']
        existing_user = [
            u for u in existing_users_in_room if u['id'] == user['id']
        ]
        if len(existing_user) > 0:
            existing_user = existing_user[0]
        else:
            existing_user = None

        if existing_user:
            user_connections = existing_user['connections']
            if connection.id in user_connections:
                # return directly if connection already in
                return room
            user_connections.append(connection.id)
            existing_user['connections'] = user_connections[
                -MAX_USER_CONNECTION:]
            # TODO: tell the connection client it's removed
            # so UI would show disconnected
        else:
            new_user = build_room_user_from_user_data(user, connection.id)
            # shouldn't need to call this, subscribe instead
            broadcast_new_join(room, new_user)
            # broadcast to users already in the room
            # then join the new user
            room['users'].append(new_user)

        upsert_room(room)
    else:
        new_user = build_room_user_from_user_data(user, connection.id)
        room = {'id': room_id, 'users': [new_user]}
        upsert_room(room)
    return room
예제 #9
0
def lambda_handler(event, context):
    """
    Client tell room id,
    broadcast to the room
    """
    connection_id = event["requestContext"].get("connectionId")
    data = json.loads(event['body'])['data']
    message_id = data['id']
    room_id = data['roomId']
    content = get_content(data['content'])
    # TODO: sanitize input!!!!!!

    room = get_room(room_id)
    # get sender from token
    sender = get_sender_basic_info(get_user(data.get('token')))
    if sender and room:

        # sometimes sender's connection isn't in the room
        # add it to room first? Better to fix the source of bug then patching here..

        room_type = room['type']
        chat_message = {
            "id": message_id,
            "roomId": room_id,
            "roomType": room_type,
            "user": sender,
            "content": content
        }
        payload = {"name": "chat message", "data": chat_message}
        endpoint_url = 'https://' + \
            event["requestContext"]["domainName"] + \
            '/'+event["requestContext"]["stage"]
        send_msg_to_room(endpoint_url,
                         payload,
                         room_id,
                         exclude_connection=connection_id)
        save_msg(chat_message, room_id)

        return {'statusCode': 200, 'body': json.dumps(payload)}
    return {'statusCode': 400, 'body': json.dumps('room not exist!')}
예제 #10
0
def handle(connection, data):
    """
    Client tell room id,
    broadcast to that room
    """

    message_id = data['id']
    room_id = data['roomId']
    content = get_content(data['content'])
    # TODO: sanitize input!!!!!!

    room = get_room(room_id)
    # get sender from token
    sender = get_sender_basic_info(get_user(data.get('token')))
    if sender and room:

        # sometimes sender's connection isn't in the room
        # add it to room first? Better to fix the source of bug then patching here..

        chat_message = {
            "id": message_id,
            "roomId": room_id,
            "user": sender,
            "content": content,
            'created_at': datetime.datetime.utcnow().isoformat()
        }
        payload = {"name": "chat message", "data": chat_message}

        logger.info(f"[{room['id']}] {sender['name']}: {content['value']}")

        # Shouldn't need this, when room message is updated, it should
        # trigger event automatically
        send_msg_to_room(payload, room_id, exclude_connection=connection.id)
        save_msg(chat_message, room_id)
        return payload

    return {'error': 'no room'}
예제 #11
0
def message_handler(data):
    try:
        payload = json.loads(data['data'])
        room_id = payload.get('roomId')
        exclude_connection_id = payload.get('connectionId')
        connection_ids = payload.get('connectionIds')
        # Either send to all users in a room or send to specific user
        # if connectionIds is in payload, send to specific connections
        # rather than whole room
        if connection_ids:
            for connection_id in connection_ids:
                send_msg_to_connection(connection_id, payload, room_id)
        else:
            room = get_room(room_id)
            users = room['users']
            for user in users:
                # dead_connections = []
                for connection in user['connections']:
                    connection_id = connection['id']
                    if exclude_connection_id == connection_id:
                        continue
                    send_msg_to_connection(connection_id, payload, room_id)
    except Exception as e:
        logger.exception('exception in redis subscriber')