From 28917aaf5647b6cc0c8e8d62d5dfe19fba48ef4b Mon Sep 17 00:00:00 2001
From: Yann Leboulanger <yann@leboulanger.org>
Date: Wed, 26 Jul 2017 22:24:19 +0200
Subject: [PATCH] Do not use XEP-0012 anymore to know idle time. Use XEP-0319

---
 data/gui/tooltip_roster_contact.ui         | 102 ++++++------------
 gajim/common/config.py                     |   1 -
 gajim/common/connection.py                 |  42 ++++----
 gajim/common/connection_handlers.py        |  21 +---
 gajim/common/connection_handlers_events.py |  35 ++-----
 gajim/common/contacts.py                   |  15 +--
 gajim/gui_interface.py                     |  95 +++++++----------
 gajim/remote_control.py                    |  10 --
 gajim/roster_window.py                     |   6 +-
 gajim/tooltips.py                          | 114 +++++----------------
 gajim/vcard.py                             |  30 ------
 11 files changed, 131 insertions(+), 340 deletions(-)

diff --git a/data/gui/tooltip_roster_contact.ui b/data/gui/tooltip_roster_contact.ui
index 2d9a3550c4..58e8d92c1a 100644
--- a/data/gui/tooltip_roster_contact.ui
+++ b/data/gui/tooltip_roster_contact.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.20.0 -->
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <object class="GtkGrid" id="tooltip_grid">
@@ -14,7 +14,6 @@
         <property name="halign">start</property>
         <property name="valign">start</property>
         <property name="use_markup">True</property>
-        <property name="xalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -29,8 +28,6 @@
         <property name="halign">start</property>
         <property name="valign">start</property>
         <property name="label" translatable="yes">Jabber ID:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -41,13 +38,12 @@
       <object class="GtkImage" id="avatar">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="xalign">0</property>
         <property name="stock">gtk-missing-image</property>
       </object>
       <packing>
         <property name="left_attach">2</property>
         <property name="top_attach">0</property>
-        <property name="height">14</property>
+        <property name="height">13</property>
       </packing>
     </child>
     <child>
@@ -55,9 +51,8 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Resource:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -70,8 +65,6 @@
         <property name="can_focus">False</property>
         <property name="halign">start</property>
         <property name="valign">start</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -83,9 +76,9 @@
       <object class="GtkLabel" id="resource">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -96,9 +89,9 @@
       <object class="GtkLabel" id="jid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
         <attributes>
           <attribute name="weight" value="bold"/>
         </attributes>
@@ -117,8 +110,6 @@
         <property name="label" translatable="yes">Status:</property>
         <property name="wrap">True</property>
         <property name="max_width_chars">40</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -130,63 +121,34 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Idle since:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
         <property name="top_attach">12</property>
       </packing>
     </child>
-    <child>
-      <object class="GtkLabel" id="idle_for_label">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="halign">start</property>
-        <property name="label" translatable="yes">Idle for:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
-      </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">13</property>
-      </packing>
-    </child>
     <child>
       <object class="GtkLabel" id="idle_since">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
         <property name="top_attach">12</property>
       </packing>
     </child>
-    <child>
-      <object class="GtkLabel" id="idle_for">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
-      </object>
-      <packing>
-        <property name="left_attach">1</property>
-        <property name="top_attach">13</property>
-      </packing>
-    </child>
     <child>
       <object class="GtkLabel" id="mood_label">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Mood:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -198,10 +160,9 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Activity:</property>
         <property name="lines">2</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -213,9 +174,8 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Tune:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -227,9 +187,8 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Location:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -240,9 +199,9 @@
       <object class="GtkLabel" id="mood">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -253,9 +212,8 @@
       <object class="GtkLabel" id="activity">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -266,9 +224,9 @@
       <object class="GtkLabel" id="tune">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -279,9 +237,9 @@
       <object class="GtkLabel" id="location">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -293,9 +251,8 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">OpenPGP:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -306,9 +263,9 @@
       <object class="GtkLabel" id="pgp">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -320,9 +277,8 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="label" translatable="yes">Subscription:</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -333,9 +289,9 @@
       <object class="GtkLabel" id="sub">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
@@ -346,11 +302,11 @@
       <object class="GtkLabel" id="status">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
         <property name="hexpand">True</property>
         <property name="wrap">True</property>
         <property name="max_width_chars">30</property>
-        <property name="xalign">0</property>
-        <property name="yalign">0</property>
         <attributes>
           <attribute name="style" value="italic"/>
         </attributes>
