diff --git a/Pleroma/Pleroma.cs b/Pleroma/Pleroma.cs index cc859f9..59d60a6 100644 --- a/Pleroma/Pleroma.cs +++ b/Pleroma/Pleroma.cs @@ -40,6 +40,85 @@ public class Pleroma Authorization = authorization; } + async Task RequestJSONRetry(HttpRequest req) + { + while (true) + { + try + { + await RequestJSON(req); + return; + } + catch (PleromaException e) + { + if (e.Text == "Throttled") + { + await Task.Delay(5000); + continue; + } + else + throw; + } + } + } + + async Task RequestJSONRetry(HttpRequest req) where T : class + { + while (true) + { + try + { + return await RequestJSON(req); + } + catch (PleromaException e) + { + if (e.Text == "Throttled") + { + await Task.Delay(5000); + continue; + } + else + throw; + } + } + } + + async Task RequestJSON(HttpRequest req) + { + req.Fields.UserAgent = UserAgent; + req.Fields.Authorization = Authorization; + + HttpResponse res = await HttpClient.Request(Host, true, req); + + if (res.StatusCode == 404) + return; + + if (!res.Fields.ContentType.HasValue || !res.Fields.ContentType.Value.Match(JsonMIMEType)) + throw new HttpException("Server did not respond with JSON" + (res.Content.HasValue ? ", got: " + res.Content.Value.AsText : null)); + + if (!res.Content.HasValue) + throw new HttpException("Server responded with no content"); + + string text = res.Content.Value.AsText; + + if (res.StatusCode is >= 400 and < 600) + { + try + { + PleromaException? err = JsonSerializer.Deserialize(text, SerializerOptions); + if (err != null && err.Text != null) + throw err; + } + catch (JsonException) + { + //Not an error + } + } + + if (res.StatusCode is not >= 200 or not < 300) + throw new HttpException("Unknown error occurred"); + } + async Task RequestJSON(HttpRequest req) where T : class { req.Fields.UserAgent = UserAgent; @@ -88,7 +167,7 @@ public class Pleroma HttpRequest req = new HttpRequest(HttpMethod.POST, "/api/v1/statuses"); req.Content = new HttpContent(JsonMIMEType, JsonSerializer.SerializeToUtf8Bytes(status, SerializerOptions)); req.Fields.Accept = [JsonMIMEType]; - return RequestJSON(req)!; + return RequestJSONRetry(req)!; } /// @@ -99,7 +178,7 @@ public class Pleroma //TODO: Parameters and selecting different timelines (home, public, bubble) HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/timelines/public"); req.Fields.Accept = [ JsonMIMEType ]; - return RequestJSON(req)!; + return RequestJSONRetry(req)!; } /// @@ -115,7 +194,7 @@ public class Pleroma { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{account_id}/statuses"); req.Fields.Accept = [JsonMIMEType]; - return RequestJSON(req)!; + return RequestJSONRetry(req)!; } /// @@ -125,7 +204,7 @@ public class Pleroma { HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/accounts/verify_credentials"); req.Fields.Accept = [JsonMIMEType]; - return RequestJSON(req)!; + return RequestJSONRetry(req)!; } /// @@ -135,7 +214,7 @@ public class Pleroma { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{id}"); req.Fields.Accept = [JsonMIMEType]; - return RequestJSON(req); + return RequestJSONRetry(req); } /// @@ -151,6 +230,7 @@ public class Pleroma { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/statuses/{status_id}/context"); req.Fields.Accept = [JsonMIMEType]; - return RequestJSON(req); + return RequestJSONRetry(req); + } } }