kwailo888 / AxolotlTestApp

9 stars 3 forks source link

number blocked over time #17

Closed Yeremi0589 closed 8 years ago

Yeremi0589 commented 8 years ago

Help Me Please...

I'm doing a Windows Service that what it does is basically read if there are messages to send, if any sends them, on the other hand receive messages from different users after received keep them in a database, the point is that this windows service I need this connected 24/7, I worked for several days, using the code AxolotlTestApp, but now when I want to login login tells me not-authorized and verified the number is blocked, just to make it clear I'm not used to spamming is an internal chat.

How could I keep my active service 24/7 without blocking me the number?

Real help kwailo888

Yeremi0589 commented 8 years ago

@kwailo888

kwailo888 commented 8 years ago

First thing first. have you modified my code so that the axolotl keys are stored in a database and not requested each time you login? if not then eventually you'll experience problems with the service. secondly when your sending your messages are you following the standard approach of a user .. for example sending typing, pause etc to simulate actual message writing or just sending the message? if your not simulating a users actions for typing etc then eventually whatsapp will detect you as a robot and block ..

Yeremi0589 commented 8 years ago

thank you very much for answering really I appreciate it, I have two months fighting with this project I try to do, by the way excuse my English is not the best, the first question I do not understand that you mean "have you modified my code so That the axolotl keys are stored in a database and not each time you login Requested? " I what I do really is to read database credentials to establish a connection with Whats App (sender, password, target) and then establish once wa.Connect () to what I understand there should already have a connection stable, however I think it is not so ... then the idea is to keep my active servico then sending wa.SendPing () and wa.SendActive () every 5 seconds to notify my active account and not fall into a timeout, I read in database if there is any message to send and if there is I realize sending: wa.SendMessage (result.PhoneNumber, result.Message), then in the event I wa_OnGetMessage receive messages coming into my account and store them in a database data, however the service sends and receives messages well for a while but after several messages sent and received meeting wa.ConnectionStatus this DISCONNECTED, as I said before my goal is not to use this service ever to SPAM what I want is make an internal chat between users of a website messages are sent, on the other hand how could simulate the regular behavior

Yeremi0589 commented 8 years ago

using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Data; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.ServiceProcess; using System.Text; using System.Threading; using System.Threading.Tasks; using WhatsAppApi; using WhatsAppApi.Account; using WhatsAppApi.Helper; using WhatsAppApi.Register; using WhatsAppApi.Response; using ExchangeRateUtils.BusinessLogic; using Timer = System.Timers.Timer;

namespace CreditForce.BackEnd.WhatsAppService { public partial class SMSWhatsApp : ServiceBase { private bool stopping = false; private AutoResetEvent stoppedEvent = new AutoResetEvent(false);

    public SMSWhatsApp()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        Thread.Sleep(45000);
        ThreadPool.QueueUserWorkItem(new WaitCallback(ServiceWorkerThread));
    }

    protected override void OnStop()
    {
        this.stopping = true;
        this.stoppedEvent.WaitOne();
    }

    // DEMO STORE SHOULD BE DATABASE OR PERMANENT MEDIA IN REAL CASE
    static IDictionary<string, axolotl_identities_object> axolotl_identities = new Dictionary<string, axolotl_identities_object>();
    static IDictionary<uint, axolotl_prekeys_object> axolotl_prekeys = new Dictionary<uint, axolotl_prekeys_object>();
    static IDictionary<uint, axolotl_sender_keys_object> axolotl_sender_keys = new Dictionary<uint, axolotl_sender_keys_object>();
    static IDictionary<string, axolotl_sessions_object> axolotl_sessions = new Dictionary<string, axolotl_sessions_object>();
    static IDictionary<uint, axolotl_signed_prekeys_object> axolotl_signed_prekeys = new Dictionary<uint, axolotl_signed_prekeys_object>();

