net.dv8tion.jda.core.entities.impl.TextChannelImpl.java Source code

Java tutorial

Introduction

Here is the source code for net.dv8tion.jda.core.entities.impl.TextChannelImpl.java

Source

/*
 *     Copyright 2015-2017 Austin Keener & Michael Ritter & Florian Spie
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.dv8tion.jda.core.entities.impl;

import net.dv8tion.jda.client.exceptions.VerificationLevelException;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.*;
import net.dv8tion.jda.core.exceptions.PermissionException;
import net.dv8tion.jda.core.requests.Request;
import net.dv8tion.jda.core.requests.Response;
import net.dv8tion.jda.core.requests.RestAction;
import net.dv8tion.jda.core.requests.Route;
import net.dv8tion.jda.core.requests.restaction.AuditableRestAction;
import net.dv8tion.jda.core.utils.MiscUtil;
import net.dv8tion.jda.core.utils.Checks;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.InputStream;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

public class TextChannelImpl extends AbstractChannelImpl<TextChannelImpl> implements TextChannel {
    private String topic;
    private long lastMessageId;
    private boolean nsfw;

    public TextChannelImpl(long id, GuildImpl guild) {
        super(id, guild);
    }

    @Override
    public String getAsMention() {
        return "<#" + id + '>';
    }

    @Override
    public RestAction<List<Webhook>> getWebhooks() {
        checkPermission(Permission.MANAGE_WEBHOOKS);

        Route.CompiledRoute route = Route.Channels.GET_WEBHOOKS.compile(getId());
        return new RestAction<List<Webhook>>(getJDA(), route) {
            @Override
            protected void handleResponse(Response response, Request<List<Webhook>> request) {
                if (!response.isOk()) {
                    request.onFailure(response);
                    return;
                }

                List<Webhook> webhooks = new LinkedList<>();
                JSONArray array = response.getArray();
                EntityBuilder builder = api.getEntityBuilder();

                for (Object object : array) {
                    try {
                        webhooks.add(builder.createWebhook((JSONObject) object));
                    } catch (JSONException | NullPointerException e) {
                        JDAImpl.LOG.log(e);
                    }
                }

                request.onSuccess(webhooks);
            }
        };
    }

    @Override
    public RestAction<Void> deleteMessages(Collection<Message> messages) {
        Checks.notEmpty(messages, "Messages collection");

        return deleteMessagesByIds(messages.stream().map(ISnowflake::getId).collect(Collectors.toList()));
    }

    @Override
    public RestAction<Void> deleteMessagesByIds(Collection<String> messageIds) {
        checkPermission(Permission.MESSAGE_MANAGE,
                "Must have MESSAGE_MANAGE in order to bulk delete messages in this channel regardless of author.");
        if (messageIds.size() < 2 || messageIds.size() > 100)
            throw new IllegalArgumentException("Must provide at least 2 or at most 100 messages to be deleted.");

        long twoWeeksAgo = ((System.currentTimeMillis() - (14 * 24 * 60 * 60 * 1000))
                - MiscUtil.DISCORD_EPOCH) << MiscUtil.TIMESTAMP_OFFSET;
        for (String id : messageIds) {
            Checks.notEmpty(id, "Message id in messageIds");
            Checks.check(MiscUtil.parseSnowflake(id) > twoWeeksAgo,
                    "Message Id provided was older than 2 weeks. Id: " + id);
        }

        JSONObject body = new JSONObject().put("messages", messageIds);
        Route.CompiledRoute route = Route.Messages.DELETE_MESSAGES.compile(getId());
        return new RestAction<Void>(getJDA(), route, body) {
            @Override
            protected void handleResponse(Response response, Request<Void> request) {
                if (response.isOk())
                    request.onSuccess(null);
                else
                    request.onFailure(response);
            }
        };
    }

    @Override
    public AuditableRestAction<Void> deleteWebhookById(String id) {
        Checks.notEmpty(id, "webhook id");

        if (!guild.getSelfMember().hasPermission(this, Permission.MANAGE_WEBHOOKS))
            throw new PermissionException(Permission.MANAGE_WEBHOOKS);

        Route.CompiledRoute route = Route.Webhooks.DELETE_WEBHOOK.compile(id);
        return new AuditableRestAction<Void>(getJDA(), route) {
            @Override
            protected void handleResponse(Response response, Request<Void> request) {
                if (response.isOk())
                    request.onSuccess(null);
                else
                    request.onFailure(response);
            }
        };
    }

    @Override
    public boolean canTalk() {
        return canTalk(guild.getSelfMember());
    }

    @Override
    public boolean canTalk(Member member) {
        if (!guild.equals(member.getGuild()))
            throw new IllegalArgumentException(
                    "Provided Member is not from the Guild that this TextChannel is part of.");

        return member.hasPermission(this, Permission.MESSAGE_READ, Permission.MESSAGE_WRITE);
    }

    @Override
    public long getLatestMessageIdLong() {
        final long messageId = lastMessageId;
        if (messageId < 0)
            throw new IllegalStateException("No last message id found.");
        return messageId;
    }

    @Override
    public boolean hasLatestMessage() {
        return lastMessageId > 0;
    }

    @Override
    public ChannelType getType() {
        return ChannelType.TEXT;
    }

    @Override
    public String getTopic() {
        return topic;
    }

    @Override
    public boolean isNSFW() {
        return nsfw || name.equals("nsfw") || name.startsWith("nsfw-");
    }

    @Override
    public List<Member> getMembers() {
        return Collections.unmodifiableList(guild.getMembersMap().valueCollection().stream()
                .filter(m -> m.hasPermission(this, Permission.MESSAGE_READ)).collect(Collectors.toList()));
    }

    @Override
    public int getPosition() {
        //We call getTextChannels instead of directly accessing the GuildImpl.getTextChannelMap because
        // getTextChannels does the sorting logic.
        List<TextChannel> channels = guild.getTextChannels();
        for (int i = 0; i < channels.size(); i++) {
            if (channels.get(i) == this)
                return i;
        }
        throw new RuntimeException(
                "Somehow when determining position we never found the TextChannel in the Guild's channels? wtf?");
    }

    @Override
    public RestAction<Message> sendMessage(Message msg) {
        Checks.notNull(msg, "Message");

        checkVerification();
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_WRITE);
        if (msg.getRawContent().isEmpty() && !msg.getEmbeds().isEmpty())
            checkPermission(Permission.MESSAGE_EMBED_LINKS);

        //Call MessageChannel's default
        return TextChannel.super.sendMessage(msg);
    }

    @Override
    public RestAction<Message> sendFile(InputStream data, String fileName, Message message) {
        checkVerification();
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_WRITE);
        checkPermission(Permission.MESSAGE_ATTACH_FILES);

        //Call MessageChannel's default method
        return TextChannel.super.sendFile(data, fileName, message);
    }

    @Override
    public RestAction<Message> sendFile(byte[] data, String fileName, Message message) {
        checkVerification();
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_WRITE);
        checkPermission(Permission.MESSAGE_ATTACH_FILES);

        //Call MessageChannel's default method
        return TextChannel.super.sendFile(data, fileName, message);
    }

    @Override
    public RestAction<Message> getMessageById(String messageId) {
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_HISTORY);

        //Call MessageChannel's default method
        return TextChannel.super.getMessageById(messageId);
    }

    @Override
    public AuditableRestAction<Void> deleteMessageById(String messageId) {
        Checks.notEmpty(messageId, "messageId");
        checkPermission(Permission.MESSAGE_READ);

        //Call MessageChannel's default method
        return TextChannel.super.deleteMessageById(messageId);
    }

    @Override
    public RestAction<MessageHistory> getHistoryAround(String messageId, int limit) {
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_HISTORY);

        //Call MessageChannel's default method
        return TextChannel.super.getHistoryAround(messageId, limit);
    }

    @Override
    public RestAction<Void> pinMessageById(String messageId) {
        checkPermission(Permission.MESSAGE_READ,
                "You cannot pin a message in a channel you can't access. (MESSAGE_READ)");
        checkPermission(Permission.MESSAGE_MANAGE, "You need MESSAGE_MANAGE to pin or unpin messages.");

        //Call MessageChannel's default method
        return TextChannel.super.pinMessageById(messageId);
    }

    @Override
    public RestAction<Void> unpinMessageById(String messageId) {
        checkPermission(Permission.MESSAGE_READ,
                "You cannot unpin a message in a channel you can't access. (MESSAGE_READ)");
        checkPermission(Permission.MESSAGE_MANAGE, "You need MESSAGE_MANAGE to pin or unpin messages.");

        //Call MessageChannel's default method
        return TextChannel.super.unpinMessageById(messageId);
    }

    @Override
    public RestAction<List<Message>> getPinnedMessages() {
        checkPermission(Permission.MESSAGE_READ,
                "Cannot get the pinned message of a channel without MESSAGE_READ access.");

        //Call MessageChannel's default method
        return TextChannel.super.getPinnedMessages();
    }

    @Override
    public RestAction<Void> addReactionById(String messageId, String unicode) {
        checkPermission(Permission.MESSAGE_ADD_REACTION);
        checkPermission(Permission.MESSAGE_HISTORY);

        //Call MessageChannel's default method
        return TextChannel.super.addReactionById(messageId, unicode);
    }

    @Override
    public RestAction<Void> addReactionById(String messageId, Emote emote) {
        checkPermission(Permission.MESSAGE_ADD_REACTION);
        checkPermission(Permission.MESSAGE_HISTORY);

        //Call MessageChannel's default method
        return TextChannel.super.addReactionById(messageId, emote);
    }

    @Override
    public RestAction<Void> clearReactionsById(String messageId) {
        Checks.notEmpty(messageId, "Message ID");

        checkPermission(Permission.MESSAGE_MANAGE);
        Route.CompiledRoute route = Route.Messages.REMOVE_ALL_REACTIONS.compile(getId(), messageId);
        return new RestAction<Void>(getJDA(), route) {
            @Override
            protected void handleResponse(Response response, Request<Void> request) {
                if (response.isOk())
                    request.onSuccess(null);
                else
                    request.onFailure(response);
            }
        };
    }

    @Override
    public RestAction<Message> editMessageById(String id, Message newContent) {
        Checks.notNull(newContent, "Message");

        //checkVerification(); no verification needed to edit a message
        checkPermission(Permission.MESSAGE_READ);
        checkPermission(Permission.MESSAGE_WRITE);
        if (newContent.getRawContent().isEmpty() && !newContent.getEmbeds().isEmpty())
            checkPermission(Permission.MESSAGE_EMBED_LINKS);

        //Call MessageChannel's default
        return TextChannel.super.editMessageById(id, newContent);
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof TextChannelImpl))
            return false;
        TextChannelImpl oTChannel = (TextChannelImpl) o;
        return this == oTChannel || this.id == oTChannel.id;
    }

    @Override
    public String toString() {
        return "TC:" + getName() + '(' + id + ')';
    }

    @Override
    public int compareTo(TextChannel chan) {
        if (this == chan)
            return 0;

        if (!this.getGuild().equals(chan.getGuild()))
            throw new IllegalArgumentException("Cannot compare TextChannels that aren't from the same guild!");

        if (this.getPositionRaw() != chan.getPositionRaw())
            return chan.getPositionRaw() - this.getPositionRaw();

        OffsetDateTime thisTime = this.getCreationTime();
        OffsetDateTime chanTime = chan.getCreationTime();

        //We compare the provided channel's time to this's time instead of the reverse as one would expect due to how
        // discord deals with hierarchy. The more recent a channel was created, the lower its hierarchy ranking when
        // it shares the same position as another channel.
        return chanTime.compareTo(thisTime);
    }

    // -- Setters --

    public TextChannelImpl setTopic(String topic) {
        this.topic = topic;
        return this;
    }

    public TextChannelImpl setLastMessageId(long id) {
        this.lastMessageId = id;
        return this;
    }

    public TextChannelImpl setNSFW(boolean nsfw) {
        this.nsfw = nsfw;
        return this;
    }

    // -- internal --

    private void checkVerification() {
        if (!guild.checkVerification())
            throw new VerificationLevelException(guild.getVerificationLevel());
    }
}