diff --git a/gajim/common/config.py b/gajim/common/config.py
index 25320b4dd1..33e2444a3f 100644
--- a/gajim/common/config.py
+++ b/gajim/common/config.py
@@ -293,7 +293,6 @@ class Config:
             'attach_notifications_to_systray': [opt_bool, False, _('If True, notification windows from notification-daemon will be attached to notification icon.')],
             'check_idle_every_foo_seconds': [opt_int, 2, _('Choose interval between 2 checks of idleness.')],
             'uri_schemes': [opt_str, 'aaa:// aaas:// acap:// cap:// cid: crid:// data: dav: dict:// dns: fax: file:/ ftp:// geo: go: gopher:// h323: http:// https:// iax: icap:// im: imap:// info: ipp:// iris: iris.beep: iris.xpc: iris.xpcs: iris.lwz: ldap:// mid: modem: msrp:// msrps:// mtqp:// mupdate:// news: nfs:// nntp:// opaquelocktoken: pop:// pres: prospero:// rtsp:// service: shttp:// sip: sips: sms: snmp:// soap.beep:// soap.beeps:// tag: tel: telnet:// tftp:// thismessage:/ tip:// tv: urn:// vemmi:// xmlrpc.beep:// xmlrpc.beeps:// z39.50r:// z39.50s:// about: apt: cvs:// daap:// ed2k:// feed: fish:// git:// iax2: irc:// ircs:// ldaps:// magnet: mms:// rsync:// ssh:// svn:// sftp:// smb:// webcal:// aesgcm://', _('Valid uri schemes. Only schemes in this list will be accepted as "real" uri. (mailto and xmpp are handled separately)'), True],
-            'ask_offline_status_on_connection': [ opt_bool, False, _('Request offline status messages from all contacts upon connecting. WARNING: This causes a lot of requests to be sent!') ],
             'shell_like_completion': [ opt_bool, False, _('If True, completion in groupchats will be like a shell auto-completion')],
             'show_self_contact': [opt_str, 'when_other_resource', _('When is self contact row displayed. Can be "always", "when_other_resource" or "never"'), True],
             'audio_input_device': [opt_str, 'autoaudiosrc ! volume name=gajim_vol'],
diff --git a/gajim/common/connection.py b/gajim/common/connection.py
index 127d7aa427..163cd144cf 100644
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -510,24 +510,6 @@ class CommonConnection:
     def account_changed(self, new_name):
         self.name = new_name
 
