use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class FreeGameManager method sendFreeGameNotifications.
public CompletableFuture<List<ReadonlyMessage>> sendFreeGameNotifications(List<? extends FreeGame<?>> games) {
if (games.isEmpty()) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
games.forEach(this::addAnnouncedGame);
List<Document> gameData = games.stream().map(FreeGame::toData).collect(Collectors.toList());
this.bot.getMongo().insertManyAnnouncedGames(gameData).whenComplete(MongoDatabase.exceptionally());
List<Bson> guildPipeline = List.of(Aggregates.match(Operators.expr(Operators.eq("$_id", "$$guildId"))), Aggregates.project(Projections.computed("premium", Operators.lt(Operators.nowEpochSecond(), Operators.ifNull("$premium.endAt", 0L)))));
List<Bson> pipeline = List.of(Aggregates.lookup("guilds", List.of(new Variable<>("guildId", "$guildId")), guildPipeline, "premium"), Aggregates.addFields(new Field<>("premium", Operators.cond(Operators.isEmpty("$premium"), false, Operators.get(Operators.arrayElemAt("$premium", 0), "premium")))));
return this.bot.getMongo().aggregateFreeGameChannels(pipeline).thenComposeAsync(documents -> {
List<WriteModel<Document>> bulkData = new ArrayList<>();
List<CompletableFuture<List<ReadonlyMessage>>> futures = new ArrayList<>();
for (Document data : documents) {
if (!data.getBoolean("enabled", true)) {
continue;
}
BaseGuildMessageChannel channel = this.bot.getShardManager().getChannelById(BaseGuildMessageChannel.class, data.getLong("channelId"));
if (channel == null) {
continue;
}
String avatar = channel.getJDA().getSelfUser().getEffectiveAvatarUrl();
boolean premium = data.getBoolean("premium");
Document webhookData = data.get("webhook", MongoDatabase.EMPTY_DOCUMENT);
long platforms = data.get("platforms", FreeGameType.ALL);
List<WebhookMessage> messages = new ArrayList<>();
for (FreeGame<?> game : games) {
long raw = game.getType().getRaw();
if ((platforms & raw) != raw) {
continue;
}
Formatter<Document> formatter = new JsonFormatter(data.get("message", FreeGameManager.DEFAULT_MESSAGE)).addVariable("game", game);
WebhookMessage message;
try {
message = MessageUtility.fromJson(formatter.parse()).setAvatarUrl(premium ? webhookData.get("avatar", avatar) : avatar).setUsername(premium ? webhookData.get("name", "Sx4 - Free Games") : "Sx4 - Free Games").build();
} catch (IllegalArgumentException e) {
bulkData.add(new UpdateOneModel<>(Filters.eq("_id", data.getObjectId("_id")), Updates.unset("message")));
continue;
}
messages.add(message);
}
if (messages.isEmpty()) {
continue;
}
WebhookMessage firstMessage = messages.get(0);
String firstContent = firstMessage.getContent();
if (messages.size() == 1 || !messages.stream().skip(1).allMatch(message -> message.getContent().equals(firstContent))) {
futures.add(this.sendFreeGameNotificationMessages(channel, webhookData, messages));
continue;
}
List<WebhookMessage> updatedMessages = new ArrayList<>();
WebhookMessageBuilder baseMessage = new WebhookMessageBuilder().setContent(firstContent).setAvatarUrl(firstMessage.getAvatarUrl()).setUsername(firstMessage.getUsername());
int length = 0;
List<WebhookEmbed> embeds = new ArrayList<>();
for (WebhookMessage message : messages) {
List<WebhookEmbed> nextEmbeds = message.getEmbeds();
int nextLength = MessageUtility.getWebhookEmbedLength(nextEmbeds);
if (embeds.size() + nextEmbeds.size() > WebhookMessage.MAX_EMBEDS || length + nextLength > MessageEmbed.EMBED_MAX_LENGTH_BOT) {
baseMessage.addEmbeds(embeds);
updatedMessages.add(baseMessage.build());
baseMessage.resetEmbeds();
embeds.clear();
embeds.addAll(nextEmbeds);
length = nextLength;
continue;
}
embeds.addAll(nextEmbeds);
length += nextLength;
}
baseMessage.addEmbeds(embeds);
updatedMessages.add(baseMessage.build());
futures.add(this.sendFreeGameNotificationMessages(channel, webhookData, updatedMessages));
}
if (!bulkData.isEmpty()) {
this.bot.getMongo().bulkWriteFreeGameChannels(bulkData).whenComplete(MongoDatabase.exceptionally());
}
return FutureUtility.allOf(futures).thenApply(list -> list.stream().flatMap(List::stream).collect(Collectors.toList()));
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class StarboardHandler method onMessageReactionAdd.
public void onMessageReactionAdd(MessageReactionAddEvent event) {
if (!event.isFromGuild()) {
return;
}
if (event.getUser().isBot()) {
return;
}
List<Bson> starboardPipeline = List.of(Aggregates.match(Filters.or(Filters.eq("originalMessageId", event.getMessageIdLong()), Filters.eq("messageId", event.getMessageIdLong()))), Aggregates.project(Projections.include("originalMessageId", "channelId")));
List<Bson> pipeline = List.of(Aggregates.match(Filters.eq("_id", event.getGuild().getIdLong())), Aggregates.project(Projections.fields(Projections.include("starboard"), Projections.computed("premium", Operators.lt(Operators.nowEpochSecond(), Operators.ifNull("$premium.endAt", 0L))))), Aggregates.unionWith("starboards", starboardPipeline), Aggregates.group(null, Accumulators.max("messageId", "$originalMessageId"), Accumulators.max("channelId", "$channelId"), Accumulators.max("starboard", "$starboard"), Accumulators.max("premium", "$premium")));
this.bot.getMongo().aggregateGuilds(pipeline).whenComplete((documents, aggregateException) -> {
if (ExceptionUtility.sendErrorMessage(aggregateException)) {
return;
}
if (documents.isEmpty()) {
return;
}
Document data = documents.get(0);
Document starboard = data.get("starboard", MongoDatabase.EMPTY_DOCUMENT);
if (!starboard.get("enabled", false)) {
return;
}
long channelId = starboard.get("channelId", 0L), messageChannelId = data.get("channelId", 0L);
GuildMessageChannel messageChannel = messageChannelId == 0L ? (GuildMessageChannel) event.getChannel() : event.getGuild().getChannelById(GuildMessageChannel.class, messageChannelId);
BaseGuildMessageChannel channel = channelId == 0L ? null : event.getGuild().getChannelById(BaseGuildMessageChannel.class, channelId);
if (channel == null || messageChannel == null) {
return;
}
ReactionEmote emote = event.getReactionEmote();
boolean emoji = emote.isEmoji();
Document emoteData = starboard.get("emote", new Document("name", "⭐"));
if ((emoji && !emote.getEmoji().equals(emoteData.getString("name"))) || (!emoji && (!emoteData.containsKey("id") || emoteData.getLong("id") != emote.getIdLong()))) {
return;
}
Long originalMessageId = data.getLong("messageId");
long messageId = originalMessageId == null ? event.getMessageIdLong() : originalMessageId;
messageChannel.retrieveMessageById(messageId).queue(message -> {
String image = message.getAttachments().stream().filter(Attachment::isImage).map(Attachment::getUrl).findFirst().orElse(null);
Document star = new Document("userId", event.getUser().getIdLong()).append("messageId", messageId).append("guildId", event.getGuild().getIdLong());
this.bot.getMongo().insertStar(star).thenCompose(result -> {
Bson update = Updates.combine(Updates.inc("count", 1), Updates.setOnInsert("originalMessageId", messageId), Updates.setOnInsert("guildId", event.getGuild().getIdLong()), Updates.setOnInsert("channelId", event.getChannel().getIdLong()), Updates.set("content", message.getContentRaw()), Updates.set("authorId", message.getAuthor().getIdLong()));
if (image != null) {
update = Updates.combine(update, Updates.set("image", image));
}
FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER).upsert(true);
return this.bot.getMongo().findAndUpdateStarboard(Filters.eq("originalMessageId", messageId), update, options);
}).thenCompose(updatedData -> {
WebhookMessage webhookMessage = this.getStarboardMessage(starboard, updatedData, event.getGuild(), event.getMember(), emote, data.getBoolean("premium"));
if (webhookMessage == null) {
return CompletableFuture.completedFuture(null);
}
if (updatedData.containsKey("messageId")) {
this.bot.getStarboardManager().editStarboard(updatedData.getLong("messageId"), channel.getIdLong(), starboard.get("webhook", MongoDatabase.EMPTY_DOCUMENT), webhookMessage);
// return null so no update is made in the next stage
return CompletableFuture.completedFuture(null);
} else {
return this.bot.getStarboardManager().sendStarboard(channel, starboard.get("webhook", MongoDatabase.EMPTY_DOCUMENT), webhookMessage);
}
}).whenComplete((createdMessage, exception) -> {
if (exception instanceof CompletionException) {
Throwable cause = exception.getCause();
if (cause instanceof MongoWriteException && ((MongoWriteException) cause).getError().getCategory() == ErrorCategory.DUPLICATE_KEY) {
// duplicate star just ignore
return;
}
}
if (ExceptionUtility.sendErrorMessage(exception)) {
return;
}
if (createdMessage != null) {
Route.CompiledRoute route = Route.Messages.ADD_REACTION.compile(Long.toString(createdMessage.getChannelId()), Long.toString(createdMessage.getId()), EncodingUtil.encodeReaction(emote.getAsReactionCode()), "@me");
new RestActionImpl<>(event.getJDA(), route).queue(null, ErrorResponseException.ignore(ErrorResponse.UNKNOWN_EMOJI, ErrorResponse.MISSING_PERMISSIONS, ErrorResponse.MISSING_ACCESS));
this.bot.getMongo().updateStarboard(Filters.eq("originalMessageId", messageId), Updates.set("messageId", createdMessage.getId())).whenComplete(MongoDatabase.exceptionally());
}
});
});
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class ModLogManager method sendModLog.
public CompletableFuture<ReadonlyMessage> sendModLog(BaseGuildMessageChannel channel, Document webhookData, WebhookEmbed embed, boolean premium) {
User selfUser = channel.getJDA().getSelfUser();
WebhookMessage message = new WebhookMessageBuilder().setAvatarUrl(premium ? webhookData.get("avatar", selfUser.getEffectiveAvatarUrl()) : selfUser.getEffectiveAvatarUrl()).setUsername(premium ? webhookData.get("name", "Sx4 - Mod Logs") : "Sx4 - Mod Logs").addEmbeds(embed).build();
WebhookClient webhook;
if (this.webhooks.containsKey(channel.getIdLong())) {
webhook = this.webhooks.get(channel.getIdLong());
} else if (!webhookData.containsKey("id")) {
return this.createWebhook(channel, message);
} else {
webhook = new WebhookClient(webhookData.getLong("id"), webhookData.getString("token"), this.executor, this.client);
this.webhooks.put(channel.getIdLong(), webhook);
}
return webhook.send(message).thenApply(webhookMessage -> new ReadonlyMessage(webhookMessage, webhook.getId(), webhook.getToken())).exceptionallyCompose(exception -> {
Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
if (cause instanceof HttpException && ((HttpException) cause).getCode() == 404) {
this.webhooks.remove(channel.getIdLong());
return this.createWebhook(channel, message);
}
return CompletableFuture.failedFuture(exception);
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class ProfileCommand method onCommand.
public void onCommand(Sx4CommandEvent event, @Argument(value = "user", endless = true, nullDefault = true) Member member) {
User user = member == null ? event.getAuthor() : member.getUser();
long expiry = event.getMongoMain().getUserById(Filters.eq("_id", user.getIdLong()), Projections.include("premium.endAt")).getEmbedded(List.of("premium", "endAt"), 0L);
List<Bson> gamePipeline = List.of(Aggregates.match(Filters.eq("userId", user.getIdLong())), Aggregates.group(null, Accumulators.sum("gamesPlayed", 1L), Accumulators.sum("gamesWon", Operators.cond(Operators.eq("$state", GameState.WIN.getId()), 1L, 0L))));
List<Bson> commandPipeline = List.of(Aggregates.match(Filters.eq("authorId", user.getIdLong())), Aggregates.count("commands"));
List<Bson> marriagePipeline = List.of(Aggregates.project(Projections.include("proposerId", "partnerId")), Aggregates.match(Filters.or(Filters.eq("proposerId", user.getIdLong()), Filters.eq("partnerId", user.getIdLong()))), Aggregates.group(null, Accumulators.push("marriages", Operators.ROOT)));
List<Bson> pipeline = List.of(Aggregates.project(Projections.fields(Projections.computed("balance", "$economy.balance"), Projections.include("profile"), Projections.computed("reputation", "$reputation.amount"), Projections.computed("premium", Operators.lt(Operators.nowEpochSecond(), Operators.ifNull("$premium.endAt", 0L))))), Aggregates.match(Filters.eq("_id", user.getIdLong())), Aggregates.unionWith("marriages", marriagePipeline), Aggregates.unionWith("commands", commandPipeline), Aggregates.unionWith("games", gamePipeline), Aggregates.group(null, Accumulators.max("balance", "$balance"), Accumulators.max("reputation", "$reputation"), Accumulators.max("marriages", "$marriages"), Accumulators.max("profile", "$profile"), Accumulators.max("gamesPlayed", "$gamesPlayed"), Accumulators.max("gamesWon", "$gamesWon"), Accumulators.max("commands", "$commands"), Accumulators.max("premium", Operators.ifNull("$premium", false))));
event.getMongo().aggregateUsers(pipeline).thenApply(documents -> {
Document data = documents.isEmpty() ? MongoDatabase.EMPTY_DOCUMENT : documents.get(0);
List<Document> marriages = data.getList("marriages", Document.class, Collections.emptyList());
List<String> partners = new ArrayList<>();
for (Document marriage : marriages) {
long partnerId = marriage.getLong("partnerId");
long otherId = partnerId == user.getIdLong() ? marriage.getLong("proposerId") : partnerId;
User other = event.getShardManager().getUserById(otherId);
if (other != null) {
partners.add(other.getName());
}
}
Document profileData = data.get("profile", MongoDatabase.EMPTY_DOCUMENT);
Document birthdayData = profileData.get("birthday", Document.class);
String birthday = null;
boolean isBirthday = false;
if (birthdayData != null) {
LocalDate date = LocalDate.now(ZoneOffset.UTC);
int day = birthdayData.getInteger("day"), month = birthdayData.getInteger("month");
isBirthday = date.getDayOfMonth() == day && date.getMonthValue() == month;
birthday = NumberUtility.getZeroPrefixedNumber(day) + "/" + NumberUtility.getZeroPrefixedNumber(month) + (birthdayData.containsKey("year") ? "/" + birthdayData.getInteger("year") : "");
}
return new ImageRequest(event.getConfig().getImageWebserverUrl("profile")).addField("birthday", birthday == null ? "Not set" : birthday).addField("is_birthday", isBirthday).addField("description", profileData.get("description", "Nothing to see here")).addField("height", profileData.get("height", 0)).addField("balance", NumberUtility.getNumberReadable(data.get("balance", 0L))).addField("reputation", data.get("reputation", 0)).addField("married_users", partners).addField("commands", data.get("commands", 0L)).addField("games_played", data.get("gamesPlayed", 0L)).addField("games_won", data.get("gamesWon", 0L)).addField("banner_id", profileData.getString("bannerId")).addField("directory", event.getConfig().isCanary() ? "sx4-canary" : "sx4-main").addField("name", user.getAsTag()).addField("gif", Clock.systemUTC().instant().getEpochSecond() < expiry).addField("avatar", user.getEffectiveAvatarUrl()).addField("colour", profileData.getInteger("colour")).build(event.getConfig().getImageWebserver());
}).whenComplete((request, exception) -> {
if (ExceptionUtility.sendExceptionally(event, exception)) {
return;
}
event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> ImageUtility.getImageMessage(event, response).queue());
});
}
use of com.sx4.bot.annotations.command.Premium in project Sx4 by sx4-discord-bot.
the class TwitchNotificationCommand method add.
@Command(value = "add", description = "Adds a twitch notification to a specific channel")
@CommandId(494)
@Command.Cooldown(5)
@AuthorPermissions(permissions = { Permission.MANAGE_SERVER })
@Examples({ "twitch notification add #channel esl_csgo", "twitch notification add pgl" })
public void add(Sx4CommandEvent event, @Argument(value = "channel", nullDefault = true) BaseGuildMessageChannel channel, @Argument(value = "streamer name", endless = true) @Lowercase String streamer) {
MessageChannel messageChannel = event.getChannel();
if (channel == null && !(messageChannel instanceof BaseGuildMessageChannel)) {
event.replyFailure("You cannot use this channel type").queue();
return;
}
BaseGuildMessageChannel effectiveChannel = channel == null ? (BaseGuildMessageChannel) messageChannel : channel;
Request request = new Request.Builder().url("https://api.twitch.tv/helix/users?login=" + URLEncoder.encode(streamer, StandardCharsets.UTF_8)).addHeader("Authorization", "Bearer " + event.getBot().getTwitchConfig().getToken()).addHeader("Client-Id", event.getConfig().getTwitchClientId()).build();
event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> {
if (response.code() == 400) {
event.replyFailure("I could not find that twitch streamer").queue();
response.close();
return;
}
Document json = Document.parse(response.body().string());
List<Document> entries = json.getList("data", Document.class);
if (entries.isEmpty()) {
event.replyFailure("I could not find that twitch streamer").queue();
return;
}
Document data = entries.get(0);
String id = data.getString("id"), name = data.getString("display_name");
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", event.getGuild().getIdLong())));
List<Bson> countPipeline = List.of(Aggregates.match(Filters.and(Filters.eq("streamerId", id), Filters.exists("enabled", false))), Aggregates.limit(1), Aggregates.group(null, Accumulators.sum("streamerCount", 1)));
List<Bson> pipeline = List.of(Aggregates.match(Filters.eq("guildId", event.getGuild().getIdLong())), Aggregates.group(null, Accumulators.push("notifications", Operators.ROOT)), Aggregates.unionWith("twitchNotifications", countPipeline), Aggregates.unionWith("guilds", guildPipeline), AggregateOperators.mergeFields("premium", "notifications", "streamerCount"), Aggregates.project(Projections.fields(Projections.computed("webhook", Operators.first(Operators.map(Operators.filter(Operators.ifNull("$notifications", Collections.EMPTY_LIST), Operators.and(Operators.exists("$$this.webhook"), Operators.eq("$$this.channelId", effectiveChannel.getIdLong()))), "$$this.webhook"))), Projections.computed("subscribe", Operators.eq(Operators.ifNull("$streamerCount", 0), 0)), Projections.computed("premium", Operators.ifNull("$premium", false)), Projections.computed("count", Operators.size(Operators.filter(Operators.ifNull("$notifications", Collections.EMPTY_LIST), Operators.extinct("$$this.enabled")))))));
AtomicBoolean subscribe = new AtomicBoolean();
event.getMongo().aggregateTwitchNotifications(pipeline).thenCompose(documents -> {
Document counter = documents.isEmpty() ? null : documents.get(0);
int count = counter == null ? 0 : counter.getInteger("count");
if (counter != null && count >= 3 && !counter.getBoolean("premium")) {
throw new IllegalArgumentException("You need to have Sx4 premium to have more than 3 enabled twitch notifications, you can get premium at <https://www.patreon.com/Sx4>");
}
if (count >= 10) {
throw new IllegalArgumentException("You can not have any more than 10 enabled twitch notifications");
}
subscribe.set(counter == null || counter.getBoolean("subscribe"));
Document notification = new Document("streamerId", id).append("channelId", effectiveChannel.getIdLong()).append("guildId", event.getGuild().getIdLong());
Document webhook = counter == null ? null : counter.get("webhook", Document.class);
if (webhook != null) {
notification.append("webhook", webhook);
}
return event.getMongo().insertTwitchNotification(notification);
}).whenComplete((result, exception) -> {
Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
if (cause instanceof MongoWriteException && ((MongoWriteException) cause).getError().getCategory() == ErrorCategory.DUPLICATE_KEY) {
event.replyFailure("You already have a notification setup for that twitch streamer in " + effectiveChannel.getAsMention()).queue();
return;
}
if (cause instanceof IllegalArgumentException) {
event.replyFailure(cause.getMessage()).queue();
return;
}
if (ExceptionUtility.sendExceptionally(event, exception)) {
return;
}
if (subscribe.get()) {
event.getBot().getTwitchManager().subscribe(id);
}
event.replyFormat("Notifications will now be sent in %s when **%s** goes live with id `%s` %s", effectiveChannel.getAsMention(), name, result.getInsertedId().asObjectId().getValue().toHexString(), event.getConfig().getSuccessEmote()).queue();
});
});
}
Aggregations