fix-load-messages

This commit is contained in:
tonyrewin 2022-12-05 10:10:49 +03:00
parent a034eda220
commit 058fdcc64f
2 changed files with 62 additions and 35 deletions

View File

@ -1,5 +1,5 @@
import json import json
from datetime import datetime, timedelta, timezone # from datetime import datetime, timedelta, timezone
from auth.authenticate import login_required from auth.authenticate import login_required
from auth.credentials import AuthCredentials from auth.credentials import AuthCredentials
@ -14,16 +14,25 @@ from .unread import get_unread_counter
async def load_messages(chat_id: str, limit: int, offset: int): async def load_messages(chat_id: str, limit: int, offset: int):
''' load :limit messages for :chat_id with :offset ''' ''' load :limit messages for :chat_id with :offset '''
messages = [] messages = []
message_ids = await redis.lrange( # print(f'[inbox] loading messages by chat: {chat_id}[{offset}:{offset + limit}]')
f"chats/{chat_id}/message_ids", offset + limit, offset try:
message_ids = await redis.lrange(f"chats/{chat_id}/message_ids",
offset,
offset + limit
) )
# print(f'[inbox] message_ids: {message_ids}')
except Exception as e:
print(e)
if message_ids: if message_ids:
message_keys = [ message_keys = [
f"chats/{chat_id}/messages/{mid}" for mid in message_ids f"chats/{chat_id}/messages/{mid.decode('utf-8')}" for mid in message_ids
] ]
# print(message_keys)
messages = await redis.mget(*message_keys) messages = await redis.mget(*message_keys)
messages = [json.loads(msg) for msg in messages] messages = [json.loads(msg.decode('utf-8')) for msg in messages]
return set(messages) # print('[inbox] messages \n%r' % messages)
return messages
@query.field("loadChats") @query.field("loadChats")
@ -41,7 +50,8 @@ async def load_chats(_, info, limit: int = 50, offset: int = 0):
cids = [] cids = []
chats = [] chats = []
for cid in cids: for cid in cids:
c = await redis.execute("GET", "chats/" + cid.decode("utf-8")) cid = cid.decode("utf-8")
c = await redis.execute("GET", "chats/" + cid)
if c: if c:
c = dict(json.loads(c)) c = dict(json.loads(c))
c['messages'] = await load_messages(cid, 5, 0) c['messages'] = await load_messages(cid, 5, 0)
@ -71,17 +81,21 @@ async def search_user_chats(by, messages, user_id: int, limit, offset):
by_author = by.get('author') by_author = by.get('author')
body_like = by.get('body') body_like = by.get('body')
cids.union(set(await redis.execute("SMEMBERS", "chats_by_user/" + str(user_id)))) cids.union(set(await redis.execute("SMEMBERS", "chats_by_user/" + str(user_id))))
# messages_by_chat = []
if by_author: if by_author:
# all author's messages # all author's messages
cids.union(set(await redis.execute("SMEMBERS", f"chats_by_user/{by_author}"))) cids.union(set(await redis.execute("SMEMBERS", f"chats_by_user/{by_author}")))
# author's messages in filtered chat # author's messages in filtered chat
messages.union(set(filter(lambda m: m["author"] == by_author, list(messages)))) messages.union(set(filter(lambda m: m["author"] == by_author, list(messages))))
for c in cids: for c in cids:
messages.union(set(await load_messages(c, limit, offset))) c = c.decode('utf-8')
# messages_by_chat = await load_messages(c, limit, offset)
if body_like: if body_like:
# search in all messages in all user's chats # search in all messages in all user's chats
for c in cids: for c in cids:
# FIXME: use redis scan here # FIXME: use redis scan here
c = c.decode('utf-8')
mmm = set(await load_messages(c, limit, offset)) mmm = set(await load_messages(c, limit, offset))
for m in mmm: for m in mmm:
if body_like in m["body"]: if body_like in m["body"]:
@ -96,36 +110,48 @@ async def search_user_chats(by, messages, user_id: int, limit, offset):
@login_required @login_required
async def load_messages_by(_, info, by, limit: int = 10, offset: int = 0): async def load_messages_by(_, info, by, limit: int = 10, offset: int = 0):
''' load :limit messages of :chat_id with :offset ''' ''' load :limit messages of :chat_id with :offset '''
messages = set([])
auth: AuthCredentials = info.context["request"].auth
userchats = await redis.execute("SMEMBERS", "chats_by_user/" + str(auth.user_id))
userchats = [c.decode('utf-8') for c in userchats]
# print('[inbox] userchats: %r' % userchats)
if userchats:
# print('[inbox] loading messages by...')
messages = []
by_chat = by.get('chat') by_chat = by.get('chat')
if by_chat: if by_chat in userchats:
chat = await redis.execute("GET", f"chats/{by_chat}") chat = await redis.execute("GET", f"chats/{by_chat}")
# print(chat)
if not chat: if not chat:
return { return {
"messages": [], "messages": [],
"error": "chat not exist" "error": "chat not exist"
} }
# everyone's messages in filtered chat # everyone's messages in filtered chat
messages.union(set(await load_messages(by_chat, limit, offset))) messages = await load_messages(by_chat, limit, offset)
auth: AuthCredentials = info.context["request"].auth # if len(messages) == 0:
# messages.union(set(await search_user_chats(by, messages, auth.user_id, limit, offset)))
if len(messages) == 0: # days = by.get("days")
messages.union(set(await search_user_chats(by, messages, auth.user_id, limit, offset))) # if days:
# messages.union(set(filter(
days = by.get("days") # list(messages),
if days: # key=lambda m: (
messages.union(set(filter( # datetime.now(tz=timezone.utc) - int(m["createdAt"]) < timedelta(days=by["days"])
lambda m: datetime.now(tz=timezone.utc) - int(m["createdAt"]) < timedelta(days=by.get("days")), # )
list(messages) # )))
)))
return { return {
"messages": sorted( "messages": sorted(
list(messages), list(messages),
key=lambda m: m.createdAt key=lambda m: m['createdAt']
), ),
"error": None "error": None
} }
else:
return {
"error": "Cannot access messages of this chat"
}
@query.field("loadRecipients") @query.field("loadRecipients")

View File

@ -33,6 +33,7 @@ async def create_message(_, info, chat: str, body: str, replyTo=None):
"replyTo": replyTo, "replyTo": replyTo,
"createdAt": int(datetime.now(tz=timezone.utc).timestamp()), "createdAt": int(datetime.now(tz=timezone.utc).timestamp()),
} }
print(f"[inbox] creating message {new_message}")
await redis.execute( await redis.execute(
"SET", f"chats/{chat['id']}/messages/{message_id}", json.dumps(new_message) "SET", f"chats/{chat['id']}/messages/{message_id}", json.dumps(new_message)
) )