Enviando mensajes de WhatsApp

User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Enviando mensajes de WhatsApp

Post by Antonio Linares »

Versión más reciente:

Teneis que indicar vuestro código de pais y numero de telefono al inicio del ejemplo. No useis ceros delante, ni "+". Reemplazad "Your_IMEI" con el IMEI de vuestro teléfono. Supuestamente teneis que tener vuestro telefono previamente registrado en whatsapp. Tambien podeis elegir un nickname.

Code: Select all

#include "FiveWin.ch"
#include "hbsocket.ch"

function Main()

   local oWA := HB_WhatsApp():New( "34...your mobile number here...", hb_md5( StrRev( "Your_IMEI" ) ), "nickname" )

   ? oWA:Connect()
   oWA:Login()

return nil

/*
cmResponse = Chr( 0x01 )+Chr( 0x31 )+Chr( 0xF8 )+Chr( 0x04 )+Chr( 0x86 )+Chr( 0xBD )+;
Chr( 0xA7 )+Chr( 0xFD )+Chr( 0 )+Chr( 0x01 )+Chr( 0x28 )    


// this packet contains the name 

cNext = Chr( 0 )+Chr( 0x12 )+Chr( 0xf8 )+Chr( 0x05 )+Chr( 0x74 )+Chr( 0xa2 )+Chr( 0xa3 )+Chr( 0x61 )+;
Chr( 0xFC )+Chr( 0x0A )+Chr( 0x41 )+Chr( 0x68 )+Chr( 0x6D )+Chr( 0x65 )+Chr( 0x64 )+Chr( 0x20 )+;
Chr( 0x4D )+Chr( 0x6F )+Chr( 0x68 )+Chr( 0x64 )+Chr( 0 )+Chr( 0x15 )+Chr( 0xF8 )+Chr( 0x06 )+;
Chr( 0x48 )+Chr( 0x43 )+Chr( 0x05 )+Chr( 0xA2 )+Chr( 0x3A )+Chr( 0xF8 )+Chr( 0x01 )+Chr( 0xF8 )+;
Chr( 0x04 )+Chr( 0x7B )+Chr( 0xBD )+Chr( 0x4D )+Chr( 0xF8 )+Chr( 0x01 )+Chr( 0xF8 )+Chr( 0x03 )+;
Chr( 0x55 )+Chr( 0x61 )+Chr( 0x24 )+Chr( 0 )+Chr( 0x12 )+Chr( 0xF8 )+Chr( 0x08 )+Chr( 0x48 )+Chr( 0x43 )+;
Chr( 0xFC )+Chr( 0x01 )+Chr( 0x32 )+Chr( 0xA2 )+Chr( 0x3A )+Chr( 0xA0 )+Chr( 0x8A )+Chr( 0xF8 )+Chr( 0x01 )+;
Chr( 0xF8 )+Chr( 0x03 )+Chr( 0x1F )+Chr( 0xBD )+Chr( 0xB1 )
*/

CLASS HB_WhatsApp

   DATA  cNumber, cPassword, cNickname
   DATA  pSocket
   DATA  cServer INIT "s.whatsapp.net"
   DATA  cHost   INIT "bin-short.whatsapp.net"
   DATA  cRealm  INIT "s.whatsapp.net"
   DATA  nPort   INIT 5222
   DATA  cIP
   DATA  cQop    INIT "auth"
   DATA  cDigest_Uri INIT "xmpp/s.whatsapp.net"
   DATA  aResArray
   DATA  cMsg
   DATA  _Incomplete_message

   METHOD New( cNumber, cPassword, cNickname )
   METHOD Connect()
   METHOD Login()
   
   METHOD Read()
   METHOD Send( cData )

   METHOD _Authenticate( cNonce, cNC )
   METHOD _Identify( cStr )
   METHOD _Is_Full_Msg( cStr )

   DESTRUCTOR Destroy()

ENDCLASS

METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp

   ::cIP = hb_socketGetHosts( ::cHost )[ 1 ]
   ::pSocket = hb_socketOpen()

   ::cNumber   = cNumber
   ::cPassword = cPassword
   ::cNickname = cNickname

return self

METHOD Connect() CLASS HB_WhatsApp

return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } )

static function StrToHex( cStr )

   local n, cHex := "" 
   
   for n = 1 to Len( cStr )
      cHex += "0x" + hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) )
      if n < Len( cStr )
         cHex += ", "
      endif   
   next
   
