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 | |
} | |
} |