import json import logging import time import uuid from models.chat import Chat, ChatUpdate from services.auth import login_required from services.presence import notify_chat from services.rediscache import redis from services.schema import mutation logger = logging.getLogger('[resolvers.chats] ') logger.setLevel(logging.DEBUG) @mutation.field('update_chat') @login_required async def update_chat(_, info, chat_new: ChatUpdate): """ updating chat requires info.context["author_id"] to be in chat["admins"] :param _: not used :param info: GraphQLInfo with request :param chat_new: dict with chat data :return: Result { error chat } """ logger.info('update_chat') author_id = info.context['author_id'] chat_id = chat_new['id'] chat_str = await redis.execute('GET', f'chats/{chat_id}') if not chat_str: return {'error': 'chat not exist'} elif isinstance(chat_str, str): chat: Chat = json.loads(chat_str) if author_id in chat['admins']: chat.update( { 'title': chat_new.get('title', chat['title']), 'description': chat_new.get('description', chat['description']), 'updated_at': int(time.time()), 'admins': chat_new.get('admins', chat.get('admins') or []), 'members': chat_new.get('members', chat['members']), } ) await redis.execute('SET', f"chats/{chat['id']}", json.dumps(chat)) for member_id in chat['members']: await notify_chat(chat, member_id, 'update') return {'error': None, 'chat': chat} @mutation.field('create_chat') @login_required async def create_chat(_, info, title='', members=None): logger.info('create_chat') members = members or [] author_id = info.context['author_id'] chat: Chat if author_id: if author_id not in members: members.append(int(author_id)) # NOTE: private chats has no title # reuse private chat created before if exists if len(members) == 2 and title == '': chatset1 = await redis.execute('SMEMBERS', f'chats_by_author/{members[0]}') chatset2 = await redis.execute('SMEMBERS', f'chats_by_author/{members[1]}') for c in chatset1.intersection(chatset2): chat = await redis.execute('GET', f'chats/{c}') if chat['title'] == '': logger.info('[inbox] createChat found old chat') return {'chat': chat, 'error': 'existed'} chat_id = str(uuid.uuid4()) chat: Chat = { 'id': chat_id, 'members': members, 'title': title, 'description': '', 'created_by': author_id, 'created_at': int(time.time()), 'updated_at': int(time.time()), 'admins': members if (len(members) == 2 and title == '') else [], } for member_id in members: await redis.execute('SADD', f'chats_by_author/{member_id}', chat_id) await notify_chat(chat, member_id, 'create') print(f'\n\n[resolvers.chats] creating: {chat}\n\n') await redis.execute('SET', f'chats/{chat_id}', json.dumps(chat)) await redis.execute('SET', f'chats/{chat_id}/next_message_id', str(0)) return {'error': None, 'chat': chat} return {'error': 'no chat was created'} @mutation.field('delete_chat') @login_required async def delete_chat(_, info, chat_id: str): logger.info('delete_chat') author_id = info.context['author_id'] chat_str = await redis.execute('GET', f'chats/{chat_id}') if isinstance(chat_str, str): chat: Chat = json.loads(chat_str) if author_id in chat['admins']: await redis.execute('DEL', f'chats/{chat_id}') await redis.execute('SREM', f'chats_by_author/{author_id}', chat_id) for member_id in chat['members']: await notify_chat(chat, member_id, 'delete') return {'error': 'chat not exist'}