Bot Whatsapp en Python

Iniciado por ANTRAX, Febrero 22, 2017, 02:01:39 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Febrero 22, 2017, 02:01:39 PM Ultima modificación: Febrero 22, 2017, 02:41:18 PM por ANTRAX

Buenas, quería compartir un proyecto que tengo hace un tiempo con respecto a whatsapp, últimamente se esta poniendo muy difícil debido a los bloqueos, las actualizaciones que saca whatsapp para combatir esto, ademas que no tiene una api, las que se crearon o existen de forma no oficial están teniendo problemas.

Ya hace algún tiempo en github salieron apis para whatsapp, una de las primeras que use fue whatsapi después llamada No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, esta en php, si no me equivoco es la primera que salio, en base a esta se creo su equivalente en python llamada No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Para utilizar esta api primero hay que instalarla, después hacemos uso de sus clases en python.

El código que voy a compartir es básico, responde de acuerdo a algunas palabras claves, también cuenta con algunos scrapers de paginas, una de ellas es el No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, también cuenta con un monitor de inpres que tiene definido ciertos parámetros para enviar alertas,en el nuevo trabajo que estoy haciendo estoy tratando de implementar No tienes permitido ver los links. Registrarse o Entrar a mi cuenta como motor de respuestas.

Empecemos, primero instalar la api.

Código: bash
git clone https://github.com/tgalal/yowsup.git


ir a la carpeta env y editar el archivo No tienes permitido ver los links. Registrarse o Entrar a mi cuenta en github todavía no esta actualizado, no se por que pero no tiene los valores correctos y jode por el token, por lo que si no lo editan no podrán utilizar la api, No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Aquí están los tokens correctos

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Editar en ese archivo las variables

Código: text
_VERSION = "2.16.9"

_TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1471306425030{phone}"


Por

Código: text
_VERSION = "2.16.11"

_TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1478194306452{phone}"


Y con esto debería funcionar, ahora falta compilar de nuevo.

Código: bash
sudo python setup.py build


Instalar

Código: bash
sudo python setup.py install


Recomiendo comprar un chip descartable o prepago para registrar en whatsapp y utilizar la api, por los bloqueos, no queremos perder nuestra linea en whatsapp.

Procedemos a registrar nuestra linea, todo eso desde No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, el objetivo es registrar y obtener la clave que esta codificada en base64

Solicitamos el OTP

Código: bash
yowsup-cli registration --requestcode sms --phone 549XXXXXXXXXX --cc 54 --mcc 722 --mnc XX


mmc y mnc por pais

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Ejemplo

Código: bash
yowsup-cli registration --requestcode sms --phone 5493804651130 --cc 54 --mcc 722 --mnc 341


Debería salir en status : sent
mmc 722 corresponde a ARG
mnc 341 corresponde a PERSONAL

Antes de solicitar la OTP ponemos el chip en cualquier celular, solo nos interesa el sms con el código de activación
Una vez que nos llego

Código: bash
yowsup-cli registration --register XXXXX --phone 549XXXXXXXXXX --cc 54 -d


Ejemplo:

Código: bash
yowsup-cli registration --register 542301 --phone 5493804651130 --cc 54 -d


Si todo sale bien nos devolverá la clave.
ahora creamos un archivo con la configuración o credenciales.

Código: bash
nano 5493804651130.cfg


Dentro del mismo

cc=54
phone=549XXXXXXX
id=549XXXXXXX
password=b64pw

Ejemplo

cc=54
phone=5493804651130
id=5493804651130
password=m+S232dtFUfghljjKS12325pZmNELasdas=

Probamos todo en el cli.

Código: bash
yowsup-cli demos -c 5493804651130.cfg -e


-c = archivo de configuración creado anteriormente
-e = modo eco.

El modo eco, responde a todo lo que le enviamos.

Ahora probamos enviar un whatsapp que diga hola mundo a ese numero debería responder con hola mundo.

Si todo sale bien, estamos listos para utilizar el script.

DESCARGAR CODIGO: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Editar el array CREDENTIALS con sus datos en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Código: python
#!/usr/bin/python
# -*- coding: utf-8 -*-
from yowsup.stacks                             import YowStackBuilder
from yowsup.common                             import YowConstants
from yowsup.layers                             import YowLayerEvent
from layer                                     import EchoLayer
from yowsup.layers.auth                        import YowAuthenticationProtocolLayer
from yowsup.layers.coder                       import YowCoderLayer
from yowsup.layers.network                     import YowNetworkLayer
from yowsup.env                                import YowsupEnv
from scrapers.inpres                           import SCinpres
import threading, os, subprocess, time, sys