return cHex         

static function random_uuid()

return hb_strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_BitOr( hb_Random( 0, 0x0fff ), 0x4000 ),;
                     hb_BitOr( hb_Random( 0, 0x3fff ), 0x8000 ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )
              
METHOD Login() CLASS HB_WhatsApp

   local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData

   ? ::Send( "WA" + Chr( 0x01 ) + Chr( 0 ) + Chr( 0 ) + ;
             Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ;
             Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ;
             Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
             Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ;
             Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ;
             Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ;
             Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ;
             Chr( 0xBD ) + Chr( 0xA7 ) )

   cBuffer = ::Read()
   cResponse = hb_base64decode( SubStr( cBuffer, 27 ) )
   aArrResponse = HB_ATokens( cResponse, "," )
   hAuthData = {=>}
   
   for each cValue in aArrResponse
      aResData = hb_ATokens( cValue, "=" )
      hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" )
   next    
   
   cResData = ::_Authenticate( hAuthData[ "nonce" ] ) 
   ? cResData
   cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ;
               Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ;
               hb_base64encode( cResData )
   ::Send( cResponse )
   cBuffer = ::Read()
   ? cBuffer
   ? ::Read()
   
return nil

METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp

   local cCNonce := random_uuid()
   local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword )
   local cA2, cPassword

   if cNC == nil
      cNC = "00000001"
   endif
   
   cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce   
   cA2 = "AUTHENTICATE:" + ::cDigest_Uri
   cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ;
               ":" + hb_md5( cA2 )
   cPassword = hb_md5( cPassword )            
   
return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',;
                     ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, ::cPassword )   
       
METHOD Read() CLASS HB_WhatsApp

   local cBuffer := Space( 1024 ), cV, cRcvdType
   local nLen := hb_socketRecv( ::pSocket, @cBuffer )

   cBuffer = SubStr( cBuffer, 1, nLen )
   ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) )
   // ? StrToHex( cBuffer )
   
   for each cV in ::aResArray 
      cRcvdType = ::_Identify( cV ) 

      // ? cRcvdType
      // ? StrToHex( cV )

      do case
         case cRcvdType == "incomplete_msg"
              ::_incomplete_message = cV

         case cRcvdType == "msg"
              ::cMsg = ::parse_received_message( cV )
         
         case cRcvdType == "account_info"
              ::accinfo = ::parse_account_info( cV )

         case cRcvdType == "last_seen"
              ::lastseen = ::parse_last_seen( cV )
      endcase
   next

return cBuffer

METHOD Send( cData ) CLASS HB_WhatsApp

return hb_socketSend( ::pSocket, cData )

static function StartsWith( cStr, cCompare, nPos )

return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare

static function EndsWith( cStr, cCompare )

return Right( cStr, Len( cCompare ) ) == cCompare

METHOD _Identify( cStr ) CLASS HB_WhatsApp

   local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC ) 
   local cServer_delivery_identifier := Chr( 0x8C ) 
   local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD )
   local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 )    
   local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B )

   if ! ::_is_full_msg( cStr )
      return "incomplete_msg"

   elseif StartsWith( cStr, cMsg_identifier, 3 )

      if EndsWith( cStr, cServer_delivery_identifier )
         return "server_delivery_report"

      elseif EndsWith( cStr, cClient_delivery_identifier ) 
         return "client_delivery_report"

      else
         return "msg"

      endif 

   elseif StartsWith( cStr, cAcc_info_iden, 3 )
      return "account_info"

   elseif StartsWith( cStr, cLast_seen_ident, 3 ) .and. cLast_seen_ident2 $ cStr
      return "last_seen"
   
   else
      return "other"

   endif

return nil

METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp

return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1

METHOD Destroy() CLASS HB_WhatsApp

   HB_SocketShutDown( ::pSocket )
   HB_SocketClose( ::pSocket )

   ::pSocket = nil

return nil

static function pack_h32( cString )
   
   local c := "", cLeter
   local nibbleshift := 4
   local n
   local nPos   := 0
   local aOut   := {}

   for each cLeter in cString
      n = asc( cLeter )
      if n >= asc( "0" ) .and. n <= asc( "9" )
         n -= asc( "0" )
      elseif n >= asc( "a" ) .and. n <= asc( "f" )
         n -= ( asc( "a" ) - 10 )
      elseif n >= asc( "F" ) .and. n <= asc( "F" )
         n -= ( asc( "A" ) - 10 )
      endif
      
      if cLeter:__enumindex() % 2 != 0
         AAdd( aOut, 0 )         
         nPos++
      endif
      
        aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) )
      
      nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 )

      if cLeter:__enumindex() % 2 == 0
         c += Chr( aOut[ nPos ] )
      endif      
      
   next

