Search in sources :

Example 11 with JDAImpl

use of net.dv8tion.jda.internal.JDAImpl in project JDA by DV8FromTheWorld.

the class AudioWebSocket method handleCallbackError.

@Override
public void handleCallbackError(WebSocket websocket, Throwable cause) {
    LOG.error("There was some audio websocket error", cause);
    JDAImpl api = getJDA();
    api.handleEvent(new ExceptionEvent(api, cause, true));
}
Also used : ExceptionEvent(net.dv8tion.jda.api.events.ExceptionEvent) JDAImpl(net.dv8tion.jda.internal.JDAImpl)

Example 12 with JDAImpl

use of net.dv8tion.jda.internal.JDAImpl in project JDA by DV8FromTheWorld.

the class DefaultShardManager method buildInstance.

protected JDAImpl buildInstance(final int shardId) throws LoginException {
    OkHttpClient httpClient = sessionConfig.getHttpClient();
    if (httpClient == null) {
        // httpClient == null implies we have a builder
        // noinspection ConstantConditions
        httpClient = sessionConfig.getHttpBuilder().build();
    }
    // imagine if we had macros or closures or destructuring :)
    ExecutorPair<ScheduledExecutorService> rateLimitPair = resolveExecutor(threadingConfig.getRateLimitPoolProvider(), shardId);
    ScheduledExecutorService rateLimitPool = rateLimitPair.executor;
    boolean shutdownRateLimitPool = rateLimitPair.automaticShutdown;
    ExecutorPair<ScheduledExecutorService> gatewayPair = resolveExecutor(threadingConfig.getGatewayPoolProvider(), shardId);
    ScheduledExecutorService gatewayPool = gatewayPair.executor;
    boolean shutdownGatewayPool = gatewayPair.automaticShutdown;
    ExecutorPair<ExecutorService> callbackPair = resolveExecutor(threadingConfig.getCallbackPoolProvider(), shardId);
    ExecutorService callbackPool = callbackPair.executor;
    boolean shutdownCallbackPool = callbackPair.automaticShutdown;
    ExecutorPair<ExecutorService> eventPair = resolveExecutor(threadingConfig.getEventPoolProvider(), shardId);
    ExecutorService eventPool = eventPair.executor;
    boolean shutdownEventPool = eventPair.automaticShutdown;
    ExecutorPair<ScheduledExecutorService> audioPair = resolveExecutor(threadingConfig.getAudioPoolProvider(), shardId);
    ScheduledExecutorService audioPool = audioPair.executor;
    boolean shutdownAudioPool = audioPair.automaticShutdown;
    AuthorizationConfig authConfig = new AuthorizationConfig(token);
    SessionConfig sessionConfig = this.sessionConfig.toSessionConfig(httpClient);
    ThreadingConfig threadingConfig = new ThreadingConfig();
    threadingConfig.setRateLimitPool(rateLimitPool, shutdownRateLimitPool);
    threadingConfig.setGatewayPool(gatewayPool, shutdownGatewayPool);
    threadingConfig.setCallbackPool(callbackPool, shutdownCallbackPool);
    threadingConfig.setEventPool(eventPool, shutdownEventPool);
    threadingConfig.setAudioPool(audioPool, shutdownAudioPool);
    MetaConfig metaConfig = new MetaConfig(this.metaConfig.getMaxBufferSize(), this.metaConfig.getContextMap(shardId), this.metaConfig.getCacheFlags(), this.sessionConfig.getFlags());
    final JDAImpl jda = new JDAImpl(authConfig, sessionConfig, threadingConfig, metaConfig);
    jda.setMemberCachePolicy(shardingConfig.getMemberCachePolicy());
    threadingConfig.init(jda::getIdentifierString);
    // We can only do member chunking with the GUILD_MEMBERS intent
    if ((shardingConfig.getIntents() & GatewayIntent.GUILD_MEMBERS.getRawValue()) == 0)
        jda.setChunkingFilter(ChunkingFilter.NONE);
    else
        jda.setChunkingFilter(chunkingFilter);
    jda.setShardManager(this);
    if (eventConfig.getEventManagerProvider() != null)
        jda.setEventManager(this.eventConfig.getEventManagerProvider().apply(shardId));
    if (this.sessionConfig.getAudioSendFactory() != null)
        jda.setAudioSendFactory(this.sessionConfig.getAudioSendFactory());
    this.eventConfig.getListeners().forEach(jda::addEventListener);
    this.eventConfig.getListenerProviders().forEach(provider -> jda.addEventListener(provider.apply(shardId)));
    // Set the presence information before connecting to have the correct information ready when sending IDENTIFY
    PresenceImpl presence = ((PresenceImpl) jda.getPresence());
    if (presenceConfig.getActivityProvider() != null)
        presence.setCacheActivity(presenceConfig.getActivityProvider().apply(shardId));
    if (presenceConfig.getIdleProvider() != null)
        presence.setCacheIdle(presenceConfig.getIdleProvider().apply(shardId));
    if (presenceConfig.getStatusProvider() != null)
        presence.setCacheStatus(presenceConfig.getStatusProvider().apply(shardId));
    if (this.gatewayURL == null) {
        try {
            SessionController.ShardedGateway gateway = jda.getShardedGateway();
            this.sessionConfig.getSessionController().setConcurrency(gateway.getConcurrency());
            this.gatewayURL = gateway.getUrl();
            if (this.gatewayURL == null)
                LOG.error("Acquired null gateway url from SessionController");
            else
                LOG.info("Login Successful!");
            if (getShardsTotal() == -1) {
                shardingConfig.setShardsTotal(gateway.getShardTotal());
                this.shards = new ShardCacheViewImpl(getShardsTotal());
                synchronized (queue) {
                    for (int i = 0; i < getShardsTotal(); i++) queue.add(i);
                }
            }
        } catch (CompletionException e) {
            if (e.getCause() instanceof LoginException)
                // complete() can't throw this because its a checked-exception so we have to unwrap it first
                throw (LoginException) e.getCause();
            throw e;
        }
    }
    final JDA.ShardInfo shardInfo = new JDA.ShardInfo(shardId, getShardsTotal());
    // Initialize SelfUser instance before logging in
    SelfUser selfUser = getShardCache().applyStream(s -> // this should never throw!
    s.map(JDA::getSelfUser).findFirst().orElse(null));
    // Copy from other JDA instance or do initial fetch
    if (selfUser == null)
        selfUser = retrieveSelfUser(jda);
    else
        selfUser = SelfUserImpl.copyOf((SelfUserImpl) selfUser, jda);
    jda.setSelfUser(selfUser);
    // This is already set by JDA internally, but this is to make sure the listeners catch it.
    jda.setStatus(JDA.Status.INITIALIZED);
    final int shardTotal = jda.login(this.gatewayURL, shardInfo, this.metaConfig.getCompression(), false, shardingConfig.getIntents(), this.metaConfig.getEncoding());
    if (getShardsTotal() == -1)
        shardingConfig.setShardsTotal(shardTotal);
    return jda;
}
Also used : ShardCacheViewImpl(net.dv8tion.jda.internal.utils.cache.ShardCacheViewImpl) ThreadingConfig(net.dv8tion.jda.internal.utils.config.ThreadingConfig) OkHttpClient(okhttp3.OkHttpClient) PresenceImpl(net.dv8tion.jda.internal.managers.PresenceImpl) JDA(net.dv8tion.jda.api.JDA) MetaConfig(net.dv8tion.jda.internal.utils.config.MetaConfig) SessionConfig(net.dv8tion.jda.internal.utils.config.SessionConfig) JDAImpl(net.dv8tion.jda.internal.JDAImpl) AuthorizationConfig(net.dv8tion.jda.internal.utils.config.AuthorizationConfig) SessionController(net.dv8tion.jda.api.utils.SessionController) LoginException(javax.security.auth.login.LoginException) SelfUser(net.dv8tion.jda.api.entities.SelfUser)

