mirror of https://github.com/CIRCL/AIL-framework
				
				
				
			chg: [chats] improve UI + fix importer
							parent
							
								
									9125119764
								
							
						
					
					
						commit
						789210bcba
					
				|  | @ -265,6 +265,11 @@ def get_subchannels_meta_from_global_id(subchannels): | |||
|         meta.append(subchannel.get_meta({'nb_messages'})) | ||||
|     return meta | ||||
| 
 | ||||
| def get_chat_meta_from_global_id(chat_global_id): | ||||
|     _, instance_uuid, chat_id = chat_global_id.split(':', 2) | ||||
|     chat = Chats.Chat(chat_id, instance_uuid) | ||||
|     return chat.get_meta() | ||||
| 
 | ||||
| def api_get_chat_service_instance(chat_instance_uuid): | ||||
|     chat_instance = ChatServiceInstance(chat_instance_uuid) | ||||
|     if not chat_instance.exists(): | ||||
|  | @ -277,15 +282,18 @@ def api_get_chat(chat_id, chat_instance_uuid): | |||
|         return {"status": "error", "reason": "Unknown chat"}, 404 | ||||
|     meta = chat.get_meta({'img', 'subchannels', 'username'}) | ||||
|     if meta['subchannels']: | ||||
|         print(meta['subchannels']) | ||||
|         meta['subchannels'] = get_subchannels_meta_from_global_id(meta['subchannels']) | ||||
|     else: | ||||
|         meta['messages'], meta['tags_messages'] = chat.get_messages() | ||||
|     return meta, 200 | ||||
| 
 | ||||
| def api_get_subchannel(chat_id, chat_instance_uuid): | ||||
|     subchannel = ChatSubChannels.ChatSubChannel(chat_id, chat_instance_uuid) | ||||
|     if not subchannel.exists(): | ||||
|         return {"status": "error", "reason": "Unknown chat"}, 404 | ||||
|     meta = subchannel.get_meta({'img', 'nb_messages'}) | ||||
|     meta = subchannel.get_meta({'chat', 'img', 'nb_messages'}) | ||||
|     if meta['chat']: | ||||
|         meta['chat'] = get_chat_meta_from_global_id(meta['chat']) | ||||
|     meta['messages'], meta['tags_messages'] = subchannel.get_messages() | ||||
|     return meta, 200 | ||||
| 
 | ||||
|  |  | |||
|  | @ -80,8 +80,10 @@ class ChatSubChannel(AbstractChatObject): | |||
|         meta = self._get_meta(options=options) | ||||
|         meta['tags'] = self.get_tags(r_list=True) | ||||
|         meta['name'] = self.get_name() | ||||
|         if 'chat' in options: | ||||
|             meta['chat'] = self.get_chat() | ||||
|         if 'img' in options: | ||||
|             meta['sub'] = self.get_img() | ||||
|             meta['img'] = self.get_img() | ||||
|         if 'nb_messages': | ||||
|             meta['nb_messages'] = self.get_nb_messages() | ||||
|         return meta | ||||
|  |  | |||
|  | @ -63,16 +63,15 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): | |||
|     def get_chat(self):  # require ail object TODO ## | ||||
|         if self.type != 'chat': | ||||
|             parent = self.get_parent() | ||||
|             obj_type, _ = parent.split(':', 1) | ||||
|             if obj_type == 'chat': | ||||
|                 return parent | ||||
|             if parent: | ||||
|                 obj_type, _ = parent.split(':', 1) | ||||
|                 if obj_type == 'chat': | ||||
|                     return parent | ||||
| 
 | ||||
