Hi all,
Unfortunately, because of the webview processing, today the lib can't run multiple commands at the same time, i.e, make some works simultaneously like send multiple messages or read and send messages at the same time. Im developing a kind of chatbot, where interactions can start by my bot and not only from the client. That way i need to pool every time the unreaded messages (that locks other functions like send_message) and in other thread i need to send some messages (that needs to lock the read function).
The problem is: if i put a bigger sleep in the reader, to free a slot time for the sender, my chatbot will have a late response time and, in the other case, if i put a small sleep time, my sender queue can be locked when i have a large number of users.
As i can't use two instances of web whatsapp, i cant create a interface for reading and other for sending, that way i need to ask you, is there a way to get the unreaded messages assynchronous? like a kind of observable? that way i can lock the sender only when i really have a message to response.
Best.,
@brunosoaresds number will ban if you using multiple read/send message at same time
@brunosoaresds I'm working (slowly) in a refactor to avoid blocks. The idea is: it uses operation messages in order to perform actions asynchronously. It means, it calls any procedure using an operation message with an operation identifier. The result will be store in a queue (in browser) using this ID. So, only one function is called from python: "poll". The one argument is a list of new operation messages, and result is the list of results of already performed operations (it empties queue on each call). So, you need to call "poll" continuously, even you don't need to perform any action.
Operation result could be "final" (used on most of methods, it returns one entity) or "partial" (used on events and lists; it is created one per event emitted, or one per entity on list). There is another result type called "error". On list, when all items are already pushed, it will push a new error result called "StopIterator". In the same way, when a monitor is removed it will push same error.
From point of view of python, it will use Futures in order to await final results. And async iterators in order to get partial ones. So it requires Python 3.6+.
So, the idea is to create "monitors" to events which creates partial results on each emit. That should solve your issue.
But, all of this is work in progress...
@tarun82888 I think the probability of block using web WhatsApp is lower than using a emulator, I have made some tests in one number by in one week sending messages continuously and my results is no blocking, but yes, that’s could be a problem.
@alfred82santa
That’s a really good news. Today Im using python locks with a queue to “solve” that problem, but like a said, if my app locks continuously for reading, that could not have any messages to read, i lose a lot of time that can be used for sending.
Yesterday I have also studied the webehatsapp and I could create a event that can monitor when a new message arrives in the navigator. Now my problem is to create that observable scheme between JavaScript and python using the selenium api.
Best.,
@brunosoaresds @alfred82santa
After fixing the issue with the Window.Store thing, I have a problem that I don't receive unread messages like in the following loop:
for contact in driver.get_unread():
Did any of you manage to fix it? if so, can you please tell me how to bypass the problem?
Thanks
@MalkaBar
copy paste the code from pull request
Please, create a new issue for each problem. It's not easy to follow noisy threads. If you have already created one, and nobody replied it, maybe it's because we don't the response.
@alfred82santa, Sorry, I thought it is related to this topic.
If tarun's answer will not work I will create a new issue.
Thanks!
EDIT
I see the PR from @alfred82santa and he have fixed the erro that I have described below :).
@MalkaBar I think that have a interface bug in the python call of js function. I see that yesterday, if you look the wapi.js function, you can observe that the js function have 4 parameters (but the last param is the done function passes automatically by the driver when called by the selenium api). The problem is that the python caller is passing only 2 parameters, so the done function probably is being passed as the third argument and not the fourth, that way the done will be undefined and maybe the method will not return to python the result. I have not made a test yet because today I’m not in home, but you can test it and check if that is the problem. If it is, send a PR for us :)
@alfred82santa
Going back to that issue. I’m searching about how to call multiple times the done function inside a event subscription in the JavaScript to create my “observer” in python but without success. Do you know how I can do it??
Best.,
It's not possible. Selenium/webdriver don't wait for second call.
You could create a method to start function and another to check results polling it.
That’s bad, but I’m thinking if i can do it calling a async executor for each event call. Do you know if I can put a infinite timeout on async execute of selenium?
mmm I'm not an expert with selenium, but I would say there is not a timeout by default. Anyway, if there'd be an async method running, you could not call any method else. So, there would be a block...
Solution must be to call short running methods from selenium. And to let javascript to process long running stuff.
EDIT
Unfortunately, i have tested and the selenium does not support multi-threading scripts call, so i have created the logical like you commented @alfred82santa, i'm subscribed at the newMessage event and when a new message arrives i process it and save in a kind of buffer. In the python layer i have a thread pooling that "buffer" each time and if exists a subscriber, i send to then the new messages. I hope that selenium supports threading scripts soon...
Really? Even calling in another thread?
Great job @brunosoaresds!
It would be perfect if you could make an example which uses your observer-subscriber method for new messages.
EDIT
@chriso0710 one example was added by @GeovRodri in the PR #265
@chriso0710 you just need to create an object instance that implements the method on_message_received(new_messages) and subscribe it using the driver. subscribe_new_messages(observer_object_instance). I will create a script example and send it in a pull request.
Thanks :)
Most helpful comment
EDIT
@chriso0710 one example was added by @GeovRodri in the PR #265
@chriso0710 you just need to create an object instance that implements the method on_message_received(new_messages) and subscribe it using the driver. subscribe_new_messages(observer_object_instance). I will create a script example and send it in a pull request.
Thanks :)