Example 13 with JDAImpl

use of net.dv8tion.jda.internal.JDAImpl in project JDA by DV8FromTheWorld.

the class DefaultShardManager method login.

@Override
public void login() throws LoginException {
    // building the first one in the current thread ensures that LoginException and IllegalArgumentException can be thrown on login
    JDAImpl jda = null;
    try {
        final int shardId = this.queue.isEmpty() ? 0 : this.queue.peek();
        jda = this.buildInstance(shardId);
        try (UnlockHook hook = this.shards.writeLock()) {
            this.shards.getMap().put(shardId, jda);
        }
        synchronized (queue) {
            this.queue.remove(shardId);
        }
    } catch (final Exception e) {
        if (jda != null) {
            if (shardingConfig.isUseShutdownNow())
                jda.shutdownNow();
            else
                jda.shutdown();
        }
        throw e;
    }
    runQueueWorker();
    if (this.shutdownHook != null)
        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
Also used : UnlockHook(net.dv8tion.jda.internal.utils.UnlockHook) JDAImpl(net.dv8tion.jda.internal.JDAImpl) LoginException(javax.security.auth.login.LoginException)

Example 14 with JDAImpl

use of net.dv8tion.jda.internal.JDAImpl in project JDA by DV8FromTheWorld.

the class ShardManager method retrieveUserById.

/**
 * Attempts to retrieve a {@link net.dv8tion.jda.api.entities.User User} object based on the provided id.
 * <br>This first calls {@link #getUserById(long)}, and if the return is {@code null} then a request
 * is made to the Discord servers.
 *
 * <p>The returned {@link net.dv8tion.jda.api.requests.RestAction RestAction} can encounter the following Discord errors:
 * <ul>
 *     <li>{@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_USER ErrorResponse.UNKNOWN_USER}
 *     <br>Occurs when the provided id does not refer to a {@link net.dv8tion.jda.api.entities.User User}
 *     known by Discord. Typically occurs when developers provide an incomplete id (cut short).</li>
 * </ul>
 *
 * @param  id
 *         The id of the requested {@link net.dv8tion.jda.api.entities.User User}.
 *
 * @throws java.lang.IllegalStateException
 *         If there isn't any active shards.
 *
 * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link net.dv8tion.jda.api.entities.User User}
 *         <br>On request, gets the User with id matching provided id from Discord.
 */
@Nonnull
@CheckReturnValue
default RestAction<User> retrieveUserById(long id) {
    JDA api = null;
    for (JDA shard : getShardCache()) {
        api = shard;
        EnumSet<GatewayIntent> intents = shard.getGatewayIntents();
        User user = shard.getUserById(id);
        boolean isUpdated = intents.contains(GatewayIntent.GUILD_PRESENCES) || intents.contains(GatewayIntent.GUILD_MEMBERS);
        if (user != null && isUpdated)
            return new CompletedRestAction<>(shard, user);
    }
    if (api == null)
        throw new IllegalStateException("no shards active");
    JDAImpl jda = (JDAImpl) api;
    Route.CompiledRoute route = Route.Users.GET_USER.compile(Long.toUnsignedString(id));
    return new RestActionImpl<>(jda, route, (response, request) -> jda.getEntityBuilder().createUser(response.getObject()));
}
Also used : RestActionImpl(net.dv8tion.jda.internal.requests.RestActionImpl) JDA(net.dv8tion.jda.api.JDA) GatewayIntent(net.dv8tion.jda.api.requests.GatewayIntent) JDAImpl(net.dv8tion.jda.internal.JDAImpl) Route(net.dv8tion.jda.internal.requests.Route) CheckReturnValue(javax.annotation.CheckReturnValue) Nonnull(javax.annotation.Nonnull)

Example 15 with JDAImpl

use of net.dv8tion.jda.internal.JDAImpl in project JDA by DV8FromTheWorld.

the class AudioConnection method setupReceiveThread.

private synchronized void setupReceiveThread() {
    if (receiveThread == null) {
        receiveThread = new Thread(() -> {
            getJDA().setContext();
            try {
                udpSocket.setSoTimeout(1000);
            } catch (SocketException e) {
                LOG.error("Couldn't set SO_TIMEOUT for UDP socket", e);
            }
            while (!udpSocket.isClosed() && !Thread.currentThread().isInterrupted()) {
                DatagramPacket receivedPacket = new DatagramPacket(new byte[1920], 1920);
                try {
                    udpSocket.receive(receivedPacket);
                    boolean shouldDecode = receiveHandler != null && (receiveHandler.canReceiveUser() || receiveHandler.canReceiveCombined());
                    boolean canReceive = receiveHandler != null && (receiveHandler.canReceiveUser() || receiveHandler.canReceiveCombined() || receiveHandler.canReceiveEncoded());
                    if (canReceive && webSocket.getSecretKey() != null) {
                        if (!couldReceive) {
                            couldReceive = true;
                            sendSilentPackets();
                        }
                        AudioPacket decryptedPacket = AudioPacket.decryptAudioPacket(webSocket.encryption, receivedPacket, webSocket.getSecretKey());
                        if (decryptedPacket == null)
                            continue;
                        int ssrc = decryptedPacket.getSSRC();
                        final long userId = ssrcMap.get(ssrc);
                        Decoder decoder = opusDecoders.get(ssrc);
                        if (userId == ssrcMap.getNoEntryValue()) {
                            ByteBuffer audio = decryptedPacket.getEncodedAudio();
                            // and as such, we haven't yet received information to pair the SSRC with the UserId.
                            if (!audio.equals(silenceBytes))
                                LOG.debug("Received audio data with an unknown SSRC id. Ignoring");
                            continue;
                        }
                        if (decoder == null) {
                            if (AudioNatives.ensureOpus()) {
                                opusDecoders.put(ssrc, decoder = new Decoder(ssrc));
                            } else if (!receiveHandler.canReceiveEncoded()) {
                                LOG.error("Unable to decode audio due to missing opus binaries!");
                                break;
                            }
                        }
                        OpusPacket opusPacket = new OpusPacket(decryptedPacket, userId, decoder);
                        if (receiveHandler.canReceiveEncoded())
                            receiveHandler.handleEncodedAudio(opusPacket);
                        if (!shouldDecode || !opusPacket.canDecode())
                            continue;
                        User user = getJDA().getUserById(userId);
                        if (user == null) {
                            LOG.warn("Received audio data with a known SSRC, but the userId associate with the SSRC is unknown to JDA!");
                            continue;
                        }
                        short[] decodedAudio = opusPacket.decode();
                        // If decodedAudio is null, then the Opus decode failed, so throw away the packet.
                        if (decodedAudio == null) {
                            // decoder error logged in method
                            continue;
                        }
                        if (receiveHandler.canReceiveUser()) {
                            receiveHandler.handleUserAudio(new UserAudio(user, decodedAudio));
                        }
                        if (receiveHandler.canReceiveCombined() && receiveHandler.includeUserInCombinedAudio(user)) {
                            Queue<AudioData> queue = combinedQueue.get(user);
                            if (queue == null) {
                                queue = new ConcurrentLinkedQueue<>();
                                combinedQueue.put(user, queue);
                            }
                            queue.add(new AudioData(decodedAudio));
                        }
                    } else if (couldReceive) {
                        couldReceive = false;
                        sendSilentPackets();
                    }
                } catch (SocketTimeoutException e) {
                // Ignore. We set a low timeout so that we wont block forever so we can properly shutdown the loop.
                } catch (SocketException e) {
                // The socket was closed while we were listening for the next packet.
                // This is expected. Ignore the exception. The thread will exit during the next while
                // iteration because the udpSocket.isClosed() will return true.
                } catch (Exception e) {
                    LOG.error("There was some random exception while waiting for udp packets", e);
                }
            }
        });
        receiveThread.setUncaughtExceptionHandler((thread, throwable) -> {
            LOG.error("There was some uncaught exception in the audio receive thread", throwable);
            JDAImpl api = getJDA();
            api.handleEvent(new ExceptionEvent(api, throwable, true));
        });
        receiveThread.setDaemon(true);
        receiveThread.setName(threadIdentifier + " Receiving Thread");
        receiveThread.start();
    }
    if (receiveHandler.canReceiveCombined()) {
        setupCombinedExecutor();
    }
}
Also used : ExceptionEvent(net.dv8tion.jda.api.events.ExceptionEvent) User(net.dv8tion.jda.api.entities.User) JDAImpl(net.dv8tion.jda.internal.JDAImpl) ByteBuffer(java.nio.ByteBuffer)

Aggregations

JDAImpl (net.dv8tion.jda.internal.JDAImpl)43 Nonnull (javax.annotation.Nonnull)19 Route (net.dv8tion.jda.internal.requests.Route)12 RestActionImpl (net.dv8tion.jda.internal.requests.RestActionImpl)10 DataObject (net.dv8tion.jda.api.utils.data.DataObject)8 DataArray (net.dv8tion.jda.api.utils.data.DataArray)7 EntityBuilder (net.dv8tion.jda.internal.entities.EntityBuilder)6 CheckReturnValue (javax.annotation.CheckReturnValue)5 AuditableRestActionImpl (net.dv8tion.jda.internal.requests.restaction.AuditableRestActionImpl)5 ExceptionEvent (net.dv8tion.jda.api.events.ExceptionEvent)4 InsufficientPermissionException (net.dv8tion.jda.api.exceptions.InsufficientPermissionException)4 ArrayList (java.util.ArrayList)3 LoginException (javax.security.auth.login.LoginException)3 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)3 JDA (net.dv8tion.jda.api.JDA)3 WebSocketClient (net.dv8tion.jda.internal.requests.WebSocketClient)3 Parser (com.jagrosh.jagtag.Parser)2 ByteBuffer (java.nio.ByteBuffer)2 List (java.util.List)2 MessageConfig (me.duncte123.botcommons.messaging.MessageConfig)2