|     def get_subchannels(self): | ||||
|         subchannels = [] | ||||
|         if self.type == 'chat':  # category ??? | ||||
|             print(self.get_childrens()) | ||||
|             for obj_global_id in self.get_childrens(): | ||||
|                 print(obj_global_id) | ||||
|                 obj_type, _ = obj_global_id.split(':', 1) | ||||
|                 if obj_type == 'chat-subchannel': | ||||
|                     subchannels.append(obj_global_id) | ||||
|  | @ -125,12 +124,11 @@ class AbstractChatObject(AbstractSubtypeObject, ABC): | |||
|     def get_message_meta(self, message, parent=True, mess_datetime=None):  # TODO handle file message | ||||
|         obj = Message(message[9:]) | ||||
|         mess_dict = obj.get_meta(options={'content', 'link', 'parent', 'user-account'}) | ||||
|         print(mess_dict) | ||||
|         # print(mess_dict) | ||||
|         if mess_dict.get('parent') and parent: | ||||
|             mess_dict['reply_to'] = self.get_message_meta(mess_dict['parent'], parent=False) | ||||
|         if mess_dict.get('user-account'): | ||||
|             _, user_account_subtype, user_account_id = mess_dict['user-account'].split(':', 3) | ||||
|             print(mess_dict['user-account']) | ||||
|             user_account = UserAccount(user_account_id, user_account_subtype) | ||||
|             mess_dict['user-account'] = {} | ||||
|             mess_dict['user-account']['type'] = user_account.get_type() | ||||
|  | @ -224,8 +222,6 @@ class AbstractChatObjects(ABC): | |||
|         return r_object.zcard(f'{self.type}_all:{subtype}') | ||||
| 
 | ||||
|     def get_ids_by_subtype(self, subtype): | ||||
|         print(subtype) | ||||
|         print(f'{self.type}_all:{subtype}') | ||||
|         return r_object.zrange(f'{self.type}_all:{subtype}', 0, -1) | ||||
| 
 | ||||
|     def get_all_id_iterator_iter(self, subtype): | ||||
|  |  | |||
|  | @ -298,6 +298,7 @@ class AbstractObject(ABC): | |||
|                 obj_subtype = '' | ||||
|             obj_global_id = f'{obj_type}:{obj_subtype}:{obj_id}' | ||||
|         r_object.hset(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', 'parent', obj_global_id) | ||||
|         r_object.sadd(f'child:{obj_global_id}', self.get_global_id()) | ||||
| 
 | ||||
|     def add_children(self, obj_type=None, obj_subtype=None, obj_id=None, obj_global_id=None): # TODO # REMOVE ITEM DUP | ||||
|         if not obj_global_id: | ||||
|  | @ -305,6 +306,7 @@ class AbstractObject(ABC): | |||
|                 obj_subtype = '' | ||||
|             obj_global_id = f'{obj_type}:{obj_subtype}:{obj_id}' | ||||
|         r_object.sadd(f'child:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', obj_global_id) | ||||
|         r_object.hset(f'meta:{obj_global_id}', 'parent', self.get_global_id()) | ||||
| 
 | ||||
|     ## others objects ## | ||||
|     def add_obj_children(self, parent_global_id, son_global_id): | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ def chats_explorer_chat(): | |||
|         return create_json_response(chat[0], chat[1]) | ||||
|     else: | ||||
|         chat = chat[0] | ||||
|         return render_template('chat_viewer.html', chat=chat) | ||||
|         return render_template('chat_viewer.html', chat=chat, bootstrap_label=bootstrap_label) | ||||
| 
 | ||||
| @chats_explorer.route("/chats/explorer/subchannel", methods=['GET']) | ||||
| @login_required | ||||
|  | @ -95,18 +95,6 @@ def objects_subchannel_messages(): | |||
|         subchannel = subchannel[0] | ||||
|         return render_template('SubChannelMessages.html', subchannel=subchannel) | ||||
| 
 | ||||
| @chats_explorer.route("/chats/explorer/subchannel", methods=['GET']) | ||||
| @login_required | ||||
| @login_read_only | ||||
| def objects_message(): | ||||
|     message_id = request.args.get('id') | ||||
|     message = chats_viewer.api_get_message(message_id) | ||||
|     if message[1] != 200: | ||||
|         return create_json_response(message[0], message[1]) | ||||
|     else: | ||||
|         message = message[0] | ||||
|         return render_template('ChatMessage.html', message=message) | ||||
| 
 | ||||
| ############################################################################################# | ||||
| ############################################################################################# | ||||
| ############################################################################################# | ||||
|  |  | |||
|  | @ -32,6 +32,13 @@ | |||
|             flex-direction: row-reverse; | ||||
|             margin-left: auto | ||||
|         } | ||||
|         .divider:after, | ||||
|         .divider:before { | ||||
|             content: ""; | ||||
|             flex: 1; | ||||
|             height: 2px; | ||||
|             background: #eee; | ||||
|         } | ||||
| 	</style> | ||||
| </head> | ||||
| <body> | ||||
|  | @ -47,7 +54,7 @@ | |||
| 
 | ||||