-    def request_last_status_time(self, jid, resource, groupchat_jid=None):
-        """
-        groupchat_jid is used when we want to send a request to a real jid and
-        act as if the answer comes from the groupchat_jid
-        """
-        if not gajim.account_is_connected(self.name):
-            return
-        to_whom_jid = jid
-        if resource:
-            to_whom_jid += '/' + resource
-        iq = nbxmpp.Iq(to=to_whom_jid, typ='get', queryNS=nbxmpp.NS_LAST)
-        id_ = self.connection.getAnID()
-        iq.setID(id_)
-        if groupchat_jid:
-            self.groupchat_jids[id_] = groupchat_jid
-        self.last_ids.append(id_)
-        self.connection.send(iq)
-
     def request_os_info(self, jid, resource):
         """
         To be implemented by derivated classes
@@ -649,11 +631,18 @@ class CommonConnection:
                 return -1
             was_invisible = self.connected == gajim.SHOW_LIST.index('invisible')
             self.connected = gajim.SHOW_LIST.index(show)
+            idle_time = None
+            if auto:
+                global HAS_IDLE
+                if HAS_IDLE and gajim.config.get('autoaway'):
+                    idle_sec = int(self.sleeper.getIdleSec())
+                    idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ',
+                        time.gmtime(time.time() - idle_sec))
             gajim.nec.push_incoming_event(BeforeChangeShowEvent(None,
                 conn=self, show=show, message=msg))
             if was_invisible:
                 self._change_from_invisible()
-            self._update_status(show, msg)
+            self._update_status(show, msg, idle_time=idle_time)
 
 class Connection(CommonConnection, ConnectionHandlers):
     def __init__(self, name):
@@ -2027,7 +2016,7 @@ class Connection(CommonConnection, ConnectionHandlers):
         if self.privacy_rules_supported:
             self.set_active_list('')
 
-    def _update_status(self, show, msg):
+    def _update_status(self, show, msg, idle_time=None):
         xmpp_show = helpers.get_xmpp_show(show)
         priority = gajim.get_priority(self.name, xmpp_show)
         p = nbxmpp.Presence(typ=None, priority=priority, show=xmpp_show)
@@ -2037,6 +2026,9 @@ class Connection(CommonConnection, ConnectionHandlers):
         signed = self.get_signed_presence(msg)
         if signed:
             p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
+        if idle_time:
+            idle = p.setTag('idle', namespace=nbxmpp.NS_IDLE)
+            idle.setAttr('since', idle_time)
         if self.connection:
             self.connection.send(p)
             self.priority = priority
@@ -2705,7 +2697,7 @@ class Connection(CommonConnection, ConnectionHandlers):
             destroy.setAttr('jid', jid)
         self.connection.send(iq)
 
-    def send_gc_status(self, nick, jid, show, status):
+    def send_gc_status(self, nick, jid, show, status, auto=False):
         if not gajim.account_is_connected(self.name):
             return
         if show == 'invisible':
@@ -2724,6 +2716,14 @@ class Connection(CommonConnection, ConnectionHandlers):
         if gajim.config.get('send_sha_in_gc_presence') and show != 'offline':
             p = self.add_sha(p, ptype != 'unavailable')
         self.add_lang(p)
+        if auto:
+            global HAS_IDLE
+            if HAS_IDLE and gajim.config.get('autoaway'):
+                idle_sec = int(self.sleeper.getIdleSec())
+                idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ',
+                    time.gmtime(time.time() - idle_sec))
+                idle = p.setTag('idle', namespace=nbxmpp.NS_IDLE)
+                idle.setAttr('since', idle_time)
         # send instantly so when we go offline, status is sent to gc before we
         # disconnect from jabber server
         self.connection.send(p)
diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py
index fe024b54b6..48443b590c 100644
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -874,8 +874,6 @@ class ConnectionHandlersBase:
         # keep the jids we auto added (transports contacts) to not send the
         # SUBSCRIBED event to gui
         self.automatically_added = []
-        # IDs of jabber:iq:last requests
-        self.last_ids = []
 
         # keep track of sessions this connection has with other JIDs
         self.sessions = {}
@@ -918,10 +916,6 @@ class ConnectionHandlersBase:
     def _nec_iq_error_received(self, obj):
         if obj.conn.name != self.name:
             return
-        if obj.id_ in self.last_ids:
-            gajim.nec.push_incoming_event(LastResultReceivedEvent(None,
-                conn=self, stanza=obj.stanza))
-            return True
 
     def _nec_presence_received(self, obj):
         account = obj.conn.name
@@ -972,7 +966,8 @@ class ConnectionHandlersBase:
                 obj.need_redraw = True
 
             if obj.old_show == obj.new_show and obj.contact.status == \
-            obj.status and obj.contact.priority == obj.prio: # no change
+            obj.status and obj.contact.priority == obj.prio and \
+            obj.contact.idle_time = obj.idle_time: # no change
                 return True
         else:
             obj.contact = gajim.contacts.get_first_contact_from_jid(account,
@@ -1029,12 +1024,8 @@ class ConnectionHandlersBase:
         else:
             # Do not override assigned key
             obj.contact.keyID = obj.keyID
-        if obj.timestamp:
-            obj.contact.last_status_time = localtime(obj.timestamp)
-        elif not gajim.block_signed_in_notifications[account]:
-            # We're connected since more that 30 seconds
-            obj.contact.last_status_time = localtime()
         obj.contact.contact_nickname = obj.contact_nickname
+        obj.contact.idle_time = obj.idle_time
 
         if gajim.jid_is_transport(jid):
             return
@@ -1178,11 +1169,6 @@ class ConnectionHandlersBase:
             fjid=frm, error_code=msg.getErrorCode(), error_msg=error_msg,
             msg=msgtxt, time_=tim, session=session, stanza=msg))
 
-    def _LastResultCB(self, con, iq_obj):
-        log.debug('LastResultCB')
-        gajim.nec.push_incoming_event(LastResultReceivedEvent(None, conn=self,
-            stanza=iq_obj))
-
     def get_sessions(self, jid):
         """
         Get all sessions for the given full jid
@@ -2246,7 +2232,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
         con.RegisterHandler('iq', self._TimeRevisedCB, 'get',
             nbxmpp.NS_TIME_REVISED)
         con.RegisterHandler('iq', self._LastCB, 'get', nbxmpp.NS_LAST)