return c 

#pragma BEGINDUMP

#include <hbapi.h>

HB_FUNC( STRREV )
{
   int iLen = hb_parclen( 1 ), i;
   char * buffer = hb_xgrab( iLen );
   
   for( i = 0; i < iLen; i++ )
      buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ];
      
   hb_retclen( buffer, iLen );
   hb_xfree( buffer );
}

#pragma ENDDUMP      
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
José Vicente Beltrán
Posts: 279
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España
Contact:

Re: Enviando mensajes de WhatsApp

Post by José Vicente Beltrán »

Siguiendo las notas de fgondi, ya se genera el exe correctamente con xHB, siguiente paso:

- Despues de sustituir el num. de telefono y el Imei, conecta con el servidor de Whatsapp (conect() devuelve .t.)
- Seguidamente presenta en pantalla el número '50' (aun no se que significa)
- Finalmente el siguiente error y aquí nos quedamos:

Error description: Error BASE/1089 Non-integer parameters: HB_BITOR
Args:
[ 1] = N 3990.02
[ 2] = N 16384

Stack Calls
===========
Called from: => HB_BITOR(0)
Called from: D:\trabajo32\comun\whatsapp\prg\whatsapp.prg => RANDOM_UUID(97)
Called from: D:\trabajo32\comun\whatsapp\prg\whatsapp.prg => HB_WHATSAPP:_AUTHENTICATE(137)
Called from: D:\trabajo32\comun\whatsapp\prg\whatsapp.prg => HB_WHATSAPP:LOGIN(123)
Called from: D:\trabajo32\comun\whatsapp\prg\whatsapp.prg => MAIN(11)

Algo se avanza... gracias al foro :shock:
FiveWiDi
Posts: 910
Joined: Mon Oct 10, 2005 2:38 pm

Re: Enviando mensajes de WhatsApp

Post by FiveWiDi »

Antonio Linares wrote:Versión más reciente:

Teneis que indicar vuestro código de pais y numero de telefono al inicio del ejemplo. No useis ceros delante, ni "+". Reemplazad "Your_IMEI" con el IMEI de vuestro teléfono. Supuestamente teneis que tener vuestro telefono previamente registrado en whatsapp. Tambien podeis elegir un nickname.

Code: Select all

#include "FiveWin.ch"
#include "hbsocket.ch"

function Main()

   local oWA := HB_WhatsApp():New( "34...your mobile number here...", hb_md5( StrRev( "Your_IMEI" ) ), "nickname" )

   ? oWA:Connect()
   oWA:Login()

return nil

/*
cmResponse = Chr( 0x01 )+Chr( 0x31 )+Chr( 0xF8 )+Chr( 0x04 )+Chr( 0x86 )+Chr( 0xBD )+;
Chr( 0xA7 )+Chr( 0xFD )+Chr( 0 )+Chr( 0x01 )+Chr( 0x28 )    


// this packet contains the name 

cNext = Chr( 0 )+Chr( 0x12 )+Chr( 0xf8 )+Chr( 0x05 )+Chr( 0x74 )+Chr( 0xa2 )+Chr( 0xa3 )+Chr( 0x61 )+;
Chr( 0xFC )+Chr( 0x0A )+Chr( 0x41 )+Chr( 0x68 )+Chr( 0x6D )+Chr( 0x65 )+Chr( 0x64 )+Chr( 0x20 )+;
Chr( 0x4D )+Chr( 0x6F )+Chr( 0x68 )+Chr( 0x64 )+Chr( 0 )+Chr( 0x15 )+Chr( 0xF8 )+Chr( 0x06 )+;
Chr( 0x48 )+Chr( 0x43 )+Chr( 0x05 )+Chr( 0xA2 )+Chr( 0x3A )+Chr( 0xF8 )+Chr( 0x01 )+Chr( 0xF8 )+;
Chr( 0x04 )+Chr( 0x7B )+Chr( 0xBD )+Chr( 0x4D )+Chr( 0xF8 )+Chr( 0x01 )+Chr( 0xF8 )+Chr( 0x03 )+;
Chr( 0x55 )+Chr( 0x61 )+Chr( 0x24 )+Chr( 0 )+Chr( 0x12 )+Chr( 0xF8 )+Chr( 0x08 )+Chr( 0x48 )+Chr( 0x43 )+;
Chr( 0xFC )+Chr( 0x01 )+Chr( 0x32 )+Chr( 0xA2 )+Chr( 0x3A )+Chr( 0xA0 )+Chr( 0x8A )+Chr( 0xF8 )+Chr( 0x01 )+;
Chr( 0xF8 )+Chr( 0x03 )+Chr( 0x1F )+Chr( 0xBD )+Chr( 0xB1 )
*/