|                 <div class="card my-3"> | ||||
|                     <div class="card-header" style="background-color:#d9edf7;font-size: 15px"> | ||||
|                         <h3 class="text-secondary">{{ subchannel["id"] }} :</h3> | ||||
|                         <h3 class="text-secondary">{% if subchannel['chat']['name'] %}{{ subchannel['chat']['name'] }} {% else %} {{ subchannel['chat']['id'] }}{% endif %} - {% if subchannel['username'] %}{{ subchannel["username"] }} {% else %} {{ subchannel['name'] }}{% endif %} :</h3> {{ subchannel["id"] }} | ||||
|                         <ul class="list-group mb-2"> | ||||
|                             <li class="list-group-item py-0"> | ||||
|                                 <div class="row"> | ||||
|  | @ -55,7 +62,8 @@ | |||
|                                         <table class="table"> | ||||
|                                             <thead> | ||||
|                                                 <tr> | ||||
|                                                     <th>Chat Instance</th> | ||||
|                                                     <th>Name</th> | ||||
| {#                                                    <th>Chat Instance</th>#} | ||||
|                                                     <th>First seen</th> | ||||
|                                                     <th>Last seen</th> | ||||
|                                                     <th>Username</th> | ||||
|  | @ -65,10 +73,19 @@ | |||
|                                             <tbody> | ||||
|                                                 <tr> | ||||
|                                                     <td> | ||||
|                                                         {{ subchannel["subtype"] }} | ||||
| {#                                                        {{ subchannel["subtype"] }}#} | ||||
|                                                         {{ subchannel['name'] }} | ||||
|                                                     </td> | ||||
|                                                     <td> | ||||
|                                                         {% if subchannel['first_seen'] %} | ||||
|                                                             {{ subchannel['first_seen'][0:4] }}-{{ subchannel['first_seen'][4:6] }}-{{ subchannel['first_seen'][6:8] }} | ||||
|                                                         {% endif %} | ||||
|                                                     </td> | ||||
|                                                     <td> | ||||
|                                                         {% if subchannel['last_seen'] %} | ||||
|                                                             {{ subchannel['last_seen'][0:4] }}-{{ subchannel['last_seen'][4:6] }}-{{ subchannel['last_seen'][6:8] }} | ||||
|                                                         {% endif %} | ||||
|                                                     </td> | ||||
|                                                     <td>{{ subchannel['first_seen'] }}</td> | ||||
|                                                     <td>{{ subchannel['last_seen'] }}</td> | ||||
|                                                     <td> | ||||
|                                                         {% if 'username' in subchannel %} | ||||
|                                                             {{ subchannel['username'] }} | ||||
|  | @ -108,8 +125,8 @@ | |||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 {% for tag in mess_tags %} | ||||
|                     <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }} <span class="badge badge-light">{{ mess_tags[tag] }}</span></span> | ||||
|                 {% for tag in subchannel['tags_messages'] %} | ||||
|                     <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }} <span class="badge badge-light">{{ subchannel['tags_messages'][tag] }}</span></span> | ||||
|                 {%  endfor %} | ||||
| 
 | ||||
|                 <div> | ||||
|  | @ -121,10 +138,16 @@ | |||
|                 </div> | ||||
| 
 | ||||
