mirror of https://github.com/CIRCL/AIL-framework
chg: [chats] add heatmap nb messages/hour for all messages
parent
ad039e4720
commit
87dc619171
|
@ -346,14 +346,21 @@ def api_get_chat(chat_id, chat_instance_uuid, translation_target=None, nb=-1, pa
|
||||||
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, nb=nb, page=page)
|
||||||
return meta, 200
|
return meta, 200
|
||||||
|
|
||||||
def api_get_nb_message_by_week(chat_id, chat_instance_uuid):
|
def api_get_nb_message_by_week(chat_type, chat_instance_uuid, chat_id):
|
||||||
chat = Chats.Chat(chat_id, chat_instance_uuid)
|
chat = get_obj_chat(chat_type, chat_instance_uuid, chat_id)
|
||||||
if not chat.exists():
|
if not chat.exists():
|
||||||
return {"status": "error", "reason": "Unknown chat"}, 404
|
return {"status": "error", "reason": "Unknown chat"}, 404
|
||||||
week = chat.get_nb_message_this_week()
|
week = chat.get_nb_message_this_week()
|
||||||
# week = chat.get_nb_message_by_week('20231109')
|
# week = chat.get_nb_message_by_week('20231109')
|
||||||
return week, 200
|
return week, 200
|
||||||
|
|
||||||
|
def api_get_nb_week_messages(chat_type, chat_instance_uuid, chat_id):
|
||||||
|
chat = get_obj_chat(chat_type, chat_instance_uuid, chat_id)
|
||||||
|
if not chat.exists():
|
||||||
|
return {"status": "error", "reason": "Unknown chat"}, 404
|
||||||
|
week = chat.get_nb_week_messages()
|
||||||
|
return week, 200
|
||||||
|
|
||||||
def api_get_chat_participants(chat_type, chat_subtype, chat_id):
|
def api_get_chat_participants(chat_type, chat_subtype, chat_id):
|
||||||
if chat_type not in ['chat', 'chat-subchannel', 'chat-thread']:
|
if chat_type not in ['chat', 'chat-subchannel', 'chat-thread']:
|
||||||
return {"status": "error", "reason": "Unknown chat type"}, 400
|
return {"status": "error", "reason": "Unknown chat type"}, 400
|
||||||
|
|
|
@ -89,7 +89,7 @@ class Message(AbstractObject):
|
||||||
|
|
||||||
def get_date(self):
|
def get_date(self):
|
||||||
timestamp = self.get_timestamp()
|
timestamp = self.get_timestamp()
|
||||||
return datetime.fromtimestamp(float(timestamp)).strftime('%Y%m%d')
|
return datetime.utcfromtimestamp(float(timestamp)).strftime('%Y%m%d')
|
||||||
|
|
||||||
def get_timestamp(self):
|
def get_timestamp(self):
|
||||||
dirs = self.id.split('/')
|
dirs = self.id.split('/')
|
||||||
|
@ -250,7 +250,7 @@ class Message(AbstractObject):
|
||||||
timestamp = self.get_timestamp()
|
timestamp = self.get_timestamp()
|
||||||
else:
|
else:
|
||||||
timestamp = float(timestamp)
|
timestamp = float(timestamp)
|
||||||
timestamp = datetime.fromtimestamp(float(timestamp))
|
timestamp = datetime.utcfromtimestamp(float(timestamp))
|
||||||
meta['date'] = timestamp.strftime('%Y/%m/%d')
|
meta['date'] = timestamp.strftime('%Y/%m/%d')
|
||||||
meta['hour'] = timestamp.strftime('%H:%M:%S')
|
meta['hour'] = timestamp.strftime('%H:%M:%S')
|
||||||
meta['full_date'] = timestamp.isoformat(' ')
|
meta['full_date'] = timestamp.isoformat(' ')
|
||||||
|
|
|
@ -51,8 +51,6 @@ class AbstractChatObject(AbstractSubtypeObject, ABC):
|
||||||
# get useraccount / username
|
# get useraccount / username
|
||||||
# get users ?
|
# get users ?
|
||||||
# timeline name ????
|
# timeline name ????
|
||||||
# info
|
|
||||||
# created
|
|
||||||
# last imported/updated
|
# last imported/updated
|
||||||
|
|
||||||
# TODO get instance
|
# TODO get instance
|
||||||
|
@ -97,7 +95,7 @@ class AbstractChatObject(AbstractSubtypeObject, ABC):
|
||||||
def get_created_at(self, date=False):
|
def get_created_at(self, date=False):
|
||||||
created_at = self._get_field('created_at')
|
created_at = self._get_field('created_at')
|
||||||
if date and created_at:
|
if date and created_at:
|
||||||
created_at = datetime.fromtimestamp(float(created_at))
|
created_at = datetime.utcfromtimestamp(float(created_at))
|
||||||
created_at = created_at.isoformat(' ')
|
created_at = created_at.isoformat(' ')
|
||||||
return created_at
|
return created_at
|
||||||
|
|
||||||
|
@ -176,7 +174,7 @@ class AbstractChatObject(AbstractSubtypeObject, ABC):
|
||||||
def get_nb_message_by_hours(self, date_day, nb_day):
|
def get_nb_message_by_hours(self, date_day, nb_day):
|
||||||
hours = []
|
hours = []
|
||||||
# start=0, end=23
|
# start=0, end=23
|
||||||
timestamp = time.mktime(datetime.strptime(date_day, "%Y%m%d").timetuple())
|
timestamp = time.mktime(datetime.strptime(date_day, "%Y%m%d").utctimetuple())
|
||||||
for i in range(24):
|
for i in range(24):
|
||||||
timestamp_end = timestamp + 3600
|
timestamp_end = timestamp + 3600
|
||||||
nb_messages = r_object.zcount(f'messages:{self.type}:{self.subtype}:{self.id}', timestamp, timestamp_end)
|
nb_messages = r_object.zcount(f'messages:{self.type}:{self.subtype}:{self.id}', timestamp, timestamp_end)
|
||||||
|
@ -197,6 +195,34 @@ class AbstractChatObject(AbstractSubtypeObject, ABC):
|
||||||
week_date = Date.get_current_week_day()
|
week_date = Date.get_current_week_day()
|
||||||
return self.get_nb_message_by_week(week_date)
|
return self.get_nb_message_by_week(week_date)
|
||||||
|
|
||||||
|
def get_nb_week_messages(self):
|
||||||
|
week = {}
|
||||||
|
# Init
|
||||||
|
for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']:
|
||||||
|
week[day] = {}
|
||||||
|
for i in range(24):
|
||||||
|
week[day][i] = 0
|
||||||
|
|
||||||
|
# chat
|
||||||
|
for mess_t in r_object.zrange(f'messages:{self.type}:{self.subtype}:{self.id}', 0, -1, withscores=True):
|
||||||
|
timestamp = datetime.utcfromtimestamp(float(mess_t[1]))
|
||||||
|
date_name = timestamp.strftime('%a')
|
||||||
|
week[date_name][timestamp.hour] += 1
|
||||||
|
|
||||||
|
subchannels = self.get_subchannels()
|
||||||
|
for gid in subchannels:
|
||||||
|
for mess_t in r_object.zrange(f'messages:{gid}', 0, -1, withscores=True):
|
||||||
|
timestamp = datetime.utcfromtimestamp(float(mess_t[1]))
|
||||||
|
date_name = timestamp.strftime('%a')
|
||||||
|
week[date_name][timestamp.hour] += 1
|
||||||
|
stats = []
|
||||||
|
nb_day = 0
|
||||||
|
for day in week:
|
||||||
|
for hour in week[day]:
|
||||||
|
stats.append({'date': day, 'day': nb_day, 'hour': hour, 'count': week[day][hour]})
|
||||||
|
nb_day += 1
|
||||||
|
return stats
|
||||||
|
|
||||||
def get_message_meta(self, message, timestamp=None, translation_target='', options=None): # TODO handle file message
|
def get_message_meta(self, message, timestamp=None, translation_target='', options=None): # TODO handle file message
|
||||||
message = Messages.Message(message[9:])
|
message = Messages.Message(message[9:])
|
||||||
if not options:
|
if not options:
|
||||||
|
@ -222,7 +248,7 @@ class AbstractChatObject(AbstractSubtypeObject, ABC):
|
||||||
mess, pagination = self._get_messages(nb=nb, page=page)
|
mess, pagination = self._get_messages(nb=nb, page=page)
|
||||||
for message in mess:
|
for message in mess:
|
||||||
timestamp = message[1]
|
timestamp = message[1]
|
||||||
date_day = datetime.fromtimestamp(timestamp).strftime('%Y/%m/%d')
|
date_day = datetime.utcfromtimestamp(timestamp).strftime('%Y/%m/%d')
|
||||||
if date_day != curr_date:
|
if date_day != curr_date:
|
||||||
messages[date_day] = []
|
messages[date_day] = []
|
||||||
curr_date = date_day
|
curr_date = date_day
|
||||||
|
|
|
@ -98,9 +98,23 @@ def chats_explorer_chat():
|
||||||
@login_required
|
@login_required
|
||||||
@login_read_only
|
@login_read_only
|
||||||
def chats_explorer_messages_stats_week():
|
def chats_explorer_messages_stats_week():
|
||||||
|
chat_type = request.args.get('type')
|
||||||
|
instance_uuid = request.args.get('subtype')
|
||||||
chat_id = request.args.get('id')
|
chat_id = request.args.get('id')
|
||||||
instance_uuid = request.args.get('uuid')
|
week = chats_viewer.api_get_nb_message_by_week(chat_type, instance_uuid, chat_id)
|
||||||
week = chats_viewer.api_get_nb_message_by_week(chat_id, instance_uuid)
|
if week[1] != 200:
|
||||||
|
return create_json_response(week[0], week[1])
|
||||||
|
else:
|
||||||
|
return jsonify(week[0])
|
||||||
|
|
||||||
|
@chats_explorer.route("chats/explorer/messages/stats/week/all", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_read_only
|
||||||
|
def chats_explorer_messages_stats_week_all():
|
||||||
|
chat_type = request.args.get('type')
|
||||||
|
instance_uuid = request.args.get('subtype')
|
||||||
|
chat_id = request.args.get('id')
|
||||||
|
week = chats_viewer.api_get_nb_week_messages(chat_type, instance_uuid, chat_id) # TODO SELECT DATE
|
||||||
if week[1] != 200:
|
if week[1] != 200:
|
||||||
return create_json_response(week[0], week[1])
|
return create_json_response(week[0], week[1])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<script src="{{ url_for('static', filename='js/jquery.daterangepicker.min.js') }}"></script>#}
|
<script src="{{ url_for('static', filename='js/jquery.daterangepicker.min.js') }}"></script>#}
|
||||||
<script src="{{ url_for('static', filename='js/d3.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/d3.min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/d3/sparklines.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/d3/sparklines.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/d3/heatmap_week_hour.js')}}"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.chat-message-left,
|
.chat-message-left,
|
||||||
|
@ -180,6 +181,12 @@
|
||||||
<span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }} <span class="badge badge-light">{{ subchannel['tags_messages'][tag] }}</span></span>
|
<span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }} <span class="badge badge-light">{{ subchannel['tags_messages'][tag] }}</span></span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
<h5 class="mx-5 mt-2 text-secondary">All Messages:</h5>
|
||||||
|
<div id="heatmapweekhourall"></div>
|
||||||
|
|
||||||
|
<h5 class="mx-5 text-secondary">This week:</h5>
|
||||||
|
<div id="heatmapweekhour"></div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="list-group d-inline-block">
|
<div class="list-group d-inline-block">
|
||||||
{% for date in messages %}
|
{% for date in messages %}
|
||||||
|
@ -271,6 +278,17 @@ function toggle_sidebar(){
|
||||||
$('#core_content').addClass('col-lg-10')
|
$('#core_content').addClass('col-lg-10')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d3.json("{{ url_for('chats_explorer.chats_explorer_messages_stats_week_all') }}?type=chat-subchannel&subtype={{ subchannel['subtype'] }}&id={{ subchannel['id'] }}")
|
||||||
|
.then(function(data) {
|
||||||
|
create_heatmap_week_hour('#heatmapweekhourall', data);
|
||||||
|
})
|
||||||
|
|
||||||
|
d3.json("{{ url_for('chats_explorer.chats_explorer_messages_stats_week') }}?type=chat-subchannel&subtype={{ subchannel['subtype'] }}&id={{ subchannel['id'] }}")
|
||||||
|
.then(function(data) {
|
||||||
|
create_heatmap_week_hour('#heatmapweekhour', data);
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -166,7 +166,13 @@
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<h5 class="mx-5 mt-2 text-secondary">All Messages:</h5>
|
||||||
|
<div id="heatmapweekhourall"></div>
|
||||||
|
|
||||||
|
{% if not chat['subchannels'] %}
|
||||||
|
<h5 class="mx-5 text-secondary">This week:</h5>
|
||||||
<div id="heatmapweekhour"></div>
|
<div id="heatmapweekhour"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if chat['messages'] %}
|
{% if chat['messages'] %}
|
||||||
|
|
||||||
|
@ -258,11 +264,17 @@ function toggle_sidebar(){
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
d3.json("{{ url_for('chats_explorer.chats_explorer_messages_stats_week_all') }}?type=chat&subtype={{ chat['subtype'] }}&id={{ chat['id'] }}")
|
||||||
|
.then(function(data) {
|
||||||
|
create_heatmap_week_hour('#heatmapweekhourall', data);
|
||||||
|
})
|
||||||
|
|
||||||
d3.json("{{ url_for('chats_explorer.chats_explorer_messages_stats_week') }}?uuid={{ chat['subtype'] }}&id={{ chat['id'] }}")
|
{% if not chat['subchannels'] %}
|
||||||
|
d3.json("{{ url_for('chats_explorer.chats_explorer_messages_stats_week') }}?type=chat&subtype={{ chat['subtype'] }}&id={{ chat['id'] }}")
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
create_heatmap_week_hour('#heatmapweekhour', data);
|
create_heatmap_week_hour('#heatmapweekhour', data);
|
||||||
})
|
})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue