From 38ce17bc8a86032ebb96570e0effdf4aa124fe0d Mon Sep 17 00:00:00 2001 From: terrtia Date: Wed, 6 Dec 2023 16:26:26 +0100 Subject: [PATCH] chg: [chats] add chats participants + user-accounts basic template --- bin/importer/feeders/abstract_chats_feeder.py | 67 +++---- bin/lib/ail_core.py | 24 ++- bin/lib/chats_viewer.py | 47 ++++- bin/lib/objects/ChatSubChannels.py | 7 +- bin/lib/objects/ChatThreads.py | 4 + bin/lib/objects/Chats.py | 8 +- bin/lib/objects/UsersAccount.py | 47 +++-- bin/lib/objects/abstract_chat_object.py | 7 +- var/www/blueprints/chats_explorer.py | 27 +++ var/www/blueprints/objects_subtypes.py | 12 +- .../chats_explorer/SubChannelMessages.html | 4 + .../chats_explorer/ThreadMessages.html | 5 + .../chats_explorer/block_message.html | 6 +- .../chats_explorer/chat_participants.html | 174 +++++++++++++++++ .../templates/chats_explorer/chat_viewer.html | 6 +- .../chats_explorer/user_account.html | 184 ++++++++++++++++++ .../templates/sidebars/sidebar_objects.html | 6 + 17 files changed, 558 insertions(+), 77 deletions(-) create mode 100644 var/www/templates/chats_explorer/chat_participants.html create mode 100644 var/www/templates/chats_explorer/user_account.html diff --git a/bin/importer/feeders/abstract_chats_feeder.py b/bin/importer/feeders/abstract_chats_feeder.py index aebf76ef..a966e951 100755 --- a/bin/importer/feeders/abstract_chats_feeder.py +++ b/bin/importer/feeders/abstract_chats_feeder.py @@ -11,7 +11,7 @@ import datetime import os import sys -from abc import abstractmethod, ABC +from abc import ABC sys.path.append(os.environ['AIL_BIN']) ################################## @@ -144,6 +144,8 @@ class AbstractChatFeeder(DefaultFeeder, ABC): def process_chat(self, new_objs, obj, date, timestamp, reply_id=None): meta = self.json_data['meta']['chat'] # todo replace me by function chat = Chat(self.get_chat_id(), self.get_chat_instance_uuid()) + subchannel = None + thread = None # date stat + correlation chat.add(date, obj) @@ -168,24 +170,26 @@ class AbstractChatFeeder(DefaultFeeder, ABC): chat.update_username_timeline(username.get_global_id(), timestamp) if meta.get('subchannel'): - subchannel = self.process_subchannel(obj, date, timestamp, reply_id=reply_id) + subchannel, thread = self.process_subchannel(obj, date, timestamp, reply_id=reply_id) chat.add_children(obj_global_id=subchannel.get_global_id()) else: if obj.type == 'message': if self.get_thread_id(): - self.process_thread(obj, chat, date, timestamp, reply_id=reply_id) + thread = self.process_thread(obj, chat, date, timestamp, reply_id=reply_id) else: chat.add_message(obj.get_global_id(), self.get_message_id(), timestamp, reply_id=reply_id) - - # if meta.get('subchannels'): # TODO Update icon + names - - return chat - + chats_obj = [chat] + if subchannel: + chats_obj.append(subchannel) + if thread: + chats_obj.append(thread) + return chats_obj def process_subchannel(self, obj, date, timestamp, reply_id=None): # TODO CREATE DATE meta = self.json_data['meta']['chat']['subchannel'] subchannel = ChatSubChannels.ChatSubChannel(f'{self.get_chat_id()}/{meta["id"]}', self.get_chat_instance_uuid()) + thread = None # TODO correlation with obj = message/image subchannel.add(date) @@ -202,10 +206,10 @@ class AbstractChatFeeder(DefaultFeeder, ABC): if obj.type == 'message': if self.get_thread_id(): - self.process_thread(obj, subchannel, date, timestamp, reply_id=reply_id) + thread = self.process_thread(obj, subchannel, date, timestamp, reply_id=reply_id) else: subchannel.add_message(obj.get_global_id(), self.get_message_id(), timestamp, reply_id=reply_id) - return subchannel + return subchannel, thread def process_thread(self, obj, obj_chat, date, timestamp, reply_id=None): meta = self.json_data['meta']['thread'] @@ -231,7 +235,6 @@ class AbstractChatFeeder(DefaultFeeder, ABC): # else: # # ADD NEW MESSAGE REF (used by discord) - def process_sender(self, new_objs, obj, date, timestamp): meta = self.json_data['meta']['sender'] user_account = UsersAccount.UserAccount(meta['id'], self.get_chat_instance_uuid()) @@ -267,12 +270,6 @@ class AbstractChatFeeder(DefaultFeeder, ABC): return user_account - # Create abstract class: -> new API endpoint ??? => force field, check if already imported ? - # 1) Create/Get MessageInstance - # TODO uuidv5 + text like discord and telegram for default - # 2) Create/Get CHAT ID - Done - # 3) Create/Get Channel IF is in channel - # 4) Create/Get Thread IF is in thread - # 5) Create/Update Username and User-account - Done def process_meta(self): # TODO CHECK MANDATORY FIELDS """ Process JSON meta filed. @@ -316,7 +313,7 @@ class AbstractChatFeeder(DefaultFeeder, ABC): message_id = self.get_message_id() message_id = Messages.create_obj_id(self.get_chat_instance_uuid(), chat_id, message_id, timestamp, channel_id=channel_id, thread_id=thread_id) message = Messages.Message(message_id) - # create empty message if message don't exists + # create empty message if message don't exist if not message.exists(): message.create('') objs.add(message) @@ -336,46 +333,26 @@ class AbstractChatFeeder(DefaultFeeder, ABC): for obj in objs: # TODO PERF avoid parsing metas multiple times + # TODO get created subchannel + thread + # => create correlation user-account with object + # CHAT - chat = self.process_chat(new_objs, obj, date, timestamp, reply_id=reply_id) + chat_objs = self.process_chat(new_objs, obj, date, timestamp, reply_id=reply_id) # SENDER # TODO HANDLE NULL SENDER user_account = self.process_sender(new_objs, obj, date, timestamp) - # UserAccount---Chat - user_account.add_correlation(chat.type, chat.get_subtype(r_str=True), chat.id) + # UserAccount---ChatObjects + for obj_chat in chat_objs: + user_account.add_correlation(obj_chat.type, obj_chat.get_subtype(r_str=True), obj_chat.id) # if chat: # TODO Chat---Username correlation ??? # # Chat---Username => need to handle members and participants # chat.add_correlation(username.type, username.get_subtype(r_str=True), username.id) - # TODO Sender image -> correlation # image # -> subchannel ? # -> thread id ? return new_objs | objs - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/lib/ail_core.py b/bin/lib/ail_core.py index 3e34e4b8..00cefd4d 100755 --- a/bin/lib/ail_core.py +++ b/bin/lib/ail_core.py @@ -40,7 +40,7 @@ def get_all_objects(): return AIL_OBJECTS def get_objects_with_subtypes(): - return ['chat', 'cryptocurrency', 'pgp', 'username'] + return ['chat', 'cryptocurrency', 'pgp', 'username', 'user-account'] def get_object_all_subtypes(obj_type): # TODO Dynamic subtype if obj_type == 'chat': @@ -53,6 +53,8 @@ def get_object_all_subtypes(obj_type): # TODO Dynamic subtype return ['key', 'mail', 'name'] if obj_type == 'username': return ['telegram', 'twitter', 'jabber'] + if obj_type == 'user-account': + return r_object.smembers(f'all_chat:subtypes') return [] def get_objects_tracked(): @@ -75,10 +77,28 @@ def get_all_objects_with_subtypes_tuple(): def unpack_obj_global_id(global_id, r_type='tuple'): if r_type == 'dict': obj = global_id.split(':', 2) - return {'type': obj[0], 'subtype': obj[1], 'id': obj['2']} + return {'type': obj[0], 'subtype': obj[1], 'id': obj[2]} else: # tuple(type, subtype, id) return global_id.split(':', 2) +def unpack_objs_global_id(objs_global_id, r_type='tuple'): + objs = [] + for global_id in objs_global_id: + objs.append(unpack_obj_global_id(global_id, r_type=r_type)) + return objs + +def unpack_correl_obj__id(obj_type, global_id, r_type='tuple'): + obj = global_id.split(':', 1) + if r_type == 'dict': + return {'type': obj_type, 'subtype': obj[0], 'id': obj[1]} + else: # tuple(type, subtype, id) + return obj_type, obj[0], obj[1] + +def unpack_correl_objs_id(obj_type, correl_objs_id, r_type='tuple'): + objs = [] + for correl_obj_id in correl_objs_id: + objs.append(unpack_correl_obj__id(obj_type, correl_obj_id, r_type=r_type)) + return objs ##-- AIL OBJECTS --## diff --git a/bin/lib/chats_viewer.py b/bin/lib/chats_viewer.py index 1d983f0a..b083537a 100755 --- a/bin/lib/chats_viewer.py +++ b/bin/lib/chats_viewer.py @@ -278,6 +278,27 @@ def create_chat_service_instance(protocol, network=None, address=None): ####################################################################################### +def get_obj_chat(chat_type, chat_subtype, chat_id): + print(chat_type, chat_subtype, chat_id) + if chat_type == 'chat': + return Chats.Chat(chat_id, chat_subtype) + elif chat_type == 'chat-subchannel': + return ChatSubChannels.ChatSubChannel(chat_id, chat_subtype) + elif chat_type == 'chat-thread': + return ChatThreads.ChatThread(chat_id, chat_subtype) + +def get_obj_chat_meta(obj_chat, new_options=set()): + options = {} + if obj_chat.type == 'chat': + options = {'created_at', 'icon', 'info', 'subchannels', 'threads', 'username'} + elif obj_chat.type == 'chat-subchannel': + options = {'chat', 'created_at', 'icon', 'nb_messages', 'threads'} + elif obj_chat.type == 'chat-thread': + options = {'chat', 'nb_messages'} + for option in new_options: + options.add(option) + return obj_chat.get_meta(options=options) + def get_subchannels_meta_from_global_id(subchannels): meta = [] for sub in subchannels: @@ -302,6 +323,8 @@ def get_username_meta_from_global_id(username_global_id): username = Usernames.Username(username_id, instance_uuid) return username.get_meta() +#### API #### + def api_get_chat_service_instance(chat_instance_uuid): chat_instance = ChatServiceInstance(chat_instance_uuid) if not chat_instance.exists(): @@ -312,7 +335,7 @@ def api_get_chat(chat_id, chat_instance_uuid, translation_target=None): chat = Chats.Chat(chat_id, chat_instance_uuid) if not chat.exists(): return {"status": "error", "reason": "Unknown chat"}, 404 - meta = chat.get_meta({'created_at', 'icon', 'info', 'subchannels', 'threads', 'username'}) + meta = chat.get_meta({'created_at', 'icon', 'info', 'nb_participants', 'subchannels', 'threads', 'username'}) if meta['username']: meta['username'] = get_username_meta_from_global_id(meta['username']) if meta['subchannels']: @@ -329,11 +352,26 @@ def api_get_nb_message_by_week(chat_id, chat_instance_uuid): # week = chat.get_nb_message_by_week('20231109') return week, 200 +def api_get_chat_participants(chat_type, chat_subtype, chat_id): + if chat_type not in ['chat', 'chat-subchannel', 'chat-thread']: + return {"status": "error", "reason": "Unknown chat type"}, 400 + chat_obj = get_obj_chat(chat_type, chat_subtype, chat_id) + if not chat_obj.exists(): + return {"status": "error", "reason": "Unknown chat"}, 404 + else: + meta = get_obj_chat_meta(chat_obj, new_options={'participants'}) + chat_participants = [] + for participant in meta['participants']: + user_account = UsersAccount.UserAccount(participant['id'], participant['subtype']) + chat_participants.append(user_account.get_meta({'icon', 'info', 'username'})) + meta['participants'] = chat_participants + return meta, 200 + def api_get_subchannel(chat_id, chat_instance_uuid, translation_target=None): subchannel = ChatSubChannels.ChatSubChannel(chat_id, chat_instance_uuid) if not subchannel.exists(): return {"status": "error", "reason": "Unknown subchannel"}, 404 - meta = subchannel.get_meta({'chat', 'created_at', 'icon', 'nb_messages', 'threads'}) + meta = subchannel.get_meta({'chat', 'created_at', 'icon', 'nb_messages', 'nb_participants', 'threads'}) if meta['chat']: meta['chat'] = get_chat_meta_from_global_id(meta['chat']) if meta.get('threads'): @@ -347,7 +385,7 @@ def api_get_thread(thread_id, thread_instance_uuid, translation_target=None): thread = ChatThreads.ChatThread(thread_id, thread_instance_uuid) if not thread.exists(): return {"status": "error", "reason": "Unknown thread"}, 404 - meta = thread.get_meta({'chat', 'nb_messages'}) + 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['tags_messages'] = thread.get_messages(translation_target=translation_target) @@ -367,8 +405,7 @@ def api_get_user_account(user_id, instance_uuid): user_account = UsersAccount.UserAccount(user_id, instance_uuid) if not user_account.exists(): return {"status": "error", "reason": "Unknown user-account"}, 404 - meta = user_account.get_meta({'icon', 'username'}) - print(meta) + meta = user_account.get_meta({'chats', 'icon', 'info', 'subchannels', 'threads', 'username', 'username_meta'}) return meta, 200 # # # # # # # # # # LATER diff --git a/bin/lib/objects/ChatSubChannels.py b/bin/lib/objects/ChatSubChannels.py index 38a50a20..7a799240 100755 --- a/bin/lib/objects/ChatSubChannels.py +++ b/bin/lib/objects/ChatSubChannels.py @@ -70,7 +70,7 @@ class ChatSubChannel(AbstractChatObject): # else: # style = 'fas' # icon = '\uf007' - style = 'fas' + style = 'far' icon = '\uf086' return {'style': style, 'icon': icon, 'color': '#4dffff', 'radius': 5} @@ -90,7 +90,10 @@ class ChatSubChannel(AbstractChatObject): meta['created_at'] = self.get_created_at(date=True) if 'threads' in options: meta['threads'] = self.get_threads() - print(meta['threads']) + if 'participants' in options: + meta['participants'] = self.get_participants() + if 'nb_participants' in options: + meta['nb_participants'] = self.get_nb_participants() return meta def get_misp_object(self): diff --git a/bin/lib/objects/ChatThreads.py b/bin/lib/objects/ChatThreads.py index 9514a248..0609faab 100755 --- a/bin/lib/objects/ChatThreads.py +++ b/bin/lib/objects/ChatThreads.py @@ -77,6 +77,10 @@ class ChatThread(AbstractChatObject): meta['name'] = self.get_name() if 'nb_messages': meta['nb_messages'] = self.get_nb_messages() + if 'participants': + meta['participants'] = self.get_participants() + if 'nb_participants': + meta['nb_participants'] = self.get_nb_participants() # created_at ??? return meta diff --git a/bin/lib/objects/Chats.py b/bin/lib/objects/Chats.py index b631b2d2..040c3ea5 100755 --- a/bin/lib/objects/Chats.py +++ b/bin/lib/objects/Chats.py @@ -74,10 +74,14 @@ class Chat(AbstractChatObject): meta = self._get_meta(options=options) meta['name'] = self.get_name() meta['tags'] = self.get_tags(r_list=True) - if 'icon': + if 'icon' in options: meta['icon'] = self.get_icon() - if 'info': + if 'info' in options: meta['info'] = self.get_info() + if 'participants' in options: + meta['participants'] = self.get_participants() + if 'nb_participants' in options: + meta['nb_participants'] = self.get_nb_participants() if 'username' in options: meta['username'] = self.get_username() if 'subchannels' in options: diff --git a/bin/lib/objects/UsersAccount.py b/bin/lib/objects/UsersAccount.py index ced2d682..92076f24 100755 --- a/bin/lib/objects/UsersAccount.py +++ b/bin/lib/objects/UsersAccount.py @@ -54,16 +54,7 @@ class UserAccount(AbstractSubtypeObject): return url def get_svg_icon(self): # TODO change icon/color - if self.subtype == 'telegram': - style = 'fab' - icon = '\uf2c6' - elif self.subtype == 'twitter': - style = 'fab' - icon = '\uf099' - else: - style = 'fas' - icon = '\uf007' - return {'style': style, 'icon': icon, 'color': '#4dffff', 'radius': 5} + return {'style': 'fas', 'icon': '\uf2bd', 'color': '#4dffff', 'radius': 5} def get_first_name(self): return self._get_field('firstname') @@ -97,6 +88,25 @@ class UserAccount(AbstractSubtypeObject): def set_info(self, info): return self._set_field('info', info) + # TODO MESSAGES: + # 1) ALL MESSAGES + NB + # 2) ALL MESSAGES TIMESTAMP + # 3) ALL MESSAGES TIMESTAMP By: - chats + # - subchannel + # - thread + + def get_chats(self): + chats = self.get_correlation('chat')['chat'] + return chats + + def get_chat_subchannels(self): + chats = self.get_correlation('chat-subchannel')['chat-subchannel'] + return chats + + def get_chat_threads(self): + chats = self.get_correlation('chat-thread')['chat-thread'] + return chats + def _get_timeline_username(self): return Timeline(self.get_global_id(), 'username') @@ -109,20 +119,31 @@ class UserAccount(AbstractSubtypeObject): def update_username_timeline(self, username_global_id, timestamp): self._get_timeline_username().add_timestamp(timestamp, username_global_id) - def get_meta(self, options=set()): + def get_meta(self, options=set()): # TODO Username timeline meta = self._get_meta(options=options) meta['id'] = self.id meta['subtype'] = self.subtype meta['tags'] = self.get_tags(r_list=True) # TODO add in options ???? if 'username' in options: meta['username'] = self.get_username() - if meta['username'] and 'username_meta' in options: + if meta['username']: _, username_account_subtype, username_account_id = meta['username'].split(':', 3) - meta['username'] = Usernames.Username(username_account_id, username_account_subtype).get_meta() + if 'username_meta' in options: + meta['username'] = Usernames.Username(username_account_id, username_account_subtype).get_meta() + else: + meta['username'] = {'type': 'username', 'subtype': username_account_subtype, 'id': username_account_id} if 'usernames' in options: meta['usernames'] = self.get_usernames() if 'icon' in options: meta['icon'] = self.get_icon() + if 'info' in options: + meta['info'] = self.get_info() + if 'chats' in options: + meta['chats'] = self.get_chats() + if 'subchannels' in options: + meta['subchannels'] = self.get_chat_subchannels() + if 'threads' in options: + meta['threads'] = self.get_chat_threads() return meta def get_misp_object(self): diff --git a/bin/lib/objects/abstract_chat_object.py b/bin/lib/objects/abstract_chat_object.py index 2ae5ab56..5311cb85 100755 --- a/bin/lib/objects/abstract_chat_object.py +++ b/bin/lib/objects/abstract_chat_object.py @@ -19,7 +19,7 @@ sys.path.append(os.environ['AIL_BIN']) # Import Project packages ################################## from lib.objects.abstract_subtype_object import AbstractSubtypeObject -from lib.ail_core import get_object_all_subtypes, zscan_iter ################ +from lib.ail_core import unpack_correl_objs_id, zscan_iter ################ from lib.ConfigLoader import ConfigLoader from lib.objects import Messages from packages import Date @@ -244,8 +244,11 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): # def get_deleted_messages(self, message_id): + def get_participants(self): + return unpack_correl_objs_id('user-account', self.get_correlation('user-account')['user-account'], r_type='dict') - # get_messages_meta ???? + def get_nb_participants(self): + return self.get_nb_correlation('user-account') # TODO move me to abstract subtype class AbstractChatObjects(ABC): diff --git a/var/www/blueprints/chats_explorer.py b/var/www/blueprints/chats_explorer.py index 9e488273..54ae3d25 100644 --- a/var/www/blueprints/chats_explorer.py +++ b/var/www/blueprints/chats_explorer.py @@ -132,6 +132,20 @@ def objects_thread_messages(): languages = Language.get_translation_languages() return render_template('ThreadMessages.html', meta=meta, bootstrap_label=bootstrap_label, translation_languages=languages, translation_target=target) +@chats_explorer.route("/chats/explorer/participants", methods=['GET']) +@login_required +@login_read_only +def chats_explorer_chat_participants(): + chat_type = request.args.get('type') + chat_id = request.args.get('id') + chat_subtype = request.args.get('subtype') + meta = chats_viewer.api_get_chat_participants(chat_type, chat_subtype,chat_id) + if meta[1] != 200: + return create_json_response(meta[0], meta[1]) + else: + meta = meta[0] + return render_template('chat_participants.html', meta=meta, bootstrap_label=bootstrap_label) + @chats_explorer.route("/objects/message", methods=['GET']) @login_required @login_read_only @@ -145,3 +159,16 @@ def objects_message(): languages = Language.get_translation_languages() return render_template('ChatMessage.html', meta=message, bootstrap_label=bootstrap_label, modal_add_tags=Tag.get_modal_add_tags(message['id'], object_type='message')) + +@chats_explorer.route("/objects/user-account", methods=['GET']) +@login_required +@login_read_only +def objects_user_account(): + instance_uuid = request.args.get('subtype') + user_id = request.args.get('id') + user_account = chats_viewer.api_get_user_account(user_id, instance_uuid) + if user_account[1] != 200: + return create_json_response(user_account[0], user_account[1]) + else: + user_account = user_account[0] + return render_template('user_account.html', meta=user_account, bootstrap_label=bootstrap_label) \ No newline at end of file diff --git a/var/www/blueprints/objects_subtypes.py b/var/www/blueprints/objects_subtypes.py index a41066a4..97229ff1 100644 --- a/var/www/blueprints/objects_subtypes.py +++ b/var/www/blueprints/objects_subtypes.py @@ -43,7 +43,8 @@ def subtypes_objects_dashboard(obj_type, f_request): date_to = f_request.form.get('to') subtype = f_request.form.get('subtype') show_objects = bool(f_request.form.get('show_objects')) - endpoint_dashboard = url_for(f'objects_subtypes.objects_dashboard_{obj_type}') + t_obj_type = obj_type.replace('-', '_') + endpoint_dashboard = url_for(f'objects_subtypes.objects_dashboard_{t_obj_type}') endpoint_dashboard = f'{endpoint_dashboard}?from={date_from}&to={date_to}' if subtype: if subtype == 'All types': @@ -81,7 +82,8 @@ def subtypes_objects_dashboard(obj_type, f_request): for obj_t, obj_subtype, obj_id in subtypes_objs: objs.append(ail_objects.get_object_meta(obj_t, obj_subtype, obj_id, options={'sparkline'}, flask_context=True)) - endpoint_dashboard = f'objects_subtypes.objects_dashboard_{obj_type}' + t_obj_type = obj_type.replace('-', '_') + endpoint_dashboard = f'objects_subtypes.objects_dashboard_{t_obj_type}' return render_template('subtypes_objs_dashboard.html', date_from=date_from, date_to=date_to, daily_type_chart = daily_type_chart, show_objects=show_objects, obj_type=obj_type, subtype=subtype, objs=objs, @@ -115,6 +117,12 @@ def objects_dashboard_pgp(): def objects_dashboard_username(): return subtypes_objects_dashboard('username', request) +@objects_subtypes.route("/objects/user-accounts", methods=['GET']) +@login_required +@login_read_only +def objects_dashboard_user_account(): + return subtypes_objects_dashboard('user-account', request) + # TODO REDIRECT @objects_subtypes.route("/objects/subtypes/post", methods=['POST']) @login_required diff --git a/var/www/templates/chats_explorer/SubChannelMessages.html b/var/www/templates/chats_explorer/SubChannelMessages.html index f9d42e5b..7ca7da41 100644 --- a/var/www/templates/chats_explorer/SubChannelMessages.html +++ b/var/www/templates/chats_explorer/SubChannelMessages.html @@ -68,6 +68,7 @@ Last seen Username Nb Messages + Participants @@ -94,6 +95,9 @@ {% endif %} {{ subchannel['nb_messages'] }} + + {{ subchannel['nb_participants']}} + diff --git a/var/www/templates/chats_explorer/ThreadMessages.html b/var/www/templates/chats_explorer/ThreadMessages.html index be4f854b..49d26ce9 100644 --- a/var/www/templates/chats_explorer/ThreadMessages.html +++ b/var/www/templates/chats_explorer/ThreadMessages.html @@ -67,6 +67,7 @@ First seen Last seen Nb Messages + Participants @@ -74,6 +75,7 @@ {{ meta['name'] }} + {% if meta['first_seen'] %} {{ meta['first_seen'][0:4] }}-{{ meta['first_seen'][4:6] }}-{{ meta['first_seen'][6:8] }} @@ -85,6 +87,9 @@ {% endif %} {{ meta['nb_messages'] }} + + {{ meta['nb_participants']}} + diff --git a/var/www/templates/chats_explorer/block_message.html b/var/www/templates/chats_explorer/block_message.html index 1a60814c..cf407128 100644 --- a/var/www/templates/chats_explorer/block_message.html +++ b/var/www/templates/chats_explorer/block_message.html @@ -26,8 +26,10 @@
- {{ message['user-account']['id'] }} + + {{ message['user-account']['id'] }} +
{{ message['hour'] }}
diff --git a/var/www/templates/chats_explorer/chat_participants.html b/var/www/templates/chats_explorer/chat_participants.html new file mode 100644 index 00000000..455a39b2 --- /dev/null +++ b/var/www/templates/chats_explorer/chat_participants.html @@ -0,0 +1,174 @@ + + + + + Chats Protocols - AIL + + + + + + + + + + + + + + + + + + + + {% include 'nav_bar.html' %} + +
+
+ + {% include 'sidebars/sidebar_objects.html' %} + +
+ +{#
#} TODO CHAT abstract metadata +{##} +{#
#} +{#

{% if chat['username'] %}{{ chat["username"]["id"] }} {% else %} {{ chat['name'] }}{% endif %} :

#} +{# {% if chat['icon'] %}#} +{#
{{ chat['id'] }}
#} +{# {% endif %}#} +{#
    #} +{#
  • #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{#
    NameIDCreated atFirst SeenLast SeenNB Sub-ChannelsParticipants
    {{ chat['name'] }}{{ chat['id'] }}{{ chat['created_at'] }}#} +{# {% if chat['first_seen'] %}#} +{# {{ chat['first_seen'][0:4] }}-{{ chat['first_seen'][4:6] }}-{{ chat['first_seen'][6:8] }}#} +{# {% endif %}#} +{# #} +{# {% if chat['last_seen'] %}#} +{# {{ chat['last_seen'][0:4] }}-{{ chat['last_seen'][4:6] }}-{{ chat['last_seen'][6:8] }}#} +{# {% endif %}#} +{# {{ chat['nb_subchannels'] }}#} +{# {{ chat['participants'] | length}}#} +{##} +{#
    #} +{# {% if chat['info'] %}#} +{#
  • #} +{#
    {{ chat['info'] }}
    #} +{#
  • #} +{# {% endif %}#} +{# #} +{#
#} +{##} +{#
#} +{#
#} + + +

Participants:

+ + + + + + + + + + + + + + {% for user_meta in meta["participants"] %} + + + + + + + + + + {% endfor %} + +
IconUsernameIDinfoFirst SeenLast SeenNB Messages
+ + {{ user_meta['id'] }} + + + {% if user_meta['username'] %} + {{ user_meta['username']['id'] }} + {% endif %} + {{ user_meta['id'] }} + {% if user_meta['info'] %} + {{ user_meta['info'] }} + {% endif %} + + {% if user_meta['first_seen'] %} + {{ user_meta['first_seen'][0:4] }}-{{ user_meta['first_seen'][4:6] }}-{{ user_meta['first_seen'][6:8] }} + {% endif %} + + {% if user_meta['last_seen'] %} + {{ user_meta['last_seen'][0:4] }}-{{ user_meta['last_seen'][4:6] }}-{{ user_meta['last_seen'][6:8] }} + {% endif %} + {{ user_meta['nb_messages'] }}
+ +
+ +
+
+ + + + + + diff --git a/var/www/templates/chats_explorer/chat_viewer.html b/var/www/templates/chats_explorer/chat_viewer.html index 51023081..81f7e407 100644 --- a/var/www/templates/chats_explorer/chat_viewer.html +++ b/var/www/templates/chats_explorer/chat_viewer.html @@ -66,18 +66,17 @@ - + - @@ -92,6 +91,9 @@ {% endif %} +
Icon Name ID Created at First Seen Last Seen NB Sub-ChannelsParticipants
{{ chat['name'] }} {{ chat['id'] }} {{ chat['created_at'] }} {{ chat['nb_subchannels'] }} + {{ chat['nb_participants']}} +
diff --git a/var/www/templates/chats_explorer/user_account.html b/var/www/templates/chats_explorer/user_account.html new file mode 100644 index 00000000..ee8d4e88 --- /dev/null +++ b/var/www/templates/chats_explorer/user_account.html @@ -0,0 +1,184 @@ + + + + + User Account - AIL + + + + + + + + + + + + + + + + + + + + + {% include 'nav_bar.html' %} + +
+
+ + {% include 'sidebars/sidebar_objects.html' %} + +
+ +
+ +
+

{% if meta['username'] %}{{ meta["username"]["id"] }} {% else %} {{ meta['id'] }}{% endif %}

+ {% if meta['icon'] %} +
{{ meta['id'] }}
+ {% endif %} +
    +
  • + + + + + + + + + + + + + + + + + + + + + +
    usernameIDCreated atFirst SeenLast SeenNB Chats
    {{ meta['username']['id'] }}{{ meta['id'] }}{{ meta['created_at'] }} + {% if meta['first_seen'] %} + {{ meta['first_seen'][0:4] }}-{{ meta['first_seen'][4:6] }}-{{ meta['first_seen'][6:8] }} + {% endif %} + + {% if meta['last_seen'] %} + {{ meta['last_seen'][0:4] }}-{{ meta['last_seen'][4:6] }}-{{ meta['last_seen'][6:8] }} + {% endif %} + {{ meta['chats'] | length }}
    + {% if meta['info'] %} +
  • +
    {{ meta['info'] }}
    +
  • + {% endif %} + +
+ +
+ +{#
#} +{# {% with obj_type=meta['type'], obj_id=meta['id'], obj_subtype=''%}#} +{# {% include 'modals/investigations_register_obj.html' %}#} +{# {% endwith %}#} +{#
#} +{# #} +{#
#} +{#
#} +
+ +
+
+ + +{# {% if meta['subchannels'] %}#} +{#

Sub-Channels:

#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# {% for meta in meta["subchannels"] %}#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# {% endfor %}#} +{# #} +{#
#} +{# {{ meta['id'] }}#} +{# {{ meta['name'] }}{{ meta['id'] }}{{ meta['created_at'] }}#} +{# {% if meta['first_seen'] %}#} +{# {{ meta['first_seen'][0:4] }}-{{ meta['first_seen'][4:6] }}-{{ meta['first_seen'][6:8] }}#} +{# {% endif %}#} +{# #} +{# {% if meta['last_seen'] %}#} +{# {{ meta['last_seen'][0:4] }}-{{ meta['last_seen'][4:6] }}-{{ meta['last_seen'][6:8] }}#} +{# {% endif %}#} +{# {{ meta['nb_messages'] }}
#} +{##} +{# {% endif %}#} + + +
+ +
+
+ + + + + + + + + + diff --git a/var/www/templates/sidebars/sidebar_objects.html b/var/www/templates/sidebars/sidebar_objects.html index dba94772..d0a64df6 100644 --- a/var/www/templates/sidebars/sidebar_objects.html +++ b/var/www/templates/sidebars/sidebar_objects.html @@ -106,6 +106,12 @@ Username +