-        con.RegisterHandler('iq', self._LastResultCB, 'result', nbxmpp.NS_LAST)
         con.RegisterHandler('iq', self._VersionResultCB, 'result',
             nbxmpp.NS_VERSION)
         con.RegisterHandler('iq', self._TimeRevisedResultCB, 'result',
diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py
index 73e09a1c67..707f433e8c 100644
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -138,34 +138,6 @@ class HttpAuthReceivedEvent(nec.NetworkIncomingEvent):
         self.msg = self.stanza.getTagData('body')
         return True
 
-class LastResultReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
-    name = 'last-result-received'
-    base_network_events = []
-
-    def generate(self):
-        self.get_id()
-        self.get_jid_resource(check_fake_jid=True)
-        if self.id_ in self.conn.last_ids:
-            self.conn.last_ids.remove(self.id_)
-
-        self.status = ''
-        self.seconds = -1
-
-        if self.stanza.getType() == 'error':
-            return True
-
-        qp = self.stanza.getTag('query')
-        if not qp:
-            return
-        sec = qp.getAttr('seconds')
-        self.status = qp.getData()
-        try:
-            self.seconds = int(sec)
-        except Exception:
-            return
-
-        return True
-
 class VersionResultReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
     name = 'version-result-received'
     base_network_events = []
@@ -825,6 +797,13 @@ PresenceHelperEvent):
         delay_tag = self.stanza.getTag('delay', namespace=nbxmpp.NS_DELAY2)
         if delay_tag:
             self._generate_timestamp(self.stanza.getTimestamp2())
+        # XEP-0319
+        self.idle_time = None
+        idle_tag = self.stanza.getTag('idle', namespace=nbxmpp.NS_IDLE)
+        if idle_tag:
+            time_str = idle_tag.getAttr('since')
+            tim = helpers.datetime_tuple(time_str)
+            self.idle_time = timegm(tim)
         xtags = self.stanza.getTags('x')
         for x in xtags:
             namespace = x.getNamespace()
diff --git a/gajim/common/contacts.py b/gajim/common/contacts.py
index 483131e120..76ae5a0a2b 100644
--- a/gajim/common/contacts.py
+++ b/gajim/common/contacts.py
@@ -94,8 +94,7 @@ class Contact(CommonContact):
     """
     def __init__(self, jid, account, name='', groups=None, show='', status='',
     sub='', ask='', resource='', priority=0, keyID='', client_caps=None,
-    our_chatstate=None, chatstate=None, last_status_time=None, msg_log_id=None,
-    last_activity_time=None):
+    our_chatstate=None, chatstate=None, idle_time=None, msg_log_id=None):
         if not isinstance(jid, str):
             print('no str')
         if groups is None:
@@ -113,8 +112,7 @@ class Contact(CommonContact):
         self.priority = priority
         self.keyID = keyID
         self.msg_log_id = msg_log_id
-        self.last_status_time = last_status_time
-        self.last_activity_time = last_activity_time
+        self.idle_time = idle_time
 
         self.pep = {}
 
@@ -248,8 +246,7 @@ class LegacyContactsAPI:
 
     def create_contact(self, jid, account, name='', groups=None, show='',
     status='', sub='', ask='', resource='', priority=0, keyID='',
-    client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None,
-    last_activity_time=None):
+    client_caps=None, our_chatstate=None, chatstate=None, idle_time=None):
         if groups is None:
             groups = []
         # Use Account object if available
@@ -258,8 +255,7 @@ class LegacyContactsAPI:
             show=show, status=status, sub=sub, ask=ask, resource=resource,
             priority=priority, keyID=keyID, client_caps=client_caps,
             our_chatstate=our_chatstate, chatstate=chatstate,
-            last_status_time=last_status_time,
-            last_activity_time=last_activity_time)
+            idle_time=idle_time)
 
     def create_self_contact(self, jid, account, resource, show, status, priority,
     name='', keyID=''):
@@ -288,8 +284,7 @@ class LegacyContactsAPI:
             resource=contact.resource, priority=contact.priority,
             keyID=contact.keyID, client_caps=contact.client_caps,
             our_chatstate=contact.our_chatstate, chatstate=contact.chatstate,
-            last_status_time=contact.last_status_time,
-            last_activity_time=contact.last_activity_time)
+            idle_time=contact.idle_time)
 
     def add_contact(self, account, contact):
         if account not in self._accounts:
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index 6d56d92b43..0dca40ac1b 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -568,30 +568,6 @@ class Interface:
             if obj.conn.name in self.show_vcard_when_connect:
                 self.show_vcard_when_connect.remove(obj.conn.name)
 
-    def handle_event_last_status_time(self, obj):
-        # ('LAST_STATUS_TIME', account, (jid, resource, seconds, status))
-        account = obj.conn.name
-        c = gajim.contacts.get_contact(account, obj.jid, obj.resource)
-        tooltip_window = self.roster.tree.get_tooltip_window()
-        if obj.seconds < 0:
-            if tooltip_window:
-                tooltip_window.update_last_time(c, True)
-            return
-
-        if c: # c can be none if it's a gc contact
-            if obj.status:
-                c.status = obj.status
-                self.roster.draw_contact(c.jid, account) # draw offline status
-            last_time = time.localtime(time.time() - obj.seconds)
-            if c.show == 'offline':
-                c.last_status_time = last_time
-            else:
-                c.last_activity_time = last_time
-
-            # Set last time on roster tooltip
-            if tooltip_window:
-                tooltip_window.update_last_time(c)
-
     def handle_event_gc_config(self, obj):
         #('GC_CONFIG', account, (jid, form_node))  config is a dict
         account = obj.conn.name
@@ -1148,12 +1124,6 @@ class Interface:
             notify.popup(event_type, jid, account, msg_type, path_to_image=path,
                     title=event_type, text=txt)
 
-    @staticmethod
-    def ask_offline_status(account):
-        for contact in gajim.contacts.iter_contacts(account):
-            gajim.connections[account].request_last_status_time(contact.jid,
-                contact.resource)
-
     def handle_event_signed_in(self, obj):
         """
         SIGNED_IN event is emitted when we sign in, so handle it
