#Define TWILIO_ROOT "/2010-04-01/Accounts/" #Define TWILIO_ACCOUNT_SID "This is the account SID assignd by Twilio" // 34 bytes #Define TWILIO_AUTH_TOKEN "This is the authorization tocken assigned by twilio" // 32 bytes * ChilkatAx-9.5.0-win32.dll is in my EXE folder FUNCTION ChilKat_GlobalUnlock() // This need to be called once at start to unlock the ChilKet Libraries LOCAL oGlob LOCAL nSuccess := 0 * The Chilkat API can be unlocked for a fully-functional 30-day trial by passing any * string to the UnlockBundle method. A program can unlock once at the start. Once unlocked, * all subsequently instantiated objects are created in the unlocked state. * * After licensing Chilkat, replace the "Anything for 30-day trial" with the purchased unlock code. * To verify the purchased unlock code was recognized, examine the contents of the LastErrorText * property after unlocking. For example: oGlob := CreateObject('Chilkat_9_5_0.Global') IF oGlob == NIL nSuccess := 0 ELSE nSuccess = oGlob:UnlockBundle("Anything for 30-day trial") // "ChilKat Unlock Code tdMsg({"ChilKat Unlock Failure","Error Text: "+VAR2CHAR(oGlob:LastErrorText)}) ELSE * tdMsg("ChilKat Unlocked") ENDIF oGlob:Destroy() ENDIF RETURN nSuccess == 1 /* I use Clayton Jone's libraries in my application... tdMsg(xTxt,cTxt2,[nIcon],[aColor],[cCompName], [cBord],[nRowAdj],[nColAdj],[nWdAdj], [oOwner],[nTimeout],[cTitle],[cJust],[lOvdPx]) tdMsg() is a popup "black box" routine which can display multiple lines of text and an "OK" button in a Modal window. The window automatically sizes itself to accommodate the length of the text, and allows control over font, colors, border, and can display a system icon. The window centers itself by default, but may be moved off center using the nRowAdj and nColAdj parameters. tdMsg Can easily be replaced with MsgBox() with minor adjustnents tdPopMemo(nRows,nCols,bLink,[cMode],[cTitle],[lGoBottom],[nRowAdj],; [nColAdj],[cCompname],[lWrap],[lHscroll],[lVscroll],; [lModal],[nIcon],[oOwner],[aHotkeys],[nTimeOut],[lMsg],; [nVmdBgClr],[nEmdBgClr],[bTimeout],[lOvdPx],; [nDlgClr],[nEmdFgClr],[lHiLite],[lStyles]) tdPopMemo() allows editing or viewing a memo field within a popup window. It assumes that a table with a memo field is open and the record or file is locked if open in shared mode. The window displays an Mle component with 'Save' and 'Cancel' buttons, which also correspond to the "Ctrl-S" and "Esc" keys. The components are placed automatically according to the size of the window. In 'view' mode only the OK button is displayed. tdPopMemo could also be replaced with MsgBox() tdPause(n) n is amount of pause time in 1/100 of second This function returns after the specified amount of time, allowing a pause in program execution. During this pause, any events in the current thread's event queue are processed. This function is similar to the Xbase++ function sleep(), except that sleep() does not allow events to be processed. tdPause() is handy for situations such as a data processing loop which captures program flow and does not allow any event processing. Inserting tdPause(n) in the loop can allow background event processing to continue. This could probably be replaced with SLEEP() as the delay is to allow the Twilio Server to process the request. */ FUNCTION ReceiveSMS(cToPhone) // cPhone is Twilio Assigned Phone Number with Area code LOCAL oRest,; nSuccess,; nPort := 443,; // The port number which is typically 80 or 443 nBTls := 1,; // If SSL/TLS is required, then tls should be set to 1 nBAutoReconnect := 1,; // AutoReconnect indicates whether connection should automatically be established as needed for subsequent REST requests nError := 0,; // BEGIN / END SEQUENCE... BREAK / RECOVER USING nError cError,; cResponseJson,; aResponse,; oJson,; cMessages,; nMsgSize,; nMsgPnt,; oMessage,; oJsonArray,; cSid,; cDateSent,; cTo,; cFrom,; cBody,; cUri,; cSidFolder := "",; nNumMedia,; cMediaList,; oMediaList,; oMediaArray,; nMediaSize,; nMediaPnt,; cMediaUri,; oMedia,; cMediaJson,; oMediaJson,; oHTTP LOCAL cEntireJson,cRequest ,cMediaFile *Default(cToPhone,"999999999") // Default Twilio Account Phone Number (First # Assigned) cToPhone := "+1"+cToPhone // Phone number needs "1" at start for North America BEGIN SEQUENCE IF .NOT. TwilioConnect(@oRest) // Create oRest & establish initial connection to Twilio BREAK 1 ENDIF * Send the SMS text message. * Your Twilio Account SID is part of the URI path: *cResponseJson = oRest.FullRequestFormUrlEncoded("POST","/2010-04-01/Accounts/TWILIO_ACCOUNT_SID/Messages.json") cResponseJson = oRest:FullRequestFormUrlEncoded("GET",TWILIO_ROOT+TWILIO_ACCOUNT_SID+"/Messages.json") // Return All Twilio Log Entries IF (oRest:LastMethodSuccess <> 1) BREAK 2 ENDIF IF .NOT. VALTYPE(oJson := CreateObject('Chilkat_9_5_0.JsonObject')) == "O" BREAK 3 ENDIF oJson:EmitCompact = 0 IF oJson:Load(cResponseJson) <> 1 // Convert all Twilio log entries into a Json Object BREAK 4 ENDIF cEntireJson := oJson:Emit() *tdPopMemo(18,80, {|x| iif(x==nil,cEntireJson,cEntireJson:=x) } ,"view","Entire Jason") oJsonArray := oJson:ArrayOf("messages") nMsgSize := oJsonArray:size FOR nMsgPnt := 1 TO nMsgSize // Locate current Message Result from oJson Array Object of Message Logs oMessage := oJsonArray:ObjectAt(nMsgPnt-1) // oMessage is single message entry as a json Object, oJsonArray is a base 0 array IF oMessage:StringOf("direction") == "inbound" .AND.; // This is a received message (cTo := oMessage:StringOf("to")) == cToPhone cDateSent := oMessage:StringOf("date_sent") cFrom := oMessage:StringOf("from") cBody := oMessage:StringOf("body") cSid := oMessage:StringOf("sid") cUri := oMessage:StringOf("uri") // This is the Json file that needs to be deleted */* nNumMedia := VAL(oMessage:StringOf("num_media")) IF nNumMedia > 0 cRequest := TWILIO_ROOT+TWILIO_ACCOUNT_SID+"/Messages/"+cSid+"/Media.json" tdPopMemo(18,80, {|x| iif(x==nil,cRequest,cRequest:=x) } ,"view","Media List Request") cMediaList := oRest:FullRequestFormUrlEncoded("GET",cRequest) IF (oRest:LastMethodSuccess <> 1) tdMsg("Media Load Failed") ELSE *tdMsg("Media Loaded OK") *tdPopMemo(18,80, {|x| iif(x==nil,cMediaList,cMediaList:=x) } ,"view","Media Jason - raw") IF .NOT. VALTYPE(oMediaList := CreateObject('Chilkat_9_5_0.JsonObject')) == "O" BREAK 5 ENDIF oMediaList:EmitCompact = 0 IF oMediaList:Load(cMediaList) <> 1 // Convert Json Media File into a Json Object BREAK 6 ENDIF cMediaList := oMediaList:Emit() tdPopMemo(18,80, {|x| iif(x==nil,cMediaList,cMediaList:=x) } ,"view","Media List - Emit") oMediaArray := oMediaList:ArrayOf("media_list") nMediaSize := oMediaArray:Size FOR nMediaPnt := 1 TO nMediaSize oMedia := oMediaArray:ObjectAt(nMediaPnt-1) // oMessage is single message entry as a json Object, oJsonArray is a base 0 array cMediaUri := oMedia:StringOf("uri") cMediaFile := "https://api.twilio.com" + STRTRAN(cMediaUri,".json","") oHttp := CreateObject('Chilkat_9_5_0.HTTP') oHttp:Download(cMediaFile, "c:\famxbase\movie.mp4") NEXT nMediaPnt ENDIF ENDIF */ */* IF oMessage:Hasmember("subresource_uris") == 1 // Sub folder exists cSidFolder := "TWILIO_ROOT"+TWILIO_ACCOUNT_SID+"/Messages/"+cSid ENDIF tdPause(200) oRest:FullRequestFormUrlEncoded("DELETE",cUri) // Delete Sid.Json file IF oRest:LastMethodSuccess <> 1 cError := oRest:LastErrorText tdPopMemo(18,80, {|x| iif(x==nil,cError,cError:=x) } ,"view","Delete 1 Error") ENDIF IF .NOT. EMPTY(cSidFolder) oRest:FullRequestFormUrlEncoded("DELETE",cSidFolder) // Delete Sid folder if it exists IF oRest:LastMethodSuccess <> 1 cError := oRest:LastErrorText tdPopMemo(18,80, {|x| iif(x==nil,cError,cError:=x) } ,"view","Delete 2 Error") ENDIF ENDIF */ tdMsg({"From: "+cFrom,; "Date: "+DateStr(LDStoDateTime(cdateSent)[1]),; "Time: "+LDStoDateTime(cdateSent)[2],; "Message... ",; cBody}) ENDIF NEXT nMsgPnt RECOVER USING nError IF .NOT. oRest == NIL .AND. VALTYPE(oRest) == "O" tdMsg({"nError: "+VAR2CHAR(nError),"Error Text: "+VAR2CHAR(oRest:LastErrorText)}) ENDIF END SEQUENCE IF .NOT. oRest == NIL .AND. VALTYPE(oRest) == "O" oRest:Destroy() ENDIF IF .NOT. oJson == NIL .AND. VALTYPE(oJson) == "O" oJson:Destroy() ENDIF IF .NOT. oJsonArray == NIL .AND. VALTYPE(oJsonArray) == "O" oJsonArray:Destroy() ENDIF IF .NOT. oMessage == NIL .AND. VALTYPE(oMessage) == "O" oMessage:Destroy() ENDIF IF .NOT. oHttp == NIL .AND. VALTYPE(oHttp) == "O" oHttp:Destroy() ENDIF RETURN nError