use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class StarboardHandler method getStarboardMessage.
private WebhookMessage getStarboardMessage(Document guildData, Document starboard, Guild guild, Member member, ReactionEmote emote, boolean premium) {
List<Document> messages = guildData.getList("messages", Document.class, StarboardManager.DEFAULT_CONFIGURATION);
int stars = starboard.getInteger("count");
Document messageData = messages.stream().filter(d -> starboard.getInteger("count") >= d.getInteger("stars")).max(Comparator.comparingInt(d -> d.getInteger("stars"))).orElse(null);
if (messageData == null) {
return null;
}
int nextStars = messages.stream().filter(d -> starboard.getInteger("count") < d.getInteger("stars")).mapToInt(d -> d.getInteger("stars")).min().orElse(0);
User author = this.bot.getShardManager().getUserById(starboard.getLong("authorId"));
long channelId = starboard.getLong("channelId");
BaseGuildMessageChannel channel = guild.getChannelById(BaseGuildMessageChannel.class, channelId);
if (channel == null) {
return null;
}
String messageLink = "https://discord.com/channels/" + guild.getId() + "/" + channelId + "/" + starboard.getLong("originalMessageId");
// temporary while embed support isn't a thing
WebhookEmbedBuilder builder = new WebhookEmbedBuilder().setAuthor(new WebhookEmbed.EmbedAuthor(author == null ? "Anonymous#0000" : author.getAsTag(), author == null ? null : author.getEffectiveAvatarUrl(), null)).setColor(-21453).addField(new WebhookEmbed.EmbedField(false, "Message Link", "[Jump!](" + messageLink + ")")).setImageUrl(starboard.getString("image"));
String content = starboard.getString("content");
if (content != null && !content.isBlank()) {
builder.addField(new WebhookEmbed.EmbedField(false, "Message", StringUtility.limit(content, MessageEmbed.VALUE_MAX_LENGTH, "[...](" + messageLink + ")")));
}
Document webhookData = guildData.get("webhook", MongoDatabase.EMPTY_DOCUMENT);
try {
return this.format(messageData.get("message", Document.class), member, channel, emote, stars, nextStars, starboard.getObjectId("_id")).setUsername(premium ? webhookData.get("name", "Sx4 - Starboard") : "Sx4 - Starboard").setAvatarUrl(premium ? webhookData.get("avatar", this.bot.getShardManager().getShardById(0).getSelfUser().getEffectiveAvatarUrl()) : this.bot.getShardManager().getShardById(0).getSelfUser().getEffectiveAvatarUrl()).addEmbeds(builder.build()).build();
} catch (IllegalArgumentException e) {
// TODO: can't currently happen but when embed support is added handle this
return null;
}
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class WelcomerHandler method sendWelcomer.
public void sendWelcomer(Guild guild, Member member) {
JDA jda = guild.getJDA();
Document data = this.bot.getMongo().getGuildById(guild.getIdLong(), Projections.include("welcomer", "premium.endAt"));
Document welcomer = data.get("welcomer", MongoDatabase.EMPTY_DOCUMENT);
Document image = welcomer.get("image", MongoDatabase.EMPTY_DOCUMENT);
if (member.isPending() == welcomer.get("screening", true)) {
return;
}
boolean messageEnabled = welcomer.getBoolean("enabled", false), imageEnabled = image.getBoolean("enabled", false);
if (!messageEnabled && !imageEnabled) {
return;
}
long channelId = welcomer.get("channelId", 0L);
BaseGuildMessageChannel channel = channelId == 0L ? null : guild.getChannelById(BaseGuildMessageChannel.class, channelId);
boolean dm = welcomer.getBoolean("dm", false);
if (channel == null && !dm) {
return;
}
Document webhookData = welcomer.get("webhook", MongoDatabase.EMPTY_DOCUMENT);
boolean premium = Clock.systemUTC().instant().getEpochSecond() < data.getEmbedded(List.of("premium", "endAt"), 0L);
WelcomerUtility.getWelcomerMessage(this.bot.getHttpClient(), messageEnabled ? welcomer.get("message", WelcomerManager.DEFAULT_MESSAGE) : null, image.getString("bannerId"), member, this.bot.getConfig().isCanary(), imageEnabled, premium, (builder, exception) -> {
if (exception instanceof IllegalArgumentException) {
this.bot.getMongo().updateGuildById(guild.getIdLong(), Updates.unset("welcomer.message")).whenComplete(MongoDatabase.exceptionally());
return;
}
if (ExceptionUtility.sendErrorMessage(exception)) {
return;
}
if (dm) {
member.getUser().openPrivateChannel().flatMap(privateChannel -> MessageUtility.fromWebhookMessage(privateChannel, builder.build())).queue(null, ErrorResponseException.ignore(ErrorResponse.CANNOT_SEND_TO_USER));
} else {
WebhookMessage message = builder.setUsername(premium ? webhookData.get("name", "Sx4 - Welcomer") : "Sx4 - Welcomer").setAvatarUrl(premium ? webhookData.get("avatar", jda.getSelfUser().getEffectiveAvatarUrl()) : jda.getSelfUser().getEffectiveAvatarUrl()).build();
this.bot.getWelcomerManager().sendWelcomer(channel, webhookData, message);
}
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class LoggerManager method handleQueue.
private void handleQueue() {
this.executor.submit(() -> {
try {
Request request = this.queue.poll();
if (request == null) {
return;
}
if (request.getAttempts() == LoggerManager.MAX_RETRIES) {
this.handleQueue();
return;
}
Guild guild = request.getGuild();
if (guild == null) {
this.handleQueue();
return;
}
long channelId = request.getChannelId();
BaseGuildMessageChannel channel = request.getChannel(guild);
if (channel == null) {
this.bot.getMongo().deleteLogger(Filters.eq("channelId", channelId)).whenComplete((result, exception) -> {
ExceptionUtility.sendErrorMessage(exception);
this.queue.clear();
});
return;
}
List<WebhookEmbed> embeds = new ArrayList<>(request.getEmbeds());
int length = MessageUtility.getWebhookEmbedLength(embeds);
List<Request> skippedRequests = new ArrayList<>(), requests = new ArrayList<>();
requests.add(request);
Request nextRequest;
while ((nextRequest = this.queue.poll()) != null) {
List<WebhookEmbed> nextEmbeds = nextRequest.getEmbeds();
int nextLength = MessageUtility.getWebhookEmbedLength(nextEmbeds);
if (embeds.size() + nextEmbeds.size() > WebhookMessage.MAX_EMBEDS || length + nextLength > MessageEmbed.EMBED_MAX_LENGTH_BOT) {
skippedRequests.add(nextRequest);
break;
}
embeds.addAll(nextEmbeds);
requests.add(nextRequest);
length += nextLength;
}
// Keep order of logs
skippedRequests.forEach(this.queue::addFirst);
Document logger = request.getLogger();
Document webhookData = logger.get("webhook", MongoDatabase.EMPTY_DOCUMENT);
boolean premium = logger.getBoolean("premium");
WebhookMessage message = new WebhookMessageBuilder().addEmbeds(embeds).setUsername(premium ? webhookData.get("name", "Sx4 - Logger") : "Sx4 - Logger").setAvatarUrl(premium ? webhookData.get("avatar", request.getJDA().getSelfUser().getEffectiveAvatarUrl()) : request.getJDA().getSelfUser().getEffectiveAvatarUrl()).build();
if (this.webhook == null) {
if (!webhookData.containsKey("id")) {
if (guild.getSelfMember().hasPermission(channel, Permission.MANAGE_WEBHOOKS)) {
this.createWebhook(channel, requests);
return;
}
this.handleQueue();
return;
} else {
this.webhook = new WebhookClient(webhookData.getLong("id"), webhookData.getString("token"), this.webhookExecutor, this.webhookClient);
}
}
this.webhook.send(message).whenComplete((result, exception) -> {
Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
if (cause instanceof HttpException && ((HttpException) cause).getCode() == 404) {
if (guild.getSelfMember().hasPermission(channel, Permission.MANAGE_WEBHOOKS)) {
this.createWebhook(channel, requests);
return;
}
this.disableLogger(channel.getIdLong());
return;
}
if (ExceptionUtility.sendErrorMessage(exception)) {
requests.forEach(failedRequest -> this.queue.addFirst(failedRequest.incrementAttempts()));
}
this.handleQueue();
});
} catch (Throwable exception) {
// Continue queue even if an exception occurs to avoid the queue getting stuck
ExceptionUtility.sendErrorMessage(exception);
this.handleQueue();
}
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class AntiRegexHandler method handle.
public void handle(Message message) {
if (!message.isFromGuild()) {
return;
}
Member member = message.getMember();
if (member == null) {
return;
}
User user = member.getUser();
if (user.isBot()) {
return;
}
Guild guild = message.getGuild();
Member selfMember = guild.getSelfMember();
GuildMessageChannel messageChannel = message.getGuildChannel();
long guildId = guild.getIdLong(), userId = member.getIdLong(), channelId = (messageChannel instanceof ThreadChannel ? ((ThreadChannel) messageChannel).getParentChannel() : messageChannel).getIdLong();
Category parent = messageChannel instanceof ICategorizableChannel ? ((ICategorizableChannel) messageChannel).getParentCategory() : null;
List<Role> roles = member.getRoles();
String content = message.getContentRaw();
List<Bson> guildPipeline = List.of(Aggregates.project(Projections.fields(Projections.computed("premium", Operators.lt(Operators.nowEpochSecond(), Operators.ifNull("$premium.endAt", 0L))), Projections.computed("guildId", "$_id"))), Aggregates.match(Filters.eq("guildId", guild.getIdLong())));
List<Bson> pipeline = List.of(Aggregates.match(Filters.and(Filters.eq("guildId", guild.getIdLong()), Filters.exists("enabled", false))), Aggregates.group(null, Accumulators.push("regexes", Operators.ROOT)), Aggregates.unionWith("guilds", guildPipeline), Aggregates.group(null, Accumulators.max("premium", "$premium"), Accumulators.max("regexes", "$regexes")), Aggregates.project(Projections.computed("regexes", Operators.let(new Document("regexes", Operators.ifNull("$regexes", Collections.EMPTY_LIST)), Operators.cond(Operators.ifNull("$premium", false), "$$regexes", Operators.concatArrays(Operators.filter("$$regexes", Operators.ne("$$this.type", RegexType.REGEX.getId())), Operators.slice(Operators.filter("$$regexes", Operators.eq("$$this.type", RegexType.REGEX.getId())), 0, 3)))))));
this.bot.getMongo().aggregateRegexes(pipeline).whenComplete((documents, exception) -> {
if (documents.isEmpty()) {
return;
}
Document data = documents.get(0);
this.executor.submit(() -> {
List<CompletableFuture<Document>> matches = new ArrayList<>();
Regexes: for (Document regex : data.getList("regexes", Document.class)) {
if (member.hasPermission(Permission.ADMINISTRATOR) && regex.getBoolean("admin", true)) {
continue;
}
List<Document> channels = regex.getList("whitelist", Document.class, Collections.emptyList());
Document channel = channels.stream().filter(d -> (d.getInteger("type") == WhitelistType.CHANNEL.getId() && d.getLong("id") == channelId) || (d.getInteger("type") == WhitelistType.CATEGORY.getId() && parent != null && d.getLong("id") == parent.getIdLong())).min(Comparator.comparingInt(d -> d.getInteger("type", 0))).orElse(MongoDatabase.EMPTY_DOCUMENT);
List<Document> holders = channel.getList("holders", Document.class, Collections.emptyList());
for (Document holder : holders) {
long holderId = holder.getLong("id");
int type = holder.getInteger("type");
if (type == HolderType.USER.getType() && userId == holderId) {
continue Regexes;
} else if (type == HolderType.ROLE.getType() && (guildId == holderId || roles.stream().anyMatch(role -> role.getIdLong() == holderId))) {
continue Regexes;
}
}
RegexType type = RegexType.fromId(regex.getInteger("type"));
Pattern pattern = type == RegexType.REGEX ? Pattern.compile(regex.getString("pattern")) : this.invitePattern;
Matcher matcher;
try {
matcher = this.executor.submit(() -> pattern.matcher(content)).get(2000, TimeUnit.MILLISECONDS);
} catch (TimeoutException | InterruptedException | ExecutionException e) {
continue;
}
Set<String> codes = new HashSet<>();
int matchCount = 0, totalCount = 0;
while (matcher.find()) {
List<Document> groups = channel.getList("groups", Document.class, Collections.emptyList());
for (Document group : groups) {
List<String> strings = group.getList("strings", String.class, Collections.emptyList());
String match = matcher.group(group.getInteger("group"));
if (match != null && strings.contains(match)) {
matchCount++;
}
}
if (type == RegexType.INVITE) {
codes.add(matcher.group(1));
}
totalCount++;
}
if (matchCount == totalCount) {
continue;
}
CompletableFuture<Document> future;
if (type == RegexType.INVITE) {
List<CompletableFuture<Invite>> futures = codes.stream().map(code -> Invite.resolve(message.getJDA(), code, true).submit()).collect(Collectors.toList());
List<Long> guilds = channel.getList("guilds", Long.class, Collections.emptyList());
future = FutureUtility.anyOf(futures, invite -> {
Invite.Guild inviteGuild = invite.getGuild();
return inviteGuild == null || (!guilds.contains(inviteGuild.getIdLong()) && inviteGuild.getIdLong() != guildId);
}).thenApply(invite -> invite == null ? null : regex);
} else {
future = CompletableFuture.completedFuture(regex);
}
matches.add(future);
}
FutureUtility.anyOf(matches, Objects::nonNull).thenAccept(regex -> {
if (regex == null) {
return;
}
ObjectId id = regex.getObjectId("_id");
RegexType type = RegexType.fromId(regex.getInteger("type"));
Document match = regex.get("match", MongoDatabase.EMPTY_DOCUMENT);
long matchAction = match.get("action", MatchAction.ALL);
Document mod = regex.get("mod", MongoDatabase.EMPTY_DOCUMENT);
Document actionData = mod.get("action", Document.class);
Action action = actionData == null ? null : Action.fromData(actionData);
Document attempts = regex.get("attempts", MongoDatabase.EMPTY_DOCUMENT);
int maxAttempts = attempts.get("amount", 3);
if ((matchAction & MatchAction.DELETE_MESSAGE.getRaw()) == MatchAction.DELETE_MESSAGE.getRaw() && selfMember.hasPermission(messageChannel, Permission.MESSAGE_MANAGE)) {
message.delete().queue();
}
Document reset = attempts.get("reset", Document.class);
List<Bson> update = List.of(Operators.set("attempts", Operators.let(new Document("attempts", Operators.ifNull("$attempts", 0)), Operators.cond(Operators.exists("$reset"), Operators.max(1, Operators.add(1, Operators.subtract("$$attempts", Operators.multiply(Operators.toInt(Operators.floor(Operators.divide(Operators.subtract(Operators.nowEpochSecond(), "$lastAttempt"), "$reset.after"))), "$reset.amount")))), Operators.add("$$attempts", 1)))), Operators.set("lastAttempt", Operators.nowEpochSecond()), Operators.setOnInsert("guildId", guildId), reset == null ? Operators.unset("reset") : Operators.set("reset", reset));
Bson filter = Filters.and(Filters.eq("userId", userId), Filters.eq("regexId", id));
FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().upsert(true).projection(Projections.include("attempts")).returnDocument(ReturnDocument.AFTER);
this.bot.getMongo().findAndUpdateRegexAttempt(filter, update, options).whenComplete((attemptsData, attemptsException) -> {
if (ExceptionUtility.sendErrorMessage(attemptsException)) {
return;
}
int currentAttempts = attemptsData.getInteger("attempts", 0);
String matchMessage = this.format(match.get("message", type.getDefaultMatchMessage()), user, messageChannel, id, currentAttempts, maxAttempts, action);
String modMessage = this.format(mod.get("message", type.getDefaultModMessage()), user, messageChannel, id, currentAttempts, maxAttempts, action);
boolean send = (matchAction & MatchAction.SEND_MESSAGE.getRaw()) == MatchAction.SEND_MESSAGE.getRaw() && selfMember.hasPermission(messageChannel, Permission.MESSAGE_SEND);
if (action != null && currentAttempts == maxAttempts) {
Reason reason = new Reason(String.format("Sent a message which matched regex `%s` %d time%s", id.toHexString(), maxAttempts, maxAttempts == 1 ? "" : "s"));
ModUtility.performAction(this.bot, action, member, selfMember, reason).thenCompose(result -> {
if (send) {
messageChannel.sendMessage(modMessage).allowedMentions(EnumSet.allOf(Message.MentionType.class)).queue();
}
return this.bot.getMongo().deleteRegexAttempt(Filters.and(Filters.eq("userId", userId), Filters.eq("regexId", id)));
}).whenComplete((result, modException) -> {
Throwable cause = modException instanceof CompletionException ? modException.getCause() : modException;
if (cause instanceof ModException) {
messageChannel.sendMessage(modException.getMessage() + " " + this.bot.getConfig().getFailureEmote()).queue();
return;
}
ExceptionUtility.sendExceptionally(messageChannel, modException);
});
return;
}
if (send) {
messageChannel.sendMessage(matchMessage).allowedMentions(EnumSet.allOf(Message.MentionType.class)).queue();
}
});
});
});
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class HelpUtility method getHelpMessage.
public static Message getHelpMessage(ICommand initialCommand, boolean embed) {
MessageBuilder builder = new MessageBuilder();
Sx4Command command = initialCommand instanceof DummyCommand ? (Sx4Command) ((DummyCommand) initialCommand).getActualCommand() : (Sx4Command) initialCommand;
String usage = command.getSubCommands().isEmpty() ? command.getUsage() : command.getUsage().trim().equals(command.getCommandTrigger()) ? command.getUsage() + " <sub command>" : command.getUsage() + " | <sub command>";
StringBuilder options = new StringBuilder();
for (int i = 0; i < command.getOptions().size(); i++) {
IOption<?> option = command.getOptions().get(i);
options.append("`").append(option.getName()).append(option.getType() != boolean.class ? "=<value>" : "").append("` - ").append(option.getDescription()).append(i == command.getOptions().size() - 1 ? "" : "\n");
}
if (embed) {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle(command.getCommandTrigger());
embedBuilder.addField("Description", command.getDescription(), false);
embedBuilder.addField("Usage", usage, false);
if (!command.getOptions().isEmpty()) {
embedBuilder.addField("Options", options.toString(), false);
}
if (command.getExamples().length != 0) {
embedBuilder.addField("Examples", "`" + String.join("`\n`", command.getExamples()) + "`", false);
}
if (!command.getAuthorDiscordPermissions().isEmpty()) {
embedBuilder.addField("Required Permissions", command.getAuthorDiscordPermissions().stream().map(Permission::getName).collect(Collectors.joining(", ")), false);
}
if (!command.getAliases().isEmpty()) {
embedBuilder.addField("Aliases", String.join(", ", command.getAliases()), false);
}
if (command.getRedirects().length != 0) {
embedBuilder.addField("Redirects", String.join(", ", command.getRedirects()), false);
}
if (!command.getSubCommands().isEmpty()) {
embedBuilder.addField("Sub Commands", command.getSubCommands().stream().map(ICommand::getCommand).collect(Collectors.joining(", ")), false);
}
if (command.isPremiumCommand()) {
embedBuilder.setFooter("Premium Command ⭐");
}
return builder.setEmbeds(embedBuilder.build()).build();
} else {
String placeHolder = "%s:\n%s\n\n";
Formatter formatter = new Formatter();
formatter.format(">>> **" + command.getCommandTrigger() + "**\n\n");
formatter.format(placeHolder, "Description", command.getDescription());
formatter.format(placeHolder, "Usage", usage);
if (!command.getOptions().isEmpty()) {
formatter.format(placeHolder, "Options", options);
}
if (command.getExamples().length != 0) {
formatter.format(placeHolder, "Examples", "`" + String.join("`\n`", command.getExamples()) + "`");
}
if (!command.getAuthorDiscordPermissions().isEmpty()) {
formatter.format(placeHolder, "Required Permissions", command.getAuthorDiscordPermissions().stream().map(Permission::getName).collect(Collectors.joining(", ")));
}
if (!command.getAliases().isEmpty()) {
formatter.format(placeHolder, "Aliases", String.join(", ", command.getAliases()));
}
if (command.getRedirects().length != 0) {
formatter.format(placeHolder, "Redirects", String.join(", ", command.getRedirects()));
}
if (!command.getSubCommands().isEmpty()) {
formatter.format(placeHolder, "Required Permissions", command.getSubCommands().stream().map(ICommand::getCommand).collect(Collectors.joining(", ")));
}
Message message = builder.setContent(formatter.toString()).build();
formatter.close();
return message;
}
}
Aggregations