Search in sources :

Example 1 with Sx4

use of com.sx4.bot.core.Sx4 in project Sx4 by sx4-discord-bot.

the class SteamEndpoint method getSteam.

@GET
@Path("steam")
@Produces(MediaType.TEXT_HTML)
public void getSteam(@Context UriInfo info, @QueryParam("openid.identity") final String identity, @QueryParam("user_id") final long userId, @QueryParam("timestamp") long timestamp, @QueryParam("signature") String signature, @Suspended final AsyncResponse response) {
    Document failureCopy = this.failure.clone();
    long timestampNow = Instant.now().getEpochSecond();
    if (timestampNow - timestamp >= 300) {
        response.resume(Response.status(401).entity(this.setText(failureCopy, "Authorization link timed out")).build());
        return;
    }
    String hash;
    try {
        hash = HmacUtility.getSignatureHex(this.bot.getConfig().getSteam(), Long.toString(userId) + timestamp, HmacUtility.HMAC_MD5);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        response.resume(Response.status(500).entity(this.setText(failureCopy, "Something went wrong while authenticating your account")).build());
        return;
    }
    if (!hash.equals(signature)) {
        response.resume(Response.status(401).entity(this.setText(failureCopy, "Unauthorized")).build());
    }
    StringBuilder url = new StringBuilder("https://steamcommunity.com/openid/login");
    MultivaluedMap<String, String> parameters = info.getQueryParameters();
    boolean first = true;
    for (String key : parameters.keySet()) {
        if (first) {
            url.append("?");
            first = false;
        } else {
            url.append("&");
        }
        url.append(key).append("=").append(URLEncoder.encode(key.equals("openid.mode") ? "check_authentication" : parameters.get(key).get(0), StandardCharsets.UTF_8));
    }
    Request request = new Request.Builder().url(url.toString()).build();
    this.bot.getHttpClient().newCall(request).enqueue((HttpCallback) steamResponse -> {
        String body = steamResponse.body().string();
        String[] lines = body.split("\n");
        for (String line : lines) {
            String[] keyValue = line.split(":");
            if (keyValue[0].equals("is_valid") && !keyValue[1].equals("true")) {
                response.resume(Response.status(401).entity(this.setText(failureCopy, "Unauthorized")).build());
                return;
            }
        }
        long steamId = Long.parseLong(identity.substring(identity.lastIndexOf('/') + 1));
        Request steamRequest = new Request.Builder().url("https://steamcommunity.com/profiles/" + steamId + "?xml=1").build();
        this.bot.getHttpClient().newCall(steamRequest).enqueue((HttpCallback) profileResponse -> {
            JSONObject data = XML.toJSONObject(profileResponse.body().string());
            JSONObject profile = data.getJSONObject("profile");
            org.bson.Document connection = new org.bson.Document("id", steamId).append("name", profile.getString("steamID"));
            List<Bson> update = List.of(Operators.set("connections.steam", Operators.concatArrays(List.of(connection), Operators.filter(Operators.ifNull("$connections.steam", Collections.EMPTY_LIST), Operators.ne("$$this.id", steamId)))));
            this.bot.getMongo().updateUserById(userId, update).whenComplete((result, exception) -> {
                if (ExceptionUtility.sendErrorMessage(exception)) {
                    response.resume(Response.status(500).entity(this.setText(failureCopy, "Something went wrong while authenticating your account")).build());
                    return;
                }
                Document successCopy = this.success.clone();
                response.resume(Response.ok(this.setText(successCopy, "Connected your steam account to Sx4")).build());
            });
        });
    });
}
Also used : Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) Path(javax.ws.rs.Path) Bson(org.bson.conversions.Bson) JSONObject(org.json.JSONObject) QueryParam(javax.ws.rs.QueryParam) Sx4(com.sx4.bot.core.Sx4) XML(org.json.XML) Operators(com.sx4.bot.database.mongo.model.Operators) Request(okhttp3.Request) HmacUtility(com.sx4.bot.utility.HmacUtility) HttpCallback(com.sx4.bot.http.HttpCallback) AsyncResponse(javax.ws.rs.container.AsyncResponse) IOException(java.io.IOException) javax.ws.rs.core(javax.ws.rs.core) Instant(java.time.Instant) Suspended(javax.ws.rs.container.Suspended) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) URLEncoder(java.net.URLEncoder) List(java.util.List) Document(org.jsoup.nodes.Document) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) InvalidKeyException(java.security.InvalidKeyException) Jsoup(org.jsoup.Jsoup) Collections(java.util.Collections) Request(okhttp3.Request) HttpCallback(com.sx4.bot.http.HttpCallback) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Document(org.jsoup.nodes.Document) InvalidKeyException(java.security.InvalidKeyException) Bson(org.bson.conversions.Bson) JSONObject(org.json.JSONObject) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET)

