diff --git a/gajim/common/logger.py b/gajim/common/logger.py index c6cd0c576..439d14984 100644 --- a/gajim/common/logger.py +++ b/gajim/common/logger.py @@ -32,6 +32,7 @@ import os import sys import time import datetime +import calendar import json from collections import namedtuple from gzip import GzipFile @@ -766,42 +767,45 @@ class Logger: return self.con.execute(sql, (*jids, query)).fetchall() - def get_days_with_logs(self, jid, year, month, max_day, account): + def get_days_with_logs(self, account, jid, year, month): """ - Return the list of days that have logs (not status messages) + Request the days in a month where we received messages + for a given `jid`. + + :param account: The account + + :param jid: The jid for which we request the days + + :param year: The year + + :param month: The month + + returns a list of namedtuples """ - try: - self.get_jid_id(jid) - except exceptions.PysqliteOperationalError: - # Error trying to create a new jid_id. This means there is no log - return [] - days_with_logs = [] - where_sql, jid_tuple = self._build_contact_where(account, jid) + jids = self._get_family_jids(account, jid) - # First select all date of month whith logs we want - start_of_month = self.get_unix_time_from_date(year, month, 1) - seconds_in_a_day = 86400 # 60 * 60 * 24 - last_second_of_month = start_of_month + (seconds_in_a_day * max_day) - 1 + kinds = map(str, [KindConstant.STATUS, + KindConstant.GCSTATUS]) - # Select times and 'floor' them to time 0:00 - # (by dividing, they are integers) - # and take only one of the same values (distinct) - # Now we have timestamps of time 0:00 of every day with logs - self.cur.execute(''' - SELECT DISTINCT time/(86400)*86400 as time FROM logs - WHERE (%s) - AND time BETWEEN %d AND %d - AND kind NOT IN (%d, %d) + # Calculate the start and end datetime of the month + date = datetime.datetime(year, month, 1) + days = calendar.monthrange(year, month)[1] - 1 + delta = datetime.timedelta( + days=days, hours=23, minutes=59, seconds=59, microseconds=999999) + + sql = """ + SELECT DISTINCT + CAST(strftime('%d', time, 'unixepoch', 'localtime') AS INTEGER) + AS day FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) + AND time BETWEEN ? AND ? + AND kind NOT IN ({kinds}) ORDER BY time - ''' % (where_sql, start_of_month, last_second_of_month, - KindConstant.STATUS, KindConstant.GCSTATUS), jid_tuple) - result = self.cur.fetchall() + """.format(jids=', '.join('?' * len(jids)), + kinds=', '.join(kinds)) - # convert timestamps to day of month - for line in result: - days_with_logs[0:0]=[time.gmtime(line.time)[2]] - - return days_with_logs + return self.con.execute(sql, (*jids, + date.timestamp(), + (date + delta).timestamp())).fetchall() def get_last_date_that_has_logs(self, jid, account=None, is_room=False): """ diff --git a/gajim/history_window.py b/gajim/history_window.py index 02e82d856..6d4258171 100644 --- a/gajim/history_window.py +++ b/gajim/history_window.py @@ -357,20 +357,18 @@ class HistoryWindow: widget.select_day(1) return - # in gtk January is 1, in python January is 0, - # I want the second - # first day of month is 1 not 0 widget.clear_marks() month = gtkgui_helpers.make_gtk_month_python_month(month) - days_in_this_month = calendar.monthrange(year, month)[1] + try: - log_days = gajim.logger.get_days_with_logs(self.jid, year, month, - days_in_this_month, self.account) + log_days = gajim.logger.get_days_with_logs( + self.account, self.jid, year, month) except exceptions.PysqliteOperationalError as e: dialogs.ErrorDialog(_('Disk Error'), str(e)) return - for day in log_days: - widget.mark_day(day) + + for date in log_days: + widget.mark_day(date.day) def _get_string_show_from_constant_int(self, show): if show == ShowConstant.ONLINE: