Passing JSONP responses to AutoHotkey

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
tester
Posts: 84
Joined: 10 Jun 2021, 23:03

Passing JSONP responses to AutoHotkey

Post by tester » 13 Aug 2022, 01:07

Hello,

I'm trying to pass JSONP data retrieved from a JavaScript script to an AutoHotkey script.

To pass a simple JavaScript value, this works.

Code: Select all

code := "(function() { return 'This is returned form IIFE.' })();"
MsgBox, % JS.(code)

GetJScriptObject() {
	static doc := ComObjCreate("htmlfile")
	doc.write("<meta http-equiv='X-UA-Compatible' content='IE=9'>")
	return ObjBindMethod(doc.parentWindow, "eval")
}
However, when async processes are involved, it doesn't seem to work, especially when waiting for JSONP responses and trying to pass the fetched data to AutoHotkey.

Code: Select all

code =
(
function geoip(data){
    console.log('Fetched data', data);
    var stringData = JSON.stringify(data);
    alert(stringData);
    return stringData; 
}
var script = document.createElement('script');
script.src = 'https://get.geojs.io/v1/ip/geo.js';
document.getElementsByTagName('head')[0].appendChild(script);
)
MsgBox, % JS.(code)

GetJScriptObject() {
	static doc := ComObjCreate("htmlfile")
	doc.write("<meta http-equiv='X-UA-Compatible' content='IE=9'>")
	return ObjBindMethod(doc.parentWindow, "eval")
}
There is UrlDownloadToVar() or UrlDownloadToFile and you can sanitize the retrieved raw outputs but unwrapping the JSONP function and sanitizing JavaScript-generated quote characters in AutoHotkey are not reliable. So I'm looking for a JavaScript way to fetch data and pass it from JavaScript to AutoHotkey.

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Passing JSONP responses to AutoHotkey

Post by BoBo » 13 Aug 2022, 03:20

In my script :arrow: here I've used a CSV response to create an object (there are other formats available too) so I wouldn’t have to #Include JSON.ahk afterward.

Code: Select all

F12::MsgBox % var := geoIP()                                        ;press F12

geoIP() {
		whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
		whr.SetTimeouts(0, 5000, 5000, 100000)                      ; adjust timeouts accordingly. Default: (0, 30000, 30000, 600000)
		whr.Open("GET","https://get.geojs.io/v1/ip/geo.js", False)
		whr.Send()
		Sleep 100
		return whr.ResponseText
		}
HTH :)

tester
Posts: 84
Joined: 10 Jun 2021, 23:03

Re: Passing JSONP responses to AutoHotkey

Post by tester » 13 Aug 2022, 05:20

Sorry, it's not what I'm looking for.

The string contains raw data that includes a JavaScript function and the enwrapped JSON data has some escape characters and handling them in AutoHotkey is not ideal when they can be done in JavaScript in a clean reliable manner. That's why I already wrote this in the first place.
There is UrlDownloadToVar() or UrlDownloadToFile and you can sanitize the retrieved raw outputs but unwrapping the JSONP function and sanitizing JavaScript-generated quote characters in AutoHotkey are not reliable. So I'm looking for a JavaScript way to fetch data and pass it from JavaScript to AutoHotkey.

teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Passing JSONP responses to AutoHotkey

Post by teadrinker » 13 Aug 2022, 10:25

Code: Select all

res := WebRequest("https://get.geojs.io/v1/ip/geo.js",,,, error := "")
if error {
   MsgBox, % error
   Return
}
json := RegExReplace(res, "s)\{.*}(*SKIP)(*F)|.")
ahkObj := JsonToAHK(json)
str := ""
for k, v in ahkObj
   str .= (k = 1 ? "" : "`n") . k . ": " . v
MsgBox, % str

WebRequest(url, method := "GET", HeadersArray := "", body := "", ByRef error := "") {
   Whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   Whr.Open(method, url, true)
   for name, value in HeadersArray
      Whr.SetRequestHeader(name, value)
   Whr.Send(body)
   Whr.WaitForResponse()
   status := Whr.status
   if (status != 200)
      error := "HttpRequest error, status: " . status
   Arr := Whr.responseBody
   pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
   length := Arr.MaxIndex() + 1
   Return StrGet(pData, length, "UTF-8")
}

JsonToAHK(json, rec := false) {
   static doc := ComObjCreate("htmlfile")
        , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
        , JS := doc.parentWindow
   if !rec
      obj := %A_ThisFunc%(JS.JSON.parse(json), true)
   else if !IsObject(json)
      obj := json
   else if JS.Object.prototype.toString.call(json) == "[object Array]" {
      obj := []
      Loop % json.length
         obj.Push( %A_ThisFunc%(json[A_Index - 1], true) )
   }
   else {
      obj := {}
      keys := JS.Object.keys(json)
      Loop % keys.length {
         k := keys[A_Index - 1]
         obj[k] := %A_ThisFunc%(json[k], true)
      }
   }
   Return obj
}

tester
Posts: 84
Joined: 10 Jun 2021, 23:03

Re: Passing JSONP responses to AutoHotkey

Post by tester » 13 Aug 2022, 10:50

@teadrinker Sorry, it doesn't work when responses become complex with multi-dimensional objects. "https://get.geojs.io/v1/ip/geo.js" is just an example to make the question simple. The actual API endpoint is private and returns more complexly structured data and occasionally contains special characters which cause errors without proper sanitization when parsed on the AutoHotkey side.

teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Passing JSONP responses to AutoHotkey

Post by teadrinker » 13 Aug 2022, 11:40

You could give an example.

Post Reply

Return to “Ask for Help (v1)”