Example 2 with Sx4

use of com.sx4.bot.core.Sx4 in project Sx4 by sx4-discord-bot.

the class LoggerCommand method toggle.

@Command(value = "toggle", aliases = { "enable", "disable" }, description = "Toggles the state of a logger")
@CommandId(56)
@AuthorPermissions(permissions = { Permission.MANAGE_SERVER })
@Examples({ "logger toggle #logs", "logger toggle" })
public void toggle(Sx4CommandEvent event, @Argument(value = "channel", endless = true, nullDefault = true) TextChannel channel) {
    TextChannel effectiveChannel = channel == null ? event.getTextChannel() : channel;
    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> pipeline = List.of(Aggregates.match(Filters.and(Filters.eq("guildId", event.getGuild().getIdLong()), Filters.exists("enabled", false))), Aggregates.project(Projections.include("channelId")), Aggregates.group(null, Accumulators.push("loggers", Operators.ROOT)), Aggregates.unionWith("guilds", guildPipeline), Aggregates.group(null, Accumulators.max("loggers", "$loggers"), Accumulators.max("premium", "$premium")), Aggregates.project(Projections.fields(Projections.computed("premium", Operators.ifNull("$premium", false)), Projections.computed("count", Operators.size(Operators.ifNull("$loggers", Collections.EMPTY_LIST))), Projections.computed("disabled", Operators.isEmpty(Operators.filter(Operators.ifNull("$loggers", Collections.EMPTY_LIST), Operators.eq("$$this.channelId", effectiveChannel.getIdLong())))))));
    event.getMongo().aggregateLoggers(pipeline).thenCompose(documents -> {
        Document data = documents.isEmpty() ? null : documents.get(0);
        boolean disabled = data == null || data.getBoolean("disabled");
        int count = data == null ? 0 : data.getInteger("count");
        if (data != null && disabled && count >= 3 && !data.getBoolean("premium")) {
            throw new IllegalArgumentException("You need to have Sx4 premium to have more than 3 enabled loggers, you can get premium at <https://www.patreon.com/Sx4>");
        }
        if (count >= 25) {
            throw new IllegalArgumentException("You can not have any more than 25 enabled loggers");
        }
        List<Bson> update = List.of(Operators.set("enabled", Operators.cond(Operators.exists("$enabled"), Operators.REMOVE, false)));
        FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER).projection(Projections.include("enabled"));
        return event.getMongo().findAndUpdateLogger(Filters.eq("channelId", effectiveChannel.getIdLong()), update, options);
    }).whenComplete((data, exception) -> {
        Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
        if (cause instanceof IllegalArgumentException) {
            event.replyFailure(cause.getMessage()).queue();
            return;
        }
        if (ExceptionUtility.sendExceptionally(event, exception)) {
            return;
        }
        if (data == null) {
            event.replyFailure("There is not a logger in that channel").queue();
            return;
        }
        event.replySuccess("The logger in " + effectiveChannel.getAsMention() + " is now **" + (data.get("enabled", true) ? "enabled" : "disabled") + "**").queue();
    });
}
Also used : Document(org.bson.Document) java.util(java.util) Command(com.jockie.bot.core.command.Command) MongoWriteException(com.mongodb.MongoWriteException) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) TextChannel(net.dv8tion.jda.api.entities.TextChannel) ErrorResponse(net.dv8tion.jda.api.requests.ErrorResponse) PagedResult(com.sx4.bot.paged.PagedResult) Bson(org.bson.conversions.Bson) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) com.mongodb.client.model(com.mongodb.client.model) com.sx4.bot.annotations.command(com.sx4.bot.annotations.command) LoggerCategory(com.sx4.bot.entities.management.LoggerCategory) Argument(com.jockie.bot.core.argument.Argument) LoggerEvent(com.sx4.bot.entities.management.LoggerEvent) Operators(com.sx4.bot.database.mongo.model.Operators) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) Sx4Command(com.sx4.bot.core.Sx4Command) CompletionException(java.util.concurrent.CompletionException) LoggerUtility(com.sx4.bot.utility.LoggerUtility) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) ModuleCategory(com.sx4.bot.category.ModuleCategory) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) ImageUrl(com.sx4.bot.annotations.argument.ImageUrl) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) ErrorCategory(com.mongodb.ErrorCategory) TextChannel(net.dv8tion.jda.api.entities.TextChannel) CompletionException(java.util.concurrent.CompletionException) Document(org.bson.Document) Bson(org.bson.conversions.Bson) Command(com.jockie.bot.core.command.Command) Sx4Command(com.sx4.bot.core.Sx4Command)