@@ -1164,10 +1134,6 @@ class Interface:
         gajim.block_signed_in_notifications[account] = True
         state = self.sleeper.getState()
         connected = obj.conn.connected
-        if gajim.config.get('ask_offline_status_on_connection'):
-            # Ask offline status in 1 minute so w'are sure we got all online
-            # presences
-            GLib.timeout_add_seconds(60, self.ask_offline_status, account)
         if state != sleepy.STATE_UNKNOWN and connected in (2, 3):
             # we go online or free for chat, so we activate auto status
             gajim.sleeper_state[account] = 'online'
@@ -1608,7 +1574,6 @@ class Interface:
             'jingle-error-received': [self.handle_event_jingle_error],
             'jingle-request-received': [self.handle_event_jingle_incoming],
             'jingleFT-cancelled-received': [self.handle_event_jingleft_cancel],
-            'last-result-received': [self.handle_event_last_status_time],
             'message-error': [self.handle_event_msgerror],
             'message-not-sent': [self.handle_event_msgnotsent],
             'message-sent': [self.handle_event_msgsent],
@@ -2282,33 +2247,47 @@ class Interface:
             if account not in gajim.sleeper_state or \
             not gajim.sleeper_state[account]:
                 continue
-            if state == sleepy.STATE_AWAKE and \
-            gajim.sleeper_state[account] in ('autoaway', 'autoxa'):
-                # we go online
-                self.roster.send_status(account, 'online',
+            if state == sleepy.STATE_AWAKE:
+                if gajim.sleeper_state[account] in ('autoaway', 'autoxa'):
+                    # we go online
+                    self.roster.send_status(account, 'online',
+                        gajim.status_before_autoaway[account])
+                    gajim.status_before_autoaway[account] = ''
+                    gajim.sleeper_state[account] = 'online'
+                if gajim.sleeper_state[account] == 'idle':
+                    # we go to the previous state
+                    connected = gajim.connections[account].connected
+                    self.roster.send_status(account, gajim.SHOW_LIST[connected],
                         gajim.status_before_autoaway[account])
-                gajim.status_before_autoaway[account] = ''
-                gajim.sleeper_state[account] = 'online'
-            elif state == sleepy.STATE_AWAY and \
-            gajim.sleeper_state[account] == 'online' and \
-            gajim.config.get('autoaway'):
-                # we save out online status
-                gajim.status_before_autoaway[account] = \
+                    gajim.status_before_autoaway[account] = ''
+                    gajim.sleeper_state[account] = 'off'
+            elif state == sleepy.STATE_AWAY and gajim.config.get('autoaway'):
+                if gajim.sleeper_state[account] == 'online':
+                    # we save out online status
+                    gajim.status_before_autoaway[account] = \
                         gajim.connections[account].status
-                # we go away (no auto status) [we pass True to auto param]
-                auto_message = gajim.config.get('autoaway_message')
-                if not auto_message:
-                    auto_message = gajim.connections[account].status
-                else:
-                    auto_message = auto_message.replace('$S', '%(status)s')
-                    auto_message = auto_message.replace('$T', '%(time)s')
-                    auto_message = auto_message % {
+                    # we go away (no auto status) [we pass True to auto param]
+                    auto_message = gajim.config.get('autoaway_message')
+                    if not auto_message:
+                        auto_message = gajim.connections[account].status
+                    else:
+                        auto_message = auto_message.replace('$S', '%(status)s')
+                        auto_message = auto_message.replace('$T', '%(time)s')
+                        auto_message = auto_message % {
                             'status': gajim.status_before_autoaway[account],
                             'time': gajim.config.get('autoawaytime')
-                            }
-                self.roster.send_status(account, 'away', auto_message,
-                    auto=True)
-                gajim.sleeper_state[account] = 'autoaway'
+                        }
+                    self.roster.send_status(account, 'away', auto_message,
+                        auto=True)
+                    gajim.sleeper_state[account] = 'autoaway'
+                elif gajim.sleeper_state[account] == 'off':
+                    # we save out online status
+                    gajim.status_before_autoaway[account] = \
+                        gajim.connections[account].status
+                    connected = gajim.connections[account].connected
+                    self.roster.send_status(account, gajim.SHOW_LIST[connected],
+                        gajim.status_before_autoaway[account], auto=True)
+                    gajim.sleeper_state[account] = 'idle'
             elif state == sleepy.STATE_XA and \
             gajim.sleeper_state[account] in ('online', 'autoaway',
             'autoaway-forced') and gajim.config.get('autoxa'):
diff --git a/gajim/remote_control.py b/gajim/remote_control.py
index 7209b967e9..685569690d 100644
--- a/gajim/remote_control.py
+++ b/gajim/remote_control.py
@@ -107,8 +107,6 @@ class Remote:
         bus_name = dbus.service.BusName(SERVICE, bus=session_bus)
         self.signal_object = SignalObject(bus_name)
 
-        gajim.ged.register_event_handler('last-result-received', ged.POSTGUI,
-            self.on_last_status_time)
         gajim.ged.register_event_handler('version-result-received', ged.POSTGUI,
             self.on_os_info)
         gajim.ged.register_event_handler('time-result-received', ged.POSTGUI,
@@ -150,10 +148,6 @@ class Remote:
         self.raise_signal('MessageSent', (obj.conn.name, [
             obj.jid, obj.message, obj.keyID, chatstate]))
 
-    def on_last_status_time(self, obj):
-        self.raise_signal('LastStatusTime', (obj.conn.name, [
-            obj.jid, obj.resource, obj.seconds, obj.status]))
-
     def on_os_info(self, obj):
         self.raise_signal('OsInfo', (obj.conn.name, [obj.jid, obj.resource,
             obj.client_info, obj.os_info]))
@@ -278,10 +272,6 @@ class SignalObject(dbus.service.Object):
     def VcardInfo(self, account_and_vcard):
         pass
 
-    @dbus.service.signal(INTERFACE, signature='av')
-    def LastStatusTime(self, account_and_array):
-        pass
-
     @dbus.service.signal(INTERFACE, signature='av')
     def OsInfo(self, account_and_array):
         pass
diff --git a/gajim/roster_window.py b/gajim/roster_window.py
index d23491259b..9b23f4c408 100644
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -2117,9 +2117,6 @@ class RosterWindow:
     def send_status(self, account, status, txt, auto=False, to=None):
         if status != 'offline':
             if to is None:
-                if status == gajim.connections[account].get_status() and \
-                txt == gajim.connections[account].status:
-                    return
                 gajim.config.set_per('accounts', account, 'last_status', status)
                 gajim.config.set_per('accounts', account, 'last_status_msg',
                         helpers.to_one_line(txt))
@@ -2194,7 +2191,8 @@ class RosterWindow:
                 if gc_control.account == account:
                     if gajim.gc_connected[account][gc_control.room_jid]:
                         gajim.connections[account].send_gc_status(
-                            gc_control.nick, gc_control.room_jid, status, txt)
+                            gc_control.nick, gc_control.room_jid, status, txt,
+                            auto=auto)
             if was_invisible and status != 'offline':
                 # We come back from invisible, join bookmarks
                 gajim.interface.auto_join_bookmarks(account)
diff --git a/gajim/tooltips.py b/gajim/tooltips.py
index 468bc336fb..389260b5d9 100644
--- a/gajim/tooltips.py
+++ b/gajim/tooltips.py
@@ -70,7 +70,6 @@ class BaseTooltip:
         self.win = None
         self.id = None
         self.cur_data = None
-        self.check_last_time = None
         self.shown = False
         self.position_computed = False
 
@@ -142,7 +141,7 @@ class BaseTooltip:
             self.screen.get_width() + half_width:
                 self.preferred_position[0] = self.screen.get_width() - \
                     rect.width
-            elif not self.check_last_time:
+            else:
                 self.preferred_position[0] -= half_width
             self.position_computed = True
         self.win.move(self.preferred_position[0], self.preferred_position[1])
@@ -184,7 +183,6 @@ class BaseTooltip:
             self.win = None
         self.id = None
         self.cur_data = None
-        self.check_last_time = None
         self.shown = False
 
 class StatusTable:
@@ -230,8 +228,8 @@ class StatusTable:
                 str_status += ' - <i>' + status + '</i>'
         return str_status
 
-    def add_status_row(self, file_path, show, str_status, status_time=None,
-    show_lock=False, indent=True):
+    def add_status_row(self, file_path, show, str_status, show_lock=False,
+    indent=True):
         """
         Append a new row with status icon to the table
         """
@@ -420,7 +418,6 @@ class RosterTooltip(Gtk.Window, StatusTable):
         StatusTable.__init__(self)
         self.create_table()
         self.row = None
-        self.check_last_time = {}
         self.contact_jid = None
         self.last_widget = None
         self.num_resources = 0
@@ -433,11 +430,10 @@ class RosterTooltip(Gtk.Window, StatusTable):
         self.xml = gtkgui_helpers.get_gtk_builder('tooltip_roster_contact.ui')
         for name in ('name', 'status', 'jid', 'user_show', 'fillelement',
             'resource', 'avatar', 'resource_label', 'pgp', 'pgp_label',
-                'jid_label', 'tooltip_grid', 'idle_since', 'idle_for',
-                'idle_since_label', 'idle_for_label', 'mood', 'tune',
-                'activity', 'location', 'tune_label', 'location_label',
-                'activity_label', 'mood_label', 'sub_label', 'sub',
-                'status_label'):
+                'jid_label', 'tooltip_grid', 'idle_since', 'idle_since_label',
+                'mood', 'tune', 'activity', 'location', 'tune_label',
+                'location_label', 'activity_label', 'mood_label', 'sub_label',
+                'sub', 'status_label'):
             setattr(self, name, self.xml.get_object(name))
 
         self.add(self.tooltip_grid)