|                 <div class="position-relative"> | ||||
|                     <div class="chat-messages p-4"> | ||||
|                     <div class="chat-messages p-2"> | ||||
| 
 | ||||
|                         {% for date in subchannel['messages'] %} | ||||
|                             <h2 id="date_section_{{ date }}"><span class="badge badge-secondary mb-2">{{ date }}</span></h2> | ||||
| 
 | ||||
|                             <div class="divider d-flex align-items-center mb-4"> | ||||
|                                 <p class="text-center h2 mx-3 mb-0" style="color: #a2aab7;"> | ||||
|                                     <span class="badge badge-secondary mb-2" id="date_section_{{ date }}">{{ date }}</span> | ||||
|                                 </p> | ||||
|                             </div> | ||||
| 
 | ||||
|                             {% for mess in subchannel['messages'][date] %} | ||||
| 
 | ||||
|                                 <div class="chat-message-left pb-1"> | ||||
|  |  | |||
|  | @ -75,11 +75,21 @@ | |||
|                     <tbody style="font-size: 15px;"> | ||||
|                     {% for chat in chat_instance["chats"] %} | ||||
|                         <tr> | ||||
|                             <td></td> | ||||
|                             <td> | ||||
|                                 <img src="{{ url_for('static', filename='image/ail-icon.png') }}" class="rounded-circle mr-1" alt="{{ chat['id'] }}" width="40" height="40"> | ||||
|                             </td> | ||||
|                             <td>{{ chat['name'] }}</td> | ||||
|                             <td><a href="{{ url_for('chats_explorer.chats_explorer_chat') }}?uuid={{ chat_instance['uuid'] }}&id={{ chat['id'] }}">{{ chat['id'] }}</a></td> | ||||
|                             <td>{{ chat['first_seen'] }}</td> | ||||
| 							<td>{{ chat['last_seen'] }}</td> | ||||
|                             <td> | ||||
|                                 {% if chat['first_seen'] %} | ||||
|                                     {{ chat['first_seen'][0:4] }}-{{ chat['first_seen'][4:6] }}-{{ chat['first_seen'][6:8] }} | ||||
|                                 {% endif %} | ||||
|                             </td> | ||||
| 							<td> | ||||
|                                 {% if chat['last_seen'] %} | ||||
|                                     {{ chat['last_seen'][0:4] }}-{{ chat['last_seen'][4:6] }}-{{ chat['last_seen'][6:8] }} | ||||
|                                 {% endif %} | ||||
|                             </td> | ||||
|                             <td>{{ chat['nb_subchannels'] }}</td> | ||||
|                         </tr> | ||||
|                     {% endfor %} | ||||
|  |  | |||
|  | @ -17,6 +17,25 @@ | |||
| 	<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script> | ||||
| 	<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script> | ||||
| 
 | ||||
|     <style> | ||||
|         .chat-message-left, | ||||
|         .chat-message-right { | ||||
|             display: flex; | ||||
|             flex-shrink: 0; | ||||
|         } | ||||
|         .chat-message-right { | ||||
|             flex-direction: row-reverse; | ||||
|             margin-left: auto | ||||
|         } | ||||
|         .divider:after, | ||||
|         .divider:before { | ||||
|             content: ""; | ||||
|             flex: 1; | ||||
|             height: 2px; | ||||
|             background: #eee; | ||||
|         } | ||||
| 	</style> | ||||
| 
 | ||||
| </head> | ||||
| <body> | ||||
| 
 | ||||
|  | @ -32,11 +51,11 @@ | |||
|                 <div class="card my-3"> | ||||
| 
 | ||||
