Search in sources :

Example 11 with Premium

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()));
    });
}
Also used : WebhookMessageBuilder(club.minnced.discord.webhook.send.WebhookMessageBuilder) Document(org.bson.Document) Bson(org.bson.conversions.Bson) WebhookEmbed(club.minnced.discord.webhook.send.WebhookEmbed) BaseGuildMessageChannel(net.dv8tion.jda.api.entities.BaseGuildMessageChannel) WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) JsonFormatter(com.sx4.bot.formatter.JsonFormatter) ReadonlyMessage(com.sx4.bot.entities.webhook.ReadonlyMessage)

Example 12 with Premium

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());
                }
            });
        });
    });
}
Also used : Document(org.bson.Document) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) ReactionEmote(net.dv8tion.jda.api.entities.MessageReaction.ReactionEmote) MessageReactionRemoveEvent(net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent) JsonFormatter(com.sx4.bot.formatter.JsonFormatter) MongoWriteException(com.mongodb.MongoWriteException) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) ErrorResponse(net.dv8tion.jda.api.requests.ErrorResponse) Bson(org.bson.conversions.Bson) Formatter(com.sx4.bot.formatter.Formatter) WebhookEmbedBuilder(club.minnced.discord.webhook.send.WebhookEmbedBuilder) Sx4(com.sx4.bot.core.Sx4) WebhookEmbed(club.minnced.discord.webhook.send.WebhookEmbed) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) com.mongodb.client.model(com.mongodb.client.model) EncodingUtil(net.dv8tion.jda.internal.utils.EncodingUtil) WebhookMessageBuilder(club.minnced.discord.webhook.send.WebhookMessageBuilder) Operators(com.sx4.bot.database.mongo.model.Operators) Attachment(net.dv8tion.jda.api.entities.Message.Attachment) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) MessageUtility(com.sx4.bot.utility.MessageUtility) StarboardManager(com.sx4.bot.managers.StarboardManager) CompletionException(java.util.concurrent.CompletionException) Route(net.dv8tion.jda.internal.requests.Route) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) RestActionImpl(net.dv8tion.jda.internal.requests.RestActionImpl) List(java.util.List) EventListener(net.dv8tion.jda.api.hooks.EventListener) WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) ObjectId(org.bson.types.ObjectId) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) NotNull(org.jetbrains.annotations.NotNull) Comparator(java.util.Comparator) StringUtility(com.sx4.bot.utility.StringUtility) ErrorCategory(com.mongodb.ErrorCategory) MongoWriteException(com.mongodb.MongoWriteException) Attachment(net.dv8tion.jda.api.entities.Message.Attachment) Document(org.bson.Document) ReactionEmote(net.dv8tion.jda.api.entities.MessageReaction.ReactionEmote) Bson(org.bson.conversions.Bson) WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) CompletionException(java.util.concurrent.CompletionException) Route(net.dv8tion.jda.internal.requests.Route)

Example 13 with Premium

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);
    });
}
Also used : WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) WebhookMessageBuilder(club.minnced.discord.webhook.send.WebhookMessageBuilder) Document(org.bson.Document) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) BaseGuildMessageChannel(net.dv8tion.jda.api.entities.BaseGuildMessageChannel) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) Updates(com.mongodb.client.model.Updates) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) Executors(java.util.concurrent.Executors) User(net.dv8tion.jda.api.entities.User) HttpException(club.minnced.discord.webhook.exception.HttpException) WebhookClient(com.sx4.bot.entities.webhook.WebhookClient) Bson(org.bson.conversions.Bson) Guild(net.dv8tion.jda.api.entities.Guild) OkHttpClient(okhttp3.OkHttpClient) Sx4(com.sx4.bot.core.Sx4) WebhookEmbed(club.minnced.discord.webhook.send.WebhookEmbed) Map(java.util.Map) WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ReadonlyMessage(com.sx4.bot.entities.webhook.ReadonlyMessage) User(net.dv8tion.jda.api.entities.User) WebhookClient(com.sx4.bot.entities.webhook.WebhookClient) WebhookMessageBuilder(club.minnced.discord.webhook.send.WebhookMessageBuilder) CompletionException(java.util.concurrent.CompletionException) HttpException(club.minnced.discord.webhook.exception.HttpException) ReadonlyMessage(com.sx4.bot.entities.webhook.ReadonlyMessage)

Example 14 with Premium

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());
    });
}
Also used : Document(org.bson.Document) java.util(java.util) Command(com.jockie.bot.core.command.Command) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) Cooldown(com.jockie.bot.core.command.Command.Cooldown) CommandId(com.sx4.bot.annotations.command.CommandId) Member(net.dv8tion.jda.api.entities.Member) Async(com.jockie.bot.core.command.Command.Async) User(net.dv8tion.jda.api.entities.User) Bson(org.bson.conversions.Bson) Alternative(com.sx4.bot.entities.argument.Alternative) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) com.sx4.bot.utility(com.sx4.bot.utility) com.mongodb.client.model(com.mongodb.client.model) ZoneOffset(java.time.ZoneOffset) GameState(com.sx4.bot.entities.games.GameState) Argument(com.jockie.bot.core.argument.Argument) Operators(com.sx4.bot.database.mongo.model.Operators) Request(okhttp3.Request) ImageRequest(com.sx4.bot.entities.image.ImageRequest) HttpCallback(com.sx4.bot.http.HttpCallback) TextStyle(java.time.format.TextStyle) Sx4Command(com.sx4.bot.core.Sx4Command) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) File(java.io.File) com.sx4.bot.annotations.argument(com.sx4.bot.annotations.argument) ModuleCategory(com.sx4.bot.category.ModuleCategory) Examples(com.sx4.bot.annotations.command.Examples) LocalDate(java.time.LocalDate) Clock(java.time.Clock) ICooldown(com.jockie.bot.core.cooldown.ICooldown) User(net.dv8tion.jda.api.entities.User) ImageRequest(com.sx4.bot.entities.image.ImageRequest) Document(org.bson.Document) LocalDate(java.time.LocalDate) Bson(org.bson.conversions.Bson)

Example 15 with Premium

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();
        });
    });
}
Also used : Document(org.bson.Document) TwitchStream(com.sx4.bot.entities.twitch.TwitchStream) FormatterVariable(com.sx4.bot.formatter.function.FormatterVariable) MongoWriteException(com.mongodb.MongoWriteException) Permission(net.dv8tion.jda.api.Permission) TwitchManager(com.sx4.bot.managers.TwitchManager) TwitchStreamType(com.sx4.bot.entities.twitch.TwitchStreamType) PagedResult(com.sx4.bot.paged.PagedResult) AggregateOperators(com.sx4.bot.database.mongo.model.AggregateOperators) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BotPermissions(com.sx4.bot.annotations.command.BotPermissions) AuthorPermissions(com.sx4.bot.annotations.command.AuthorPermissions) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) Request(okhttp3.Request) HttpCallback(com.sx4.bot.http.HttpCallback) Sx4Command(com.sx4.bot.core.Sx4Command) CompletionException(java.util.concurrent.CompletionException) FormatterManager(com.sx4.bot.formatter.FormatterManager) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) Examples(com.sx4.bot.annotations.command.Examples) OffsetDateTime(java.time.OffsetDateTime) TwitchStreamer(com.sx4.bot.entities.twitch.TwitchStreamer) MessageChannel(net.dv8tion.jda.api.entities.MessageChannel) java.util(java.util) Command(com.jockie.bot.core.command.Command) JsonFormatter(com.sx4.bot.formatter.JsonFormatter) CommandId(com.sx4.bot.annotations.command.CommandId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) ErrorResponse(net.dv8tion.jda.api.requests.ErrorResponse) AtomicReference(java.util.concurrent.atomic.AtomicReference) Bson(org.bson.conversions.Bson) AdvancedMessage(com.sx4.bot.annotations.argument.AdvancedMessage) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) com.mongodb.client.model(com.mongodb.client.model) FutureUtility(com.sx4.bot.utility.FutureUtility) Argument(com.jockie.bot.core.argument.Argument) Lowercase(com.sx4.bot.annotations.argument.Lowercase) Operators(com.sx4.bot.database.mongo.model.Operators) BaseGuildMessageChannel(net.dv8tion.jda.api.entities.BaseGuildMessageChannel) MessageUtility(com.sx4.bot.utility.MessageUtility) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) ModuleCategory(com.sx4.bot.category.ModuleCategory) URLEncoder(java.net.URLEncoder) ImageUrl(com.sx4.bot.annotations.argument.ImageUrl) ObjectId(org.bson.types.ObjectId) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) ErrorCategory(com.mongodb.ErrorCategory) MongoWriteException(com.mongodb.MongoWriteException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Request(okhttp3.Request) Document(org.bson.Document) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MessageChannel(net.dv8tion.jda.api.entities.MessageChannel) BaseGuildMessageChannel(net.dv8tion.jda.api.entities.BaseGuildMessageChannel) CompletionException(java.util.concurrent.CompletionException) BaseGuildMessageChannel(net.dv8tion.jda.api.entities.BaseGuildMessageChannel) AuthorPermissions(com.sx4.bot.annotations.command.AuthorPermissions) Sx4Command(com.sx4.bot.core.Sx4Command) Command(com.jockie.bot.core.command.Command) CommandId(com.sx4.bot.annotations.command.CommandId) Examples(com.sx4.bot.annotations.command.Examples)

Aggregations

Document (org.bson.Document)26 Sx4Command (com.sx4.bot.core.Sx4Command)23 Command (com.jockie.bot.core.command.Command)22 Bson (org.bson.conversions.Bson)22 MongoDatabase (com.sx4.bot.database.mongo.MongoDatabase)17 CompletableFuture (java.util.concurrent.CompletableFuture)17 CompletionException (java.util.concurrent.CompletionException)17 com.mongodb.client.model (com.mongodb.client.model)16 Operators (com.sx4.bot.database.mongo.model.Operators)16 ExceptionUtility (com.sx4.bot.utility.ExceptionUtility)16 Permission (net.dv8tion.jda.api.Permission)16 ErrorCategory (com.mongodb.ErrorCategory)13 MongoWriteException (com.mongodb.MongoWriteException)13 WebhookEmbed (club.minnced.discord.webhook.send.WebhookEmbed)12 WebhookMessage (club.minnced.discord.webhook.send.WebhookMessage)12 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)12 BaseGuildMessageChannel (net.dv8tion.jda.api.entities.BaseGuildMessageChannel)12 WebhookMessageBuilder (club.minnced.discord.webhook.send.WebhookMessageBuilder)11 Sx4 (com.sx4.bot.core.Sx4)11 ErrorResponseException (net.dv8tion.jda.api.exceptions.ErrorResponseException)11