sanderdriesen / WhatsAPINet

A .NET WhatsApp API
32 stars 48 forks source link

Incorrect LastSeen time #20

Open Worldexe opened 8 years ago

Worldexe commented 8 years ago

I am trying to get LastSeen time for a certain phone (code simplified):

internal ctor()
{
    m_whatsApp = new WhatsApp(account.phone, account.password, nickname, true);
    m_whatsApp.OnGetLastSeen += OnGetLastSeen;
    m_whatsApp.Connect();
    m_whatsApp.Login();

    string phone = "xxxxxxxxxxx"; // True phone here
    WhatsUser whatsUser = new WhatsUserManager().CreateUser(phone, phone);
    m_whatsApp.SendQueryLastOnline(whatsUser.GetFullJid());
}

private void OnGetLastSeen(string from, DateTime lastSeen)
{
    // TODO: implement
    Trace("Got last seen: from " + from + ", lastSeen " + lastSeen);
}

I always get wrong and random (!) values. Two queries, immediately following one another, for the same phone, produce different (+/- 10 days!) results. For testing, I have two phone numbers, one of them does not have WhatsApp account at all, second one have it up and running (with official app), so I pretty sure about values I expect.

I checked sources (WhatsSendBase.handleIq()) and found nothing suspicious. I am able to send and recieve messages correctly, the problem is only about LastSeen time.

One more question - what I get, if there is no WhatsApp account for that phone?

Will appreciate any help, thanks.

sebas0066 commented 8 years ago

i have the same issue, any solution?.

Worldexe commented 8 years ago

It appears WA is not following XMPP strictly, this method of getting last user status does not work. To get user' status you need to use SendPresenceSubscriptionRequest() and listen to OnGetPresence event. Also, that event handling should look like this (see WhatsSendBase.cs:236)

                    if (ProtocolTreeNode.TagEquals(node, "presence"))
                    {
                        //presence node
                        string from = node.GetAttribute("from");
                        string type = node.GetAttribute("type");
                        string lastSeen = node.GetAttribute("last");

                        bool hasAccount = false;
                        DateTime? lastSeenDt= null;
                        if (!string.IsNullOrEmpty(lastSeen) && lastSeen != "none")
                        {
                            uint timestamp = uint.Parse(lastSeen);
                            lastSeenDt = timestamp.UnixToDate();
                            hasAccount = true;
                        }

                        this.fireOnGetPresence(from, hasAccount, type, lastSeenDt);
                    }

Event signature also should be changed.