Search in sources :

Example 1 with Request

use of net.dv8tion.jda.api.requests.Request in project JDA by DV8FromTheWorld.

the class Requester method execute.

public Long execute(Request<?> apiRequest, boolean retried, boolean handleOnRatelimit) {
    Route.CompiledRoute route = apiRequest.getRoute();
    Long retryAfter = rateLimiter.getRateLimit(route);
    if (retryAfter != null && retryAfter > 0) {
        if (handleOnRatelimit)
            apiRequest.handleResponse(new Response(retryAfter, Collections.emptySet()));
        return retryAfter;
    }
    okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
    String url = DISCORD_API_PREFIX + route.getCompiledRoute();
    builder.url(url);
    String method = apiRequest.getRoute().getMethod().toString();
    RequestBody body = apiRequest.getBody();
    if (body == null && HttpMethod.requiresRequestBody(method))
        body = EMPTY_BODY;
    builder.method(method, body).header("X-RateLimit-Precision", "millisecond").header("user-agent", USER_AGENT).header("accept-encoding", "gzip");
    // we can check for startsWith(DISCORD_API_PREFIX) because the cdn endpoints don't need any kind of authorization
    if (url.startsWith(DISCORD_API_PREFIX))
        builder.header("authorization", api.getToken());
    // If customHeaders is null this does nothing
    if (apiRequest.getHeaders() != null) {
        for (Entry<String, String> header : apiRequest.getHeaders().entrySet()) builder.addHeader(header.getKey(), header.getValue());
    }
    okhttp3.Request request = builder.build();
    Set<String> rays = new LinkedHashSet<>();
    okhttp3.Response[] responses = new okhttp3.Response[4];
    // we have an array of all responses to later close them all at once
    // the response below this comment is used as the first successful response from the server
    okhttp3.Response lastResponse = null;
    try {
        LOG.trace("Executing request {} {}", apiRequest.getRoute().getMethod(), url);
        int attempt = 0;
        do {
            if (apiRequest.isSkipped())
                return null;
            Call call = httpClient.newCall(request);
            lastResponse = call.execute();
            responses[attempt] = lastResponse;
            String cfRay = lastResponse.header("CF-RAY");
            if (cfRay != null)
                rays.add(cfRay);
            if (lastResponse.code() < 500)
                // break loop, got a successful response!
                break;
            attempt++;
            LOG.debug("Requesting {} -> {} returned status {}... retrying (attempt {})", apiRequest.getRoute().getMethod(), url, lastResponse.code(), attempt);
            try {
                Thread.sleep(50 * attempt);
            } catch (InterruptedException ignored) {
            }
        } while (attempt < 3 && lastResponse.code() >= 500);
        LOG.trace("Finished Request {} {} with code {}", route.getMethod(), lastResponse.request().url(), lastResponse.code());
        if (lastResponse.code() >= 500) {
            // Epic failure from other end. Attempted 4 times.
            Response response = new Response(lastResponse, -1, rays);
            apiRequest.handleResponse(response);
            return null;
        }
        retryAfter = rateLimiter.handleResponse(route, lastResponse);
        if (!rays.isEmpty())
            LOG.debug("Received response with following cf-rays: {}", rays);
        if (retryAfter == null)
            apiRequest.handleResponse(new Response(lastResponse, -1, rays));
        else if (handleOnRatelimit)
            apiRequest.handleResponse(new Response(lastResponse, retryAfter, rays));
        return retryAfter;
    } catch (UnknownHostException e) {
        LOG.error("DNS resolution failed: {}", e.getMessage());
        apiRequest.handleResponse(new Response(e, rays));
        return null;
    } catch (IOException e) {
        if (retryOnTimeout && !retried && isRetry(e))
            return execute(apiRequest, true, handleOnRatelimit);
        LOG.error("There was an I/O error while executing a REST request: {}", e.getMessage());
        apiRequest.handleResponse(new Response(e, rays));
        return null;
    } catch (Exception e) {
        LOG.error("There was an unexpected error while executing a REST request", e);
        apiRequest.handleResponse(new Response(e, rays));
        return null;
    } finally {
        for (okhttp3.Response r : responses) {
            if (r == null)
                break;
            r.close();
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Call(okhttp3.Call) UnknownHostException(java.net.UnknownHostException) Request(net.dv8tion.jda.api.requests.Request) IOException(java.io.IOException) SocketException(java.net.SocketException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) SSLPeerUnverifiedException(javax.net.ssl.SSLPeerUnverifiedException) Response(net.dv8tion.jda.api.requests.Response) RequestBody(okhttp3.RequestBody)

Example 2 with Request

use of net.dv8tion.jda.api.requests.Request in project pokeraidbot by magnusmickelsson.

the class InstallEmotesCommand method createEmote.

// Code taken from JDA's GuildController since they have a limitation that bot accounts can't upload emotes.
private void createEmote(String iconName, CommandEvent commandEvent, Icon icon, Role... roles) {
    JSONObject body = new JSONObject();
    body.put("name", iconName);
    body.put("image", icon.getEncoding());
    if (// making sure none of the provided roles are null before mapping them to the snowflake id
    roles.length > 0) {
        body.put("roles", Stream.of(roles).filter(Objects::nonNull).map(ISnowflake::getId).collect(Collectors.toSet()));
    }
    StringWriter writer = new StringWriter();
    body.write(writer);
    DataObject dataObject = DataObject.fromJson(writer.toString());
    GuildImpl guild = (GuildImpl) commandEvent.getGuild();
    JDA jda = commandEvent.getJDA();
    Route.CompiledRoute route = Route.Emotes.CREATE_EMOTE.compile(guild.getId());
    AuditableRestAction<Emote> action = new AuditableRestActionImpl<Emote>(jda, route, dataObject) {

        @Override
        public void handleResponse(Response response, Request<Emote> request) {
            if (response.isOk()) {
                DataObject obj = response.getObject();
                final long id = obj.getLong("id");
                String name = obj.getString("name");
                EmoteImpl emote = new EmoteImpl(id, guild).setName(name);
                // managed is false by default, should always be false for emotes created by client accounts.
                DataArray rolesArr = obj.getArray("roles");
                Set<Role> roleSet = emote.getRoleSet();
                for (int i = 0; i < rolesArr.length(); i++) {
                    roleSet.add(guild.getRoleById(rolesArr.getString(i)));
                }
                // put emote into cache
                guild.createEmote(name, icon, roles);
                request.onSuccess(emote);
            } else {
                request.onFailure(response);
                throw new RuntimeException("Couldn't install emojis. " + "Make sure that pokeraidbot has access to manage emojis.");
            }
        }
    };
    action.queue();
}
Also used : JDA(net.dv8tion.jda.api.JDA) Emote(net.dv8tion.jda.api.entities.Emote) Request(net.dv8tion.jda.api.requests.Request) DataArray(net.dv8tion.jda.api.utils.data.DataArray) Response(net.dv8tion.jda.api.requests.Response) Role(net.dv8tion.jda.api.entities.Role) GuildImpl(net.dv8tion.jda.internal.entities.GuildImpl) EmoteImpl(net.dv8tion.jda.internal.entities.EmoteImpl) DataObject(net.dv8tion.jda.api.utils.data.DataObject) AuditableRestActionImpl(net.dv8tion.jda.internal.requests.restaction.AuditableRestActionImpl) JSONObject(org.json.JSONObject) StringWriter(java.io.StringWriter) Route(net.dv8tion.jda.internal.requests.Route) ISnowflake(net.dv8tion.jda.api.entities.ISnowflake)

Example 3 with Request

use of net.dv8tion.jda.api.requests.Request in project JDA by DV8FromTheWorld.

the class SessionControllerAdapter method getShardedGateway.

@Nonnull
@Override
public ShardedGateway getShardedGateway(@Nonnull JDA api) {
    AccountTypeException.check(api.getAccountType(), AccountType.BOT);
    return new RestActionImpl<ShardedGateway>(api, Route.Misc.GATEWAY_BOT.compile()) {

        @Override
        public void handleResponse(Response response, Request<ShardedGateway> request) {
            if (response.isOk()) {
                DataObject object = response.getObject();
                String url = object.getString("url");
                int shards = object.getInt("shards");
                int concurrency = object.getObject("session_start_limit").getInt("max_concurrency", 1);
                request.onSuccess(new ShardedGateway(url, shards, concurrency));
            } else if (response.code == 401) {
                api.shutdownNow();
                request.onFailure(new LoginException("The provided token is invalid!"));
            } else {
                request.onFailure(response);
            }
        }
    }.priority().complete();
}
Also used : Response(net.dv8tion.jda.api.requests.Response) RestActionImpl(net.dv8tion.jda.internal.requests.RestActionImpl) DataObject(net.dv8tion.jda.api.utils.data.DataObject) Request(net.dv8tion.jda.api.requests.Request) LoginException(javax.security.auth.login.LoginException) Nonnull(javax.annotation.Nonnull)

Example 4 with Request

use of net.dv8tion.jda.api.requests.Request in project JDA by DV8FromTheWorld.

the class BotRateLimiter method cancelRequests.

@Override
public int cancelRequests() {
    return MiscUtil.locked(bucketLock, () -> {
        // Empty buckets will be removed by the cleanup worker, which also checks for rate limit parameters
        AtomicInteger count = new AtomicInteger(0);
        buckets.values().stream().map(Bucket::getRequests).flatMap(Collection::stream).filter(request -> !request.isPriority() && !request.isCancelled()).forEach(request -> {
            request.cancel();
            count.incrementAndGet();
        });
        int cancelled = count.get();
        if (cancelled == 1)
            RateLimiter.log.warn("Cancelled 1 request!");
        else if (cancelled > 1)
            RateLimiter.log.warn("Cancelled {} requests!", cancelled);
        return cancelled;
    });
}
Also used : Contract(org.jetbrains.annotations.Contract) java.util(java.util) ReentrantLock(java.util.concurrent.locks.ReentrantLock) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) java.util.concurrent(java.util.concurrent) RateLimiter(net.dv8tion.jda.internal.requests.RateLimiter) Request(net.dv8tion.jda.api.requests.Request) MiscUtil(net.dv8tion.jda.api.utils.MiscUtil) Requester(net.dv8tion.jda.internal.requests.Requester) Route(net.dv8tion.jda.internal.requests.Route) Headers(okhttp3.Headers) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Aggregations

Request (net.dv8tion.jda.api.requests.Request)4 Response (net.dv8tion.jda.api.requests.Response)3 DataObject (net.dv8tion.jda.api.utils.data.DataObject)2 Route (net.dv8tion.jda.internal.requests.Route)2 IOException (java.io.IOException)1 StringWriter (java.io.StringWriter)1 SocketException (java.net.SocketException)1 SocketTimeoutException (java.net.SocketTimeoutException)1 UnknownHostException (java.net.UnknownHostException)1 java.util (java.util)1 LinkedHashSet (java.util.LinkedHashSet)1 java.util.concurrent (java.util.concurrent)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 ReentrantLock (java.util.concurrent.locks.ReentrantLock)1 Nonnull (javax.annotation.Nonnull)1 SSLPeerUnverifiedException (javax.net.ssl.SSLPeerUnverifiedException)1 LoginException (javax.security.auth.login.LoginException)1 JDA (net.dv8tion.jda.api.JDA)1 Emote (net.dv8tion.jda.api.entities.Emote)1