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());
});
});
});
}
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();
});
}
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 + "×tamp=" + 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();
}
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()));
});
}
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);
});
}
Aggregations