#Include <Socket2> Persistent ; From WebViewToo ParseUri(Uri) { static Pattern := "^(?:(?<Scheme>\w+):)?(?://(?:(?<UserInfo>[^@]+)@)?(?<Host>[^:/?#]+)(?::(?<Port>\d+))?)?(?<Path>[^?#]*)?(?:\?(?<Query>[^#]*))?(?:#(?<Fragment>.*))?$" if (!RegExMatch(String(Uri), Pattern, &Match)) { return } Parsed := {} Parsed.Scheme := Match["Scheme"], Parsed.UserInfo := Match["UserInfo"], Parsed.Host := Match["Host"] Parsed.Port := Match["Port"], Parsed.Path := Match["Path"], Parsed.Query := Match["Query"] Parsed.Fragment := Match["Fragment"], Parsed.Authority := (Parsed.UserInfo != "" ? Parsed.UserInfo "@" : "") . Parsed.Host . (Parsed.Port != "" ? ":" Parsed.Port : "") return Parsed } ; From https://www.autohotkey.com/boards/viewtopic.php?p=372262 UrlUnescape(url) { if r := DllCall("Shlwapi.dll\UrlUnescape", "Str", url, "Ptr", 0, "UInt", 0, "UInt", 0x100000, "UInt") throw OsError(r) return url } RecvLine(this, encoding:='UTF-8', keepEnd:=false) { newlinePos := 0 ; MsgSize should block until some size is available. If there is ; an error, it returns early with zero. while size := this.MsgSize() { ; Peek at what's in the buffer and only break when a ; full line is available this._recv(buf := Buffer(size), size, Socket.MSG.PEEK) if newlinePos := InStr(StrGet(buf, 'cp0'), '`n') break Sleep 1 } this._recv(buf := Buffer(newlinePos), newlinePos) data := StrGet(buf, encoding) return keepEnd ? data : RTrim(data, '`r`n') } class DeckServer extends Socket.Server { onACCEPT(err) { client := this.AcceptAsClient() request := StrSplit(RecvLine(client), ' ') if request[1] != 'GET' { client.SendText('HTTP/1.0 501 Not Implemented`r`n`r`n') Sleep 50 return } uri := ParseUri(request[2]) fname := LTrim(UrlUnescape(uri.Path), "/") if !(Buttons.HasOwnProp(fname)) { client.SendText('HTTP/1.0 404 Not Found`r`n`r`n') Sleep 50 return } args := Map() for pair in StrSplit(uri.Query, '&') { pair := StrSplit(pair, "=",, 2) args[UrlUnescape(pair[1])] := UrlUnescape(pair[2]) } SetTimer () => Buttons.%fname%(args), -1 client.SendText('HTTP/1.0 200 OK`r`n`r`n') Sleep 50 return } } server := DeckServer(1337, '127.0.0.1') ; --- User Functions --- class Buttons { static Example(args) { MsgBox args['text'] } }
Window Management:
Shape tools:
Clipboard tools:
Launcher:
*RunAsUser
verb so you can run them with administrative privilegesSnippets! The stream deck can send blocks of text but with AHK you can paste them for better performance.
Open script in default editor
Reload script