    static WhatsApp wa = null;
    private void ServiceWorkerThread(object state)
    {
        ExchangeRateUtils.BusinessLogic.WhatsAppLogic whats = new WhatsAppLogic();
        var parameters =
            whats.GetParamtersWhatsApp(Convert.ToInt32(CreditForce.Common.DataContract.ServiceType.Collection));

        WhatsApp wa = new WhatsApp(parameters.PhoneNumber, parameters.Password, parameters.NickName, true);

        wa.OnGetMessage += wa_OnGetMessage;
        wa.OnGetMessageImage += wa_OnGetMessageImage;
        //ISessionStore AxolotlStore
        wa.OnstoreSession += wa_OnstoreSession;
        wa.OnloadSession += wa_OnloadSession;
        wa.OngetSubDeviceSessions += wa_OngetSubDeviceSessions;
        wa.OncontainsSession += wa_OncontainsSession;
        wa.OndeleteSession += wa_OndeleteSession;
        // IPreKeyStore AxolotlStore
        wa.OnstorePreKey += wa_OnstorePreKey;
        wa.OnloadPreKey += wa_OnloadPreKey;
        wa.OnloadPreKeys += wa_OnloadPreKeys;
        wa.OncontainsPreKey += wa_OncontainsPreKey;
        wa.OnremovePreKey += wa_OnremovePreKey;
        // ISignedPreKeyStore AxolotlStore
        wa.OnstoreSignedPreKey += wa_OnstoreSignedPreKey;
        wa.OnloadSignedPreKey += wa_OnloadSignedPreKey;
        wa.OnloadSignedPreKeys += wa_OnloadSignedPreKeys;
        wa.OncontainsSignedPreKey += wa_OncontainsSignedPreKey;
        wa.OnremoveSignedPreKey += wa_OnremoveSignedPreKey;
        // IIdentityKeyStore AxolotlStore
        wa.OngetIdentityKeyPair += wa_OngetIdentityKeyPair;
        wa.OngetLocalRegistrationId += wa_OngetLocalRegistrationId;
        wa.OnisTrustedIdentity += wa_OnisTrustedIdentity;
        wa.OnsaveIdentity += wa_OnsaveIdentity;
        wa.OnstoreLocalData += wa_OnstoreLocalData;
        // Error Notification ErrorAxolotl
        wa.OnErrorAxolotl += wa_OnErrorAxolotl;

        wa.Connect();
        string datFile = getDatFileName(parameters.PhoneNumber);
        byte[] nextChallenge = null;
        if (File.Exists(datFile))
        {
            try
            {
                string foo = File.ReadAllText(datFile);
                nextChallenge = Convert.FromBase64String(foo);
            }
            catch (Exception) { };
        }
        wa.Login(nextChallenge);
        wa.SendGetPrivacyList();
        wa.SendGetClientConfig();

        if (wa.LoadPreKeys() == null)
            wa.sendSetPreKeys(true);

        ProcessChat(wa);
    }

    private void ProcessChat(WhatsApp wa)
    {
        var thRecv = new Thread(t =>
        {
            try
            {
                while (wa != null)
                {
                    wa.PollMessages();
                    Thread.Sleep(100);
                    continue;
                }
            }
            catch (ThreadAbortException)
            {
            }
        })
        { IsBackground = true };
        thRecv.Start();
        while (!this.stopping)
        {
            Thread.Sleep(5000);
            ExchangeRateUtils.BusinessLogic.WhatsAppLogic whats = new WhatsAppLogic();
            var result = whats.GetWhatsApp();
            wa.SendPing();
            wa.SendActive();
            if (wa.ConnectionStatus == ApiBase.CONNECTION_STATUS.DISCONNECTED)
            {
                wa.Connect();
            }
            else
                if (!string.IsNullOrEmpty(result.Message) && !string.IsNullOrEmpty(result.PhoneNumber))
            {
                var respuesta = wa.SendMessage(result.PhoneNumber, result.Message);
                whats.MarkSentWhatsApp(respuesta.Substring(respuesta.IndexOf("=") + 1, respuesta.IndexOf(",") - respuesta.IndexOf("=") - 1), result.Id);
            }
        }
        this.stoppedEvent.Set();
    }

    static void wa_OnGetMessage(ProtocolTreeNode node, string from, string id, string name, string message, bool receipt_sent)
    {
        ExchangeRateUtils.BusinessLogic.WhatsAppLogic whatsAppLogic = new WhatsAppLogic();
        whatsAppLogic.GetReceiveWhatsApp(from.Split('@')[0], id, name, message);
    }