CLASS HB_WhatsApp

   DATA  cNumber, cPassword, cNickname
   DATA  pSocket
   DATA  cServer INIT "s.whatsapp.net"
   DATA  cHost   INIT "bin-short.whatsapp.net"
   DATA  cRealm  INIT "s.whatsapp.net"
   DATA  nPort   INIT 5222
   DATA  cIP
   DATA  cQop    INIT "auth"
   DATA  cDigest_Uri INIT "xmpp/s.whatsapp.net"
   DATA  aResArray
   DATA  cMsg
   DATA  _Incomplete_message

   METHOD New( cNumber, cPassword, cNickname )
   METHOD Connect()
   METHOD Login()
   
   METHOD Read()
   METHOD Send( cData )

   METHOD _Authenticate( cNonce, cNC )
   METHOD _Identify( cStr )
   METHOD _Is_Full_Msg( cStr )

   DESTRUCTOR Destroy()

ENDCLASS

METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp

   ::cIP = hb_socketGetHosts( ::cHost )[ 1 ]
   ::pSocket = hb_socketOpen()

   ::cNumber   = cNumber
   ::cPassword = cPassword
   ::cNickname = cNickname

return self

METHOD Connect() CLASS HB_WhatsApp

return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } )

static function StrToHex( cStr )

   local n, cHex := "" 
   
   for n = 1 to Len( cStr )
      cHex += "0x" + hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) )
      if n < Len( cStr )
         cHex += ", "
      endif   
   next
   
return cHex         

static function random_uuid()

return hb_strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_BitOr( hb_Random( 0, 0x0fff ), 0x4000 ),;
                     hb_BitOr( hb_Random( 0, 0x3fff ), 0x8000 ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )
              
METHOD Login() CLASS HB_WhatsApp

   local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData

   ? ::Send( "WA" + Chr( 0x01 ) + Chr( 0 ) + Chr( 0 ) + ;
             Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ;
             Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ;
             Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
             Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ;
             Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ;
             Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ;
             Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ;
             Chr( 0xBD ) + Chr( 0xA7 ) )

   cBuffer = ::Read()
   cResponse = hb_base64decode( SubStr( cBuffer, 27 ) )
   aArrResponse = HB_ATokens( cResponse, "," )
   hAuthData = {=>}
   
   for each cValue in aArrResponse
      aResData = hb_ATokens( cValue, "=" )
      hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" )
   next    
   
   cResData = ::_Authenticate( hAuthData[ "nonce" ] ) 
   ? cResData
   cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ;
               Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ;
               hb_base64encode( cResData )
   ::Send( cResponse )
   cBuffer = ::Read()
   ? cBuffer
   ? ::Read()
   
return nil

METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp

   local cCNonce := random_uuid()
   local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword )
   local cA2, cPassword

   if cNC == nil
      cNC = "00000001"
   endif
   
   cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce   
   cA2 = "AUTHENTICATE:" + ::cDigest_Uri
   cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ;
               ":" + hb_md5( cA2 )
   cPassword = hb_md5( cPassword )            
   
return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',;
                     ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, ::cPassword )   
       
METHOD Read() CLASS HB_WhatsApp

   local cBuffer := Space( 1024 ), cV, cRcvdType
   local nLen := hb_socketRecv( ::pSocket, @cBuffer )

   cBuffer = SubStr( cBuffer, 1, nLen )
   ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) )
   // ? StrToHex( cBuffer )
   
   for each cV in ::aResArray 
      cRcvdType = ::_Identify( cV ) 

      // ? cRcvdType
      // ? StrToHex( cV )

      do case
         case cRcvdType == "incomplete_msg"
              ::_incomplete_message = cV

         case cRcvdType == "msg"
              ::cMsg = ::parse_received_message( cV )
         
         case cRcvdType == "account_info"
              ::accinfo = ::parse_account_info( cV )

         case cRcvdType == "last_seen"
              ::lastseen = ::parse_last_seen( cV )
      endcase
   next

