Open rdiasfreitas opened 9 years ago
You should find asyncore out correctly and use it to get the good result! Just call asyncore.loop in new thread and don't use yowstack.loop directly and make new instance(yowstack) with new credentials again and again... no problem! several SIMs at the same time can be connected without any problem! But i think this asyncore is obsolete and i'm in doubt about using it by Tgalal!!!
Hi @emamirazavi
That's amazing, it's really working the way you suggested! Thanks a lot!
I come from a Java world, and I'm very familiar with multi-thread applications... But I'm just trying to figure it out how the Python world works. And I can tell you, it's not so easy to understand and start coding low level functions.
I've got this exception every time I restarted the application, I think it's related to some kind of synchronization, but I'm not sure how to start digging about that. Could you please help me?
asyncore.loop()
File "/usr/lib/python2.7/asyncore.py", line 216, in loop poll_fun(timeout, map) File "/usr/lib/python2.7/asyncore.py", line 156, in poll read(obj) File "/usr/lib/python2.7/asyncore.py", line 87, in read obj.handle_error() File "/usr/lib/python2.7/asyncore.py", line 83, in read obj.handle_read_event() File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event self.handle_read() File "/storage/projetos/my_project/venv/lib/python2.7/site-packages/yowsup/layers/network/layer.py", line 47, in handle_read data = self.recv(readSize) File "/usr/lib/python2.7/asyncore.py", line 387, in recv data = self.socket.recv(buffer_size) error: [Errno 11] Resource temporarily unavailable
Probably this exception reads when you stop(terminate) your code. Does it?
On Tue, Mar 3, 2015 at 6:34 AM, Rodrigo Freitas notifications@github.com wrote:
Hi @emamirazavi https://github.com/emamirazavi
That's amazing, it's really working the way you suggested! Thanks a lot!
I come from a Java world, and I'm very familiar with multi-thread applications... But I'm just trying to figure it out how the Python world works. And I can tell you, it's not so easy to understand and start coding low level functions.
I've got this exception every time I restarted the application, I think it's related to some kind of synchronization, but I'm not sure how to start digging about that. Could you please help me?
asyncore.loop()
File "/usr/lib/python2.7/asyncore.py", line 216, in loop poll_fun(timeout, map) File "/usr/lib/python2.7/asyncore.py", line 156, in poll read(obj) File "/usr/lib/python2.7/asyncore.py", line 87, in read obj.handle_error() File "/usr/lib/python2.7/asyncore.py", line 83, in read obj.handle_read_event() File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event self.handle_read() File "/storage/projetos/my_project/venv/lib/python2.7/site-packages/yowsup/layers/network/layer.py", line 47, in handle_read data = self.recv(readSize) File "/usr/lib/python2.7/asyncore.py", line 387, in recv data = self.socket.recv(buffer_size) error: [Errno 11] Resource temporarily unavailable
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-76878619.
No, it's just after the start...
Where do you use asyncore.loop?! You should use in a thread
import threading
loop_thread = threading.Thread(target=asyncore.loop, name="Asyncore Loop")# If you want to make the thread a daemon# loop_thread.daemon = True loop_thread.start()
On Tue, Mar 3, 2015 at 7:06 AM, Rodrigo Freitas notifications@github.com wrote:
No, it's just after the start...
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-76881257.
If in your view, everything is okay, what just stays suspicious is your stack starter! See yowsup demos more accurate. To start see EchoClient. Everything you want to start is there.
On Tue, Mar 3, 2015 at 7:10 AM, S.Mohammad Emami Razavi < emamirazavi@gmail.com> wrote:
Where do you use asyncore.loop?! You should use in a thread
import threading
loop_thread = threading.Thread(target=asyncore.loop, name="Asyncore Loop")# If you want to make the thread a daemon# loop_thread.daemon = True loop_thread.start()
On Tue, Mar 3, 2015 at 7:06 AM, Rodrigo Freitas notifications@github.com wrote:
No, it's just after the start...
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-76881257.
Hmm, I did the changes you suggested, but the error is still happening. I was spawning a new thread, and calling asyncore.loop inside the run(self), I think this would have the same behavior. I will dedicate more time studying this issue, and I will keep you posted if I find something.
Thanks for the help
@rdiasfreitas did it work out with you?
@rdiasfreitas @emamirazavi does this work? I've implemented the stuff mentioned here but its unstable. each thread disconnects the other... any solution?
it works! i moved all my multi-threaded code to asyncore and it is working now.
@yniv Can you give any specifics about your solution? I've tried the following solution:
def login(self): self.logger.debug("CLIENT: Iniciando login para %s", self.credentials) self.layer.init() self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: self.stack.loop() except (KeyboardInterrupt, SystemExit): self.logger.error("CLIENT: Interrupcao forcada") return False except AuthError as e: self.logger.error("CLIENT: Erro de autenticacao!\n%s", e.message) # Desabilita o telefone self.disable_sender() return False def call(self, method, params): return self.layer.call(method, params)
The I call login method in a thread:
t[sender.id] = threading.Thread(target=stack_list[sender.id].login) t[sender.id].daemon = True t[sender.id].start()
Calling the call method still producess the error:
stack_list[recipient.sender.id].call( 'message_send', [recipient.get_full_phone(), campaign.message] )
This code still producess the error:
Exception in thread Thread-2: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 763, in run self.__target(*self.__args, **self.__kwargs) File "/vagrant/web/src/djyowsup/client/stack.py", line 61, in login self.stack.loop() File "/home/vagrant/.virtualenvs/plataforma_marketing_web/src/yowsup2/yowsup/stacks/yowstack.py", line 195, in loop asyncore.loop(*args, **kwargs) File "/usr/lib/python2.7/asyncore.py", line 216, in loop poll_fun(timeout, map) File "/usr/lib/python2.7/asyncore.py", line 156, in poll read(obj) File "/usr/lib/python2.7/asyncore.py", line 87, in read obj.handle_error() File "/usr/lib/python2.7/asyncore.py", line 83, in read obj.handle_read_event() File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event self.handle_read() File "/home/vagrant/.virtualenvs/plataforma_marketing_web/src/yowsup2/yowsup/layers/network/layer.py", line 85, in handle_read data = self.recv(readSize) File "/usr/lib/python2.7/asyncore.py", line 387, in recv data = self.socket.recv(buffer_size) error: [Errno 11] Resource temporarily unavailable
Can you give more details regarding the loop in asyncore ? Thank you!
@funnybones the asyncore.loop() should be called only once in your server main(). you don't need to call stack.loop(). you don't need threads if you work with asyncore (only if you want an input thread or something like that)
hope that helps. ask me specific questions and i'll try to help more.
@yniv thanks for the reply. I want to implement 2 numbers receiving messages in the same time. Unfortunately, I cannot come up with the flow for this. Can you guide me ?
Yowstack constructor does this. For each client you must call yowstack separately. You must not call asyncore.loop after calling each yowstack and it must be called once(see asyncore documentation). On Dec 17, 2015 7:31 PM, "Alexandru Serban" notifications@github.com wrote:
@yniv https://github.com/yniv thanks for the reply. I want to implement 2 numbers receiving messages in the same time. Unfortunately, I cannot come up with the flow for this. Can you guide me ?
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-165494006.
Can you post a small piece of c9de where you connect 2 clients ? Thabk you!
How do you start more than one stack and NOT call asyncore.loop more than once? Isn't starting one stack callilng asycore.loop? Apologies if my question sounds too dumb.
Alex, please search for asyncore.loop in Yowsup. Finally it will be found in the method. You must handle the method manually! I have no time to send my code and after all this feature must not be developed by yowsup as Tgalal mentioned me beforehand. It's not difficult and can make you more sophisticated in Yowsup coding.
see this file: https://github.com/tgalal/yowsup/blob/a59ac410c057e8042c528e9f73e9f3eaada6e79e/yowsup/stacks/yowstack.py
you must not call YowStack.loop and you should pay attention that asyncore exists in Network layer. For each client finally you have a certain NetworkLayer extending asyncore.dispatcher_with_send and YowLayer
see this file: https://github.com/tgalal/yowsup/blob/92dcf0a54f663848e806411117d2f8bb1c0bda0b/yowsup/layers/network/layer.py
Give me a feedback.
On Sat, Dec 19, 2015 at 6:04 PM, Alex notifications@github.com wrote:
How do you start more than one stack and NOT call asyncore.loop more than once? Isn't starting one stack callilng asycore.loop? Apologies if my question sounds too dumb.
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-165990254.
Hi, here is how I did it. I added the following lines on line 198 of yowstack.py
def newLoop(self,isDaemon,onException,*args,**kwargs):
if "discrete" in kwargs:
discreteVal = kwargs["discrete"]
del kwargs["discrete"]
def discreteLoop(*args,**kwargs):
while True:
asyncore.loop(*args, **kwargs)
time.sleep(discreteVal)
try:
callback = self.__class__.__detachedQueue.get(False) #doesn't block
callback()
except Queue.Empty:
pass
t1=threading.Thread(target=discreteLoop,args=args,kwargs=kwargs)
else:
t1=threading.Thread(target=asyncore.loop,args=args,kwargs=kwargs)
t1.daemon=isDaemon
try:
t1.start()
except Exception as e:
onException(e)
except OSError as e:
onException(e)
return t1
It creates one thread for each loop. You can call it like this from the stack:
def start(self):
self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
def onException(e):
...
t1=self.stack.newLoop(isDaemon=True,onException=onException,timeout = 0.5, discrete = 0.5) #
return t1
With this approach I have been able to create several threads, one for each line. But when I run disconnect() from the layer, asyncore fails with a 'Bad File Descriptor' error for one of the threads and all other threads disconnect.
And even then, I still get a [Errno 11] Resource temporarily unavailable, after a few minutes
I am planning to implement something similar. (Running different numbers on different threads) From what I've understood about asyncore from different sites is that if you are planning to use asyncore on multiple threads, you should provide a global dictionary as the parameter, "map", to the dispatcher's constructor. Plus pass this dictionary to each loop you start in each thread.
I am planning to modify the dispatcher to implement this. I'll keep you guys updated if it works.
Victor, asyncore itself supports multiple sessions, it can handle over almost 1k clients depends on your machine specifications, if the server supports. Therefore using threading is very vain and incorrect method! Asyncore uses eventlet to handle multiple connections. Yowsup uses threading just to handle ping of connection. On Dec 29, 2015 5:16 PM, "Victor Otieno" notifications@github.com wrote:
I am planning to implement something similar. (Running different numbers on different threads) From what I've understood about asyncore from different sites is that if you are planning to use asyncore on multiple threads, you should provide a global dictionary as the parameter, "map", to the dispatcher's constructor. Plus pass this dictionary to each loop you start in each thread.
I am planning to modify the dispatcher to implement this. I'll keep you guys updated if it works.
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-167793886.
I understand you. So in essence I can have three or more different stacks created under one thread and instead of calling the stack.loop of each stack, I call the asyncore.loop and they will work perfectly??
You can instantiate several stacks in single thread and don't call stack.loop. But then you must call asyncore.loop once. All things will go forward perfectly... asyncore.loop in one thread and all other instantiated stacks in one other thread. It means generally you need just two threads. After that you can trigger disconnect event to disconnect your client from WA server or instantiate new stack to connect your desire client to WA server freely without calling asyncore.loop again. Give me feedback.
On Wed, Dec 30, 2015 at 3:41 AM, Victor Otieno notifications@github.com wrote:
I understand you. So in essence I can have three or more different stacks created under one thread and instead of calling the stack.loop of each stack, I call the asyncore.loop and they will work perfectly??
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-167903286.
Thank you so much for your feedback. Dude you are a life saver. Let me do just that and I will get back to you with the results.
This is what I have tried:
def stackInitiator():
stack1 = YowStack(layers)
stack2 = YowStack(layers)
stack1.setCredentials(CREDENTIALS1)
stack2.setCredentials(CREDENTIALS2)
stack1.broadcastEvent(
YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
stack2.broadcastEvent(
YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
thread = threading.Thread(target=stackInitiator)
thread.start()
asyncore.loop(timeout=1.0)
and here is the output:
DEBUG:yowsup.stacks.yowstack:Initializing stack
DEBUG:yowsup.stacks.yowstack:Constructed Network Layer
DEBUG:yowsup.stacks.yowstack:Constructed Stanza Regulator Layer
DEBUG:yowsup.stacks.yowstack:Constructed Crypt Layer
DEBUG:yowsup.stacks.yowstack:Constructed Coder Layer
DEBUG:yowsup.stacks.yowstack:Constructed Logger Layer
DEBUG:yowsup.stacks.yowstack:Constructed Axolotl Layer
DEBUG:yowsup.stacks.yowstack:Constructed Authentication Layer - Messages Layer - Receipt Layer - Iq Layer - Ack Layer
DEBUG:yowsup.stacks.yowstack:Constructed Interface Layer
DEBUG:yowsup.stacks.yowstack:Initializing stack
DEBUG:yowsup.stacks.yowstack:Constructed Network Layer
DEBUG:yowsup.stacks.yowstack:Constructed Stanza Regulator Layer
DEBUG:yowsup.stacks.yowstack:Constructed Crypt Layer
DEBUG:yowsup.stacks.yowstack:Constructed Coder Layer
DEBUG:yowsup.stacks.yowstack:Constructed Logger Layer
DEBUG:yowsup.stacks.yowstack:Constructed Axolotl Layer
DEBUG:yowsup.stacks.yowstack:Constructed Authentication Layer - Messages Layer - Receipt Layer - Iq Layer - Ack Layer
DEBUG:yowsup.stacks.yowstack:Constructed Interface Layer
DEBUG:yowsup.layers.network.layer:Connecting to e9.whatsapp.net:443
DEBUG:yowsup.layers.network.layer:Connecting to e9.whatsapp.net:443
No error...It just stops..
Victor, it's better you postpone some seconds to trigger connect event after calling asyncore.loop(In fact you must trigger connect event after onconnect event of asyncore being called) and to prevent thread to die create a while loop at the end of stackInitiator method. Test it and give the feedback.
On Thu, Dec 31, 2015 at 2:10 PM, Victor Otieno notifications@github.com wrote:
This is what I have tried:
def stackInitiator(): stack1 = YowStack(layers) stack2 = YowStack(layers) stack1.setCredentials(CREDENTIALS1) stack2.setCredentials(CREDENTIALS2)
stack1.broadcastEvent( YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) stack2.broadcastEvent( YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) thread = threading.Thread(target=stackInitiator) thread.start() asyncore.loop(timeout=1.0)
and here is the output:
DEBUG:yowsup.stacks.yowstack:Initializing stack DEBUG:yowsup.stacks.yowstack:Constructed Network Layer DEBUG:yowsup.stacks.yowstack:Constructed Stanza Regulator Layer DEBUG:yowsup.stacks.yowstack:Constructed Crypt Layer DEBUG:yowsup.stacks.yowstack:Constructed Coder Layer DEBUG:yowsup.stacks.yowstack:Constructed Logger Layer DEBUG:yowsup.stacks.yowstack:Constructed Axolotl Layer DEBUG:yowsup.stacks.yowstack:Constructed Authentication Layer - Messages Layer - Receipt Layer - Iq Layer - Ack Layer DEBUG:yowsup.stacks.yowstack:Constructed Interface Layer DEBUG:yowsup.stacks.yowstack:Initializing stack DEBUG:yowsup.stacks.yowstack:Constructed Network Layer DEBUG:yowsup.stacks.yowstack:Constructed Stanza Regulator Layer DEBUG:yowsup.stacks.yowstack:Constructed Crypt Layer DEBUG:yowsup.stacks.yowstack:Constructed Coder Layer DEBUG:yowsup.stacks.yowstack:Constructed Logger Layer DEBUG:yowsup.stacks.yowstack:Constructed Axolotl Layer DEBUG:yowsup.stacks.yowstack:Constructed Authentication Layer - Messages Layer - Receipt Layer - Iq Layer - Ack Layer DEBUG:yowsup.stacks.yowstack:Constructed Interface Layer DEBUG:yowsup.layers.network.layer:Connecting to e9.whatsapp.net:443 DEBUG:yowsup.layers.network.layer:Connecting to e9.whatsapp.net:443
No error...It just stops..
— Reply to this email directly or view it on GitHub https://github.com/tgalal/yowsup/issues/666#issuecomment-168167127.
Ok.. Updating it with your recommendations.
problem is how to add layers after the core.loop?
Hi, I have created an http interface project that uses telegram bot api to communicate through whatsapp using yowsup. You can check it out here.
Unfortunately, I am having big trouble in connecting with several accounts simultaneously. In fact, I have resorted to using different docker containers, one for each account. I wonder if you can check it out and let me know how to make several accounts run in the same container.
I got it working with a very simple solution:
class Phones(object):
phs=[]
def __init__(self,cred):
self.cred=cred
self.__class__.phs.append(self)
stackBuilder = YowStackBuilder()
self.stack = stackBuilder\
.pushDefaultLayers(True)\
.push(EchoLayer)\
.build()
print("started for "+cred[0])
self.stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, self.cred)
self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
self.stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0])
self.stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN)
self.stack.setProp(YowCoderLayer.PROP_RESOURCE, YowsupEnv.getCurrent().getResource())
@classmethod
def start(cls):
asyncore.loop()
@classmethod
def send(cls,data):
for c in cls.phs:
if c.cred[0]+'@s.whatsapp.net'==data["phone_from"]:
c.stack.broadcastEvent(YowLayerEvent('send_message', message=data['message'], phone_to=data['phone_to']))
It is very easy to use:
CREDENTIALS=[('phone','pass')]
for cred in CREDENTIALS:
Phones(cred)
Phones.start()
I have tried a similar solution, but the code after self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
is never executed...
I could make it work for multiple lines, but had to comment out line 33 in dispatcher_asyncore.py
:
asyncore.loop(timeout=1)
This line was blocking the code, preventing other lines to connect to Whatsapp.
buenas, intento hacer un bot de WASAP con varias sesiones(diferentes numeros) pero al 2 numero, le responde lo que el 1 numero tiene q ver, porfavor alguien sabe como lo puedo solucionar para diferentes numeros?
Hi there Thanks for the beautiful work!
I'm working on a prototype that will need to have multiple sessions (different numbers) connected at the same time to whatsapp servers.
What I'm trying to do is:
1) I have a class ThisIsMyLayer(YowInterfaceLayer), that connects to my backend services 2) Stack declaration is implemented in a class that extends Threading, and I pass ThisIsMyLayer in the stack 3) There's a main Thread, that starts N other threads, one to each number I wish to get connected
The problem is that it looks like Yowsup was not built to be used with multiple sessions, and when the second session is started, the solution stops working.
Could you please offer me some guidance in how to perform such a thing?
Thanks
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.