Yowsup: A simple send message python script

Created on 24 Dec 2014  路  20Comments  路  Source: tgalal/yowsup

Hello every one,

Can anyone help me in writing a very basic send-message python script that simply connects, sends message, acknowledges the receipt, and disconnects.

Since last two days, I've been struggling with the code and the sample application, but can't get my head around this. The library is very well written but a bit difficult to comprehend for python newbies like me. Any help, hint, referrence etc. would be highly appreciated.

Best Regards,
Khizer

Most helpful comment

Hey guys, could somebody send the full script? Thanks

All 20 comments

Yeah I am also intersted in that,

I have also try to figure out how to send a simple text message from command line without results.
Also, the problem with yowsup-cli application is that if you want to have the application always running, listen for a new messages, the whatsapp server closed the connection after a while.

My suggestion to you would be to study the files under yousup/demos/cli and analyse the 3 files in depth, It will take time but at the end of the day you would be able to Create the desired application.

if you follow sample app demo try this:

layer.py

def message_send(self, number, content):
    outgoingMessage = TextMessageProtocolEntity(content, to=self.normalizeJid(number))
    self.toLower(outgoingMessage)

def normalizeJid(self, number):
    if '@' in number:
        return number

    return "%[email protected]" % number

run.py

 def send_msg(self, phone, body):
    layer = self.stack.getLayer(5)
    layer.message_send(phone, body)

@jnaxo Thank you very much for your reply. Really appreciate you helping us out. Your code example does give a very good hint.

I tried it out, this is my python code (layer.py and run.py combined in one file):
Executing the file shows no errors, but the message is not sent

from yowsup.layers.interface                            import YowInterfaceLayer, ProtocolEntityCallback
from yowsup.layers.auth                                 import YowAuthenticationProtocolLayer
from yowsup.layers.protocol_messages.protocolentities   import TextMessageProtocolEntity
from yowsup.layers.protocol_receipts.protocolentities   import OutgoingReceiptProtocolEntity
from yowsup.layers.protocol_acks.protocolentities       import OutgoingAckProtocolEntity
from yowsup.layers.protocol_messages                    import YowMessagesProtocolLayer
from yowsup.layers.protocol_receipts                    import YowReceiptProtocolLayer
from yowsup.layers.protocol_acks                        import YowAckProtocolLayer
from yowsup.layers.network                              import YowNetworkLayer
from yowsup.layers.coder                                import YowCoderLayer
from yowsup.stacks                                      import YowStack
from yowsup.common                                      import YowConstants
from yowsup.layers                                      import YowLayerEvent
from yowsup.stacks                                      import YowStack, YOWSUP_CORE_LAYERS

CREDENTIALS = ("123456789099", "MyPasswordHERE")

class TestLayer(YowInterfaceLayer):

    def message_send(self, number, content):
        outgoingMessage = TextMessageProtocolEntity(content, to=self.normalizeJid(number))
        self.toLower(outgoingMessage)

    def normalizeJid(self, number):
        if '@' in number:
            return number
        return "%[email protected]" % number

if __name__==  "__main__":

    layers = (
        TestLayer,
        (YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer)
    ) + YOWSUP_CORE_LAYERS

    stack = YowStack(layers)
    stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, CREDENTIALS)         #setting credentials
    stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0])    #whatsapp server address
    stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN)
    stack.setProp(YowCoderLayer.PROP_RESOURCE, YowConstants.RESOURCE)          #info about us as WhatsApp client

    stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))   #sending the connect signal

    #stack.loop()

    layer = stack.getLayer(5)
    layer.message_send("123456789099", "TestMessage")

Can you suggest what is missing here?

Thanks a lot again.

Best,
Khizer

Hello I'm trying the same and I can't do it works.I know very few things about python but I have knowledge about programming.I have layer.py and run.py. My code it's very similar as kxr and in layer.py and I'm trying to debug printing outgoingMessageProtocolEntity
You can see the result below:
Run.py:
from layer import Envio
from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer
from yowsup.layers.coder import YowCoderLayer
from yowsup.layers.network import YowNetworkLayer
from yowsup.layers.protocol_messages import YowMessagesProtocolLayer
from yowsup.layers.stanzaregulator import YowStanzaRegulator
from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer
from yowsup.layers.protocol_acks import YowAckProtocolLayer
from yowsup.stacks import YowStack
from yowsup.common import YowConstants
from yowsup.layers import YowLayerEvent

CREDENTIALS = ("XXXXXXXX", "XXXXXXXXXXXX") # replace with your phone and password

if name== "main":
layers = (
Envio,
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowCoderLayer,
YowCryptLayer,
YowStanzaRegulator,
YowNetworkLayer
)

stack = YowStack(layers)
stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, CREDENTIALS)         #setting credentials
stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0])    #whatsapp server address
stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN)
stack.setProp(YowCoderLayer.PROP_RESOURCE, YowConstants.RESOURCE)          #info about us as WhatsApp client

stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))   #sending the connect signal

body="Test"
telephone="XXXXXXXXX"
layer = stack.getLayer(5)
layer.message_send(body, telephone)

Layer.py:
from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity
from yowsup.layers import YowLayer

class Envio(YowLayer):

def message_send(self,content,number):

    outgoingMessageProtocolEntity = TextMessageProtocolEntity(content, to=number)
    print outgoingMessageProtocolEntity # I'm trying to debug
    self.toLower(outgoingMessageProtocolEntity)

When I run layer.py I see on screen the following:

Message:
ID: 1419938814-0
To: XXXXXXXX
Type: text
body: Test

I think message_send it's working but message does not arrive. Perhaps I'm not connected to whatsapp service or the message it's not been pass trought the correct layer.
I don't know why it's not working I think I'm missing with layers.
Thank you very much, regards.