return cBuffer

METHOD Send( cData ) CLASS HB_WhatsApp

return hb_socketSend( ::pSocket, cData )

static function StartsWith( cStr, cCompare, nPos )

return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare

static function EndsWith( cStr, cCompare )

return Right( cStr, Len( cCompare ) ) == cCompare

METHOD _Identify( cStr ) CLASS HB_WhatsApp

   local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC ) 
   local cServer_delivery_identifier := Chr( 0x8C ) 
   local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD )
   local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 )    
   local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B )

   if ! ::_is_full_msg( cStr )
      return "incomplete_msg"

   elseif StartsWith( cStr, cMsg_identifier, 3 )

      if EndsWith( cStr, cServer_delivery_identifier )
         return "server_delivery_report"

      elseif EndsWith( cStr, cClient_delivery_identifier ) 
         return "client_delivery_report"

      else
         return "msg"

      endif 

   elseif StartsWith( cStr, cAcc_info_iden, 3 )
      return "account_info"

   elseif StartsWith( cStr, cLast_seen_ident, 3 ) .and. cLast_seen_ident2 $ cStr
      return "last_seen"
   
   else
      return "other"

   endif

return nil

METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp

return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1

METHOD Destroy() CLASS HB_WhatsApp

   HB_SocketShutDown( ::pSocket )
   HB_SocketClose( ::pSocket )

   ::pSocket = nil

return nil

static function pack_h32( cString )
   
   local c := "", cLeter
   local nibbleshift := 4
   local n
   local nPos   := 0
   local aOut   := {}

   for each cLeter in cString
      n = asc( cLeter )
      if n >= asc( "0" ) .and. n <= asc( "9" )
         n -= asc( "0" )
      elseif n >= asc( "a" ) .and. n <= asc( "f" )
         n -= ( asc( "a" ) - 10 )
      elseif n >= asc( "F" ) .and. n <= asc( "F" )
         n -= ( asc( "A" ) - 10 )
      endif
      
      if cLeter:__enumindex() % 2 != 0
         AAdd( aOut, 0 )         
         nPos++
      endif
      
        aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) )
      
      nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 )

      if cLeter:__enumindex() % 2 == 0
         c += Chr( aOut[ nPos ] )
      endif      
      
   next

return c 

#pragma BEGINDUMP

#include <hbapi.h>

HB_FUNC( STRREV )
{
   int iLen = hb_parclen( 1 ), i;
   char * buffer = hb_xgrab( iLen );
   
   for( i = 0; i < iLen; i++ )
      buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ];
      
   hb_retclen( buffer, iLen );
   hb_xfree( buffer );
}

#pragma ENDDUMP      
Antonio,

Mírate el METHOD _Authenticate(), en él se usa "cPassword" (variable local) y no se para qué.
En su Return usas "::cPassword" (data de la clase).
Un Saludo
Carlos G.

FiveWin 19.06 + Harbour 3.2, BCC 7 Windows 10
User avatar
fgondi
Posts: 636
Joined: Fri Oct 07, 2005 6:58 am
Location: Palencia, España
Contact:

Re: Enviando mensajes de WhatsApp

Post by fgondi »

En xHarbour no funciona hb_BitOr, desconozco el porque.

Asi que lo he quitado y funciona:

Code: Select all

return strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0x0fff ),;
                     hb_Random( 0, 0x3fff ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )
Lo que si que hay que cambiar es:
cLeter:__enumindex()
En xharbour la instrucción correcta Hb_EnumIndex()
Un saludo
Fernando González Diez
ALSIS GHE Sistemas Informáticos
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Enviando mensajes de WhatsApp

Post by Antonio Linares »

Carlos,

efectivamente al final hay que usar cPassword en vez de ::cPassword

gracias! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Enviando mensajes de WhatsApp

Post by Antonio Linares »

Jose, Fernando,

No quiteis el hb_bitor(), modificadlo asi:

hb_BitOr( int( hb_Random( 0, 0x0fff ) ), 0x4000 ),;
hb_BitOr( int( hb_Random( 0, 0x3fff ) ), 0x8000 ),;
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
José Vicente Beltrán
Posts: 279
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España
Contact:

Re: Enviando mensajes de WhatsApp

Post by José Vicente Beltrán »

Antonio, siguiente paso con XHB

Error description: Error BASE/1005 Class: 'CHARACTER' has no property: _ENUMINDEX

:shock:

EDITADO:
No habia leido entero el post de fgondi, corregido y parece que ya funciona, ahora a interpretarlo..

Gracias Antonio, fgondi :shock:
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Enviando mensajes de WhatsApp

Post by Antonio Linares »

El método Login() ya esta completo:

Code: Select all

#include "FiveWin.ch"
#include "hbsocket.ch"

function Main()

   local oWA := HB_WhatsApp():New( "tu codigo de pais y tu numero", hb_md5( StrRev( "tu IMEI" ) ), "tu nickname" )

   ? oWA:Connect()
   oWA:Login()

return nil

CLASS HB_WhatsApp

   DATA  cNumber, cPassword, cNickname
   DATA  pSocket
   DATA  cServer INIT "s.whatsapp.net"
   DATA  cHost   INIT "bin-short.whatsapp.net"
   DATA  cRealm  INIT "s.whatsapp.net"
   DATA  nPort   INIT 5222
   DATA  cIP
   DATA  cQop    INIT "auth"
   DATA  cDigest_Uri INIT "xmpp/s.whatsapp.net"
   DATA  aResArray
   DATA  cMsg
   DATA  _Incomplete_message

   METHOD New( cNumber, cPassword, cNickname )
   METHOD Connect()
   METHOD Login()
   
   METHOD Read()
   METHOD Send( cData )

   METHOD _Authenticate( cNonce, cNC )
   METHOD _Identify( cStr )
   METHOD _Is_Full_Msg( cStr )

   DESTRUCTOR Destroy()

ENDCLASS

METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp

   ::cIP = hb_socketGetHosts( ::cHost )[ 1 ]
   ::pSocket = hb_socketOpen()

   ::cNumber   = cNumber
   ::cPassword = cPassword
   ::cNickname = cNickname

return self

METHOD Connect() CLASS HB_WhatsApp

return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } )

static function StrToHex( cStr )

   local n, cHex := "" 
   
   for n = 1 to Len( cStr )
      cHex += "0x" + hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) )
      if n < Len( cStr )
         cHex += ", "
      endif   
   next
   
return cHex         

static function random_uuid()

return hb_strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_BitOr( hb_Random( 0, 0x0fff ), 0x4000 ),;
                     hb_BitOr( hb_Random( 0, 0x3fff ), 0x8000 ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )
              
METHOD Login() CLASS HB_WhatsApp

   local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData

   ? ::Send( "WA" + Chr( 0x01 ) + Chr( 0 ) + Chr( 0 ) + ;
             Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ;
             Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ;
             Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
             Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ;
             Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ;
             Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ;
             Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ;
             Chr( 0xBD ) + Chr( 0xA7 ) )

   cBuffer = ::Read()
   cResponse = hb_base64decode( SubStr( cBuffer, 27 ) )
   aArrResponse = HB_ATokens( cResponse, "," )
   hAuthData = {=>}
   
   for each cValue in aArrResponse
      aResData = hb_ATokens( cValue, "=" )
      hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" )
   next    
   
   cResData = ::_Authenticate( hAuthData[ "nonce" ] ) 
   cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ;
               Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ;
               hb_base64encode( cResData )
   ::Send( cResponse )
   cBuffer = ::Read()
   ::Read()
   cResponse = Chr( 0 ) + Chr( 8 + Len( ::cNickname ) ) + Chr( 0xF8 ) + Chr( 5 ) + Chr( 0x74 ) + ;
               Chr( 0xA2 ) + Chr( 0xA3 ) + Chr( 0x61 ) + Chr( 0xFC ) + Chr( Len( ::cNickName ) ) + ;
               ::cNickName + Chr( 0 ) + Chr( 0x15 ) + Chr( 0xF8 ) + Chr( 6 ) + Chr( 0x48 ) + ;
               Chr( 0x43 ) + Chr( 5 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xF8 ) + Chr( 1 ) + ;
               Chr( 0xF8 ) + Chr( 4 ) + Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4D ) + Chr( 0xF8 ) + ;
               Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x55 ) + Chr( 0x61 ) + Chr( 0x24 ) + ;
               Chr( 0 ) + Chr( 0x12 ) + Chr( 0xF8 ) + Chr( 8 ) + Chr( 0x48 ) + Chr( 0x43 ) + ;
               Chr( 0xFC ) + Chr( 1 ) + Chr( 0x32 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 ) + ;
               Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x1F ) + ;
               Chr( 0xBD ) + Chr( 0xB1 )
        ::Send( cResponse )
        ? ::Read()    
   