@@ -612,8 +608,7 @@ class RosterTooltip(Gtk.Window, StatusTable):
 
                     status_line = self.get_status_info(acontact.resource,
                     acontact.priority, acontact.show, status)
-                    self.add_status_row(file_path, icon_name, status_line,
-                        acontact.last_status_time)
+                    self.add_status_row(file_path, icon_name, status_line)
                     if add_text:
                         self.add_text_row(acontact.status, 2)
 
@@ -621,31 +616,12 @@ class RosterTooltip(Gtk.Window, StatusTable):
             self.table.show_all()
 
         else:  # only one resource
-            if contact.show:
-                request_time = False
-                try:
-                    last_time = self.check_last_time[contact]
-                    if isinstance(last_time, float) and last_time < time.time() - 60:
-                        request_time = True
-                except KeyError:
-                    request_time = True
-
-                if request_time:
-                    if contact.show == 'offline':
-                        gajim.connections[account].\
-                            request_last_status_time(contact.jid, '')
-                    elif contact.resource:
-                        gajim.connections[account].\
-                            request_last_status_time(
-                            contact.jid, contact.resource)
-                    self.check_last_time[contact] = time.time()
-
-                if contact.status:
-                    status = contact.status.strip()
-                    if status:
-                        self.status.set_text(status)
-                        self.status.show()
-                        self.status_label.show()
+            if contact.show and contact.status:
+                status = contact.status.strip()
+                if status:
+                    self.status.set_text(status)
+                    self.status.show()
+                    self.status_label.show()
 
         # PEP Info
         self._append_pep_info(contact)
