mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-12-26 17:18:29 +01:00
More progress on the first party api parts
This commit is contained in:
parent
b149acb36f
commit
1707074410
@ -23,7 +23,12 @@
|
||||
|
||||
package com.discordsrv.api.discord.api;
|
||||
|
||||
import com.discordsrv.api.discord.api.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.api.entity.user.DiscordUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A basic Discord API wrapper for a limited amount of functions, with a minimal amount of breaking changes.
|
||||
@ -35,5 +40,19 @@ public interface DiscordAPI {
|
||||
* @param id the id for the text channel
|
||||
* @return the text channel
|
||||
*/
|
||||
DiscordTextChannel getTextChannelById(String id);
|
||||
Optional<DiscordTextChannel> getTextChannelById(@NotNull String id);
|
||||
|
||||
/**
|
||||
* Gets a Discord server by id.
|
||||
* @param id the id for the Discord server
|
||||
* @return the Discord server
|
||||
*/
|
||||
Optional<DiscordGuild> getGuildById(@NotNull String id);
|
||||
|
||||
/**
|
||||
* Gets a Discord user by id.
|
||||
* @param id the id for the Discord user
|
||||
* @return the Discord user
|
||||
*/
|
||||
Optional<DiscordUser> getUserById(@NotNull String id);
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.discordsrv.api.discord.api.entity;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A snowflake identifier.
|
||||
*/
|
||||
public interface Snowflake {
|
||||
|
||||
/**
|
||||
* Gets the id of this entity.
|
||||
* @return the id of this entity
|
||||
*/
|
||||
@NotNull
|
||||
String getId();
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.discordsrv.api.discord.api.entity.channel;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.Snowflake;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* A Discord channel that can send/receive messages.
|
||||
*/
|
||||
public interface DiscordMessageChannel extends Snowflake {
|
||||
|
||||
/**
|
||||
* Sends the provided message to the channel.
|
||||
* @param message the channel to send to the channel
|
||||
* @return a future returning the message after being sent
|
||||
* @throws com.discordsrv.api.discord.api.exception.NotReadyException if DiscordSRV is not ready, {@link com.discordsrv.api.DiscordSRVApi#isReady()}
|
||||
*/
|
||||
@NotNull
|
||||
CompletableFuture<ReceivedDiscordMessage> sendMessage(SendableDiscordMessage message);
|
||||
|
||||
/**
|
||||
* Edits the message identified by the id.
|
||||
* @param id the id of the message to edit
|
||||
* @param message the new message content
|
||||
* @return a future returning the message after being edited
|
||||
* @throws com.discordsrv.api.discord.api.exception.NotReadyException if DiscordSRV is not ready, {@link com.discordsrv.api.DiscordSRVApi#isReady()}
|
||||
*/
|
||||
@NotNull
|
||||
CompletableFuture<ReceivedDiscordMessage> editMessageById(String id, SendableDiscordMessage message);
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.discordsrv.api.discord.api.entity.guild;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A Discord server.
|
||||
*/
|
||||
public interface DiscordGuild {
|
||||
|
||||
/**
|
||||
* Gets the id of this Discord guild.
|
||||
* @return the guild's id
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Gets the member count of the guild.
|
||||
* @return the guild's member count
|
||||
*/
|
||||
int getMemberCount();
|
||||
|
||||
/**
|
||||
* Gets a Discord guild member by id from the cache.
|
||||
* @param id the id for the Discord guild member
|
||||
* @return the Discord guild member from the cache
|
||||
*/
|
||||
Optional<DiscordGuildMember> getMemberById(String id);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.discordsrv.api.discord.api.entity.guild;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.user.DiscordUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A Discord server member.
|
||||
*/
|
||||
public interface DiscordGuildMember extends DiscordUser {
|
||||
|
||||
/**
|
||||
* Gets the nickname of the Discord server member.
|
||||
* @return the nickname server member
|
||||
*/
|
||||
@NotNull
|
||||
Optional<String> getNickname();
|
||||
|
||||
/**
|
||||
* Gets the effective name of this Discord server member.
|
||||
* @return the Discord server member's effective name
|
||||
*/
|
||||
default String getEffectiveName() {
|
||||
return getNickname().orElseGet(this::getUsername);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.discordsrv.api.discord.api.entity.guild;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.Snowflake;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A Discord server role.
|
||||
*/
|
||||
public interface DiscordRole extends Snowflake {
|
||||
|
||||
/**
|
||||
* Gets the name of the Discord role.
|
||||
* @return the role name
|
||||
*/
|
||||
@NotNull
|
||||
String getName();
|
||||
}
|
@ -21,24 +21,49 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.message;
|
||||
package com.discordsrv.api.discord.api.entity.message;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
/**
|
||||
* An allowed mention that can be used with {@link com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage.Builder#addAllowedMention(AllowedMention)}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API
|
||||
public interface AllowedMention {
|
||||
|
||||
/**
|
||||
* Permits the @everyone and @here mentions.
|
||||
*/
|
||||
AllowedMention EVERYONE = Standard.EVERYONE;
|
||||
|
||||
/**
|
||||
* Permits all role mentions, unless at least one specific role is specified.
|
||||
*/
|
||||
AllowedMention ALL_ROLES = Standard.ROLE;
|
||||
|
||||
/**
|
||||
* Permits all user mentions, unless at least one specific user is specified.
|
||||
*/
|
||||
AllowedMention ALL_USERS = Standard.USER;
|
||||
|
||||
static AllowedMention user(String id) {
|
||||
return new Snowflake(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permits the role identified by the id to be mentioned.
|
||||
* @param id the id of the role
|
||||
* @return a {@link AllowedMention} object
|
||||
*/
|
||||
static AllowedMention role(String id) {
|
||||
return new Snowflake(id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permits the user identified by the id to be mentioned.
|
||||
* @param id the id of the user
|
||||
* @return a {@link AllowedMention} object
|
||||
*/
|
||||
static AllowedMention user(String id) {
|
||||
return new Snowflake(id, true);
|
||||
}
|
||||
|
||||
enum Standard implements AllowedMention {
|
||||
|
||||
EVERYONE(Message.MentionType.EVERYONE),
|
@ -21,7 +21,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.message;
|
||||
package com.discordsrv.api.discord.api.entity.message;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
@ -33,9 +33,16 @@ import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Discord embed.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API
|
||||
public class DiscordMessageEmbed {
|
||||
|
||||
/**
|
||||
* Create a new builder for {@link DiscordMessageEmbed}s.
|
||||
* @return a new builder
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
@ -21,34 +21,35 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.message;
|
||||
package com.discordsrv.api.discord.api.entity.message;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.Snowflake;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface ReceivedDiscordMessage extends SendableDiscordMessage {
|
||||
/**
|
||||
* A message received from Discord.
|
||||
*/
|
||||
public interface ReceivedDiscordMessage extends SendableDiscordMessage, Snowflake {
|
||||
|
||||
/**
|
||||
* Gets the ID for this message.
|
||||
* @return the id from Discord for this message
|
||||
* Gets the channel that the message was sent in.
|
||||
* @return the channel the message was sent in
|
||||
*/
|
||||
String getId();
|
||||
|
||||
// TODO: Author
|
||||
|
||||
@Override
|
||||
String getContent();
|
||||
@NotNull
|
||||
DiscordTextChannel getChannel();
|
||||
|
||||
/**
|
||||
* Gets the content displayed on Discord, without markdown or other formatting.
|
||||
* @return the displayed content of the message
|
||||
* Gets the Discord server the message was posted in.
|
||||
* @return the Discord server the message was posted in
|
||||
*/
|
||||
String getDisplayedContent();
|
||||
|
||||
/**
|
||||
* Gets the raw content with markdown characters stripped from it.
|
||||
* @return the stripped content of the message
|
||||
*/
|
||||
String getStrippedContent();
|
||||
@NotNull
|
||||
default DiscordGuild getGuild() {
|
||||
return getChannel().getGuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this message to the provided message, the webhook username and avatar url will be ignored.
|
||||
@ -56,5 +57,6 @@ public interface ReceivedDiscordMessage extends SendableDiscordMessage {
|
||||
* @param message the new message
|
||||
* @return the future for the message edit
|
||||
*/
|
||||
@NotNull
|
||||
CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message);
|
||||
}
|
@ -21,16 +21,26 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.message;
|
||||
package com.discordsrv.api.discord.api.entity.message;
|
||||
|
||||
import com.discordsrv.api.discord.api.message.impl.SendableDiscordMessageImpl;
|
||||
import com.discordsrv.api.discord.api.entity.message.impl.SendableDiscordMessageImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A message that can be sent to Discord.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API
|
||||
public interface SendableDiscordMessage {
|
||||
|
||||
/**
|
||||
* Creates a new builder for {@link SendableDiscordMessage}.
|
||||
* @return a new builder
|
||||
*/
|
||||
@NotNull
|
||||
static Builder builder() {
|
||||
return new SendableDiscordMessageImpl.BuilderImpl();
|
||||
}
|
||||
@ -39,30 +49,35 @@ public interface SendableDiscordMessage {
|
||||
* The raw content of the message.
|
||||
* @return the unmodified content of the message
|
||||
*/
|
||||
@Nullable
|
||||
String getContent();
|
||||
|
||||
/**
|
||||
* Gets the embeds of the message.
|
||||
* @return the unmodifiable list of embeds in this message
|
||||
*/
|
||||
@NotNull
|
||||
List<DiscordMessageEmbed> getEmbeds();
|
||||
|
||||
/**
|
||||
* Gets the allowed mentions of the message.
|
||||
* @return the allowed mentions in this message
|
||||
*/
|
||||
@Nullable
|
||||
Set<AllowedMention> getAllowedMentions();
|
||||
|
||||
/**
|
||||
* Gets the webhook username.
|
||||
* @return the webhook username or {@code null} if this isn't a webhook message
|
||||
*/
|
||||
@Nullable
|
||||
String getWebhookUsername();
|
||||
|
||||
/**
|
||||
* Gets the webhook avatar url.
|
||||
* @return the webhook avatar url or {@code null} if no webhook avatar url is specified
|
||||
*/
|
||||
@Nullable
|
||||
String getWebhookAvatarUrl();
|
||||
|
||||
/**
|
||||
@ -79,6 +94,7 @@ public interface SendableDiscordMessage {
|
||||
* Gets the current content of this message in this builder.
|
||||
* @return the content
|
||||
*/
|
||||
@Nullable
|
||||
String getContent();
|
||||
|
||||
/**
|
||||
@ -86,12 +102,14 @@ public interface SendableDiscordMessage {
|
||||
* @param content the new content
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder setContent(String content);
|
||||
|
||||
/**
|
||||
* Gets the embeds that are currently in this builder.
|
||||
* @return this builder's current embeds
|
||||
*/
|
||||
@NotNull
|
||||
List<DiscordMessageEmbed> getEmbeds();
|
||||
|
||||
/**
|
||||
@ -99,6 +117,7 @@ public interface SendableDiscordMessage {
|
||||
* @param embed the embed to add
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder addEmbed(DiscordMessageEmbed embed);
|
||||
|
||||
/**
|
||||
@ -106,12 +125,14 @@ public interface SendableDiscordMessage {
|
||||
* @param embed the embed to remove
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder removeEmbed(DiscordMessageEmbed embed);
|
||||
|
||||
/**
|
||||
* Gets the allowed mentions in this builder.
|
||||
* @return the builder's current allowed mentions
|
||||
*/
|
||||
@Nullable
|
||||
Set<AllowedMention> getAllowedMentions();
|
||||
|
||||
/**
|
||||
@ -119,6 +140,7 @@ public interface SendableDiscordMessage {
|
||||
* @param allowedMention the allowed mention to add
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder addAllowedMention(AllowedMention allowedMention);
|
||||
|
||||
/**
|
||||
@ -126,12 +148,14 @@ public interface SendableDiscordMessage {
|
||||
* @param allowedMention the allowed mention to remove
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder removeAllowedMention(AllowedMention allowedMention);
|
||||
|
||||
/**
|
||||
* Gets the webhook username for this builder or {@code null} if webhooks are not being used.
|
||||
* @return the webhook username
|
||||
*/
|
||||
@Nullable
|
||||
String getWebhookUsername();
|
||||
|
||||
/**
|
||||
@ -139,12 +163,14 @@ public interface SendableDiscordMessage {
|
||||
* @param webhookUsername the new webhook username
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder setWebhookUsername(String webhookUsername);
|
||||
|
||||
/**
|
||||
* Gets the webhook avatar url for this builder.
|
||||
* @return the webhook avatar url
|
||||
*/
|
||||
@Nullable
|
||||
String getWebhookAvatarUrl();
|
||||
|
||||
/**
|
||||
@ -153,12 +179,14 @@ public interface SendableDiscordMessage {
|
||||
* @throws IllegalStateException if there is no webhook username set
|
||||
* @return the builder, useful for chaining
|
||||
*/
|
||||
@NotNull
|
||||
Builder setWebhookAvatarUrl(String webhookAvatarUrl);
|
||||
|
||||
/**
|
||||
* Builds a {@link SendableDiscordMessage} from this builder.
|
||||
* @return the new {@link SendableDiscordMessage}
|
||||
*/
|
||||
@NotNull
|
||||
SendableDiscordMessage build();
|
||||
}
|
||||
|
@ -21,11 +21,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.message.impl;
|
||||
package com.discordsrv.api.discord.api.entity.message.impl;
|
||||
|
||||
import com.discordsrv.api.discord.api.message.AllowedMention;
|
||||
import com.discordsrv.api.discord.api.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.AllowedMention;
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@ -40,7 +41,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
private final String webhookUsername;
|
||||
private final String webhookAvatarUrl;
|
||||
|
||||
public SendableDiscordMessageImpl(String content,
|
||||
protected SendableDiscordMessageImpl(String content,
|
||||
List<DiscordMessageEmbed> embeds,
|
||||
Set<AllowedMention> allowedMentions,
|
||||
String webhookUsername,
|
||||
@ -58,7 +59,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiscordMessageEmbed> getEmbeds() {
|
||||
public @NotNull List<DiscordMessageEmbed> getEmbeds() {
|
||||
return embeds;
|
||||
}
|
||||
|
||||
@ -91,24 +92,24 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderImpl setContent(String content) {
|
||||
public @NotNull BuilderImpl setContent(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiscordMessageEmbed> getEmbeds() {
|
||||
public @NotNull List<DiscordMessageEmbed> getEmbeds() {
|
||||
return embeds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder addEmbed(DiscordMessageEmbed embed) {
|
||||
public @NotNull Builder addEmbed(DiscordMessageEmbed embed) {
|
||||
this.embeds.add(embed);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder removeEmbed(DiscordMessageEmbed embed) {
|
||||
public @NotNull Builder removeEmbed(DiscordMessageEmbed embed) {
|
||||
this.embeds.remove(embed);
|
||||
return this;
|
||||
}
|
||||
@ -119,13 +120,13 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder addAllowedMention(AllowedMention allowedMention) {
|
||||
public @NotNull Builder addAllowedMention(AllowedMention allowedMention) {
|
||||
this.allowedMentions.add(allowedMention);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder removeAllowedMention(AllowedMention allowedMention) {
|
||||
public @NotNull Builder removeAllowedMention(AllowedMention allowedMention) {
|
||||
this.allowedMentions.remove(allowedMention);
|
||||
return this;
|
||||
}
|
||||
@ -136,7 +137,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderImpl setWebhookUsername(String webhookUsername) {
|
||||
public @NotNull BuilderImpl setWebhookUsername(String webhookUsername) {
|
||||
this.webhookUsername = webhookUsername;
|
||||
return this;
|
||||
}
|
||||
@ -147,13 +148,13 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderImpl setWebhookAvatarUrl(String webhookAvatarUrl) {
|
||||
public @NotNull BuilderImpl setWebhookAvatarUrl(String webhookAvatarUrl) {
|
||||
this.webhookAvatarUrl = webhookAvatarUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendableDiscordMessage build() {
|
||||
public @NotNull SendableDiscordMessage build() {
|
||||
return new SendableDiscordMessageImpl(content, embeds, allowedMentions, webhookUsername, webhookAvatarUrl);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.discordsrv.api.discord.api.entity.user;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.Snowflake;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A Discord user.
|
||||
*/
|
||||
public interface DiscordUser extends Snowflake {
|
||||
|
||||
/**
|
||||
* Gets the username of the Discord user.
|
||||
* @return the user's username
|
||||
*/
|
||||
@NotNull
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* Gets the Discord user's discriminator.
|
||||
* @return the user's discriminator
|
||||
*/
|
||||
@NotNull
|
||||
String getDiscriminator();
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.exception;
|
||||
|
||||
public class NotReadyException extends RuntimeException {}
|
@ -21,22 +21,18 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.channel;
|
||||
package com.discordsrv.api.discord.api.exception;
|
||||
|
||||
import com.discordsrv.api.discord.api.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
|
||||
public class RestErrorResponseException extends RuntimeException {
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
private final int errorCode;
|
||||
|
||||
public interface DiscordTextChannel {
|
||||
|
||||
String getId();
|
||||
|
||||
String getName();
|
||||
String getTopic();
|
||||
|
||||
CompletableFuture<ReceivedDiscordMessage> sendMessage(SendableDiscordMessage message);
|
||||
|
||||
CompletableFuture<ReceivedDiscordMessage> editMessageById(String id, SendableDiscordMessage message);
|
||||
public RestErrorResponseException(int errorCode, Throwable cause) {
|
||||
super(cause);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.exception;
|
||||
|
||||
public class UnknownChannelException extends RuntimeException {
|
||||
|
||||
public UnknownChannelException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.discord.api.exception;
|
||||
|
||||
public class UnknownMessageException extends RuntimeException {
|
||||
|
||||
public UnknownMessageException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -19,56 +19,184 @@
|
||||
package com.discordsrv.common.discord.api;
|
||||
|
||||
import club.minnced.discord.webhook.WebhookClient;
|
||||
import club.minnced.discord.webhook.WebhookClientBuilder;
|
||||
import com.discordsrv.api.discord.api.DiscordAPI;
|
||||
import com.discordsrv.api.discord.api.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.api.entity.user.DiscordUser;
|
||||
import com.discordsrv.api.discord.api.exception.NotReadyException;
|
||||
import com.discordsrv.api.discord.api.exception.UnknownChannelException;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.ChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.ChannelConfigHolder;
|
||||
import com.discordsrv.common.discord.api.channel.DiscordTextChannelImpl;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.RemovalListener;
|
||||
import com.discordsrv.common.discord.api.guild.DiscordGuildImpl;
|
||||
import com.discordsrv.common.discord.api.user.DiscordUserImpl;
|
||||
import com.github.benmanes.caffeine.cache.*;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.Webhook;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DiscordAPIImpl implements DiscordAPI {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final Map<String, WebhookClient> configuredClients = new HashMap<>();
|
||||
private final Cache<String, WebhookClient> cachedClients = Caffeine.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||
|
||||
private final AsyncLoadingCache<String, WebhookClient> cachedClients = Caffeine.newBuilder()
|
||||
.removalListener((RemovalListener<String, WebhookClient>) (id, client, cause) -> {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
.expireAfter(new CacheExpiry())
|
||||
.buildAsync(new CacheLoader());
|
||||
|
||||
public DiscordAPIImpl(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
public WebhookClient getWebhookClient(String channelId) {
|
||||
WebhookClient client = configuredClients.get(channelId);
|
||||
if (client != null) {
|
||||
return client;
|
||||
}
|
||||
|
||||
return cachedClients.getIfPresent(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscordTextChannel getTextChannelById(String id) {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
CompletableFuture<WebhookClient> clientFuture = cachedClients.getIfPresent(channelId);
|
||||
if (clientFuture == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TextChannel textChannel = jda.getTextChannelById(id);
|
||||
return textChannel != null ? new DiscordTextChannelImpl(discordSRV, textChannel) : null;
|
||||
return clientFuture.join();
|
||||
}
|
||||
|
||||
public CompletableFuture<WebhookClient> queryWebhookClient(String channelId) {
|
||||
return cachedClients.get(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DiscordTextChannel> getTextChannelById(@NotNull String id) {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
TextChannel textChannel = jda.getTextChannelById(id);
|
||||
return textChannel != null
|
||||
? Optional.of(new DiscordTextChannelImpl(discordSRV, textChannel))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DiscordGuild> getGuildById(@NotNull String id) {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Guild guild = jda.getGuildById(id);
|
||||
return guild != null
|
||||
? Optional.of(new DiscordGuildImpl(discordSRV, guild))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DiscordUser> getUserById(@NotNull String id) {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
User user = jda.getUserById(id);
|
||||
return user != null
|
||||
? Optional.of(new DiscordUserImpl(user))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
private class CacheLoader implements AsyncCacheLoader<String, WebhookClient> {
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<WebhookClient> asyncLoad(@NonNull String channelId, @NonNull Executor executor) {
|
||||
CompletableFuture<WebhookClient> future = new CompletableFuture<>();
|
||||
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
future.completeExceptionally(new NotReadyException());
|
||||
return future;
|
||||
}
|
||||
|
||||
TextChannel textChannel = jda.getTextChannelById(channelId);
|
||||
if (textChannel == null) {
|
||||
future.completeExceptionally(new UnknownChannelException(null));
|
||||
return future;
|
||||
}
|
||||
|
||||
return textChannel.retrieveWebhooks().submit().thenApply(webhooks -> {
|
||||
Webhook hook = null;
|
||||
for (Webhook webhook : webhooks) {
|
||||
User user = webhook.getOwnerAsUser();
|
||||
if (user == null
|
||||
|| !user.getId().equals(jda.getSelfUser().getId())
|
||||
|| !webhook.getName().equals("DiscordSRV")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hook = webhook;
|
||||
break;
|
||||
}
|
||||
|
||||
return hook;
|
||||
}).thenCompose(webhook -> {
|
||||
if (webhook != null) {
|
||||
CompletableFuture<Webhook> completableFuture = new CompletableFuture<>();
|
||||
completableFuture.complete(webhook);
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
return textChannel.createWebhook("DiscordSRV").submit();
|
||||
}).thenApply(webhook ->
|
||||
WebhookClientBuilder.fromJDA(webhook)
|
||||
.setHttpClient(jda.getHttpClient())
|
||||
.setExecutorService(discordSRV.scheduler().executor())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private class CacheExpiry implements Expiry<String, WebhookClient> {
|
||||
|
||||
private boolean isConfiguredChannel(String channelId) {
|
||||
for (ChannelConfigHolder value : discordSRV.config().channels.values()) {
|
||||
BaseChannelConfig config = value.get();
|
||||
if (config instanceof ChannelConfig
|
||||
&& ((ChannelConfig) config).channelIds.contains(channelId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private long expireAfterWrite(String channelId) {
|
||||
return isConfiguredChannel(channelId) ? Long.MAX_VALUE : TimeUnit.MINUTES.toNanos(15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long expireAfterCreate(@NonNull String channelId, @NonNull WebhookClient webhookClient, long currentTime) {
|
||||
return expireAfterWrite(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long expireAfterUpdate(@NonNull String channelId, @NonNull WebhookClient webhookClient, long currentTime, @NonNegative long currentDuration) {
|
||||
return expireAfterWrite(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long expireAfterRead(@NonNull String channelId, @NonNull WebhookClient webhookClient, long currentTime, @NonNegative long currentDuration) {
|
||||
return isConfiguredChannel(channelId) ? Long.MAX_VALUE : TimeUnit.MINUTES.toNanos(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,58 +18,128 @@
|
||||
|
||||
package com.discordsrv.common.discord.api.channel;
|
||||
|
||||
import com.discordsrv.api.discord.api.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
|
||||
import club.minnced.discord.webhook.WebhookClient;
|
||||
import club.minnced.discord.webhook.receive.ReadonlyMessage;
|
||||
import club.minnced.discord.webhook.send.WebhookMessage;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.exception.NotReadyException;
|
||||
import com.discordsrv.api.discord.api.exception.RestErrorResponseException;
|
||||
import com.discordsrv.api.discord.api.exception.UnknownChannelException;
|
||||
import com.discordsrv.api.discord.api.exception.UnknownMessageException;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.discord.api.guild.DiscordGuildImpl;
|
||||
import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageImpl;
|
||||
import com.discordsrv.common.discord.api.message.util.SendableDiscordMessageUtil;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import net.dv8tion.jda.api.utils.MiscUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class DiscordTextChannelImpl implements DiscordTextChannel {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final TextChannel textChannel;
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final String topic;
|
||||
private final DiscordGuild guild;
|
||||
|
||||
public DiscordTextChannelImpl(DiscordSRV discordSRV, TextChannel textChannel) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.textChannel = textChannel;
|
||||
this.id = textChannel.getId();
|
||||
this.name = textChannel.getName();
|
||||
this.topic = textChannel.getTopic();
|
||||
this.guild = new DiscordGuildImpl(discordSRV, textChannel.getGuild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return textChannel.getId();
|
||||
public @NotNull String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return textChannel.getName();
|
||||
public @NotNull String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTopic() {
|
||||
return textChannel.getTopic();
|
||||
public @NotNull String getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ReceivedDiscordMessage> sendMessage(SendableDiscordMessage message) {
|
||||
// TODO
|
||||
public @NotNull DiscordGuild getGuild() {
|
||||
return guild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> sendMessage(SendableDiscordMessage message) {
|
||||
return message(message, WebhookClient::send, MessageChannel::sendMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(String id, SendableDiscordMessage message) {
|
||||
return message(
|
||||
message,
|
||||
(client, msg) -> client.edit(MiscUtil.parseLong(id), msg),
|
||||
(textChannel, msg) -> textChannel.editMessageById(id, msg)
|
||||
);
|
||||
}
|
||||
|
||||
private CompletableFuture<ReceivedDiscordMessage> message(
|
||||
SendableDiscordMessage message,
|
||||
BiFunction<WebhookClient, WebhookMessage, CompletableFuture<ReadonlyMessage>> webhookFunction,
|
||||
BiFunction<TextChannel, Message, MessageAction> jdaFunction) {
|
||||
CompletableFuture<ReceivedDiscordMessage> future;
|
||||
if (message.isWebhookMessage()) {
|
||||
|
||||
future = discordSRV.discordAPI().queryWebhookClient(getId())
|
||||
.thenCompose(client -> webhookFunction.apply(
|
||||
client, SendableDiscordMessageUtil.toWebhook(message)))
|
||||
.thenApply(msg -> ReceivedDiscordMessageImpl.fromWebhook(discordSRV, msg));
|
||||
} else {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
throw new NotReadyException();
|
||||
}
|
||||
|
||||
TextChannel textChannel = jda.getTextChannelById(getId());
|
||||
if (textChannel == null) {
|
||||
future = new CompletableFuture<>();
|
||||
future.completeExceptionally(new UnknownChannelException(null));
|
||||
return future;
|
||||
}
|
||||
|
||||
future = jdaFunction
|
||||
.apply(textChannel, SendableDiscordMessageUtil.toJDA(message))
|
||||
.submit()
|
||||
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ReceivedDiscordMessage> editMessageById(String id, SendableDiscordMessage message) {
|
||||
// TODO
|
||||
if (message.isWebhookMessage()) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
return null;
|
||||
return future.handle((msg, t) -> {
|
||||
if (t instanceof ErrorResponseException) {
|
||||
ErrorResponse errorResponse = ((ErrorResponseException) t).getErrorResponse();
|
||||
if (errorResponse != null) {
|
||||
if (errorResponse == ErrorResponse.UNKNOWN_MESSAGE) {
|
||||
throw new UnknownMessageException(t);
|
||||
} else if (errorResponse == ErrorResponse.UNKNOWN_CHANNEL) {
|
||||
throw new UnknownChannelException(t);
|
||||
}
|
||||
}
|
||||
throw new RestErrorResponseException(((ErrorResponseException) t).getErrorCode(), t);
|
||||
} else if (t != null) {
|
||||
throw (RuntimeException) t;
|
||||
}
|
||||
return msg;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.discordsrv.common.discord.api.guild;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DiscordGuildImpl implements DiscordGuild {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final String id;
|
||||
private final int memberCount;
|
||||
|
||||
public DiscordGuildImpl(DiscordSRV discordSRV, Guild guild) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.id = guild.getId();
|
||||
this.memberCount = guild.getMemberCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMemberCount() {
|
||||
return memberCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DiscordGuildMember> getMemberById(String id) {
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Guild guild = jda.getGuildById(this.id);
|
||||
if (guild == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Member member = guild.getMemberById(id);
|
||||
return member != null
|
||||
? Optional.of(new DiscordGuildMemberImpl(member))
|
||||
: Optional.empty();
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.discordsrv.common.discord.api.guild;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember;
|
||||
import com.discordsrv.common.discord.api.user.DiscordUserImpl;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DiscordGuildMemberImpl extends DiscordUserImpl implements DiscordGuildMember {
|
||||
|
||||
private final String nickname;
|
||||
|
||||
public DiscordGuildMemberImpl(Member member) {
|
||||
super(member.getUser());
|
||||
this.nickname = member.getNickname();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<String> getNickname() {
|
||||
return Optional.ofNullable(nickname);
|
||||
}
|
||||
}
|
@ -18,97 +18,147 @@
|
||||
|
||||
package com.discordsrv.common.discord.api.message;
|
||||
|
||||
import com.discordsrv.api.discord.api.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.message.AllowedMention;
|
||||
import com.discordsrv.api.discord.api.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.message.impl.SendableDiscordMessageImpl;
|
||||
import club.minnced.discord.webhook.receive.ReadonlyEmbed;
|
||||
import club.minnced.discord.webhook.receive.ReadonlyMessage;
|
||||
import club.minnced.discord.webhook.receive.ReadonlyUser;
|
||||
import club.minnced.discord.webhook.send.WebhookEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.exception.UnknownChannelException;
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.impl.SendableDiscordMessageImpl;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ReceivedDiscordMessageImpl extends SendableDiscordMessageImpl implements ReceivedDiscordMessage {
|
||||
|
||||
private static List<DiscordMessageEmbed> mapEmbeds(List<MessageEmbed> embeds) {
|
||||
public static ReceivedDiscordMessage fromJDA(DiscordSRV discordSRV, Message message) {
|
||||
List<DiscordMessageEmbed> mappedEmbeds = new ArrayList<>();
|
||||
for (MessageEmbed embed : embeds) {
|
||||
for (MessageEmbed embed : message.getEmbeds()) {
|
||||
mappedEmbeds.add(new DiscordMessageEmbed(embed));
|
||||
}
|
||||
return mappedEmbeds;
|
||||
|
||||
boolean webhookMessage = message.isWebhookMessage();
|
||||
String webhookUsername = webhookMessage ? message.getAuthor().getName() : null;
|
||||
String webhookAvatarUrl = webhookMessage ? message.getAuthor().getEffectiveAvatarUrl() : null;
|
||||
|
||||
DiscordTextChannel textChannel = discordSRV.discordAPI().getTextChannelById(message.getChannel().getId())
|
||||
.orElse(null);
|
||||
return new ReceivedDiscordMessageImpl(
|
||||
discordSRV,
|
||||
textChannel,
|
||||
message.getChannel().getId(),
|
||||
message.getId(),
|
||||
message.getContentRaw(),
|
||||
mappedEmbeds,
|
||||
webhookUsername,
|
||||
webhookAvatarUrl
|
||||
);
|
||||
}
|
||||
|
||||
private static Set<AllowedMention> allowedMentions(Message message) {
|
||||
Set<AllowedMention> allowedMentions = new HashSet<>();
|
||||
if (message.mentionsEveryone()) {
|
||||
allowedMentions.add(AllowedMention.EVERYONE);
|
||||
}
|
||||
for (User user : message.getMentionedUsers()) {
|
||||
allowedMentions.add(AllowedMention.user(user.getId()));
|
||||
}
|
||||
for (Role role : message.getMentionedRoles()) {
|
||||
allowedMentions.add(AllowedMention.role(role.getId()));
|
||||
}
|
||||
return allowedMentions;
|
||||
}
|
||||
public static ReceivedDiscordMessage fromWebhook(DiscordSRV discordSRV, ReadonlyMessage webhookMessage) {
|
||||
List<DiscordMessageEmbed> mappedEmbeds = new ArrayList<>();
|
||||
for (ReadonlyEmbed embed : webhookMessage.getEmbeds()) {
|
||||
List<DiscordMessageEmbed.Field> fields = new ArrayList<>();
|
||||
for (WebhookEmbed.EmbedField field : embed.getFields()) {
|
||||
fields.add(new DiscordMessageEmbed.Field(field.getName(), field.getValue(), field.isInline()));
|
||||
}
|
||||
|
||||
private static String webhookUsername(Message message) {
|
||||
if (!message.isWebhookMessage()) {
|
||||
return null;
|
||||
Integer color = embed.getColor();
|
||||
WebhookEmbed.EmbedAuthor author = embed.getAuthor();
|
||||
WebhookEmbed.EmbedTitle title = embed.getTitle();
|
||||
ReadonlyEmbed.EmbedImage thumbnail = embed.getThumbnail();
|
||||
ReadonlyEmbed.EmbedImage image = embed.getImage();
|
||||
WebhookEmbed.EmbedFooter footer = embed.getFooter();
|
||||
|
||||
mappedEmbeds.add(new DiscordMessageEmbed(
|
||||
color != null ? color : Role.DEFAULT_COLOR_RAW,
|
||||
author != null ? author.getName() : null,
|
||||
author != null ? author.getUrl() : null,
|
||||
author != null ? author.getIconUrl() : null,
|
||||
title != null ? title.getText() : null,
|
||||
title != null ? title.getUrl() : null,
|
||||
embed.getDescription(),
|
||||
fields,
|
||||
thumbnail != null ? thumbnail.getUrl() : null,
|
||||
image != null ? image.getUrl() : null,
|
||||
embed.getTimestamp(),
|
||||
footer != null ? footer.getText() : null,
|
||||
footer != null ? footer.getIconUrl() : null
|
||||
));
|
||||
}
|
||||
|
||||
return message.getAuthor().getName();
|
||||
}
|
||||
ReadonlyUser author = webhookMessage.getAuthor();
|
||||
String authorId = Long.toUnsignedString(author.getId());
|
||||
String avatarId = author.getAvatarId();
|
||||
String avatarUrl = avatarId != null
|
||||
? String.format(User.AVATAR_URL, authorId, avatarId, avatarId.startsWith("a_") ? "gif" : "png")
|
||||
: String.format(User.DEFAULT_AVATAR_URL, Integer.parseInt(author.getDiscriminator()) % 5);
|
||||
|
||||
private static String webhookAvatarUrl(Message message) {
|
||||
if (!message.isWebhookMessage()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return message.getAuthor().getEffectiveAvatarUrl();
|
||||
DiscordTextChannel textChannel = discordSRV.discordAPI().getTextChannelById(
|
||||
Long.toUnsignedString(webhookMessage.getChannelId())).orElse(null);
|
||||
return new ReceivedDiscordMessageImpl(
|
||||
discordSRV,
|
||||
textChannel,
|
||||
Long.toUnsignedString(webhookMessage.getChannelId()),
|
||||
Long.toUnsignedString(webhookMessage.getId()),
|
||||
webhookMessage.getContent(),
|
||||
mappedEmbeds,
|
||||
author.getName(),
|
||||
avatarUrl
|
||||
);
|
||||
}
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final Message message;
|
||||
private final DiscordTextChannel textChannel;
|
||||
private final String channelId;
|
||||
private final String id;
|
||||
|
||||
public ReceivedDiscordMessageImpl(DiscordSRV discordSRV, Message message) {
|
||||
super(
|
||||
message.getContentRaw(),
|
||||
mapEmbeds(message.getEmbeds()),
|
||||
allowedMentions(message),
|
||||
webhookUsername(message),
|
||||
webhookAvatarUrl(message)
|
||||
);
|
||||
private ReceivedDiscordMessageImpl(
|
||||
DiscordSRV discordSRV,
|
||||
DiscordTextChannel textChannel,
|
||||
String channelId,
|
||||
String id,
|
||||
String content,
|
||||
List<DiscordMessageEmbed> embeds,
|
||||
String webhookUsername,
|
||||
String webhookAvatarUrl
|
||||
) {
|
||||
super(content, embeds, null, webhookUsername, webhookAvatarUrl);
|
||||
this.discordSRV = discordSRV;
|
||||
this.message = message;
|
||||
this.textChannel = textChannel;
|
||||
this.channelId = channelId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return message.getId();
|
||||
public @NotNull String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayedContent() {
|
||||
return message.getContentDisplay();
|
||||
public @NotNull DiscordTextChannel getChannel() {
|
||||
return textChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStrippedContent() {
|
||||
return message.getContentStripped();
|
||||
}
|
||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message) {
|
||||
DiscordTextChannel textChannel = discordSRV.discordAPI().getTextChannelById(channelId).orElse(null);
|
||||
if (textChannel == null) {
|
||||
CompletableFuture<ReceivedDiscordMessage> future = new CompletableFuture<>();
|
||||
future.completeExceptionally(new UnknownChannelException(null));
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message) {
|
||||
DiscordTextChannel textChannel = discordSRV.discordAPI().getTextChannelById(this.message.getChannel().getId());
|
||||
return textChannel.editMessageById(textChannel.getId(), message);
|
||||
}
|
||||
}
|
||||
|
@ -20,35 +20,40 @@ package com.discordsrv.common.discord.api.message.util;
|
||||
|
||||
import club.minnced.discord.webhook.send.WebhookMessage;
|
||||
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
|
||||
import com.discordsrv.api.discord.api.message.AllowedMention;
|
||||
import com.discordsrv.api.discord.api.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.AllowedMention;
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import net.dv8tion.jda.api.MessageBuilder;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SendableDiscordMessageUtil {
|
||||
|
||||
private SendableDiscordMessageUtil() {}
|
||||
|
||||
public static Message toJDA(SendableDiscordMessage message) {
|
||||
public static Message toJDA(@NotNull SendableDiscordMessage message) {
|
||||
List<Message.MentionType> allowedTypes = new ArrayList<>();
|
||||
List<String> allowedUsers = new ArrayList<>();
|
||||
List<String> allowedRoles = new ArrayList<>();
|
||||
|
||||
for (AllowedMention allowedMention : message.getAllowedMentions()) {
|
||||
if (allowedMention instanceof AllowedMention.Snowflake) {
|
||||
String id = ((AllowedMention.Snowflake) allowedMention).getId();
|
||||
if (((AllowedMention.Snowflake) allowedMention).isUser()) {
|
||||
allowedUsers.add(id);
|
||||
} else {
|
||||
allowedRoles.add(id);
|
||||
Set<AllowedMention> allowedMentions = message.getAllowedMentions();
|
||||
if (allowedMentions != null) {
|
||||
for (AllowedMention allowedMention : allowedMentions) {
|
||||
if (allowedMention instanceof AllowedMention.Snowflake) {
|
||||
String id = ((AllowedMention.Snowflake) allowedMention).getId();
|
||||
if (((AllowedMention.Snowflake) allowedMention).isUser()) {
|
||||
allowedUsers.add(id);
|
||||
} else {
|
||||
allowedRoles.add(id);
|
||||
}
|
||||
} else if (allowedMention instanceof AllowedMention.Standard) {
|
||||
allowedTypes.add(((AllowedMention.Standard) allowedMention).getMentionType());
|
||||
}
|
||||
} else if (allowedMention instanceof AllowedMention.Standard) {
|
||||
allowedTypes.add(((AllowedMention.Standard) allowedMention).getMentionType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +71,7 @@ public final class SendableDiscordMessageUtil {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static WebhookMessage toWebhook(SendableDiscordMessage message) {
|
||||
public static WebhookMessage toWebhook(@NotNull SendableDiscordMessage message) {
|
||||
return WebhookMessageBuilder.fromJDA(toJDA(message))
|
||||
.setUsername(message.getWebhookUsername())
|
||||
.setAvatarUrl(message.getWebhookAvatarUrl())
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.discordsrv.common.discord.api.user;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.user.DiscordUser;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DiscordUserImpl implements DiscordUser {
|
||||
|
||||
private final String id;
|
||||
private final String username;
|
||||
private final String discriminator;
|
||||
|
||||
public DiscordUserImpl(User user) {
|
||||
this.id = user.getId();
|
||||
this.username = user.getName();
|
||||
this.discriminator = user.getDiscriminator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDiscriminator() {
|
||||
return discriminator;
|
||||
}
|
||||
}
|
@ -18,10 +18,8 @@
|
||||
|
||||
package com.discordsrv.common.listener;
|
||||
|
||||
import club.minnced.discord.webhook.WebhookClientBuilder;
|
||||
import club.minnced.discord.webhook.send.WebhookMessage;
|
||||
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.event.bus.EventPriority;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.message.receive.game.ChatMessageReceiveEvent;
|
||||
@ -35,9 +33,6 @@ import com.discordsrv.common.player.util.PlayerUtil;
|
||||
import com.discordsrv.common.string.util.Placeholders;
|
||||
import dev.vankka.enhancedlegacytext.EnhancedLegacyText;
|
||||
import dev.vankka.mcdiscordreserializer.discord.DiscordSerializer;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.Webhook;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
|
||||
@ -82,12 +77,7 @@ public class DefaultChatListener extends AbstractListener {
|
||||
|
||||
@Subscribe(priority = EventPriority.LAST)
|
||||
public void onChatSend(ChatMessageSendEvent event) {
|
||||
if (checkProcessor(event) || checkCancellation(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JDA jda = discordSRV.jda();
|
||||
if (jda == null) {
|
||||
if (checkProcessor(event) || checkCancellation(event) || !discordSRV.isReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -99,19 +89,14 @@ public class DefaultChatListener extends AbstractListener {
|
||||
}
|
||||
|
||||
for (String channelId : channelIds) {
|
||||
TextChannel textChannel = jda.getTextChannelById(channelId);
|
||||
if (textChannel == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
textChannel.retrieveWebhooks().queue(webhooks -> {
|
||||
Webhook webhook = webhooks.get(0);
|
||||
WebhookMessage webhookMessage = new WebhookMessageBuilder()
|
||||
.setUsername(event.getDiscordUsername())
|
||||
.setContent(event.getDiscordMessage())
|
||||
.build();
|
||||
WebhookClientBuilder.fromJDA(webhook).buildJDA().send(webhookMessage);
|
||||
});
|
||||
discordSRV.discordAPI().getTextChannelById(channelId).ifPresent(textChannel ->
|
||||
textChannel.sendMessage(
|
||||
SendableDiscordMessage.builder()
|
||||
.setWebhookUsername(event.getDiscordUsername())
|
||||
.setContent(event.getDiscordMessage())
|
||||
.build()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user