Example 3 with Sx4

use of com.sx4.bot.core.Sx4 in project Sx4 by sx4-discord-bot.

the class SteamCommand method connect.

@Command(value = "connect", description = "Connect your steam account with Sx4")
@CommandId(488)
@Examples({ "steam connect" })
public void connect(Sx4CommandEvent event) {
    String id = event.getAuthor().getId();
    long timestamp = Instant.now().getEpochSecond();
    String signature;
    try {
        signature = HmacUtility.getSignatureHex(event.getConfig().getSteam(), id + timestamp, HmacUtility.HMAC_MD5);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        event.replyFailure("Something went wrong there, try again").queue();
        return;
    }
    String redirectUrl = URLEncoder.encode(event.getConfig().getBaseUrl() + "/redirect/steam?user_id=" + id + "&timestamp=" + timestamp + "&signature=" + signature, StandardCharsets.UTF_8);
    MessageEmbed embed = new EmbedBuilder().setAuthor("Steam Authorization").setDescription("The link below will allow you to link your steam account on Sx4\n**:warning: Do not give this link to anyone :warning:**\n\n[Authorize](https://sx4.dev/connect/steam?redirect_url=" + redirectUrl + ")").setColor(event.getConfig().getOrange()).setFooter("The authorization link will expire in 5 minutes").build();
    event.getAuthor().openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embed)).flatMap($ -> event.replySuccess("I sent you a message containing your authorization link")).onErrorFlatMap($ -> event.replyFailure("I failed to send you your authorization link, make sure to have your dms open")).queue();
}
Also used : Document(org.bson.Document) java.util(java.util) Command(com.jockie.bot.core.command.Command) Permission(net.dv8tion.jda.api.Permission) Projections(com.mongodb.client.model.Projections) CommandId(com.sx4.bot.annotations.command.CommandId) Cooldown(com.jockie.bot.core.command.Command.Cooldown) PagedResult(com.sx4.bot.paged.PagedResult) EmbedType(net.dv8tion.jda.api.entities.EmbedType) JSONObject(org.json.JSONObject) Matcher(java.util.regex.Matcher) Role(net.dv8tion.jda.api.entities.Role) XML(org.json.XML) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Option(com.jockie.bot.core.option.Option) BotPermissions(com.sx4.bot.annotations.command.BotPermissions) Argument(com.jockie.bot.core.argument.Argument) Request(okhttp3.Request) HmacUtility(com.sx4.bot.utility.HmacUtility) HttpCallback(com.sx4.bot.http.HttpCallback) Sx4Command(com.sx4.bot.core.Sx4Command) NumberUtility(com.sx4.bot.utility.NumberUtility) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) ModuleCategory(com.sx4.bot.category.ModuleCategory) URLEncoder(java.net.URLEncoder) Examples(com.sx4.bot.annotations.command.Examples) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) LocalDate(java.time.LocalDate) DateTimeFormatter(java.time.format.DateTimeFormatter) InvalidKeyException(java.security.InvalidKeyException) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) Jsoup(org.jsoup.Jsoup) Pattern(java.util.regex.Pattern) StringUtility(com.sx4.bot.utility.StringUtility) JSONArray(org.json.JSONArray) SteamGameCache(com.sx4.bot.cache.SteamGameCache) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) Command(com.jockie.bot.core.command.Command) Sx4Command(com.sx4.bot.core.Sx4Command) CommandId(com.sx4.bot.annotations.command.CommandId) Examples(com.sx4.bot.annotations.command.Examples)

