use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.
the class WelcomeUtils method sendJoinLeaveMessage.
public static void sendJoinLeaveMessage(User user, Guild guild, TextChannel tc, List<String> extraMessages, String msg, boolean test) {
var message = msg;
if (!extraMessages.isEmpty()) {
if (msg != null) {
extraMessages.add(msg);
}
message = extraMessages.get(RANDOM.nextInt(extraMessages.size()));
;
}
if (tc != null && message != null) {
if (!tc.canTalk()) {
return;
}
if (message.contains("$(")) {
message = new DynamicModifiers().mapFromJoinLeave("event", tc, user, guild).resolve(message);
}
var modIndex = message.indexOf(':');
if (modIndex != -1) {
// Wonky?
var matcher = MODIFIER_PATTERN.matcher(message);
var modifier = "none";
// Find the first occurrence of a modifier (word:)
if (matcher.find()) {
modifier = matcher.group().replace(":", "");
}
var json = message.substring(modIndex + 1);
var extra = "";
// Somehow (?) this fails sometimes? I really dunno how, but sure.
try {
extra = message.substring(0, modIndex - modifier.length()).trim();
} catch (Exception ignored) {
}
try {
if (modifier.equals("embed")) {
EmbedJSON embed;
try {
embed = JsonDataManager.fromJson('{' + json + '}', EmbedJSON.class);
} catch (Exception e) {
tc.sendMessage(EmoteReference.ERROR2 + "The string\n```json\n{" + json + "}```\n" + "Is not a valid welcome/leave message (failed to Convert to EmbedJSON). Check the wiki for more information.").queue();
// So I know what is going on, regardless.
e.printStackTrace();
return;
}
var builder = new MessageBuilder().setEmbeds(embed.gen(null));
if (!extra.isEmpty()) {
builder.append(extra);
}
if (test) {
builder.append("\n**This is a test message. No mentions will be shown or resolved.**");
}
tc.sendMessage(builder.build()).allowedMentions(test ? EnumSet.noneOf(Message.MentionType.class) : EnumSet.of(Message.MentionType.USER, Message.MentionType.ROLE)).queue(success -> {
}, error -> tc.sendMessage("Failed to send join/leave message.").queue());
return;
}
} catch (Exception e) {
if (e.getMessage().toLowerCase().contains("url must be a valid")) {
tc.sendMessage("Failed to send join/leave message: Wrong image URL in thumbnail, image, footer and/or author.").queue();
} else {
tc.sendMessage("Failed to send join/leave message: Unknown error, try checking your message.").queue();
e.printStackTrace();
}
}
}
if (test) {
message += "\n**This is a test message. No mentions will be shown or resolved.**";
}
tc.sendMessage(message).allowedMentions(test ? EnumSet.noneOf(Message.MentionType.class) : EnumSet.of(Message.MentionType.USER, Message.MentionType.ROLE)).queue(success -> {
}, failure -> tc.sendMessage("Failed to send join/leave message.").queue());
}
}
use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.
the class BirthdayTask method handle.
public static void handle(int shardId) {
final var bot = MantaroBot.getInstance();
final var instant = Instant.now();
try {
final var cache = bot.getBirthdayCacher();
// There's no cache to be seen here
if (cache == null) {
return;
}
// We haven't finished caching all members, somehow?
if (!cache.isDone) {
return;
}
final var start = System.currentTimeMillis();
var membersAssigned = 0;
var membersDivested = 0;
final var jda = bot.getShardManager().getShardById(shardId);
if (jda == null) {
// To be fair, this shouldn't be possible as it only starts it with the shards it knows...
return;
}
log.info("Checking birthdays in shard {} to assign roles...", jda.getShardInfo().getShardId());
// Well, fuck, this was a day off. NYC time was 23:00 when Chicago time was at 00:00, so it checked the
// birthdays for THE WRONG DAY. Heck.
// 17-02-2022: Fuck again, I was using the wrong thing. Now it works, lol.
final var timezone = ZonedDateTime.ofInstant(instant, ZoneId.of("America/Chicago"));
// Example: 25-02
final var now = timezone.format(dayMonthFormat);
// Example: 02
final var month = timezone.format(monthFormat);
// Example: 01
final var lastMonthTz = ZonedDateTime.ofInstant(instant, ZoneId.of("America/Chicago")).minusMonths(1);
final var lastMonth = lastMonthTz.format(dateFormat);
final var cached = cache.getCachedBirthdays();
final var guilds = jda.getGuildCache();
// Backoff sending: we need to backoff the birthday requests,
// else we're gonna find ourselves quite often hitting ratelimits, which might slow the whole
// bot down. Therefore, we're just gonna get all of the messages we need to send and *slowly*
// send them over the course of a few minutes, instead of trying to send them all at once.
Map<BirthdayGuildInfo, Queue<Message>> toSend = new HashMap<>();
List<BirthdayRoleInfo> roleBackoffAdd = new ArrayList<>();
List<BirthdayRoleInfo> roleBackoffRemove = new ArrayList<>();
// For all current -cached- guilds.
for (final var guild : guilds) {
// This is quite a db spam, lol
final var dbGuild = MantaroData.db().getGuild(guild);
final var guildData = dbGuild.getData();
// If we have a birthday guild and channel here, continue
if (guildData.getBirthdayChannel() != null && guildData.getBirthdayRole() != null) {
final var birthdayRole = guild.getRoleById(guildData.getBirthdayRole());
final var channel = guild.getTextChannelById(guildData.getBirthdayChannel());
if (channel != null && birthdayRole != null) {
if (!guild.getSelfMember().canInteract(birthdayRole))
// Go to next guild...
continue;
if (!channel.canTalk())
// cannot talk here...
continue;
if (guildData.getGuildAutoRole() != null && birthdayRole.getId().equals(guildData.getGuildAutoRole()))
// Birthday role is autorole role
continue;
if (birthdayRole.isPublicRole())
// Birthday role is public role
continue;
if (birthdayRole.isManaged())
// This was meant to be a bot role?
continue;
// Guild map is now created from allowed birthdays. This is a little hacky, but we don't really care.
// The other solution would have been just disabling this completely, which would have been worse.
// @formatter:off
Map<Long, BirthdayCacher.BirthdayData> guildMap = cached.entrySet().stream().filter(map -> guildData.getAllowedBirthdays().contains(String.valueOf(map.getKey()))).filter(map -> map.getValue().getBirthday().substring(3, 5).equals(month) || map.getValue().getBirthday().substring(3, 5).equals(lastMonth)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// @formatter:on
var birthdayAnnouncerText = new MessageBuilder();
birthdayAnnouncerText.append("**New birthdays for today, wish them Happy Birthday!**").append("\n\n");
int birthdayNumber = 0;
List<Long> nullMembers = new ArrayList<>();
for (var data : guildMap.entrySet()) {
var birthday = data.getValue().getBirthday();
if (guildData.getBirthdayBlockedIds().contains(String.valueOf(data.getKey()))) {
continue;
}
if (birthday == null) {
log.debug("Birthday is null? Continuing...");
nullMembers.add(data.getKey());
continue;
}
// This needs to be a retrieveMemberById call, sadly. This will get cached, though.
Member member;
try {
// This is expensive!
member = guild.retrieveMemberById(data.getKey(), false).complete();
} catch (Exception ex) {
nullMembers.add(data.getKey());
continue;
}
// Make sure we announce on March 1st for birthdays on February 29 if the current
// year is not a leap year.
var compare = birthday.substring(0, 5);
if (compare.equals("29-02") && !Year.isLeap(LocalDate.now().getYear())) {
compare = "28-02";
}
if (compare.equals(now)) {
log.debug("Assigning birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
var tempBirthdayMessage = String.format(EmoteReference.POPPER + "**%s is a year older now! Wish them a happy birthday.** :tada:", member.getEffectiveName());
if (guildData.getBirthdayMessage() != null) {
tempBirthdayMessage = guildData.getBirthdayMessage().replace("$(user)", member.getEffectiveName()).replace("$(usermention)", member.getAsMention()).replace("$(tag)", member.getUser().getAsTag());
}
// Variable used in lambda expression should be final or effectively final...
final var birthdayMessage = tempBirthdayMessage;
if (!member.getRoles().contains(birthdayRole)) {
log.debug("Backing off adding birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
// We can pretty much do all of this only based on the IDs
roleBackoffAdd.add(new BirthdayRoleInfo(guild.getId(), member.getId(), birthdayRole));
birthdayAnnouncerText.append(birthdayMessage).append("\n");
membersAssigned++;
birthdayNumber++;
Metrics.BIRTHDAY_COUNTER.inc();
}
} else {
// day passed
if (member.getRoles().contains(birthdayRole)) {
log.debug("Backing off removing birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
roleBackoffRemove.add(new BirthdayRoleInfo(guild.getId(), member.getId(), birthdayRole));
membersDivested++;
}
}
}
if (birthdayNumber != 0) {
toSend.put(new BirthdayGuildInfo(guild.getId(), channel.getId()), birthdayAnnouncerText.buildAll(MessageBuilder.SplitPolicy.NEWLINE));
}
// If any of the member lookups to discord returned null, remove them.
if (!nullMembers.isEmpty()) {
guildData.getAllowedBirthdays().removeAll(nullMembers.stream().map(String::valueOf).collect(Collectors.toList()));
dbGuild.save();
}
}
}
}
final var end = System.currentTimeMillis();
log.info("{} (birthdays): people assigned: {}, people divested: {}, took {}ms", jda.getShardInfo(), membersAssigned, membersDivested, (end - start));
// A poll inside a pool?
// Send the backoff sending comment above, this basically avoids hitting
// discord with one billion requests at once.
final var backoff = 400;
final var roleBackoff = 100;
backOffPool.submit(() -> {
log.info("{} (birthdays): Backoff messages: {}. Sending them with {}ms backoff.", jda.getShardInfo(), toSend.size(), backoff);
final var startMessage = System.currentTimeMillis();
for (var entry : toSend.entrySet()) {
try {
final var info = entry.getKey();
final var guildId = info.guildId;
final var channelId = info.channelId;
final var messages = entry.getValue();
final var guild = bot.getShardManager().getGuildById(guildId);
if (guild == null)
continue;
final var channel = guild.getTextChannelById(channelId);
if (channel == null)
continue;
messages.forEach(message -> channel.sendMessage(message).allowedMentions(EnumSet.of(Message.MentionType.USER, Message.MentionType.CHANNEL, Message.MentionType.ROLE, Message.MentionType.EMOTE)).queue());
// If 100 guilds (about 1/10th of all the shard guilds! so very unlikely) do
// get a birthday now, the maximum delay will be 40,000ms, which is 40 seconds.
// Not much of an issue for the end user, but avoid sending too many requests
// to discord at once. If half of all the guilds in the shard do, the delay
// will be about 200,000ms, so 2 minutes.
Thread.sleep(backoff);
} catch (Exception e) {
e.printStackTrace();
}
}
final var endMessage = System.currentTimeMillis();
toSend.clear();
log.info("Sent all birthday backoff messages, backoff was {}ms, took {}ms", backoff, endMessage - startMessage);
});
backOffRolePool.submit(() -> {
log.info("{} (birthdays): Backoff roles (add): {}. Sending them with {}ms backoff.", jda.getShardInfo(), roleBackoffAdd.size(), roleBackoff);
final var startRole = System.currentTimeMillis();
for (var roleInfo : roleBackoffAdd) {
try {
var guild = bot.getShardManager().getGuildById(roleInfo.guildId);
if (guild == null)
continue;
guild.addRoleToMember(roleInfo.memberId, roleInfo.role).reason(modLogMessage).queue();
Thread.sleep(roleBackoff);
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("{} (birthdays): Backoff roles (remove): {}. Sending them with {}ms backoff.", jda.getShardInfo(), roleBackoffRemove.size(), roleBackoff);
for (var roleInfo : roleBackoffRemove) {
try {
var guild = bot.getShardManager().getGuildById(roleInfo.guildId);
if (guild == null)
continue;
guild.removeRoleFromMember(roleInfo.memberId, roleInfo.role).reason(modLogMessage).queue();
Thread.sleep(roleBackoff);
} catch (Exception e) {
e.printStackTrace();
}
}
final var endRole = System.currentTimeMillis();
roleBackoffAdd.clear();
roleBackoffRemove.clear();
log.info("{} (birthdays): All roles done (add and removal), backoff was {}ms. Took {}ms", jda.getShardInfo(), roleBackoff, endRole - startRole);
});
} catch (Exception e) {
e.printStackTrace();
}
}
use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.
the class ImageActionCmd method call.
@Override
protected void call(Context ctx, String content) {
if (!RatelimitUtils.ratelimit(rateLimiter, ctx, null)) {
return;
}
var languageContext = ctx.getGuildLanguageContext();
var random = "";
try {
if (type != null) {
var result = weebapi.getRandomImageByType(type, false, "gif");
var image = result.getKey();
if (image == null) {
ctx.sendLocalized("commands.action.error_retrieving", EmoteReference.SAD);
return;
}
images = Collections.singletonList(image);
// Guaranteed random selection :^).
random = images.get(0);
} else {
if (images.isEmpty()) {
ctx.sendLocalized("commands.action.no_type", EmoteReference.ERROR);
return;
}
random = images.get(rand.nextInt(images.size()));
}
} catch (Exception e) {
ctx.sendLocalized("commands.action.error_retrieving", EmoteReference.ERROR);
return;
}
try {
var mentionedMembers = ctx.getMentionedMembers();
if (mentionedMembers.isEmpty()) {
ctx.sendLocalized("commands.action.no_mention", EmoteReference.ERROR);
return;
}
boolean filtered = false;
if (mentionedMembers.size() == 1) {
final var dbUser = ctx.getDBUser(mentionedMembers.get(0).getId());
if (dbUser.getData().isActionsDisabled()) {
ctx.sendLocalized("commands.action.actions_disabled", EmoteReference.ERROR);
return;
}
} else {
var filter = mentionedMembers.stream().filter(member -> ctx.getDBUser(member).getData().isActionsDisabled()).collect(Collectors.toList());
// Needs to be mutable.
mentionedMembers = new ArrayList<>(mentionedMembers);
if (mentionedMembers.removeAll(filter)) {
filtered = true;
}
if (mentionedMembers.isEmpty()) {
ctx.sendLocalized("commands.action.no_mention_disabled", EmoteReference.ERROR);
return;
}
}
var toSend = new MessageBuilder().append(emoji).append(String.format(languageContext.get(format), "**%s**".formatted(noMentions(mentionedMembers)), "**%s**".formatted(ctx.getMember().getEffectiveName())));
if (swapNames) {
toSend = new MessageBuilder().append(emoji).append(String.format(languageContext.get(format), "**%s**".formatted(ctx.getMember().getEffectiveName()), "**%s**".formatted(noMentions(mentionedMembers))));
}
if (isLonely(ctx)) {
toSend = new MessageBuilder().append("**").append(languageContext.get(lonelyLine)).append("**");
}
if (isMentioningBot(ctx)) {
toSend = new MessageBuilder().append("**").append(languageContext.get(botLine)).append("**");
}
if (filtered) {
toSend.append("\n").append(String.format(languageContext.get("commands.action.filtered"), EmoteReference.WARNING));
}
var member = ctx.getMember();
toSend.setEmbeds(new EmbedBuilder().setColor(ctx.getMemberColor()).setImage(random).build());
ctx.getChannel().sendMessage(toSend.build()).queue();
} catch (Exception e) {
e.printStackTrace();
ctx.sendLocalized("commands.action.permission_or_unexpected_error", EmoteReference.ERROR);
}
}
use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.
the class ImageGame method sendEmbedImage.
protected RestAction<Message> sendEmbedImage(MessageChannel channel, String url, Consumer<EmbedBuilder> embedConfigurator) {
var eb = new EmbedBuilder();
embedConfigurator.accept(eb);
eb.setImage("attachment://image.png").setColor(Color.PINK);
var message = new MessageBuilder().setEmbeds(eb.build());
return channel.sendMessage(message.build()).addFile(cache.getInput(url), "image.png");
}
use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.
the class CustomCommandHandler method handle.
public void handle(boolean preview) {
if (!processResponse())
return;
if (specialHandling())
return;
if (response.startsWith("v3:")) {
CCv3.process(prefixUsed, ctx, new Parser(response.substring(3)).parse(), preview);
return;
}
MessageBuilder builder = new MessageBuilder().setContent(filtered.matcher(response).replaceAll("-filtered regex-"));
builder.setActionRows(ActionRow.of(Button.primary("yes", ctx.getLanguageContext().get("commands.custom.custom_notice")).asDisabled()));
if (preview) {
builder.append("\n\n").append(EmoteReference.WARNING).append("**This is a preview of how a CC with this content would look like, ALL MENTIONS ARE DISABLED ON THIS MODE.**\n").append("`Command preview requested by: ").append(ctx.getAuthor().getAsTag()).append("`");
builder.denyMentions(Message.MentionType.ROLE, Message.MentionType.USER, Message.MentionType.EVERYONE, Message.MentionType.HERE);
} else {
builder.denyMentions(Message.MentionType.ROLE, Message.MentionType.EVERYONE, Message.MentionType.HERE);
}
ctx.send(builder.build());
}
Aggregations