diff --git a/bin/lib/objects/Usernames.py b/bin/lib/objects/Usernames.py
index c9154b99..bcd808b7 100755
--- a/bin/lib/objects/Usernames.py
+++ b/bin/lib/objects/Usernames.py
@@ -13,7 +13,7 @@ sys.path.append(os.environ['AIL_BIN'])
# Import Project packages
##################################
from lib.ConfigLoader import ConfigLoader
-from lib.objects.abstract_subtype_object import AbstractSubtypeObject, get_all_id
+from lib.objects.abstract_subtype_object import AbstractSubtypeObject, AbstractSubtypeObjects, get_all_id
config_loader = ConfigLoader()
baseurl = config_loader.get_config_str("Notifications", "ail_domain")
@@ -65,7 +65,7 @@ class Username(AbstractSubtypeObject):
meta = self._get_meta(options=options)
meta['id'] = self.id
meta['subtype'] = self.subtype
- meta['tags'] = self.get_tags(r_list=True)
+ meta['tags'] = self.get_tags(r_list=True) # TODO NB Chats
return meta
def get_misp_object(self):
@@ -136,7 +136,20 @@ def search_usernames_by_name(name_to_search, subtype, r_pos=False):
return usernames
+class Usernames(AbstractSubtypeObjects):
+ """
+ Usernames Objects
+ """
+ def __init__(self):
+ super().__init__('username', Username)
+
+ def sanitize_id_to_search(self, subtypes, name_to_search):
+ return name_to_search
+
+
# if __name__ == '__main__':
# name_to_search = 'co'
-# subtype = 'telegram'
-# print(search_usernames_by_name(name_to_search, subtype))
+# subtypes = ['telegram']
+# u = Usernames()
+# r = u.search_by_id(name_to_search, subtypes, r_pos=True)
+# print(r)
diff --git a/bin/lib/objects/abstract_subtype_object.py b/bin/lib/objects/abstract_subtype_object.py
index 71d9d267..17be1add 100755
--- a/bin/lib/objects/abstract_subtype_object.py
+++ b/bin/lib/objects/abstract_subtype_object.py
@@ -7,8 +7,9 @@ Base Class for AIL Objects
# Import External packages
##################################
import os
+import re
import sys
-from abc import ABC
+from abc import ABC, abstractmethod
# from flask import url_for
@@ -192,6 +193,62 @@ class AbstractSubtypeObject(AbstractObject, ABC):
def _delete(self):
pass
+
+class AbstractSubtypeObjects(ABC):
+ """
+ Abstract Subtype Objects
+ """
+ def __init__(self, obj_type, obj_class):
+ self.type = obj_type
+ self.obj_class = obj_class
+
+ def get_ids(self): # TODO FORMAT
+ ids = []
+ for subtype in get_object_all_subtypes(self.type):
+ ids += r_object.zrange(f'{self.type}_all:{subtype}', 0, -1)
+ return ids
+
+ def get_id_iterators_by_subtype(self, subtype):
+ return zscan_iter(r_object, f'{self.type}_all:{subtype}')
+
+ def get_metas(self, subtype, obj_ids, options=set()):
+ dict_obj = {}
+ for obj_id in obj_ids:
+ obj = self.obj_class(obj_id, subtype)
+ dict_obj[obj_id] = obj.get_meta(options=options)
+ return dict_obj
+
+ @abstractmethod
+ def sanitize_id_to_search(self, subtypes, id_to_search):
+ return id_to_search
+
+ # TODO
+ def search_by_id(self, name_to_search, subtypes=[], r_pos=False, case_sensitive=True):
+ objs = {}
+ if case_sensitive:
+ flags = 0
+ else:
+ flags = re.IGNORECASE
+ # for subtype in subtypes:
+ r_name = self.sanitize_id_to_search(subtypes, name_to_search)
+ if not name_to_search or isinstance(r_name, dict):
+ return objs
+ r_name = re.compile(r_name, flags=flags)
+ for subtype in subtypes:
+ for obj_id in self.get_id_iterators_by_subtype(subtype):
+ obj_id = obj_id[0]
+ res = re.search(r_name, obj_id)
+ if res:
+ objs[obj_id] = {}
+ if r_pos:
+ objs[obj_id]['hl-start'] = res.start()
+ objs[obj_id]['hl-end'] = res.end()
+ return objs
+
+########################################################################
+########################################################################
+########################################################################
+
def get_all_id(obj_type, subtype):
return r_object.zrange(f'{obj_type}_all:{subtype}', 0, -1)
@@ -246,3 +303,5 @@ def get_subtypes_objs_range_json(obj_type, date_from, date_to):
objs_range.append(day_dict)
return objs_range
+
+
diff --git a/var/www/blueprints/chats_explorer.py b/var/www/blueprints/chats_explorer.py
index 342f67e4..1552ae62 100644
--- a/var/www/blueprints/chats_explorer.py
+++ b/var/www/blueprints/chats_explorer.py
@@ -49,7 +49,7 @@ def chats_explorer_dashboard():
@login_read_only
def chats_explorer_protocols():
protocols = chats_viewer.get_chat_protocols_meta()
- return render_template('chats_protocols.html', protocols=protocols)
+ return render_template('chats_protocols.html', protocols=protocols, username_subtypes=ail_core.get_object_all_subtypes('username'))
@chats_explorer.route("chats/explorer/networks", methods=['GET'])
@login_required
diff --git a/var/www/blueprints/objects_subtypes.py b/var/www/blueprints/objects_subtypes.py
index 85944365..70d3b0b3 100644
--- a/var/www/blueprints/objects_subtypes.py
+++ b/var/www/blueprints/objects_subtypes.py
@@ -23,6 +23,7 @@ from lib import ail_core
from lib.objects import abstract_subtype_object
from lib.objects import ail_objects
from lib.objects import CryptoCurrencies
+from lib.objects import Usernames
from packages import Date
# ============ BLUEPRINT ============
@@ -117,6 +118,43 @@ def objects_dashboard_pgp():
def objects_dashboard_username():
return subtypes_objects_dashboard('username', request)
+@objects_subtypes.route("/objects/usernames/search", methods=['GET', 'POST'])
+@login_required
+@login_read_only
+def objects_username_search():
+ if request.method == 'POST':
+ to_search = request.form.get('to_search')
+ subtype = request.form.get('search_subtype')
+ page = request.form.get('page', 1)
+ try:
+ page = int(page)
+ except (TypeError, ValueError):
+ page = 1
+ return redirect(url_for('objects_subtypes.objects_username_search', search=to_search, page=page, subtype=subtype))
+ else:
+ to_search = request.args.get('search')
+ subtype = request.args.get('subtype') # TODO sanityze
+ page = request.args.get('page', 1)
+ try:
+ page = int(page)
+ except (TypeError, ValueError):
+ page = 1
+
+ usernames = Usernames.Usernames()
+ search_result = usernames.search_by_id(to_search, [subtype], page)
+
+ if search_result:
+ ids = sorted(search_result.keys())
+ dict_page = ail_core.paginate_iterator(ids, nb_obj=500, page=page)
+ dict_objects = usernames.get_metas(subtype, dict_page['list_elem'], options={'icon', 'sparkline'}) # TODO OPTIONS
+ else:
+ dict_objects = {}
+ dict_page = {}
+
+ return render_template("username/search_usernames_result.html", dict_objects=dict_objects, search_result=search_result,
+ dict_page=dict_page, subtypes=ail_core.get_object_all_subtypes('username'),
+ to_search=to_search, subtype=subtype)
+
@objects_subtypes.route("/objects/user-accounts", methods=['GET'])
@login_required
@login_read_only
diff --git a/var/www/templates/chats_explorer/chats_protocols.html b/var/www/templates/chats_explorer/chats_protocols.html
index 6870a220..5cc914e4 100644
--- a/var/www/templates/chats_explorer/chats_protocols.html
+++ b/var/www/templates/chats_explorer/chats_protocols.html
@@ -70,6 +70,12 @@
+
+
+ {% with subtypes=username_subtypes %}
+ {% include 'username/block_usernames_search.html' %}
+ {% endwith %}
+
diff --git a/var/www/templates/objects/subtypes_objs_dashboard.html b/var/www/templates/objects/subtypes_objs_dashboard.html
index 15c30f5a..3113864e 100644
--- a/var/www/templates/objects/subtypes_objs_dashboard.html
+++ b/var/www/templates/objects/subtypes_objs_dashboard.html
@@ -76,28 +76,35 @@
Subtype | +ID | +First Seen | +Last Seen | +NB Seen | +Sparkline | +
---|---|---|---|---|---|
+ {% with style=dict_objects[obj_id]['icon']['style'], icon=dict_objects[obj_id]['icon']['icon'] , color=dict_objects[obj_id]['icon']['color'] %} + {% include 'objects/obj_svg_block.html' %} + {% endwith %} + {{ dict_objects[obj_id]['subtype'] }} + | ++ + {{ dict_objects[obj_id]['id'][:search_result[obj_id]['hl-start']] }}{{dict_objects[obj_id]['id'][search_result[obj_id]['hl-start']:search_result[obj_id]['hl-end']]}}{{ dict_objects[obj_id]['id'][search_result[obj_id]['hl-end']:] }} + + | ++ {% if dict_objects[obj_id]['first_seen'] %} + {{ dict_objects[obj_id]['first_seen'][0:4] }}-{{ dict_objects[obj_id]['first_seen'][4:6] }}-{{ dict_objects[obj_id]['first_seen'][6:8] }} + {% endif %} + | ++ {% if dict_objects[obj_id]['last_seen'] %} + {{ dict_objects[obj_id]['last_seen'][0:4] }}-{{ dict_objects[obj_id]['last_seen'][4:6] }}-{{ dict_objects[obj_id]['last_seen'][6:8] }} + {% endif %} + | +{{ dict_objects[obj_id]['nb_seen'] }} + | ++ |