use of org.javacord.core.util.rest.RestRequest in project Javacord by BtoBastian.
the class RatelimitManager method handleResponse.
/**
* Updates the ratelimit information and sets the result if the request was successful.
*
* @param request The request.
* @param result The result of the request.
* @param bucket The bucket the request belongs to.
* @param responseTimestamp The timestamp directly after the response finished.
*/
private void handleResponse(RestRequest<?> request, RestRequestResult result, RatelimitBucket bucket, long responseTimestamp) {
if (result == null || result.getResponse() == null) {
return;
}
Response response = result.getResponse();
boolean global = response.header("X-RateLimit-Global", "false").equalsIgnoreCase("true");
int remaining = Integer.parseInt(response.header("X-RateLimit-Remaining", "1"));
long reset = request.getEndpoint().getHardcodedRatelimit().map(ratelimit -> responseTimestamp + api.getTimeOffset() + ratelimit).orElseGet(() -> (long) (Double.parseDouble(response.header("X-RateLimit-Reset", "0")) * 1000));
// Check if we received a 429 response
if (result.getResponse().code() == 429) {
if (response.header("Via") == null) {
logger.warn("Hit a CloudFlare API ban! This means you were sending a very large " + "amount of invalid requests.");
long retryAfter = Long.parseLong(response.header("Retry-after")) * 1000;
RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter);
return;
}
long retryAfter = result.getJsonBody().isNull() ? 0 : (long) (result.getJsonBody().get("retry_after").asDouble() * 1000);
if (global) {
// We hit a global ratelimit. Time to panic!
logger.warn("Hit a global ratelimit! This means you were sending a very large " + "amount within a very short time frame.");
RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter);
} else {
logger.debug("Received a 429 response from Discord! Recalculating time offset...");
// Setting the offset to null causes a recalculate for the next request
api.setTimeOffset(null);
// Update the bucket information
bucket.setRatelimitRemaining(0);
bucket.setRatelimitResetTimestamp(responseTimestamp + retryAfter);
}
} else {
// Check if we didn't already complete it exceptionally.
CompletableFuture<RestRequestResult> requestResult = request.getResult();
if (!requestResult.isDone()) {
requestResult.complete(result);
}
// Update bucket information
bucket.setRatelimitRemaining(remaining);
bucket.setRatelimitResetTimestamp(reset);
}
}
use of org.javacord.core.util.rest.RestRequest in project Javacord by BtoBastian.
the class ServerImpl method getAuditLogBefore.
@Override
public CompletableFuture<AuditLog> getAuditLogBefore(int limit, AuditLogEntry before, AuditLogActionType type) {
CompletableFuture<AuditLog> future = new CompletableFuture<>();
api.getThreadPool().getExecutorService().submit(() -> {
try {
AuditLogImpl auditLog = new AuditLogImpl(this);
boolean requestMore = true;
while (requestMore) {
int requestAmount = limit - auditLog.getEntries().size();
requestAmount = Math.min(requestAmount, 100);
RestRequest<JsonNode> request = new RestRequest<JsonNode>(getApi(), RestMethod.GET, RestEndpoint.AUDIT_LOG).setUrlParameters(getIdAsString()).addQueryParameter("limit", String.valueOf(requestAmount));
List<AuditLogEntry> lastAuditLogEntries = auditLog.getEntries();
if (!lastAuditLogEntries.isEmpty()) {
// It's not the first request, so append a "before"
request.addQueryParameter("before", lastAuditLogEntries.get(lastAuditLogEntries.size() - 1).getIdAsString());
} else if (before != null) {
// It's the first request, and we have a non-null "before" parameter
request.addQueryParameter("before", before.getIdAsString());
}
if (type != null) {
request.addQueryParameter("action_type", String.valueOf(type.getValue()));
}
JsonNode data = request.execute(RestRequestResult::getJsonBody).join();
// Add the new entries
auditLog.addEntries(data);
// Check if we have to make another request
requestMore = auditLog.getEntries().size() < limit && data.get("audit_log_entries").size() >= requestAmount;
}
future.complete(auditLog);
} catch (Throwable t) {
future.completeExceptionally(t);
}
});
return future;
}
use of org.javacord.core.util.rest.RestRequest in project Javacord by BtoBastian.
the class InteractionMessageBuilderDelegateImpl method checkForAttachmentsAndExecuteRequest.
private CompletableFuture<Message> checkForAttachmentsAndExecuteRequest(RestRequest<Message> request, ObjectNode body) {
if (!attachments.isEmpty() || embeds.stream().anyMatch(EmbedBuilder::requiresAttachments)) {
CompletableFuture<Message> future = new CompletableFuture<>();
// We access files etc. so this should be async
request.getApi().getThreadPool().getExecutorService().submit(() -> {
try {
List<FileContainer> tempAttachments = new ArrayList<>(attachments);
// Add the attachments required for the embed
for (EmbedBuilder embed : embeds) {
tempAttachments.addAll(((EmbedBuilderDelegateImpl) embed.getDelegate()).getRequiredAttachments());
}
addMultipartBodyToRequest(request, body, tempAttachments, request.getApi());
request.execute(result -> request.getApi().getOrCreateMessage(request.getApi().getTextChannelById(result.getJsonBody().get("channel_id").asLong()).orElseThrow(() -> new NoSuchElementException("TextChannel is not cached")), result.getJsonBody())).whenComplete((message, throwable) -> {
if (throwable != null) {
future.completeExceptionally(throwable);
} else {
future.complete(message);
}
});
} catch (Throwable t) {
future.completeExceptionally(t);
}
});
return future;
} else {
request.setBody(body);
return request.execute(result -> request.getApi().getOrCreateMessage(request.getApi().getTextChannelById(result.getJsonBody().get("channel_id").asLong()).orElseThrow(() -> new NoSuchElementException("TextChannel is not cached")), result.getJsonBody()));
}
}
use of org.javacord.core.util.rest.RestRequest in project Javacord by BtoBastian.
the class ServerTextChannelBuilderDelegateImpl method create.
@Override
public CompletableFuture<ServerTextChannel> create() {
ObjectNode body = JsonNodeFactory.instance.objectNode();
body.put("type", 0);
super.prepareBody(body);
if (topic != null) {
body.put("topic", topic);
}
if (category != null) {
body.put("parent_id", category.getIdAsString());
}
if (delayModified) {
body.put("rate_limit_per_user", delay);
}
return new RestRequest<ServerTextChannel>(server.getApi(), RestMethod.POST, RestEndpoint.SERVER_CHANNEL).setUrlParameters(server.getIdAsString()).setBody(body).setAuditLogReason(reason).execute(result -> server.getOrCreateServerTextChannel(result.getJsonBody()));
}
use of org.javacord.core.util.rest.RestRequest in project Javacord by BtoBastian.
the class ServerVoiceChannelBuilderDelegateImpl method create.
@Override
public CompletableFuture<ServerVoiceChannel> create() {
ObjectNode body = JsonNodeFactory.instance.objectNode();
body.put("type", 2);
super.prepareBody(body);
if (bitrate != null) {
body.put("bitrate", (int) bitrate);
}
if (userlimit != null) {
body.put("user_limit", (int) userlimit);
}
if (category != null) {
body.put("parent_id", category.getIdAsString());
}
return new RestRequest<ServerVoiceChannel>(server.getApi(), RestMethod.POST, RestEndpoint.SERVER_CHANNEL).setUrlParameters(server.getIdAsString()).setBody(body).setAuditLogReason(reason).execute(result -> server.getOrCreateServerVoiceChannel(result.getJsonBody()));
}
Aggregations