Example 4 with Sx4

use of com.sx4.bot.core.Sx4 in project Sx4 by sx4-discord-bot.

the class FreeGameManager method sendFreeGameNotifications.

public CompletableFuture<List<ReadonlyMessage>> sendFreeGameNotifications(List<? extends FreeGame<?>> games) {
    games.forEach(this::addAnnouncedGame);
    List<Document> gameData = games.stream().map(FreeGame::toData).collect(Collectors.toList());
    if (!gameData.isEmpty()) {
        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;
            }
            TextChannel channel = this.bot.getShardManager().getTextChannelById(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()) {
                futures.add(this.sendFreeGameNotificationMessages(channel, webhookData, messages));
            }
        }
        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 : Document(org.bson.Document) Bson(org.bson.conversions.Bson) WebhookMessage(club.minnced.discord.webhook.send.WebhookMessage) JsonFormatter(com.sx4.bot.formatter.JsonFormatter) TextChannel(net.dv8tion.jda.api.entities.TextChannel) ReadonlyMessage(com.sx4.bot.entities.webhook.ReadonlyMessage)

Example 5 with Sx4

use of com.sx4.bot.core.Sx4 in project Sx4 by sx4-discord-bot.

the class ModLogManager method sendModLog.

public CompletableFuture<ReadonlyMessage> sendModLog(TextChannel 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) 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) TextChannel(net.dv8tion.jda.api.entities.TextChannel) 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)

Aggregations

Document (org.bson.Document)23 Sx4Command (com.sx4.bot.core.Sx4Command)16 Command (com.jockie.bot.core.command.Command)15 Bson (org.bson.conversions.Bson)15 Permission (net.dv8tion.jda.api.Permission)13 com.mongodb.client.model (com.mongodb.client.model)11 MongoDatabase (com.sx4.bot.database.mongo.MongoDatabase)11 Operators (com.sx4.bot.database.mongo.model.Operators)11 CompletableFuture (java.util.concurrent.CompletableFuture)11 Sx4 (com.sx4.bot.core.Sx4)10 User (net.dv8tion.jda.api.entities.User)10 Argument (com.jockie.bot.core.argument.Argument)9 CommandId (com.sx4.bot.annotations.command.CommandId)9 ModuleCategory (com.sx4.bot.category.ModuleCategory)9 Sx4CommandEvent (com.sx4.bot.core.Sx4CommandEvent)9 ExceptionUtility (com.sx4.bot.utility.ExceptionUtility)9 List (java.util.List)9 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)9 Guild (net.dv8tion.jda.api.entities.Guild)9 Examples (com.sx4.bot.annotations.command.Examples)8