return nil

METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp

   local cCNonce := random_uuid()
   local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword )
   local cA2, cPassword

   if cNC == nil
      cNC = "00000001"
   endif
   
   cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce   
   cA2 = "AUTHENTICATE:" + ::cDigest_Uri
   cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ;
               ":" + hb_md5( cA2 )
   cPassword = hb_md5( cPassword )            
   
return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',;
                     ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, cPassword )   
       
METHOD Read() CLASS HB_WhatsApp

   local cBuffer := Space( 1024 ), cV, cRcvdType
   local nLen := hb_socketRecv( ::pSocket, @cBuffer )

   cBuffer = SubStr( cBuffer, 1, nLen )
   ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) )
   // ? StrToHex( cBuffer )
   
   for each cV in ::aResArray 
      cRcvdType = ::_Identify( cV ) 

      // ? cRcvdType
      // ? StrToHex( cV )

      do case
         case cRcvdType == "incomplete_msg"
              ::_incomplete_message = cV

         case cRcvdType == "msg"
              ::cMsg = ::parse_received_message( cV )
         
         case cRcvdType == "account_info"
              ::accinfo = ::parse_account_info( cV )

         case cRcvdType == "last_seen"
              ::lastseen = ::parse_last_seen( cV )
      endcase
   next

return cBuffer

METHOD Send( cData ) CLASS HB_WhatsApp

return hb_socketSend( ::pSocket, cData )

static function StartsWith( cStr, cCompare, nPos )

return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare

static function EndsWith( cStr, cCompare )

return Right( cStr, Len( cCompare ) ) == cCompare

METHOD _Identify( cStr ) CLASS HB_WhatsApp

   local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC ) 
   local cServer_delivery_identifier := Chr( 0x8C ) 
   local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD )
   local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 )    
   local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B )

   if ! ::_is_full_msg( cStr )
      return "incomplete_msg"

   elseif StartsWith( cStr, cMsg_identifier, 3 )

      if EndsWith( cStr, cServer_delivery_identifier )
         return "server_delivery_report"

      elseif EndsWith( cStr, cClient_delivery_identifier ) 
         return "client_delivery_report"

      else
         return "msg"

      endif 

   elseif StartsWith( cStr, cAcc_info_iden, 3 )
      return "account_info"

   elseif StartsWith( cStr, cLast_seen_ident, 3 ) .and. cLast_seen_ident2 $ cStr
      return "last_seen"
   
   else
      return "other"

   endif

return nil

METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp

return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1

METHOD Destroy() CLASS HB_WhatsApp

   HB_SocketShutDown( ::pSocket )
   HB_SocketClose( ::pSocket )

   ::pSocket = nil

return nil

static function pack_h32( cString )
   
   local c := "", cLeter
   local nibbleshift := 4
   local n
   local nPos   := 0
   local aOut   := {}

   for each cLeter in cString
      n = asc( cLeter )
      if n >= asc( "0" ) .and. n <= asc( "9" )
         n -= asc( "0" )
      elseif n >= asc( "a" ) .and. n <= asc( "f" )
         n -= ( asc( "a" ) - 10 )
      elseif n >= asc( "F" ) .and. n <= asc( "F" )
         n -= ( asc( "A" ) - 10 )
      endif
      
      if cLeter:__enumindex() % 2 != 0
         AAdd( aOut, 0 )         
         nPos++
      endif
      
        aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) )
      
      nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 )

      if cLeter:__enumindex() % 2 == 0
         c += Chr( aOut[ nPos ] )
      endif      
      
   next

return c 

#pragma BEGINDUMP

#include <hbapi.h>

HB_FUNC( STRREV )
{
   int iLen = hb_parclen( 1 ), i;
   char * buffer = hb_xgrab( iLen );
   
   for( i = 0; i < iLen; i++ )
      buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ];
      
   hb_retclen( buffer, iLen );
   hb_xfree( buffer );
}

#pragma ENDDUMP      
regards, saludos

