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'])
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' }, }
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)}
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' }
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
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
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
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
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!')}
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'}
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')