I added a "send and exit" message demo, see here

Tarek,
Thank you very much for this wonderful library and for your effort and dedication!!!

In order to support sending a groups for the send and exit demo application, I have done these changes in the "yowsup/demos/sendclient/layer.py":

import threading

class SendLayer(YowInterfaceLayer):

    PROP_MESSAGES = "org.openwhatsapp.yowsup.prop.sendclient.queue" #list of (jid, message) tuples

    def __init__(self):
        super(SendLayer, self).__init__()
        self.ackQueue = []
        self.lock = threading.Condition()

    @ProtocolEntityCallback("success")
    def onSuccess(self, successProtocolEntity):
        self.lock.acquire()
        for target in self.getProp(self.__class__.PROP_MESSAGES, []):
            phone, message = target
            if '@' in phone:
                messageEntity = TextMessageProtocolEntity(message, to = phone)
            elif '-' in phone:
                messageEntity = TextMessageProtocolEntity(message, to = "%[email protected]" % phone)
            else:
                messageEntity = TextMessageProtocolEntity(message, to = "%[email protected]" % phone)
            print(phone)
            self.ackQueue.append(messageEntity.getId())
            self.toLower(messageEntity)
        self.lock.release()

    @ProtocolEntityCallback("ack")
    def onAck(self, entity):
        self.lock.acquire()
        if entity.getId() in self.ackQueue:
            self.ackQueue.pop(self.ackQueue.index(entity.getId()))

        if not len(self.ackQueue):
            self.lock.release()
            raise KeyboardInterrupt()

        self.lock.release()

So, now,
If you put a phone number with '-' (ex: 396458709-1419286200) it is sent to a whatsapp group.
If you put a simple phone number (ex:396709908) it is sent to a whatsapp number.
And if you put a complete whatsapp address (ex: [email protected]) it is sent to that whatsapp address.

Thanks again for your work and Happy New Year!!!

Agusti.

@tgalal Thank you so much. You are awesome!

@tinet Spot on!

Happy new year every body

Best Regards,
Khizer

Happy new year!!!
Thank you so much for your work and effort, it's incredible!!.

Best regards.

Hello everyone,

I want to send image file through yowsup, is there any way to send using command line same like sending message.

Hello everyone,

I want to make run.py call "yowsup/demos/sendclient/layer.py". I don't know to make that. would you like to explain or give an complete example please...

Hi Everyone! and thanks Tarek, this piece of code-art is wonderful!

I'm looking for the simples way to send a message, using:
MORE_IMPORTS_EXCLUDED in this message

from yowsup.demos import sendclient
unSender=sendclient.YowsupSendStack(CREDENTIALS, [(['mobile_number', 'message_text'])],True)
unSender.start()

And the message is sent, but as I can see in layer.py, it raises an exception to end the process.

I've been trying other examples, like the ones above, but If when I call send_message, it never gets out of the loop. If a comment the try_except block that makes the stack.loop(), the the message is sent, but subsequent calls to the function do not deliver the messages.

Additionally: the EchoLayer, sends the echo message an and works perfectly, using:

outgoingMessageProtocolEntity = TextMessageProtocolEntity( messageProtocolEntity.getBody(),
to = messageProtocolEntity.getFrom())
self.toLower(outgoingMessageProtocolEntity)

So, what if I create a method, in the EchoLayer class:
@ProtocolEntityCallback("send_message")
def sendMessage(self, destination, message, messageProtocolEntity):
print 'en sendMessage', destination, message, messageProtocolEntity
outgoingMessageProtocolEntity = TextMessageProtocolEntity(
message,
to = destination)
self.toLower(outgoingMessageProtocolEntity)

and use it lit this:

aSender=EchoLayer()
unSender.sendMessage('destination','text',messageProtocolEntity)

BUT, what is messajeProtocolEntity? is it the output of messageProtocolEntity=TextMessageProtocolEntity('message_text', to = 'wa_number')? It would be redundant. I do not not how to call the send_message method.

Can someone shed some light on this?

Many thanks in advance,
Diego

@tgalal after handling the onsuccess by passing the message to the self.toLower(messageEntity) do we have to send something back to the whatsapp server as a ack ? Can I get more clarity on why the number gets blocked. Or is there a way to be safe from getting blocked by whatspp ?

please send complete example...

Hey guys, could somebody send the full script? Thanks

Please send me full working script.

@kxr
assalamu'alaikum

dear kxr,
i have a problem that same with you about "how to write a very basic send-message python script that simply connects, sends message, acknowledges the receipt, and disconnects. have you found the solution?
please help me how to solve my problem. i cant read tarek's comment. i really need that script to finish my study.
thank you for your attention.

best regards
ilham hidayat

I have almost the same problem.

I want to run a python script on a RaspberryPI which permanently queries the status of a GPIO pin and writes a message when changing to high. So far no problem.

This works with the command
os.system('/usr/local/bin/yowsup-cli demos -c /home/pi/yowsup.config -s XXXXXXXXXXXXXXXX "Message"')
But it takes quite a long time until the message is sent because the yowsup-cli has to log in first.

Therefore I look for a way to register the pi permanently with yowsup and to send the message when the pin goes to high.

Can someone give me a hint?

@junky84 have you make the code when gpio goes high, the message should send.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Realitaetsverlust picture Realitaetsverlust  路  4Comments

bahtiarp picture bahtiarp  路  4Comments

EliasinnKamachoo picture EliasinnKamachoo  路  3Comments

mathslimin picture mathslimin  路  4Comments

mannemvamsi picture mannemvamsi  路  4Comments