Antonio Linares
www.fivetechsoft.com
Enrrique Vertiz
Posts: 440
Joined: Fri Oct 07, 2005 2:17 pm
Location: Lima - Peru
Contact:

Re: Enviando mensajes de WhatsApp

Post by Enrrique Vertiz »

Saludos, con las ultimas indicaciones de Fernando y la ultima version compilada, ya no bota ningun error, al ejecutar el programa, muestra 3 mensajes de Alerta y termina :
1.- .T.
2.- 50
3.- "En Blanco"

con FWH y xHB, ahora veamos que sigue ......
Enrrique Vertiz Pitta
Lima-Peru
xHb 1.23, Fwh 20.04, MySQL 5.7 - 8.0, SQLLIB 1.9m, SQLRDD
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Enviando mensajes de WhatsApp

Post by Antonio Linares »

Enrique,

Bien! Ahora falta portar el método Message() y deberiamos poder enviar un mensaje...

https://github.com/aesedepece/WhatsAPI/ ... .class.php
regards, saludos

Antonio Linares
www.fivetechsoft.com
FiveWiDi
Posts: 910
Joined: Mon Oct 10, 2005 2:38 pm

Re: Enviando mensajes de WhatsApp

Post by FiveWiDi »

Antonio Linares wrote:Enrique,

Bien! Ahora falta portar el método Message() y deberiamos poder enviar un mensaje...

https://github.com/aesedepece/WhatsAPI/ ... .class.php
"Rizando el rizo",

Antonio cuando tengais el método Message(), por favor id a por el Suscribe(). Yo tengo un SIM nuevecito para conectar el portátil a Internet y serviría para poder probar si además se puede realizar una subscripción.

Que gran trabajo!
Un Saludo
Carlos G.

FiveWin 19.06 + Harbour 3.2, BCC 7 Windows 10
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Post by mastintin »

Antonio , para messages :

Code: Select all


static function isShort(cStr)
return if( len(cStr) < 256 , .t. , .f. )

 
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Post by mastintin »

Prototipo de funcion Message ( para ir quitando codigo) :

Code: Select all

METHOD Message(cMmsgid,cTo,cTtxt) CLASS HB_WhatsApp
local lLong_txt_bool = isShort(cTxt)
local cStream , cMsg

//$txt_length = hex2str(_hex(strlen($txt)));
        
//      $to_length = chr(mb_strlen($to,"UTF-8"));
//      $msgid_length = chr(mb_strlen($msgid));

        cContent = Chr( 0xF8)+Chr( 0x08 )+Chr( 0x5D )+Chr( 0xA0 )+Chr( 0xFA )+Chr( 0xFC )+cTo_length
        cContent += cTo
        cContent += Chr( 0x8A )+Chr( 0xA2 )+Chr( 0x1B )+Chr( 0x43 )+Chr( 0xFC )+cMsgid_length
        cContent += cMsgid
    cContent += Chr( 0xF8 )+Chr( 0x02 )+Chr( 0xF8 )+Chr( 0x04 )+Chr( 0xBA )+Chr( 0xBD )+Chr( 0x4F)+;
                Chr( 0xF8 )+Chr( 0x01 )+Chr( 0xF8 )+Chr( 0x01 )+Chr( 0x8C )+Chr( 0xF8 )+Chr( 0x02 )+Chr( 0x16 )


   if lLong_txt_bool
      cContent += Chr( 0xFD )+Chr( 0 )+cTxt_length
   else
      cContent += Chr( 0xFC )+cTxt_length
   endif
  
   cContent += cTxt
 
  //    cTotal_length = hex2str(_hex(strlen($content)));
    
    
        if len(cTotal_length) == '1' 
            cTotal_length = Chr( 0 )+cTotal_length
            endif
        
    
      cMsg:= ""+cTotal_length+cContent 
        cStream := ::Send(cMsg)
        ::Read()
        ::Read()
        ::Read()
        
Return nil
 
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Post by mastintin »

Otra funciones mas :

Code: Select all


function _hex(nInt)
    return  len(  if( hb_strformat("%X", nInt) %2 ==0 , hb_strformat("%X", nInt) , hb_strformat("0%X", nInt ) ) )

 
Function lenUTF8(cText)
Return len(hb_StrtoUTF8(cText) )

 
Nos falta hex2str()
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Post by mastintin »

El codigo de las funciones pack y unpack de php :
http://gcov.php.net/PHP_5_3/lcov_html/s ... c.gcov.php
Post Reply