|                     <div class="card-header" style="background-color:#d9edf7;font-size: 15px"> | ||||
|                         <h4 class="text-secondary">{{ chat["username"] }} {{ chat["id"] }} :</h4> | ||||
|                         <h4 class="text-secondary">{% if chat['username'] %}{{ chat["username"] }} {% else %} {{ chat['name'] }}{% endif %} :</h4> {{ chat["id"] }} | ||||
|                         <ul class="list-group mb-2"> | ||||
|                             <li class="list-group-item py-0"> | ||||
|                                 <table class="table"> | ||||
|                                     <thead class="bg-dark text-white"> | ||||
|                                     <thead class=""> | ||||
|                                     <tr> | ||||
|                                         <th>Icon</th> | ||||
|                                         <th>Name</th> | ||||
|  | @ -51,8 +70,16 @@ | |||
|                                             <td></td> | ||||
|                                             <td>{{ chat['name'] }}</td> | ||||
|                                             <td>{{ chat['id']  }}</td> | ||||
|                                             <td>{{ chat['first_seen'] }}</td> | ||||
|                                             <td>{{ chat['last_seen'] }}</td> | ||||
|                                             <td> | ||||
|                                                 {% if chat['first_seen'] %} | ||||
|                                                     {{ chat['first_seen'][0:4] }}-{{ chat['first_seen'][4:6] }}-{{ chat['first_seen'][6:8] }} | ||||
|                                                 {% endif %} | ||||
|                                             </td> | ||||
|                                             <td> | ||||
|                                                 {% if chat['last_seen'] %} | ||||
|                                                     {{ chat['last_seen'][0:4] }}-{{ chat['last_seen'][4:6] }}-{{ chat['last_seen'][6:8] }} | ||||
|                                                 {% endif %} | ||||
|                                             </td> | ||||
|                                             <td>{{ chat['nb_subchannels'] }}</td> | ||||
|                                     </tr> | ||||
|                                     </tbody> | ||||
|  | @ -63,6 +90,10 @@ | |||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 {% for tag in chat['tags_messages'] %} | ||||
|                     <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }} <span class="badge badge-light">{{ chat['tags_messages'][tag] }}</span></span> | ||||
|                 {%  endfor %} | ||||
| 
 | ||||
|                 {% if chat['subchannels'] %} | ||||
|                     <h4>Sub-Channels:</h4> | ||||
|                     <table id="tablesubchannels" class="table"> | ||||
|  | @ -84,8 +115,16 @@ | |||
|                                 </td> | ||||
|                                 <td><b>{{ meta['name'] }}</b></td> | ||||
|                                 <td><a href="{{ url_for('chats_explorer.objects_subchannel_messages') }}?uuid={{ meta['subtype'] }}&id={{ meta['id'] }}">{{ meta['id'] }}</a></td> | ||||
|                                 <td>{{ meta['first_seen'] }}</td> | ||||
|                                 <td>{{ meta['last_seen'] }}</td> | ||||
|                                 <td> | ||||
|                                     {% if meta['first_seen'] %} | ||||
|                                         {{ meta['first_seen'][0:4] }}-{{ meta['first_seen'][4:6] }}-{{ meta['first_seen'][6:8] }} | ||||
|                                     {% endif %} | ||||
|                                 </td> | ||||
|                                 <td> | ||||
|                                     {% if meta['last_seen'] %} | ||||
|                                         {{ meta['last_seen'][0:4] }}-{{ meta['last_seen'][4:6] }}-{{ meta['last_seen'][6:8] }} | ||||
|                                     {% endif %} | ||||
|                                 </td> | ||||
|                                 <td>{{ meta['nb_messages'] }}</td> | ||||
|                             </tr> | ||||
|                         {% endfor %} | ||||
|  | @ -94,6 +133,74 @@ | |||
| 
 | ||||
|                 {% endif %} | ||||
| 
 | ||||
|                 {% if chat['messages'] %} | ||||
| 
 | ||||
|                     <div class="position-relative"> | ||||
|                         <div class="chat-messages p-2"> | ||||
| 
 | ||||
|                             {% for date in chat['messages'] %} | ||||
| 
 | ||||
|                                 <div class="divider d-flex align-items-center mb-4"> | ||||
|                                     <p class="text-center h2 mx-3 mb-0" style="color: #a2aab7;"> | ||||
|                                         <span class="badge badge-secondary mb-2" id="date_section_{{ date }}">{{ date }}</span> | ||||
|                                     </p> | ||||
|                                 </div> | ||||
| 
 | ||||
