diff --git a/bin/lib/chats_viewer.py b/bin/lib/chats_viewer.py index 34e1468b..f937eb74 100755 --- a/bin/lib/chats_viewer.py +++ b/bin/lib/chats_viewer.py @@ -786,7 +786,7 @@ def api_get_chats_selector(): selector.append({'id': chat.get_global_id(), 'name': f'{chat.get_chat_instance()}: {chat.get_label()}'}) return selector -def api_get_chat(chat_id, chat_instance_uuid, translation_target=None, nb=-1, page=-1, messages=True, heatmap=False): +def api_get_chat(chat_id, chat_instance_uuid, translation_target=None, nb=-1, page=-1, messages=True, message=None, heatmap=False): chat = Chats.Chat(chat_id, chat_instance_uuid) if not chat.exists(): return {"status": "error", "reason": "Unknown chat"}, 404 @@ -800,7 +800,7 @@ def api_get_chat(chat_id, chat_instance_uuid, translation_target=None, nb=-1, pa if translation_target not in Language.get_translation_languages(): translation_target = None if messages: - meta['messages'], meta['pagination'], meta['tags_messages'] = chat.get_messages(translation_target=translation_target, nb=nb, page=page) + meta['messages'], meta['pagination'], meta['tags_messages'] = chat.get_messages(translation_target=translation_target, message=message, nb=nb, page=page) meta['messages'] = get_chat_object_messages_meta(meta['messages']) if heatmap: meta['years'] = chat.get_message_years() @@ -849,7 +849,7 @@ def api_get_chat_participants(chat_type, chat_subtype, chat_id): meta['participants'] = chat_participants return meta, 200 -def api_get_subchannel(chat_id, chat_instance_uuid, translation_target=None, nb=-1, page=-1): +def api_get_subchannel(chat_id, chat_instance_uuid, translation_target=None, message=None, nb=-1, page=-1): subchannel = ChatSubChannels.ChatSubChannel(chat_id, chat_instance_uuid) if not subchannel.exists(): return {"status": "error", "reason": "Unknown subchannel"}, 404 @@ -861,11 +861,11 @@ def api_get_subchannel(chat_id, chat_instance_uuid, translation_target=None, nb= meta['threads'] = get_threads_metas(meta['threads']) if meta.get('username'): meta['username'] = get_username_meta_from_global_id(meta['username']) - meta['messages'], meta['pagination'], meta['tags_messages'] = subchannel.get_messages(translation_target=translation_target, nb=nb, page=page) + meta['messages'], meta['pagination'], meta['tags_messages'] = subchannel.get_messages(translation_target=translation_target, message=message, nb=nb, page=page) meta['messages'] = get_chat_object_messages_meta(meta['messages']) return meta, 200 -def api_get_thread(thread_id, thread_instance_uuid, translation_target=None, nb=-1, page=-1): +def api_get_thread(thread_id, thread_instance_uuid, translation_target=None, message=None, nb=-1, page=-1): thread = ChatThreads.ChatThread(thread_id, thread_instance_uuid) if not thread.exists(): return {"status": "error", "reason": "Unknown thread"}, 404 @@ -873,7 +873,7 @@ def api_get_thread(thread_id, thread_instance_uuid, translation_target=None, nb= meta = thread.get_meta({'chat', 'nb_messages', 'nb_participants'}) # if meta['chat']: # meta['chat'] = get_chat_meta_from_global_id(meta['chat']) - meta['messages'], meta['pagination'], meta['tags_messages'] = thread.get_messages(translation_target=translation_target, nb=nb, page=page) + meta['messages'], meta['pagination'], meta['tags_messages'] = thread.get_messages(translation_target=translation_target, message=message, nb=nb, page=page) meta['messages'] = get_chat_object_messages_meta(meta['messages']) return meta, 200 @@ -881,7 +881,7 @@ def api_get_message(message_id, translation_target=None): message = Messages.Message(message_id) if not message.exists(): return {"status": "error", "reason": "Unknown uuid"}, 404 - meta = message.get_meta({'barcodes', 'chat', 'content', 'files-names', 'forwarded_from', 'icon', 'images', 'language', 'link', 'parent', 'parent_meta', 'qrcodes', 'reactions', 'thread', 'translation', 'user-account'}, translation_target=translation_target) + meta = message.get_meta({'barcodes', 'chat', 'container', 'content', 'files-names', 'forwarded_from', 'icon', 'images', 'language', 'link', 'parent', 'parent_meta', 'qrcodes', 'reactions', 'thread', 'translation', 'user-account'}, translation_target=translation_target) if 'forwarded_from' in meta: chat = get_obj_chat_from_global_id(meta['forwarded_from']) meta['forwarded_from'] = chat.get_meta({'icon'}) diff --git a/bin/lib/objects/ChatSubChannels.py b/bin/lib/objects/ChatSubChannels.py index 54952471..3c92579d 100755 --- a/bin/lib/objects/ChatSubChannels.py +++ b/bin/lib/objects/ChatSubChannels.py @@ -55,9 +55,9 @@ class ChatSubChannel(AbstractChatObject): def get_link(self, flask_context=False): if flask_context: - url = url_for('correlation.show_correlation', type=self.type, subtype=self.subtype, id=self.id) + url = url_for('chats_explorer.objects_subchannel_messages', subtype=self.subtype, id=self.id) else: - url = f'{baseurl}/correlation/show?type={self.type}&subtype={self.subtype}&id={self.id}' + url = f'{baseurl}/chats/explorer/subchannel?subtype={self.subtype}&id={self.id}' return url def get_svg_icon(self): # TODO diff --git a/bin/lib/objects/ChatThreads.py b/bin/lib/objects/ChatThreads.py index bb7eddd7..4b623470 100755 --- a/bin/lib/objects/ChatThreads.py +++ b/bin/lib/objects/ChatThreads.py @@ -49,9 +49,9 @@ class ChatThread(AbstractChatObject): def get_link(self, flask_context=False): if flask_context: - url = url_for('correlation.show_correlation', type=self.type, subtype=self.subtype, id=self.id) + url = url_for('chats_explorer.objects_thread_messages', subtype=self.subtype, id=self.id) else: - url = f'{baseurl}/correlation/show?type={self.type}&subtype={self.subtype}&id={self.id}' + url = f'{baseurl}/chats/explorer/thread?subtype={self.subtype}&id={self.id}' return url def get_svg_icon(self): # TODO diff --git a/bin/lib/objects/Chats.py b/bin/lib/objects/Chats.py index 3a9407ba..e7e2f864 100755 --- a/bin/lib/objects/Chats.py +++ b/bin/lib/objects/Chats.py @@ -50,7 +50,7 @@ class Chat(AbstractChatObject): if flask_context: url = url_for('chats_explorer.chats_explorer_chat', subtype=self.subtype, id=self.id) else: - url = f'{baseurl}/correlation/show?type={self.type}&subtype={self.subtype}&id={self.id}' + url = f'{baseurl}/chats/explorer/chat?subtype={self.subtype}&id={self.id}' return url def get_origin_link(self): diff --git a/bin/lib/objects/Messages.py b/bin/lib/objects/Messages.py index abecd594..9c007061 100755 --- a/bin/lib/objects/Messages.py +++ b/bin/lib/objects/Messages.py @@ -265,6 +265,8 @@ class Message(AbstractObject): if options is None: options = set() meta = self.get_default_meta(tags=True) + # original_id + meta['_id'] = self.id.rsplit('/', 1)[-1] # timestamp if not timestamp: @@ -304,6 +306,8 @@ class Message(AbstractObject): meta['user-account'] = self.get_user_account(meta=True) if not meta['user-account']: meta['user-account'] = {'id': 'UNKNOWN'} + if 'container' in options: + meta['container'] = self.get_container() if 'chat' in options: meta['chat'] = self.get_chat_id() if 'thread' in options: @@ -345,7 +349,16 @@ class Message(AbstractObject): ## Language ## def get_root_obj(self): - return self.get_objs_container(root=True) + return self.get_objs_container(root=True).pop() + + def get_container(self): + thread = self.get_current_thread() + if thread: + return thread + subchannel = self.get_subchannel() + if subchannel: + return subchannel + return self.get_chat() def get_objs_container(self, root=False): objs_containers = set() diff --git a/bin/lib/objects/abstract_chat_object.py b/bin/lib/objects/abstract_chat_object.py index cf7f88fa..f1949b5c 100755 --- a/bin/lib/objects/abstract_chat_object.py +++ b/bin/lib/objects/abstract_chat_object.py @@ -128,6 +128,12 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): def get_nb_messages(self): return r_object.zcard(f'messages:{self.type}:{self.subtype}:{self.id}') + def get_message_page(self, message, nb): + rank = r_object.zrank(f'messages:{self.type}:{self.subtype}:{self.id}', f'message::{message}') + if not rank: + return -1 + return int(rank/ nb) + 1 + def _get_messages(self, nb=-1, page=-1): if nb < 1: messages = r_object.zrange(f'messages:{self.type}:{self.subtype}:{self.id}', 0, -1, withscores=True) @@ -273,7 +279,7 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): meta = message.get_meta(options=options, timestamp=timestamp, translation_target=translation_target) return meta - def get_messages(self, start=0, page=-1, nb=500, unread=False, options=None, translation_target='en'): # threads ???? # TODO ADD last/first message timestamp + return page + def get_messages(self, start=0, page=-1, nb=500, message=None, unread=False, options=None, translation_target='en'): # threads ???? # TODO ADD last/first message timestamp + return page # TODO return message meta tags = {} messages = {} @@ -282,12 +288,15 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): nb = int(nb) except TypeError: nb = 500 - if not page: - page = -1 - try: - page = int(page) - except TypeError: - page = 1 + if message: + page = self.get_message_page(message, nb) + else: + if not page: + page = -1 + try: + page = int(page) + except TypeError: + page = 1 mess, pagination = self._get_messages(nb=nb, page=page) for message in mess: timestamp = message[1] diff --git a/var/www/blueprints/chats_explorer.py b/var/www/blueprints/chats_explorer.py index eaae835e..229d45c3 100644 --- a/var/www/blueprints/chats_explorer.py +++ b/var/www/blueprints/chats_explorer.py @@ -24,6 +24,7 @@ from lib import chats_viewer from lib import Language from lib import Tag from lib import module_extractor +from lib.objects import ail_objects # ============ BLUEPRINT ============ chats_explorer = Blueprint('chats_explorer', __name__, template_folder=os.path.join(os.environ['AIL_FLASK'], 'templates/chats_explorer')) @@ -93,8 +94,16 @@ def chats_explorer_chat(): if target == "Don't Translate": target = None nb_messages = request.args.get('nb') - page = request.args.get('page') - chat = chats_viewer.api_get_chat(chat_id, instance_uuid, translation_target=target, nb=nb_messages, page=page, heatmap=True) + mess = request.args.get('message') + if mess: + message = mess + page = -1 + message_id = message.rsplit('/', 1)[-1] + else: + message = None + message_id = None + page = request.args.get('page') + chat = chats_viewer.api_get_chat(chat_id, instance_uuid, translation_target=target, message=message, nb=nb_messages, page=page, heatmap=True) if chat[1] != 200: return create_json_response(chat[0], chat[1]) else: @@ -102,6 +111,7 @@ def chats_explorer_chat(): languages = Language.get_translation_languages() return render_template('chat_viewer.html', chat=chat, bootstrap_label=bootstrap_label, ail_tags=Tag.get_modal_add_tags(chat['id'], chat['type'], chat['subtype']), + message_id=message_id, translation_languages=languages, translation_target=target) @chats_explorer.route("chats/explorer/messages/stats/week", methods=['GET']) @@ -154,8 +164,16 @@ def objects_subchannel_messages(): if target == "Don't Translate": target = None nb_messages = request.args.get('nb') - page = request.args.get('page') - subchannel = chats_viewer.api_get_subchannel(subchannel_id, instance_uuid, translation_target=target, nb=nb_messages, page=page) + mess = request.args.get('message') + if mess: + message = mess + page = -1 + message_id = message.rsplit('/', 1)[-1] + else: + message = None + message_id = None + page = request.args.get('page') + subchannel = chats_viewer.api_get_subchannel(subchannel_id, instance_uuid, translation_target=target, message=message, nb=nb_messages, page=page) if subchannel[1] != 200: return create_json_response(subchannel[0], subchannel[1]) else: @@ -163,6 +181,7 @@ def objects_subchannel_messages(): languages = Language.get_translation_languages() return render_template('SubChannelMessages.html', subchannel=subchannel, ail_tags=Tag.get_modal_add_tags(subchannel['id'], subchannel['type'], subchannel['subtype']), + message_id=message_id, bootstrap_label=bootstrap_label, translation_languages=languages, translation_target=target) @chats_explorer.route("/chats/explorer/thread", methods=['GET']) @@ -175,14 +194,24 @@ def objects_thread_messages(): if target == "Don't Translate": target = None nb_messages = request.args.get('nb') - page = request.args.get('page') - thread = chats_viewer.api_get_thread(thread_id, instance_uuid, translation_target=target, nb=nb_messages, page=page) + mess = request.args.get('message') + if mess: + message = mess + page = -1 + message_id = message.rsplit('/', 1)[-1] + else: + message = None + message_id = None + page = request.args.get('page') + thread = chats_viewer.api_get_thread(thread_id, instance_uuid, translation_target=target, message=message, nb=nb_messages, page=page) if thread[1] != 200: return create_json_response(thread[0], thread[1]) else: meta = thread[0] languages = Language.get_translation_languages() - return render_template('ThreadMessages.html', meta=meta, bootstrap_label=bootstrap_label, translation_languages=languages, translation_target=target) + return render_template('ThreadMessages.html', meta=meta, bootstrap_label=bootstrap_label, + message_id=message_id, + translation_languages=languages, translation_target=target) @chats_explorer.route("/chats/explorer/participants", methods=['GET']) @login_required @@ -286,12 +315,13 @@ def objects_message(): else: message = message[0] languages = Language.get_translation_languages() + container_url = ail_objects.get_obj_from_global_id(message['container']).get_link(flask_context=True) extracted = module_extractor.extract(current_user.get_user_id(), 'message', '', message['id'], content=message['content']) extracted_matches = module_extractor.get_extracted_by_match(extracted) message['extracted'] = extracted message['extracted_matches'] = extracted_matches return render_template('ChatMessage.html', meta=message, bootstrap_label=bootstrap_label, - translation_languages=languages, translation_target=target, + translation_languages=languages, translation_target=target, container_url=container_url, modal_add_tags=Tag.get_modal_add_tags(message['id'], object_type='message')) @chats_explorer.route("/objects/message/translate", methods=['POST']) diff --git a/var/www/templates/chats_explorer/SubChannelMessages.html b/var/www/templates/chats_explorer/SubChannelMessages.html index e4c36d6a..4c0225f8 100644 --- a/var/www/templates/chats_explorer/SubChannelMessages.html +++ b/var/www/templates/chats_explorer/SubChannelMessages.html @@ -179,6 +179,9 @@ "order": [[ 3, "desc" ]] }); {% endif %} + {% if message_id %} + document.location.hash = '#{{ message_id }}'; + {% endif %} }); function toggle_sidebar(){ diff --git a/var/www/templates/chats_explorer/ThreadMessages.html b/var/www/templates/chats_explorer/ThreadMessages.html index 70995962..2982038d 100644 --- a/var/www/templates/chats_explorer/ThreadMessages.html +++ b/var/www/templates/chats_explorer/ThreadMessages.html @@ -196,7 +196,9 @@ $(document).ready(function(){ $("#page-Decoded").addClass("active"); $("#nav_chat").addClass("active"); - + {% if message_id %} + document.location.hash = '#{{ message_id }}'; + {% endif %} }); function toggle_sidebar(){ diff --git a/var/www/templates/chats_explorer/block_message.html b/var/www/templates/chats_explorer/block_message.html index 3ae742bc..5ec06d40 100644 --- a/var/www/templates/chats_explorer/block_message.html +++ b/var/www/templates/chats_explorer/block_message.html @@ -22,7 +22,7 @@ } -
diff --git a/var/www/templates/chats_explorer/chat_viewer.html b/var/www/templates/chats_explorer/chat_viewer.html index 13510095..6c993ba3 100644 --- a/var/www/templates/chats_explorer/chat_viewer.html +++ b/var/www/templates/chats_explorer/chat_viewer.html @@ -201,6 +201,9 @@ "order": [[ 5, "desc" ]] }); {% endif %} + {% if message_id %} + document.location.hash = '#{{ message_id }}'; + {% endif %} }); function toggle_sidebar(){