#define __NOBINARY__
/*----------------------------------------------------------------------------*/
//REEMPLAZAR POR LOS QUE LES INDIQUE AL REGISTRARSE EN GREENAPI, HAY UN MODO DEMO, DEBEN CREAR UNA CUENTA DESSARLLOADOR, CREAR UNA INSTANCIA Y VINCULAR UN DISPOSITIVO.
#define GREEN_IDINSTANCE "7100068281"
#define GREEN_APITOKEN "1427d09058014f3cbb5033f3fccc8b0d0ed0ae8d44e946c8c2"
/*----------------------------------------------------------------------------*/
CLASS GreenApi
DATA cApiURL, cMediaURL
DATA cIdInstance, cIdToken
DATA oHttp
DATA lLog
DATA cError
METHOD New( cIdInstance, cIdToken ) CONSTRUCTOR
METHOD SetLog( lLog ) INLINE ::lLog := lLog
METHOD SetIdInstance( cIdInstance ) INLINE ::cIdInstance := cIdInstance
METHOD SetIdToken( cIdToken ) INLINE ::cIdToken := cIdToken
METHOD SetURL( cMethod, lMedia )
METHOD sendMessage( cPhone, cMessage )
METHOD sendFileByUpload( cPhone, cFile, cCaption )
METHOD sendContact( cPhone, hContact )
METHOD End()
ENDCLASS
/*----------------------------------------------------------------------------*/
METHOD New( cIdInstance, cIdToken ) CLASS GreenApi
LOCAL oErr
DEFAULT cIdInstance TO GREEN_IDINSTANCE
DEFAULT cIdToken TO GREEN_APITOKEN
::lLog := FALSE
::SetIdInstance( cIdInstance )
::SetIdToken( cIdToken )
::cApiURL := "https://api.green-api.com/waInstance"
::cMediaURL := "https://media.greenapi.com/waInstance"
::cError := ""
TRY
::oHttp := CreateObject( "MSXML2.ServerXMLHTTP.6.0" )
CATCH
TRY
::oHttp := CreateObject( "MSXML2.XMLHTTP" )
CATCH oErr
::cError := "Error en la creación de objeto HTTP: " + oErr:Description
END
END
RETURN Self
/*----------------------------------------------------------------------------*/
METHOD End() CLASS GreenApi
IF hb_isObject( ::oHttp )
::oHttp := NIL
ENDIF
RETURN
/*----------------------------------------------------------------------------*/
METHOD setURL( cMethod, lMedia ) CLASS GreenApi
LOCAL cUrl := ::cApiURL + ::cIdInstance + "/" + cMethod + "/" + ::cIdToken
DEFAULT lMedia TO FALSE
IF lMedia
cUrl := ::cMediaURL + ::cIdInstance + "/" + cMethod + "/" + ::cIdToken
ENDIF
IF ::lLog
TraceLog( cUrl )
ENDIF
RETURN cUrl
/*----------------------------------------------------------------------------*/
METHOD sendMessage( cPhone, cMessage ) CLASS GreenApi
LOCAL hInfo
LOCAL lSend := FALSE
LOCAL oErr
::cError := ""
IF !hb_isObject( ::oHttp )
::cError := "No se pudo crer objeto HTTP!"
RETURN lSend
ENDIF
IF Empty( cPhone ) .or. Empty( cMessage )
::cError := "Datos insuficientes para enviar mensaje por Whatsapp!"
RETURN lSend
ENDIF
hInfo := { "chatId" => cPhone + "@c.us", "message" => cMessage }
TRY
::oHttp:Open( "POST", ::setURL( "sendMessage", FALSE ), FALSE )
::oHttp:SetRequestHeader( "Content-Type", "application/json" )
::oHttp:Send( hb_jsonEncode( hInfo ) )
IF ::oHttp:Status == 200
IF ::lLog
TraceLog( ::oHttp:ResponseBody )
ENDIF
lSend := TRUE
SysRefresh()
ENDIF
CATCH oErr
::cError := "Error en Objeto HTTP: " + oErr:Description
END
RETURN lSend
/*----------------------------------------------------------------------------*/
METHOD sendContact( cPhone, cPhoneContact, cFirstName, cMiddelName, cLastName, cCompany ) CLASS GreenApi
LOCAL hInfo, hContact
LOCAL lSend := FALSE
LOCAL oErr
DEFAULT cMiddelName TO ""
DEFAULT cCompany TO ""
IF !hb_isObject( ::oHttp )
::cError := "No se pudo crer objeto HTTP!"
RETURN lSend
ENDIF
IF Empty( cPhone ) .or. ;
Empty( cPhoneContact ) .or. ;
Empty( cFirstName ) .or. ;
Empty( cLastName )
::cError := "Datos insuficientes para enviar contacto por Whatsapp!"
RETURN lSend
ENDIF
hContact := { "phoneContact" => cPhoneContact, ;
"firstName" => cFirstName , ;
"middleName" => cMiddelName , ;
"lastName" => cLastName , ;
"company" => cCompany }
hInfo := { "chatId" => cPhone + "@c.us", ;
"contact" => hContact }
TRY
::oHttp:Open( "POST", ::setURL( "sendContact", FALSE ), FALSE )
::oHttp:SetRequestHeader( "Content-Type", "application/json" )
::oHttp:Send( hb_jsonEncode( hInfo ) )
IF ::oHttp:Status == 200
IF ::lLog
TraceLog( ::oHttp:ResponseBody )
ENDIF
lSend := TRUE
SysRefresh()
ENDIF
CATCH oErr
::cError := "Error en Objeto HTTP: " + oErr:Description
END
RETURN lSend
/*----------------------------------------------------------------------------*/
METHOD sendFileByUpload( cPhone, cFileName, cCaption ) CLASS GreenApi
LOCAL lSend := FALSE
LOCAL hInfo, oPost
LOCAL oErr
::cError := ""
IF !hb_isObject( ::oHttp )
::cError := "No se pudo crer objeto HTTP!"
RETURN lSend
ENDIF
IF Empty( cPhone )
::cError := "Datos insuficientes para enviar mensaje por Whatsapp!"
RETURN lSend
ENDIF
IF !File( cFileName )
::cError := "No existe el archivo indicado!"
RETURN lSend
ENDIF
DEFAULT cCaption TO cFileName( cFileName )
oPost := TPostHtml():New() //"utf-8"
oPost:AddField( "chatId", cPhone + "@c.us" )
oPost:AddField( "caption", cCaption )
oPost:AddFile( "file", cCaption, cFileName )
oPost:Save( ".\prueba.uue" )
TRY
::oHttp:setTimeouts( 15000, 15000, 15000, 15000 )
::oHttp:Open( "POST", ::setURL( "sendFileByUpload", FALSE ), FALSE )
::oHttp:SetRequestHeader( "Content-Type", "multipart/form-data; boundary=" + oPost:cBoundaryBase )
::oHttp:Send( oPost:Read() )
IF ::oHttp:Status == 200
IF ::lLog
TraceLog( ::oHttp:ResponseBody )
ENDIF
lSend := TRUE
SysRefresh()
ELSE
::cError := cValToChar( ::oHttp:Status )
ENDIF
CATCH oErr
::cError := "Error en Objeto HTTP: " + oErr:Description
END
oPost:End()
RETURN lSend
/*----------------------------------------------------------------------------*/
//EOF
/*----------------------------------------------------------------------------*/
#define adModeUnknown 0
#define adModeRead 1
#define adModeWrite 2
#define adModeReadWrite 3
#define adModeShareDenyRead 4
#define adModeShareDenyWrite 8
#define adModeShareExclusive 12
#define adModeShareDenyNone 16
#define adModeRecursive 0x400000
#define adTypeBinary 1
#define adTypeText 2
#define adReadAll -1
/*----------------------------------------------------------------------------*/
CLASS TPostHTML
DATA oStream
DATA cBoundary, cBoundaryBase
DATA cCharSet INIT "Windows-1252"
DATA aExtraRequestHeader INIT {}
DATA Status
METHOD New( cCharSet ) CONSTRUCTOR
METHOD AddField( cField, cValue )
METHOD AddExtraRequest( cClave,cValor )
METHOD AddFile( cFieldName, cFileName, cFilePath )
METHOD Read()
METHOD Save( cFileName )
METHOD End() INLINE ( ::oStream:Close(), ::oStream := NIL )
ENDCLASS
/*----------------------------------------------------------------------------*/
METHOD New( cCharSet ) CLASS TPostHTML
DEFAULT cCharSet TO ::cCharSet
::cBoundaryBase := "BorderLine-1234567890"
::cBoundary := "--" + ::cBoundaryBase
WITH OBJECT ( ::oStream := CreateObject( "ADODB.Stream" ) )
:Charset := cCharSet
:Mode := adModeReadWrite
:Type := adTypeText
:Open()
END
RETURN Self
/*----------------------------------------------------------------------------*/
METHOD AddField( cField, cValue ) CLASS TPostHtml
::oStream:WriteText( ::cBoundary + FINL + 'Content-Disposition: form-data; name="' + cField + '"' + FINL + FINL + cValue + FINL )
RETURN NIL
/*----------------------------------------------------------------------------*/
METHOD AddExtraRequest( cClave,cValor ) CLASS TPostHtml
AAdd( ::aExtraRequestHeader, { cClave, cValor } )
RETURN NIL
/*----------------------------------------------------------------------------*/
METHOD AddFile( cFieldName, cFileName, cFilePath ) CLASS TPostHtml
#ifdef __NOBINARY__
LOCAL cFileStr, nFileLen
cFileStr := hb_StrToUTF8( hb_Base64Encode( FileStr( cFilePath ) ) )
//cFileStr := CharRem( CRLF, cFileStr )
//hb_StrToUTF8(
//cFileStr := FileStr( cFilePath )
//nFileLen := Len( cFilePath )
//cFileStr := hb_base64Encode( cFileStr, nFileLen )
WITH OBJECT ::oStream
:WriteText( ::cBoundary + FINL )
:WriteText( 'Content-Disposition: form-data; name="'+ cFieldName + '"; filename="' + cFileName + '"' + FINL ) // + FINL
:WriteText( 'Content-Type: ' + GetContentType( cFileName ) + FINL )
:WriteText( 'Content-Transfer-Encoding: base64' + FINL + FINL )
:WriteText( cFileStr + FINL )
:WriteText( ::cBoundary + "--" )
END
cFileStr := NIL
nFileLen := 0
#else
LOCAL oStream
WITH OBJECT ( oStream := CreateObject( "ADODB.Stream" ) )
:Charset := ::cCharSet
:Type := adTypeBinary
:Mode := adModeReadWrite
:Open()
:LoadFromFile( cFilePath )
END
WITH OBJECT ::oStream
:WriteText( ::cBoundary + FINL )
:WriteText( 'Content-Disposition: form-data; name="'+ cFieldName + '"; filename="' + cFileName + '"' + FINL + FINL )
:WriteText( 'Content-Type: ' + GetContentType( cFileName ) + FINL )
:WriteText( 'Content-Transfer-Encoding: binary' + FINL + FINL )
:Position := 0
:Type := adTypeBinary
:Position := :Size()
oStream:CopyTo( ::oStream )
:Position := 0
:Type := adTypeText
:Position := :Size()
:WriteText( FINL + ::cBoundary + "--" )
:Position := 0
:Type := adTypeBinary
END
oStream:Close()
#endif
RETURN NIL
/*----------------------------------------------------------------------------*/
METHOD Read() CLASS TPostHtml
::oStream:Position := 0
#ifdef __NOBINARY__
RETURN ::oStream:ReadText()
#else
::oStream:Position := 0
::oStream:Type := adTypeBinary
RETURN ::oStream:Read()
#endif
/*----------------------------------------------------------------------------*/
METHOD Save( cFileName ) CLASS TPostHtml
::oStream:Position := 0
#ifdef __NOBINARY__
RETURN StrFile( ::oStream:ReadText(), cFileName)
#else
::oStream:Position := 0
::oStream:Type := adTypeBinary
RETURN StrFile( ::oStream:Read( adReadAll ), cFileName )
#endif
/*----------------------------------------------------------------------------*/
STATIC FUNCTION FixFileName( cFileName )
RETURN CharRem( "[<(-)>]*&@:", cFileName )
/*----------------------------------------------------------------------------*/
STATIC FUNCTION GetContentType( cFileName )
LOCAL cExt := cFileExt( cFileName )
LOCAL aItem, cTipo := "text/plain"
LOCAL aTipeFile
aTipeFile := { ;
{ "php" , "application/x-php"},;
{ "vbs" , "application/x-vbs"},;
{ "jpe" , "image/jpeg"},;
{ "jpg" , "image/jpeg"},;
{ "jpeg" , "image/jpeg"},;
{ "gif" , "image/gif"},;
{ "png" , "image/png"},;
{ "bmp" , "image/bmp"},;
{ "ico" , "image/x-icon"},;
{ "svg" , "image/svg+xml"},;
{ "svgz" , "image/svg+xml"},;
{ "tif" , "image/tiff"},;
{ "tiff" , "image/tiff"},;
{ "pct" , "image/x-pict"},;
{ "psd" , "image/vnd.adobe.photoshop"},;
{ "aac" , "audio/x-aac"},;
{ "aif" , "audio/x-aiff"},;
{ "flac" , "audio/x-flac"},;
{ "m4a" , "audio/x-m4a"},;
{ "m4b" , "audio/x-m4b"},;
{ "mid" , "audio/midi"},;
{ "midi" , "audio/midi"},;
{ "mp3" , "audio/mpeg"},;
{ "mpa" , "audio/mpeg"},;
{ "mpc" , "audio/x-musepack"},;
{ "oga" , "audio/ogg"},;
{ "ogg" , "audio/ogg"},;
{ "ra" , "audio/vnd.rn-realaudio"},;
{ "ram" , "audio/vnd.rn-realaudio"},;
{ "snd" , "audio/x-snd"},;
{ "wav" , "audio/x-wav"},;
{ "wma" , "audio/x-ms-wma"},;
{ "avi" , "video/x-msvideo"},;
{ "divx" , "video/divx"},;
{ "flv" , "video/x-flv"},;
{ "m4v" , "video/mp4"},;
{ "mkv" , "video/x-matroska"},;
{ "mov" , "video/quicktime"},;
{ "mp4" , "video/mp4"},;
{ "mpeg" , "video/mpeg"},;
{ "mpg" , "video/mpeg"},;
{ "ogm" , "application/ogg"},;
{ "ogv" , "video/ogg"},;
{ "rm" , "application/vnd.rn-realmedia"},;
{ "rmvb" , "application/vnd.rn-realmedia-vbr"},;
{ "smil" , "application/x-smil"},;
{ "webm" , "video/webm"},;
{ "wmv" , "video/x-ms-wmv"},;
{ "xvid" , "video/x-msvideo"},;
{ "js" , "application/javascript"},;
{ "xml" , "text/xml"},;
{ "html" , "text/html"},;
{ "css" , "text/css"},;
{ "txt" , "text/plain"},;
{ "py" , "text/x-python"},;
{ "pdf" , "application/pdf"},;
{ "xhtml", "application/xhtml+xml"},;
{ "zip" , "application/x-zip-compressed, application/zip"},;
{ "rar" , "application/x-rar-compressed"},;
{ "cmd" , "application/cmd"},;
{ "bat" , "application/x-bat, application/x-msdos-program"},;
{ "exe" , "application/exe, application/x-ms-dos-executable"},;
{ "msi" , "application/x-msi"},;
{ "bin" , "application/x-binary"},;
{ "crt" , "application/x-x509-ca-cert"},;
{ "crl" , "application/x-pkcs7-crl"},;
{ "pfx" , "application/x-pkcs12"},;
{ "p12" , "application/x-pkcs12"},;
{ "odc" , "application/vnd.oasis.opendocument.chart"},;
{ "odf" , "application/vnd.oasis.opendocument.formula"},;
{ "odb" , "application/vnd.oasis.opendocument.database"},;
{ "odg" , "application/vnd.oasis.opendocument.graphics"},;
{ "odi" , "application/vnd.oasis.opendocument.image"},;
{ "odp" , "application/vnd.oasis.opendocument.presentation"},;
{ "ods" , "application/vnd.oasis.opendocument.spreadsheet"},;
{ "odt" , "application/vnd.oasis.opendocument.tex"},;
{ "docx" , "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},;
{ "dotx" , "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},;
{ "potx" , "application/vnd.openxmlformats-officedocument.presentationml.template"},;
{ "ppsx" , "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},;
{ "pptx" , "application/vnd.openxmlformats-officedocument.presentationml.presentation"},;
{ "xlsx" , "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},;
{ "xltx" , "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},;
{ "ppam" , "application/vnd.ms-powerpoint.addin.macroEnabled.12"},;
{ "ppa" , "application/vnd.ms-powerpoint"},;
{ "potm" , "application/vnd.ms-powerpoint.template.macroEnabled.12"},;
{ "ppsm" , "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},;
{ "xlsm" , "application/vnd.ms-excel.sheet.macroEnabled.12"},;
{ "pptm" , "application/vnd.ms-powerpoint.presentation.macroEnabled.12"},;
{ "dotm" , "application/vnd.ms-word.template.macroEnabled.12"},;
{ "docm" , "application/vnd.ms-word.document.macroEnabled.12"},;
{ "doc" , "application/msword"},;
{ "dot" , "application/msword"},;
{ "pps" , "application/mspowerpoint"},;
{ "ppt" , "application/mspowerpoint,application/powerpoint,application/vnd.ms-powerpoint,application/x-mspowerpoint"},;
{ "xls" , "application/vnd.ms-excel"},;
{ "xlt" , "application/vnd.ms-excel" } }
FOR EACH aItem IN aTipeFile
IF aItem[ 1 ] == cExt
cTipo := aItem[ 2 ]
ENDIF
NEXT
RETURN cTipo
/*----------------------------------------------------------------------------*/
//EOF
/*----------------------------------------------------------------------------*/