CREDENTIALS = ("549XXXXXXXXX", "pwB64")
laye = EchoLayer()

def workerinpress():
inpre = SCinpres()
print "Monitor inpres start\n"
while (True):
al = inpre.monitor()
if (al and al.strip() and al !='Error en consulta'):
print al
laye.envialertainpres(al)
time.sleep(1)

def workerwhatsapp():
stackBuilder = YowStackBuilder()
stack = stackBuilder.pushDefaultLayers(True).push(laye).build()
stack.setCredentials(CREDENTIALS)
stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0])
stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN)
stack.setProp(YowCoderLayer.PROP_RESOURCE, YowsupEnv.getCurrent().getResource())
stack.loop( timeout = 0.5, discrete = 0.5 )

if __name__==  "__main__":
threads = list()
moninp = threading.Thread(target=workerinpress)
threads.append(moninp)
wasa = threading.Thread(target=workerwhatsapp)
threads.append(wasa)
moninp.start()
wasa.start()


En No tienes permitido ver los links. Registrarse o Entrar a mi cuenta editar

permitidos=['5493834621141′,'5493834654414']   #Agregar los números a los cuales solo quieren responder

name = "Bort" #nombre del usuario
ALERTAN = ("[email protected]")  #numero al cual queremos enviar las alertas del impres

Código: python
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, subprocess, time, sys
from sys import exit
from yowsup.layers.interface                           import YowInterfaceLayer,ProtocolEntityCallback     
import mimetypes
from yowsup.layers.protocol_messages.protocolentities  import TextMessageProtocolEntity 
from yowsup.layers.protocol_presence.protocolentities  import AvailablePresenceProtocolEntity   
from yowsup.layers.protocol_presence.protocolentities  import UnavailablePresenceProtocolEntity
from yowsup.layers.protocol_presence.protocolentities  import PresenceProtocolEntity           
from yowsup.layers.protocol_chatstate.protocolentities import OutgoingChatstateProtocolEntity   
from yowsup.common.tools                               import Jid
from yowsup.layers.protocol_media.mediadownloader      import MediaDownloader
from yowsup.layers.protocol_media.protocolentities     import *
from respuesta                                         import Respuesta                             
import sys, shutil

permitidos=['5493834621141']
ac = set(permitidos)

name = "Bort"
ALERTAN = ("[email protected]")

class EchoLayer(YowInterfaceLayer):

@ProtocolEntityCallback("message")
def envialertainpres(self, al):
self.toLower(AvailablePresenceProtocolEntity())
time.sleep(0.5)
self.toLower(PresenceProtocolEntity(name = name))#Set presencia
time.sleep(0.5)
textmsg = TextMessageProtocolEntity
for tel in ALERTAN:
self.toLower(textmsg(al, to = tel))
time.sleep(0.4)
time.sleep(1)
self.toLower(UnavailablePresenceProtocolEntity())#Setoffline

@ProtocolEntityCallback("message")
def onMessage(self, messageProtocolEntity):
if messageProtocolEntity.getType() == 'text':
time.sleep(0.5)
self.toLower(messageProtocolEntity.ack())#Set visto
time.sleep(0.5)
self.toLower(AvailablePresenceProtocolEntity())
time.sleep(0.5)
self.toLower(PresenceProtocolEntity(name = name))#Set presencia
time.sleep(0.5)
self.toLower(messageProtocolEntity.ack(True))#Set doble visto
time.sleep(0.5)
self.toLower(OutgoingChatstateProtocolEntity(OutgoingChatstateProtocolEntity.STATE_TYPING, Jid.normalize(messageProtocolEntity.getFrom(False))))#Set esta escribiendo
time.sleep(1)
self.onTextMessage(messageProtocolEntity)#envia la respuesta
time.sleep(0.5)
self.toLower(OutgoingChatstateProtocolEntity(OutgoingChatstateProtocolEntity.STATE_PAUSED, Jid.normalize(messageProtocolEntity.getFrom(False))))#Set pausa
time.sleep(1)
self.toLower(UnavailablePresenceProtocolEntity())#Setoffline
elif messageProtocolEntity.getType() == 'media':
time.sleep(0.5)
self.toLower(AvailablePresenceProtocolEntity())
time.sleep(0.5)
self.toLower(PresenceProtocolEntity(name = name))#Set presencia
#self.onMediaMessage(messageProtocolEntity)
self.toLower(messageProtocolEntity.ack())
self.toLower(messageProtocolEntity.ack(True))
time.sleep(1)
self.toLower(UnavailablePresenceProtocolEntity())#Set offline
else:
pass

@ProtocolEntityCallback("receipt")
def onReceipt(self, entity):
print entity.ack()
self.toLower(entity.ack())

def onTextMessage(self,messageProtocolEntity):
namemitt   = messageProtocolEntity.getNotify()
message    = messageProtocolEntity.getBody()
recipient  = messageProtocolEntity.getFrom()
textmsg    = TextMessageProtocolEntity
if messageProtocolEntity.getFrom(False) in ac:
resp = Respuesta()
answer = resp.obtener(message,namemitt,recipient)
if answer and answer.strip():
if recipient.lower().find("-") == -1:
self.toLower(textmsg(answer, to = recipient ))
print answer+"\n Personal"
else:
self.toLower(textmsg(answer, to = recipient ))
print answer+"\n Grupo"
else:
answer = "Hola "+namemitt+", no estas en la lista de respuesta\n"
print recipient + "\n"
print message + "\n"
if recipient.lower().find("-") == -1:
time.sleep(1)
self.toLower(textmsg(answer, to = recipient))
print answer
else:
print answer

def onMediaMessage(self, messageProtocolEntity):
if messageProtocolEntity.getFrom(False) in ac:
if messageProtocolEntity.getMediaType() == "image":
url = messageProtocolEntity.url
self.extension = self.getExtension(messageProtocolEntity.getMimeType())
return self.downloadMedia(url)

def downloadMedia(self, url):
print("Descargando %s" % url)
downloader = MediaDownloader(self.onSuccess, self.onError, self.onProgress)
downloader.download(url)

def onError(self):
print "Error al descargar archivo"

def onSuccess(self, path):
outPath = "/home/yowsup/imgs/%s%s" % (os.path.basename(path), self.extension)
shutil.copyfile(path, outPath)
print("\nImagen descargada en %s" % outPath)

def onProgress(self, progress):
sys.stdout.write("Progreso descarga => %d%% \r" % progress)
sys.stdout.flush()

def getExtension(self, mimetype):
type = mimetypes.guess_extension(mimetype.split(';')[0])
if type is None:
raise Exception("Unsupported/unrecognized mimetype: "+mimetype);
return type


Por ultimo dentro de scrapers en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta editar a gusto

provincias = ['CATAMARCA','LA RIOJA','CORDOBA']#Las provincias que importan
mgtmax= 4.3 #valor igual o máximo del temblor para que envié la alerta al numero definido

Código: python
#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib2
import datetime
import time
from bs4 import BeautifulSoup
from controladores import Cinpresdb

class SCinpres:

    def __init__(self):
        pass

    def extraer(self):
url = 'http://www.inpres.gov.ar/desktop/'
formateado = ''
try:
respuesta = urllib2.urlopen(url)
datos = respuesta.read().decode('utf-8')
scrapsismo = BeautifulSoup(datos, "lxml")
tabla = scrapsismo.find("table", {"id" : "sismos"})
formateado = ''
registros = tabla.find_all('tr')
cantidadr = len(registros)
i=0
for reg in registros:
if (i>1 and i<cantidadr-3):
sctd = BeautifulSoup(str(reg), "lxml")
tds = sctd.find_all('td')
fecha = tds[1].text
hora = tds[2].text
mntud = tds[4].text
lugar = tds[7].text
formateado = formateado+"Fecha: "+fecha+" H: "+hora+" magnitud: "+mntud+" lugar: "+lugar+ "\n"
i += 1
except:
formateado = 'Error en consulta'
return formateado

    def monitor(self):
url = 'http://www.inpres.gov.ar/desktop/'
provincias = ['CATAMARCA','LA RIOJA','CORDOBA']
mgtmax= 4.3
hoyhora = datetime.datetime.now()
controlador = Cinpresdb()
i=0
tdin=0
ale=False
formateado = ''
try:
respuesta = urllib2.urlopen(url)
datos = respuesta.read().decode('utf-8')
scrapsismo = BeautifulSoup(datos, "lxml")
tabla = scrapsismo.find("table", {"id" : "sismos"})
registros = tabla.find_all('tr')
cantidadr = len(registros)
for reg in registros:
if (i>1 and i<cantidadr-3):
sctd = BeautifulSoup(str(reg), "lxml")
tds = sctd.find_all('td')
fechat = tds[1].text
horat = tds[2].text
proft = tds[3].text
mntud = float(tds[4].text)
magnitudt = tds[4].text
latt = tds[5].text
longt = tds[6].text
lugart = tds[7].text
h = datetime.datetime.strptime(fechat.strip()+" "+horat.strip(), '%d/%m/%Y %H:%M:%S')
ds_ts = time.mktime(hoyhora.timetuple())
dr_ts = time.mktime(h.timetuple())
diff = int(ds_ts-dr_ts) / 60
ck = controlador.checkdb(h,lugart)
if (lugart in provincias and ck==False):
controlador.inserta(h,proft,magnitudt,latt,longt,lugart)
if (mntud>mgtmax):
tdin = i
ale=True
formateado = "Alerta Temblor!!\nHace "+str(diff)+" min\n"
i += 1
if (ale==True):
formateado = formateado + registros[tdin].text
except:
formateado = 'Error en consulta'
return formateado


También almacena en una bd los valores que va recolectando del impres, de las provincias que vamos definiendo, esto es opcional y lo pueden sacar.

En fin, en el zip esta el .sql con la estructura de la tabla.

Si quisieran utilizarlo, en el archivo No tienes permitido ver los links. Registrarse o Entrar a mi cuenta que esta dentro de la carpeta de scrapers esta para que editen la conexión a la base de datos.

Si no quieren almacenar nada, editar el No tienes permitido ver los links. Registrarse o Entrar a mi cuenta que esta dentro de la carpeta de scrapers con este código

Código: python
#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib2
import datetime
import time
from bs4 import BeautifulSoup

class SCinpres:

    def __init__(self):
        pass

    def extraer(self):
url = 'http://www.inpres.gov.ar/desktop/'
formateado = ''
try:
respuesta = urllib2.urlopen(url)
datos = respuesta.read().decode('utf-8')
scrapsismo = BeautifulSoup(datos, "lxml")
tabla = scrapsismo.find("table", {"id" : "sismos"})
formateado = ''
registros = tabla.find_all('tr')
cantidadr = len(registros)
i=0
for reg in registros:
if (i>1 and i<cantidadr-3):
sctd = BeautifulSoup(str(reg), "lxml")
tds = sctd.find_all('td')
fecha = tds[1].text
hora = tds[2].text
mntud = tds[4].text
lugar = tds[7].text
formateado = formateado+"Fecha: "+fecha+" H: "+hora+" magnitud: "+mntud+" lugar: "+lugar+ "\n"
i += 1
except:
formateado = 'Error en consulta'
return formateado

    def monitor(self):
url = 'http://www.inpres.gov.ar/desktop/'
provincias = ['CATAMARCA','LA RIOJA','CORDOBA']
mgtmax= 4.3
hoyhora = datetime.datetime.now()
i=0
tdin=0
ale=False
formateado = ''
try:
respuesta = urllib2.urlopen(url)
datos = respuesta.read().decode('utf-8')
scrapsismo = BeautifulSoup(datos, "lxml")
tabla = scrapsismo.find("table", {"id" : "sismos"})
registros = tabla.find_all('tr')
cantidadr = len(registros)
for reg in registros:
if (i>1 and i<cantidadr-3):
sctd = BeautifulSoup(str(reg), "lxml")
tds = sctd.find_all('td')
fechat = tds[1].text
horat = tds[2].text
proft = tds[3].text
mntud = float(tds[4].text)
magnitudt = tds[4].text
latt = tds[5].text
longt = tds[6].text
lugart = tds[7].text
h = datetime.datetime.strptime(fechat.strip()+" "+horat.strip(), '%d/%m/%Y %H:%M:%S')
ds_ts = time.mktime(hoyhora.timetuple())
dr_ts = time.mktime(h.timetuple())
diff = int(ds_ts-dr_ts) / 60
if (lugart in provincias):
if (mntud>mgtmax):
tdin = i
ale=True
formateado = "Alerta Temblor!!\nHace "+str(diff)+" min\n"
i += 1
if (ale==True):
formateado = formateado + registros[tdin].text
except:
formateado = 'Error en consulta'
return formateado


Por ultimo correr el script

Código: bash
python run.py &


Si tienen algún vps o servidor dedicado pueden usar tmux, para que siga su ejecución después de cerrar la sesion ssh.

Código: bash
tmux
python run.py &


ctrl+b y luego presionar d
para volver a la sesión tmux

Código: bash
tmux attach


para salir nuevamente ctrl+b y luego presionar d
Para ver la lista de comandos del bot enviar la palabra:

ayuda


El codigo puede fallar a la primera ya que tiene algunas dependencias que no vienen instaladas con python por defecto. Los scrapers utilizan BeautifulSoup, MySQLdb y otros, que deberán ir instalando con pip install

Código: bash
pip install MySQLdb
pip install beautifulsoup


SI falla deberían parar el script con ctrl + z , ya que utiliza hilos.
Como conclusión, se pueden automatizar consultas procesos, responder consultas para empresas, todo usando de gateway whatsapp.




Actualización Fix 22/02/2017

Esta dando problemas al recibir contactos y audios la api, por lo que el script se detiene.

Reemplazar el código de  /usr/lib/python2.7/site-packages/yowsup2-2.5.0-py2.7.egg/yowsup/layers/axolotl/layer_receive.py

Código: python
from .layer_base import AxolotlBaseLayer

from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity
from yowsup.layers.protocol_messages.proto.wa_pb2 import *
from yowsup.layers.axolotl.protocolentities import *
from yowsup.structs import ProtocolTreeNode
from yowsup.layers.axolotl.props import PROP_IDENTITY_AUTOTRUST

from axolotl.protocol.prekeywhispermessage import PreKeyWhisperMessage
from axolotl.protocol.whispermessage import WhisperMessage
from axolotl.sessioncipher import SessionCipher
from axolotl.groups.groupcipher import GroupCipher
from axolotl.invalidmessageexception import InvalidMessageException
from axolotl.duplicatemessagexception import DuplicateMessageException
from axolotl.invalidkeyidexception import InvalidKeyIdException
from axolotl.nosessionexception import NoSessionException
from axolotl.untrustedidentityexception import UntrustedIdentityException
from axolotl.axolotladdress import AxolotlAddress
from axolotl.groups.senderkeyname import SenderKeyName
from axolotl.groups.groupsessionbuilder import GroupSessionBuilder
from axolotl.protocol.senderkeydistributionmessage import SenderKeyDistributionMessage

import logging
import copy
logger = logging.getLogger(__name__)
#/usr/lib/python2.7/site-packages/yowsup2-2.5.0-py2.7.egg/yowsup/layers/axolotl path fix
class AxolotlReceivelayer(AxolotlBaseLayer):
    def __init__(self):
        super(AxolotlReceivelayer, self).__init__()
        self.v2Jids = [] #people we're going to send v2 enc messages
        self.sessionCiphers = {}
        self.groupCiphers = {}
        self.pendingIncomingMessages = {} #(jid, participantJid?) => message

    def receive(self, protocolTreeNode):
        """
        :type protocolTreeNode: ProtocolTreeNode
        """
        if not self.processIqRegistry(protocolTreeNode):
            if protocolTreeNode.tag == "message":
                self.onMessage(protocolTreeNode)
            elif not protocolTreeNode.tag == "receipt":
                #receipts will be handled by send layer
                self.toUpper(protocolTreeNode)

            # elif protocolTreeNode.tag == "iq":
            #     if protocolTreeNode.getChild("encr_media"):
            #         protocolTreeNode.addChild("media", {
            #             "url": protocolTreeNode["url"],
            #             "ip": protocolTreeNode["ip"],
            #         })
            #         self.toUpper(protocolTreeNode)
            #         return

    ######

    def onEncrMediaResult(self, resultNode):
        pass


    def processPendingIncomingMessages(self, jid, participantJid = None):
        conversationIdentifier = (jid, participantJid)
        if conversationIdentifier in self.pendingIncomingMessages:
            for messageNode in self.pendingIncomingMessages[conversationIdentifier]:
                self.onMessage(messageNode)

            del self.pendingIncomingMessages[conversationIdentifier]

    ##### handling received data #####

    def onMessage(self, protocolTreeNode):
        encNode = protocolTreeNode.getChild("enc")
        if encNode:
            self.handleEncMessage(protocolTreeNode)
        else:
            self.toUpper(protocolTreeNode)

    def handleEncMessage(self, node):
        encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
        isGroup =  node["participant"] is not None
        senderJid = node["participant"] if isGroup else node["from"]
        if node.getChild("enc")["v"] == "2" and node["from"] not in self.v2Jids:
            self.v2Jids.append(node["from"])
        try:
            if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG):
                self.handlePreKeyWhisperMessage(node)
            elif encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG):
                self.handleWhisperMessage(node)
            if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG):
                self.handleSenderKeyMessage(node)
        except (InvalidMessageException, InvalidKeyIdException) as e:
            logger.warning("InvalidMessage or KeyId for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False))
            retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode(node, self.store.getLocalRegistrationId())
            self.toLower(retry.toProtocolTreeNode())
        except NoSessionException as e:
            logger.warning("No session for %s, getting their keys now", encMessageProtocolEntity.getAuthor(False))

            conversationIdentifier = (node["from"], node["participant"])

            if conversationIdentifier not in self.pendingIncomingMessages:
                self.pendingIncomingMessages[conversationIdentifier] = []
            self.pendingIncomingMessages[conversationIdentifier].append(node)

            successFn = lambda successJids, b: self.processPendingIncomingMessages(*conversationIdentifier) if len(successJids) else None

            self.getKeysFor([senderJid], successFn)

        except DuplicateMessageException as e:
            logger.warning("Received a message that we've previously decrypted, goint to send the delivery receipt myself")
            self.toLower(OutgoingReceiptProtocolEntity(node["id"], node["from"], participant=node["participant"]).toProtocolTreeNode())

        except UntrustedIdentityException as e:
            if self.getProp(PROP_IDENTITY_AUTOTRUST, False):
                logger.warning("Autotrusting identity for %s", e.getName())
                self.store.saveIdentity(e.getName(), e.getIdentityKey())
                return self.handleEncMessage(node)
            else:
                logger.error("Ignoring message with untrusted identity")

    def handlePreKeyWhisperMessage(self, node):
        pkMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
        enc = pkMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG)
        preKeyWhisperMessage = PreKeyWhisperMessage(serialized=enc.getData())
        sessionCipher = self.getSessionCipher(pkMessageProtocolEntity.getAuthor(False))
        plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage)
        if enc.getVersion() == 2:
            paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord(plaintext[-1])
            padding = paddingByte & 0xFF
            self.parseAndHandleMessageProto(pkMessageProtocolEntity, plaintext[:-padding])
        else:
            self.handleConversationMessage(node, plaintext)

    def handleWhisperMessage(self, node):
        encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)

        enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG)
        whisperMessage = WhisperMessage(serialized=enc.getData())
        sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getAuthor(False))
        plaintext = sessionCipher.decryptMsg(whisperMessage)

        if enc.getVersion() == 2:
            paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord(plaintext[-1])
            padding = paddingByte & 0xFF
            self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext[:-padding])
        else:
            self.handleConversationMessage(encMessageProtocolEntity.toProtocolTreeNode(), plaintext)

    def handleSenderKeyMessage(self, node):
        encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
        enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG)

        senderKeyName = SenderKeyName(encMessageProtocolEntity.getFrom(True), AxolotlAddress(encMessageProtocolEntity.getParticipant(False), 0))
        groupCipher = GroupCipher(self.store, senderKeyName)
        try:
            plaintext = groupCipher.decrypt(enc.getData())
            padding = ord(plaintext[-1]) & 0xFF
            plaintext = plaintext[:-padding]
            plaintext = plaintext.encode() if sys.version_info >= (3, 0) else plaintext
            self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext)

        except NoSessionException as e:
            logger.warning("No session for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False))
            retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode(node, self.store.getLocalRegistrationId())
            self.toLower(retry.toProtocolTreeNode())

    def parseAndHandleMessageProto(self, encMessageProtocolEntity, serializedData):
        node = encMessageProtocolEntity.toProtocolTreeNode()
        m = Message()
        handled = False
        try:
            m.ParseFromString(serializedData)
        except:
            print("DUMP:")
            print(serializedData)
            print([s for s in serializedData])
            print([ord(s) for s in serializedData])
            raise
        if not m or not serializedData:
            raise ValueError("Empty message")

        if m.HasField("sender_key_distribution_message"):
            handled = True
            axolotlAddress = AxolotlAddress(encMessageProtocolEntity.getParticipant(False), 0)
            self.handleSenderKeyDistributionMessage(m.sender_key_distribution_message, axolotlAddress)

        if m.HasField("conversation"):
            handled = True
            self.handleConversationMessage(node, m.conversation)
        elif m.HasField("contact_message"):
            handled = True
            self.handleContactMessage(node, m.contact_message)
        elif m.HasField("url_message"):
            handled = True
            self.handleUrlMessage(node, m.url_message)
        elif m.HasField("location_message"):
            handled = True
            #self.handleLocationMessage(node, m.location_message)
        elif m.HasField("image_message"):
            handled = True
            self.handleImageMessage(node, m.image_message)

        if not handled:
            print(m)
            #raise ValueError("Unhandled")

    def handleSenderKeyDistributionMessage(self, senderKeyDistributionMessage, axolotlAddress):
        groupId = senderKeyDistributionMessage.groupId
        axolotlSenderKeyDistributionMessage = SenderKeyDistributionMessage(serialized=senderKeyDistributionMessage.axolotl_sender_key_distribution_message)
        groupSessionBuilder = GroupSessionBuilder(self.store)
        senderKeyName = SenderKeyName(groupId, axolotlAddress)
        groupSessionBuilder.process(senderKeyName, axolotlSenderKeyDistributionMessage)

    def handleConversationMessage(self, originalEncNode, text):
        messageNode = copy.deepcopy(originalEncNode)
        messageNode.children = []
        messageNode.addChild(ProtocolTreeNode("body", data = text))
        self.toUpper(messageNode)

    def handleImageMessage(self, originalEncNode, imageMessage):
        messageNode = copy.deepcopy(originalEncNode)
        messageNode["type"] = "media"
        mediaNode = ProtocolTreeNode("media", {
            "type": "image",
            "filehash": imageMessage.file_sha256,
            "size": str(imageMessage.file_length),
            "url": imageMessage.url,
            "mimetype": imageMessage.mime_type,
            "width": imageMessage.width,
            "height": imageMessage.height,
            "caption": imageMessage.caption,
            "encoding": "raw",
            "file": "enc",
            "ip": "0"
        }, data = imageMessage.jpeg_thumbnail)
        messageNode.addChild(mediaNode)

        self.toUpper(messageNode)

    def handleUrlMessage(self, originalEncNode, urlMessage):
        #convert to ??
        pass

    def handleDocumentMessage(self, originalEncNode, documentMessage):
        #convert to ??
        pass

    def handleLocationMessage(self, originalEncNode, locationMessage):
        messageNode = copy.deepcopy(originalEncNode)
        messageNode["type"] = "media"
        mediaNode = ProtocolTreeNode("media", {
            "latitude": locationMessage.degrees_latitude,
            "longitude": locationMessage.degress_longitude,
            "name": "%s %s" % (locationMessage.name, locationMessage.address),
            "url": locationMessage.url,
            "encoding": "raw",
            "type": "location"
        }, data=locationMessage.jpeg_thumbnail)
        messageNode.addChild(mediaNode)
        self.toUpper(messageNode)

    def handleContactMessage(self, originalEncNode, contactMessage):
        messageNode = copy.deepcopy(originalEncNode)
        messageNode["type"] = "media"
        mediaNode = ProtocolTreeNode("media", {
            "type": "vcard"
        }, [
            ProtocolTreeNode("vcard", {"name": contactMessage.display_name}, data = contactMessage.vcard)
        ] )
        messageNode.addChild(mediaNode)
        self.toUpper(messageNode)

    def getSessionCipher(self, recipientId):
        if recipientId in self.sessionCiphers:
            sessionCipher = self.sessionCiphers[recipientId]
        else:
            sessionCipher = SessionCipher(self.store, self.store, self.store, self.store, recipientId, 1)
            self.sessionCiphers[recipientId] = sessionCipher

        return sessionCipher

    def getGroupCipher(self, groupId, senderId):
        senderKeyName = SenderKeyName(groupId, AxolotlAddress(senderId, 1))
        if senderKeyName in self.groupCiphers:
            groupCipher = self.groupCiphers[senderKeyName]
        else:
            groupCipher = GroupCipher(self.store, senderKeyName)
            self.groupCiphers[senderKeyName] = groupCipher
        return groupCipher




Autor: Jorge T
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta



Espero que les sirva!
ANTRAX



Hola, en los comandos que dice "sudo", desde que programa lo tendría que hacer en Windows?

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola, en los comandos que dice "sudo", desde que programa lo tendría que hacer en Windows?

no tienes que... y si te jode por permisos, abre ese cmd con clic derecho "Abrir como administrador"

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Acepta con humildad y aprecio que en la vida la muerte es inevitable y amarás ésta, adorando la muerte

Febrero 26, 2017, 01:22:03 AM #4 Ultima modificación: Febrero 26, 2017, 01:25:31 AM por Leo_
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola, en los comandos que dice "sudo", desde que programa lo tendría que hacer en Windows?

no tienes que... y si te jode por permisos, abre ese cmd con clic derecho "Abrir como administrador"

Listo, puse "setup.py build" y funcionó, gracias!

Marzo 02, 2017, 09:01:42 AM #5 Ultima modificación: Marzo 02, 2017, 09:07:56 AM por Leo_
Hola, tengo un problema, es que al poner el codigo
Código: bash
yowsup-cli registration --requestcode sms --phone 549XXXXXXXXXX --cc 54 --mcc 722 --mnc XX
me dice que el mensaje se está enviando pero nunca llega, ya intenté con otro número y pasa lo mismo

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola, tengo un problema, es que al poner el codigo
Código: bash
yowsup-cli registration --requestcode sms --phone 549XXXXXXXXXX --cc 54 --mcc 722 --mnc XX
me dice que el mensaje se está enviando pero nunca llega, ya intenté con otro número y pasa lo mismo

Bueno, estuve hablando con el autor del post sobre tu problema. Al parecer a partir del 28 de Febrero cambiaron las politicas de WhatsApp y bannean los numeros que intentan ser bots.
En el github del script varios comentan que les ha pasado lo mismo.

Lo que habría que hacer, es probar un numero que ya use whatsapp desde hace rato para ver que pasa... Pero bueno, corres el riesgo de que lo banneen tambien.

Por el momento lo mas seguro es hacer bots para Telegram. Pronto subiré un post sobre como hacerlos.

Saludos,
ANTRAX


No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola, tengo un problema, es que al poner el codigo
Código: bash
yowsup-cli registration --requestcode sms --phone 549XXXXXXXXXX --cc 54 --mcc 722 --mnc XX
me dice que el mensaje se está enviando pero nunca llega, ya intenté con otro número y pasa lo mismo

Bueno, estuve hablando con el autor del post sobre tu problema. Al parecer a partir del 28 de Febrero cambiaron las politicas de WhatsApp y bannean los numeros que intentan ser bots.
En el github del script varios comentan que les ha pasado lo mismo.

Lo que habría que hacer, es probar un numero que ya use whatsapp desde hace rato para ver que pasa... Pero bueno, corres el riesgo de que lo banneen tambien.

Por el momento lo mas seguro es hacer bots para Telegram. Pronto subiré un post sobre como hacerlos.

Saludos,
ANTRAX
Ah ok, muchas gracias por responder!

Hola a todos y muchas gracias por el contenido para el bot,

Ahora bien, tengo una duda, tendrán los tokens correspondientes a la versión 2.17.52 de whatsapp?, ya que pruebo los expuestos en el sitio, pero me arroja lo siguiente:

Código: php

yowsup-cli  v2.0.15
yowsup      v2.5.2

Copyright (c) 2012-2016 Tarek Galal
http://www.openwhatsapp.org

This software is provided free of charge. Copying and redistribution is
encouraged.

If you appreciate this software and you would like to support future
development please consider donating:
http://openwhatsapp.org/yowsup/donate


INFO:yowsup.common.http.warequest:b'{"login":"XXXXXXXXXX","status":"fail","reason":"bad_token"}\n'
status: b'fail'
reason: b'bad_token'
login: b'XXXXXXXXXX'



Saludos.


Excelente trabajo, me parece excepcional el código. Me parece muy bien que la gente se interese por innovar en la tecnología.
Profesor virtual de programación
Experto en inteligencia artificial y modelado de sistemas fisicos

Saludos, me puede decir alguien si aun funciona el Bot Whatsapp en Python ???¡

Buenas Tardes,
Podría re-subir el código fuente, el link me está dando error.
Un Saludo.