    static string getDatFileName(string pn)
    {
        string filename = string.Format("{0}.next.dat", pn);
        string path = "C:\\";
        return path + filename;
    }

    static void wa_OnGetMessageImage(ProtocolTreeNode mediaNode, string from, string id, string fileName, int size, string url, byte[] preview, string name)
    {
        ExchangeRateUtils.BusinessLogic.WhatsAppLogic whatsAppLogic = new WhatsAppLogic();
        whatsAppLogic.OnGetMessageImage(from.Split('@')[0], id, url, name);
    }

    // ALL NE REQUIRED INTERFACES FOR AXOLOTL ARE BELOW
    /// <summary>
    /// recieve all errormessgaes from the Axolotl process to record
    /// </summary>
    /// <param name="ErrorMessage"></param>
    static void wa_OnErrorAxolotl(string ErrorMessage)
    {
    }

    #region DATABASE BINDING FOR IIdentityKeyStore
    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="identityKey"></param>
    static bool wa_OnsaveIdentity(string recipientId, byte[] identityKey)
    {
        if (axolotl_identities.ContainsKey(recipientId))
            axolotl_identities.Remove(recipientId);

        axolotl_identities.Add(recipientId, new axolotl_identities_object()
        {
            recipient_id = recipientId,
            public_key = identityKey
        });

        return true;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="identityKey"></param>
    /// <returns></returns>
    static bool wa_OnisTrustedIdentity(string recipientId, byte[] identityKey)
    {
        axolotl_identities_object trusted;
        axolotl_identities.TryGetValue(recipientId, out trusted);
        return true; // (trusted == null || trusted.public_key.Equals(identityKey));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    static uint wa_OngetLocalRegistrationId()
    {
        axolotl_identities_object identity;
        axolotl_identities.TryGetValue("-1", out identity);
        return (identity == null) ? 000000 : uint.Parse(identity.registration_id);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    static List<byte[]> wa_OngetIdentityKeyPair()
    {
        List<byte[]> result = new List<byte[]> { };
        axolotl_identities_object identity;
        axolotl_identities.TryGetValue("-1", out identity);
        if (identity != null)
        {
            result.Add(identity.public_key);
            result.Add(identity.private_key);
        }

        if (result.Count == 0)
            return null;

        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="registrationId"></param>
    /// <param name="identityKeyPair"></param>
    static void wa_OnstoreLocalData(uint registrationId, byte[] publickey, byte[] privatekey)
    {
        if (axolotl_identities.ContainsKey("-1"))
            axolotl_identities.Remove("-1");

        axolotl_identities.Add("-1", new axolotl_identities_object()
        {
            recipient_id = "-1",
            registration_id = registrationId.ToString(),
            public_key = publickey,
            private_key = privatekey
        });

    }
    #endregion

    #region DATABASE BINDING FOR ISignedPreKeyStore
    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    static void wa_OnremoveSignedPreKey(uint preKeyId)
    {
        if (axolotl_signed_prekeys.ContainsKey(preKeyId))
            axolotl_signed_prekeys.Remove(preKeyId);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    /// <returns></returns>
    static bool wa_OncontainsSignedPreKey(uint preKeyId)
    {
        axolotl_signed_prekeys_object prekey;
        axolotl_signed_prekeys.TryGetValue(preKeyId, out prekey);
        return (prekey == null) ? false : true;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    static List<byte[]> wa_OnloadSignedPreKeys()
    {
        List<byte[]> result = new List<byte[]> { };
        foreach (axolotl_signed_prekeys_object key in axolotl_signed_prekeys.Values)
            result.Add(key.record);

        if (result.Count == 0)
            return null;

        return result;

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    /// <returns></returns>
    static byte[] wa_OnloadSignedPreKey(uint preKeyId)
    {
        axolotl_signed_prekeys_object prekey;
        axolotl_signed_prekeys.TryGetValue(preKeyId, out prekey);
        return (prekey == null) ? new byte[] { } : prekey.record;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="signedPreKeyId"></param>
    /// <param name="signedPreKeyRecord"></param>
    static void wa_OnstoreSignedPreKey(uint signedPreKeyId, byte[] signedPreKeyRecord)
    {
        if (axolotl_signed_prekeys.ContainsKey(signedPreKeyId))
            axolotl_signed_prekeys.Remove(signedPreKeyId);

        axolotl_signed_prekeys.Add(signedPreKeyId, new axolotl_signed_prekeys_object()
        {
            prekey_id = signedPreKeyId,
            record = signedPreKeyRecord
        });

    }
    #endregion

    #region DATABASE BINDING FOR IPreKeyStore
    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    static void wa_OnremovePreKey(uint preKeyId)
    {
        if (axolotl_prekeys.ContainsKey(preKeyId))
            axolotl_prekeys.Remove(preKeyId);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    /// <returns></returns>
    static bool wa_OncontainsPreKey(uint preKeyId)
    {
        axolotl_prekeys_object prekey;
        axolotl_prekeys.TryGetValue(preKeyId, out prekey);
        return (prekey == null) ? false : true;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="preKeyId"></param>
    /// <returns></returns>
    static byte[] wa_OnloadPreKey(uint preKeyId)
    {
        axolotl_prekeys_object prekey;
        axolotl_prekeys.TryGetValue(preKeyId, out prekey);
        return (prekey == null) ? new byte[] { } : prekey.record;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    static List<byte[]> wa_OnloadPreKeys()
    {
        List<byte[]> result = new List<byte[]> { };
        foreach (axolotl_prekeys_object key in axolotl_prekeys.Values)
            result.Add(key.record);

        if (result.Count == 0)
            return null;

        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="prekeyId"></param>
    /// <param name="preKeyRecord"></param>
    static void wa_OnstorePreKey(uint prekeyId, byte[] preKeyRecord)
    {
        if (axolotl_prekeys.ContainsKey(prekeyId))
            axolotl_prekeys.Remove(prekeyId);

        axolotl_prekeys.Add(prekeyId, new axolotl_prekeys_object()
        {
            prekey_id = prekeyId.ToString(),
            record = preKeyRecord
        });
    }
    #endregion

    #region DATABASE BINDING FOR ISessionStore
    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="deviceId"></param>
    static void wa_OndeleteSession(string recipientId, uint deviceId)
    {
        if (axolotl_sessions.ContainsKey(recipientId))
            axolotl_sessions.Remove(recipientId);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="deviceId"></param>
    /// <returns></returns>
    static bool wa_OncontainsSession(string recipientId, uint deviceId)
    {
        axolotl_sessions_object session;
        axolotl_sessions.TryGetValue(recipientId, out session);
        return (session == null) ? false : true;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <returns></returns>
    static List<uint> wa_OngetSubDeviceSessions(string recipientId)
    {
        List<uint> result = new List<uint> { };
        foreach (axolotl_sessions_object key in axolotl_sessions.Values)
            result.Add(key.device_id);

        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="deviceId"></param>
    /// <returns></returns>
    static byte[] wa_OnloadSession(string recipientId, uint deviceId)
    {
        axolotl_sessions_object session;
        axolotl_sessions.TryGetValue(recipientId, out session);
        return (session == null) ? new byte[] { } : session.record;

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipientId"></param>
    /// <param name="deviceId"></param>
    /// <param name="sessionRecord"></param>
    static void wa_OnstoreSession(string recipientId, uint deviceId, byte[] sessionRecord)
    {

        if (axolotl_sessions.ContainsKey(recipientId))
            axolotl_sessions.Remove(recipientId);

        axolotl_sessions.Add(recipientId, new axolotl_sessions_object()
        {
            device_id = deviceId,
            recipient_id = recipientId,
            record = sessionRecord
        });
    }
    #endregion
}

public class axolotl_identities_object
{
    public string recipient_id { get; set; }
    public string registration_id { get; set; }
    public byte[] public_key { get; set; }
    public byte[] private_key { get; set; }
}
public class axolotl_prekeys_object
{
    public string prekey_id { get; set; }
    public byte[] record { get; set; }

}
public class axolotl_sender_keys_object
{
    public uint sender_key_id { get; set; }
    public byte[] record { get; set; }
}
public class axolotl_sessions_object
{
    public string recipient_id { get; set; }
    public uint device_id { get; set; }
    public byte[] record { get; set; }
}
public class axolotl_signed_prekeys_object
{
    public uint prekey_id { get; set; }
    public byte[] record { get; set; }
}

}

alijundi commented 8 years ago

same here another number just got blocked by simply staying online and not sending anything!

pablokere commented 8 years ago

They block me one number per day. Only being online. Not send. Not receive. Why? Something we are doing wrong.

Saludos, Pablo El 12/3/2016 4:04, "alijundi" notifications@github.com escribió:

same here another number just got blocked by simply staying online and not sending anything!

— Reply to this email directly or view it on GitHub https://github.com/kwailo888/AxolotlTestApp/issues/17#issuecomment-195676426 .

alijundi commented 8 years ago

@kwailo888 do you know why this is happening? I am putting my work on hold until this is all figured out.

Yeremi0589 commented 8 years ago

just think, something we are doing wrong, @pablokerestezachi, just as I have suspended my project until I know the problem @alijundi , hopefully help us @kwailo888

kwailo888 commented 8 years ago

first thing first. If your not sending or receiving any messages there's no logical reason for whatsapp to block the number, I've had the same base code running in my production environment with more that 100 users on a single system without number blocking.. Unless the environment for whats app is different in various countries i don't see the code being the cause of blocking. Now that being said, obviously the number blocking is happening therefore I believe it's probably caused by how you use the base code to interact with the whatsapp service. There is a strict approach to the interaction with whatsapp and if they detect your not following their process they will identify you as a non standard client and probably block.

kwailo888 commented 8 years ago

@Yeremi0589 by keeping your account online 24/7 you are clearly showing whatsapp that your a bot service. no human client is online for that extended period of time. you should periodically disconnect and reconnect to the whatsapp service randomly. even if it's only for a minute or two but don't have a tracable pattern. remember that whatsapp is actively testing for bots or non standard client and blocking those accounts. the basic rule it that you must simulate the interactions of an average human. :)

kwailo888 commented 8 years ago

@Yeremi0589 the snippet of code below was only there for demonstration. you must reimplement the functions to store the keys in a permanent database

// DEMO STORE SHOULD BE DATABASE OR PERMANENT MEDIA IN REAL CASE static IDictionary<string, axolotl_identities_object> axolotl_identities = new Dictionary<string, axolotl_identities_object>(); static IDictionary<uint, axolotl_prekeys_object> axolotl_prekeys = new Dictionary<uint, axolotl_prekeys_object>(); static IDictionary<uint, axolotl_sender_keys_object> axolotl_sender_keys = new Dictionary<uint, axolotl_sender_keys_object>(); static IDictionary<string, axolotl_sessions_object> axolotl_sessions = new Dictionary<string, axolotl_sessions_object>(); static IDictionary<uint, axolotl_signed_prekeys_object> axolotl_signed_prekeys = new Dictionary<uint, axolotl_signed_prekeys_object>();

here's a link to a sample mysql database and function to implement: https://github.com/kwailo888/AxolotlTestApp/files/162661/sample.zip

Yeremi0589 commented 8 years ago

@kwailo888 clearly understand what you say and do is completely logical reason you give me why WhatsApp is blocking my numbers, a normal user will not find online 24/7, I must then have a better management of service and be online really only when I need it, that is when I send or receive a message, now before you get to work on what I've indicated I want to ask you a query: how I can receive messages with envent wa_OnGetMessage without being online, the above I ask because a normal user is not online when you receive a message, when he will read if I ask this because in my service I need detect when I get a message, however as said before I can not be connected 24/7

Yeremi0589 commented 8 years ago

@kwailo888 as the demo code that sent me good research will use to implement it, really thank you very much for all the contributions you make.

kwailo888 commented 8 years ago

@Yeremi0589 it's ok to stay online for long periods .. but you must configure your service to randomly go offline periodically. this is how a normal whatsapp client reacts. the system expects you to disconnect and reconnect randomly through the day. simulating standard 3G network connections as users move around. so a function to randomly disconnect then wait a few minutes and then reconnect should solve your issue :)