|                                 {% for mess in chat['messages'][date] %} | ||||
| 
 | ||||
|                                     <div class="chat-message-left pb-1"> | ||||
|                                         <div> | ||||
|                                             <img src="{{ url_for('static', filename='image/ail-icon.png') }}" class="rounded-circle mr-1" alt="{{ mess['user-account']['id'] }}" width="40" height="40"> | ||||
|                                             <div class="text-muted small text-nowrap mt-2">{{ mess['hour'] }}</div> | ||||
|                                         </div> | ||||
|                                         <div class="flex-shrink-1 bg-light rounded py-2 px-3 ml-4 pb-4" style="overflow-x: auto"> | ||||
|                                             <div class="font-weight-bold mb-1"> | ||||
|                                                 {% if mess['user-account']['username'] %} | ||||
|                                                     {{ mess['user-account']['username']['id'] }} | ||||
|                                                 {% else %} | ||||
|                                                     {{ mess['user-account']['id'] }} | ||||
|                                                 {% endif %} | ||||
|                                             </div> | ||||
|                                             {% if mess['reply_to'] %} | ||||
|                                                 <div class="flex-shrink-1 border rounded py-2 px-3 ml-4 mb-3" style="overflow-x: auto"> | ||||
|                                                     <div class="font-weight-bold mb-1"> | ||||
|                                                         {% if mess['reply_to']['user-account']['username'] %} | ||||
|                                                             {{ mess['reply_to']['user-account']['username']['id'] }} | ||||
|                                                         {% else %} | ||||
|                                                             {{ mess['reply_to']['user-account']['id'] }} | ||||
|                                                         {% endif %} | ||||
|                                                     </div> | ||||
|                                                     <pre class="my-0">{{ mess['reply_to']['content'] }}</pre> | ||||
|                                                     {% for tag in mess['reply_to']['tags'] %} | ||||
|                                                         <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span> | ||||
|                                                     {%  endfor %} | ||||
|                                                     <div class="text-muted small text-nowrap">{{ mess['reply_to']['date'] }}</div> | ||||
|     {#                                                <div class="">#} | ||||
|     {#                                                    <a class="btn btn-light btn-sm text-secondary py-0" href="{{ url_for('correlation.show_correlation')}}?type={{ mess['reply_to']['type'] }}&subtype={{ mess['reply_to']['subtype'] }}&id={{ mess['reply_to']['id'] }}"><i class="fas fa-project-diagram"></i></a>#} | ||||
|     {#                                                    <a class="btn btn-light btn-sm text-secondary py-0" href="{{ mess['reply_to']['link'] }}"><i class="fas fa-eye"></i></a>#} | ||||
|     {#                                                </div>#} | ||||
|                                                 </div> | ||||
|                                             {% endif %} | ||||
|                                             <pre class="my-0">{{ mess['content'] }}</pre> | ||||
|                                             {% for tag in mess['tags'] %} | ||||
|                                                 <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span> | ||||
|                                             {%  endfor %} | ||||
|                                             <div class=""> | ||||
|                                                 <a class="btn btn-light btn-sm text-secondary px-1" href="{{ url_for('correlation.show_correlation')}}?type={{ mess['type'] }}&subtype={{ mess['subtype'] }}&id={{ mess['id'] }}"><i class="fas fa-project-diagram"></i></a> | ||||
|                                                 <a class="btn btn-light btn-sm text-secondary px-1" href="{{ mess['link'] }}"><i class="fas fa-eye"></i></a> | ||||
|                                             </div> | ||||
|                                         </div> | ||||
|                                     </div> | ||||
| 
 | ||||
|                                 {% endfor %} | ||||
|                                 <br> | ||||
|                             {% endfor %} | ||||
| 
 | ||||
|                         </div> | ||||
|                     </div> | ||||
| 
 | ||||
|                 {% endif %} | ||||
| 
 | ||||
|             </div> | ||||
| 
 | ||||
|         </div> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 terrtia
						terrtia