@@ -736,51 +712,24 @@ class RosterTooltip(Gtk.Window, StatusTable):
             self.location_label.show()
 
     def _set_idle_time(self, contact):
-        if contact.last_activity_time:
-            last_active = datetime(*contact.last_activity_time[:6])
+        if contact.idle_time:
+            idle_color = gajim.config.get('tooltip_idle_color')
+            idle_time = contact.idle_time
+            idle_time = time.localtime(contact.idle_time)
+            idle_time = datetime(*(idle_time[:6]))
             current = datetime.now()
-
-            diff = current - last_active
-            diff = timedelta(diff.days, diff.seconds)
-
-            if last_active.date() == current.date():
-                formatted = last_active.strftime("%X")
+            if idle_time.date() == current.date():
+                formatted = idle_time.strftime("%X")
             else:
-                formatted = last_active.strftime("%c")
-
-            # Do not show the "Idle since" and "Idle for" items if there
-            # is no meaningful difference between last activity time and
-            # current time.
-            if diff.days > 0 or diff.seconds > 0:
-                idle_color = gajim.config.get('tooltip_idle_color')
-                idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, formatted)
-                self.idle_since.set_markup(idle_markup)
-                self.idle_since.show()
-                self.idle_since_label.show()
-                idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, str(diff))
-                self.idle_for.set_markup(idle_markup)
-                self.idle_for_label.show()
-                self.idle_for.show()
+                formatted = idle_time.strftime("%c")
+            idle_markup = "<span foreground='{}'>{}</span>".format(idle_color,
+                formatted)
+            self.idle_since.set_markup(idle_markup)
+            self.idle_since.show()
+            self.idle_since_label.show()
 
         if contact.show and self.num_resources < 2:
             show = helpers.get_uf_show(contact.show)
