About: https://redd.it/on9gab
Example with dependencies: ImgUr_Api.ahk.zip
About: https://redd.it/on9gab
Example with dependencies: ImgUr_Api.ahk.zip
| | |
| ; Version: 2022.11.11.1 | |
| ; About: https://redd.it/on9gab | |
| #Include %A_LineFile%\..\Socket.ahk | |
| #Include %A_LineFile%\..\WinHttpRequest.ahk | |
| class ImgUr_Api { | |
| __New(Ini, Section:="IMGUR") { | |
| IniRead buffer, % Ini, % Section | |
| if (!buffer) | |
| throw Exception("Invalid configuration file.", -1) | |
| for _,line in StrSplit(buffer, "`n") { | |
| parts := StrSplit(line, "=",, 2) | |
| this["_" parts[1]] := parts[2] | |
| } | |
| if (!this._client_id || !this._client_secret) | |
| throw Exception("No Client ID/Secret.", -1, Ini) | |
| if (!this._port) | |
| throw Exception("Port not defined.", -1, Ini) | |
| if (this._port < 1024 && !A_IsAdmin) | |
| throw Exception("Invalid port for server.", -1, Ini) | |
| this._ini := Ini | |
| this._section := Section | |
| this.http := new WinHttpRequest() | |
| if (!this._access_token) | |
| this.Auth() | |
| while (!this._access_token) | |
| Sleep 50 | |
| } | |
| Auth() { | |
| server := new SocketTCP() | |
| server.OnAccept := ObjBindMethod(this, "_Socket") | |
| server.Bind(["0.0.0.0", this._port]) | |
| server.Listen() | |
| this._access_token := "" | |
| Run % "https://api.imgur.com/oauth2/authorize" | |
| . "?client_id=" this._client_id | |
| . "&response_type=token" | |
| } | |
| Refresh() { | |
| epoch := this._Epoch() | |
| if (epoch < this._expires_at) | |
| return | |
| ep := "https://api.imgur.com/oauth2/token" | |
| body := { "client_secret": this._client_secret | |
| , "grant_type": "refresh_token" | |
| , "refresh_token": this._refresh_token | |
| , "client_id": this._client_id } | |
| try { | |
| response := this.http.Post(ep, body) | |
| if (!response.Json.HasKey("access_token")) | |
| throw | |
| } catch e { | |
| this.Auth() | |
| return | |
| } | |
| this._Persist("access_token", response.access_token) | |
| this._Persist("expires_at", epoch + response.expires_in) | |
| this._Persist("refresh_token", response.refresh_token) | |
| } | |
| Rest(Method, Endpoint, Body:="", Headers:="") { | |
| this.Refresh() | |
| if (!IsObject(Headers)) | |
| Headers := {} | |
| Headers.Authorization := "Bearer " this._access_token | |
| http := ObjBindMethod(this.http, Method) | |
| try | |
| response := http.Call(Endpoint, Body, Headers) | |
| catch | |
| return {"error": "Couldn't complete request."} | |
| try | |
| return response.Json | |
| catch | |
| return {"error": "JSON parse error."} | |
| } | |
| _Epoch() { | |
| epoch := A_NowUTC | |
| epoch -= 19700101, Seconds | |
| return epoch | |
| } | |
| _Persist(Key, Value) { | |
| this["_" Key] := Value | |
| IniWrite % " " Value, % this._ini, % this._section, % Key | |
| } | |
| _Socket(Instance) { | |
| conn := Instance.Accept() | |
| request := conn.RecvText() | |
| request := StrSplit(request, A_Space,, 3)[2] | |
| if (request = "/") { | |
| txt := "HTTP/1.1 200 OK" "`r`n" | |
| txt .= "Connection: Close" "`r`n" | |
| txt .= "Content-Type: text/html" "`r`n" | |
| txt .= "`r`n" | |
| ; Content in quirks mode | |
| txt .= "<title>ImgUr Authotization</title>" | |
| txt .= "<script>" | |
| txt .= "http = new XMLHttpRequest();" | |
| txt .= "http.open('GET', '?' + window.location.hash.substring(1), true);" | |
| txt .= "http.send()" | |
| txt .= "</script>" | |
| txt .= "<h1>You can close this tab now.</h1>" | |
| } else { | |
| txt := "HTTP/1.1 204 No Content" "`r`n" | |
| txt .= "Connection: Close" "`r`n" | |
| txt .= "`r`n" | |
| } | |
| conn.SendText(txt) | |
| conn.Disconnect() | |
| if (InStr(request, "error")) { | |
| Instance.Disconnect() | |
| throw Exception("Permission not granted, can't continue.", -1) | |
| } | |
| if (InStr(request, "/?")) { | |
| Instance.Disconnect() | |
| RegExMatch(request, "access_token=\K[^&]+", access) | |
| RegExMatch(request, "expires_in=\K[^&]+", expires) | |
| RegExMatch(request, "refresh_token=\K[^&]+", refresh) | |
| this._Persist("access_token", access) | |
| this._Persist("expires_at", this._Epoch() + expires) | |
| this._Persist("refresh_token", refresh) | |
| } | |
| } | |
| __Delete() { | |
| ObjRelease(this.http) | |
| this.http := "" | |
| } | |
| } |
| | |
| ; Version: 2022.11.11.1 | |
| ; About: https://redd.it/on9gab | |
| #Include %A_LineFile%\..\ImgUr_Api.ahk | |
| class ImgUr_Image extends ImgUr_Api { | |
| ; id | |
| Delete(ImgId) { | |
| ep := "https://api.imgur.com/3/image/" ImgId | |
| response := this.Rest("DELETE", ep) | |
| return response.HasKey("data") ? response.data : response | |
| } | |
| Info(ImgId) { | |
| ep := "https://api.imgur.com/3/image/" ImgId | |
| ; Use `.http` rather than `Rest()` | |
| header := {"Authorization": "Client-ID " this._client_id} | |
| try | |
| response := this.http.GET(ep,, header) | |
| catch | |
| return {"error": "Couldn't complete request."} | |
| try | |
| return response.Json | |
| catch | |
| return {"error": "JSON parse error."} | |
| } | |
| ; id, {title, description} | |
| Update(ImgId, Body) { | |
| ep := "https://api.imgur.com/3/image/" ImgId | |
| response := this.Rest("POST", ep, Body) | |
| return response.HasKey("data") ? response.data : response | |
| } | |
| ; {image|url|video, album, name, title, description, disable_audio} | |
| Upload(Body) { | |
| ; old: https://api.imgur.com/3/image | |
| ep := "https://api.imgur.com/3/upload" | |
| Body.type := "file" | |
| if (Body.HasKey("image")) { | |
| Body.image := [Body.image] | |
| } else if (Body.HasKey("video")) { | |
| Body.video := [Body.video] | |
| } else if (Body.HasKey("url")) { | |
| Body.type := "url" | |
| Body.image := Body.url | |
| } | |
| if (!Body.HasKey("disable_audio")) | |
| Body.disable_audio := 0 | |
| response := this.Rest("POST", ep, Body) | |
| if (response.HasKey("data")) | |
| return response.data | |
| if (Body.type != "url") | |
| return response | |
| path := A_Temp "\" A_Now | |
| UrlDownloadToFile % Body.url, % path | |
| Body.Delete("url") | |
| Body.image := path | |
| response := this.Upload(Body) | |
| FileDelete % path | |
| return response | |
| } | |
| } |