-            if contact.last_status_time:
-                if contact.show == 'offline':
-                    text = ' - ' + _('Last status: %s')
-                else:
-                    text = _(' since %s')
-
-                if time.strftime('%j', time.localtime()) == \
-                        time.strftime('%j', contact.last_status_time):
-                    # it's today, show only the locale hour representation
-                    local_time = time.strftime('%X', contact.last_status_time)
-                else:
-                    # time.strftime returns locale encoded string
-                    local_time = time.strftime('%c', contact.last_status_time)
-
-                text = text % local_time
-                show += text
-
             # Contact is Groupchat
             if (self.account and
                     self.prim_contact.jid in gajim.gc_connected[self.account]):
@@ -805,15 +754,6 @@ class RosterTooltip(Gtk.Window, StatusTable):
             return contact.show
         return 'not in roster'
 
-    def update_last_time(self, contact, error=False):
-        if not contact:
-            return
-        if error:
-            self.check_last_time[contact] = 'error'
-            return
-        if contact.jid == self.contact_jid:
-            self._set_idle_time(contact)
-
 
 class FileTransfersTooltip(BaseTooltip):
     """
diff --git a/gajim/vcard.py b/gajim/vcard.py
index be3daf0f36..033b13283f 100644
--- a/gajim/vcard.py
+++ b/gajim/vcard.py
@@ -134,8 +134,6 @@ class VcardWindow:
 
         gajim.ged.register_event_handler('version-result-received', ged.GUI1,
             self.set_os_info)
-        gajim.ged.register_event_handler('last-result-received', ged.GUI2,
-            self.set_last_status_time)
         gajim.ged.register_event_handler('time-result-received', ged.GUI1,
             self.set_entity_time)
         gajim.ged.register_event_handler('vcard-received', ged.GUI1,
@@ -181,8 +179,6 @@ class VcardWindow:
             connection.store_annotations()
         gajim.ged.remove_event_handler('version-result-received', ged.GUI1,
             self.set_os_info)
-        gajim.ged.remove_event_handler('last-result-received', ged.GUI2,
-            self.set_last_status_time)
         gajim.ged.remove_event_handler('time-result-received', ged.GUI1,
             self.set_entity_time)
         gajim.ged.remove_event_handler('vcard-received', ged.GUI1,
@@ -294,13 +290,6 @@ class VcardWindow:
         self.clear_values()
         self.set_values(obj.vcard_dict)
 
-    def set_last_status_time(self, obj):
-        if obj.conn.name != self.account:
-            return
-        if obj.fjid != self.real_jid:
-            return
-        self.fill_status_label()
-
     def set_os_info(self, obj):
         if obj.conn.name != self.account:
             return
@@ -387,18 +376,12 @@ class VcardWindow:
             stats = helpers.get_uf_show(self.contact.show)
             if self.contact.status:
                 stats += ': ' + self.contact.status
-            if self.contact.last_status_time:
-                stats += '\n' + _('since %s') % time.strftime('%c',
-                        self.contact.last_status_time)
             for c in connected_contact_list:
                 if c.resource != self.contact.resource:
                     stats += '\n'
                     stats += helpers.get_uf_show(c.show)
                     if c.status:
                         stats += ': ' + c.status
-                    if c.last_status_time:
-                        stats += '\n' + _('since %s') % time.strftime('%c',
-                                c.last_status_time)
         else: # Maybe gc_vcard ?
             stats = helpers.get_uf_show(self.contact.show)
             if self.contact.status:
@@ -452,16 +435,6 @@ class VcardWindow:
         if not self.contact.status:
             self.contact.status = ''
 
-        # Request list time status only if contact is offline
-        if self.contact.show == 'offline':
-            if self.gc_contact:
-                j, r = gajim.get_room_and_nick_from_fjid(self.real_jid)
-                gajim.connections[self.account].request_last_status_time(j, r,
-                        self.contact.jid)
-            else:
-                gajim.connections[self.account].request_last_status_time(
-                        self.contact.jid, '')
-
         # do not wait for os_info if contact is not connected or has error
         # additional check for observer is needed, as show is offline for him
         if self.contact.show in ('offline', 'error')\
@@ -599,9 +572,6 @@ class ZeroconfVcardWindow:
                 stats += helpers.get_uf_show(c.show)
                 if c.status:
                     stats += ': ' + c.status
-                if c.last_status_time:
-                    stats += '\n' + _('since %s') % time.strftime('%c',
-                            c.last_status_time).decode(locale.getpreferredencoding())
                 one = False
         else: # Maybe gc_vcard ?
             stats = helpers.get_uf_show(self.contact.show)
-- 
GitLab