use of com.jockie.bot.core.option.Option in project Sx4 by sx4-discord-bot.
the class YouTubeCommand method onCommand.
public void onCommand(Sx4CommandEvent event, @Argument(value = "query", endless = true) String query, @Option(value = "channel", description = "Only return a channel") boolean channel, @Option(value = "playlist", description = "Only return a playlist") boolean playlist, @Option(value = "video", description = "Only return a video") boolean video) {
String type = channel ? "channel" : video ? "video" : playlist ? "playlist" : null;
Request request = new Request.Builder().url(String.format("https://www.googleapis.com/youtube/v3/search?key=%s&part=snippet&maxResults=50&safeSearch=none&q=%s%s", event.getConfig().getYouTube(), URLEncoder.encode(query, StandardCharsets.UTF_8), type == null ? "" : "&type=" + type)).build();
event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> {
Document json = Document.parse(response.body().string());
List<Document> items = json.getList("items", Document.class);
if (items.isEmpty()) {
event.replyFailure("I could not find any results").queue();
return;
}
PagedResult<Document> paged = new PagedResult<>(event.getBot(), items).setAuthor("YouTube Results", null, "https://media-thumbs.golden.com/4hBhjfnhOC6J3uJZglZG0quRsPU=/200x200/smart/golden-media.s3.amazonaws.com%2Ftopic_images%2F6c3fdb0966b049eba2b9c2331da224f0.png").setAutoSelect(true).setDisplayFunction(data -> {
Document id = data.get("id", Document.class);
String kind = id.getString("kind");
return "[" + data.getEmbedded(List.of("snippet", "title"), String.class) + "](" + this.getUrlFromId(id) + ")" + " (" + StringUtility.title(kind.substring(kind.indexOf('#') + 1)) + ")";
});
paged.onSelect(select -> {
Document result = select.getSelected();
Document id = result.get("id", Document.class);
Document snippet = result.get("snippet", Document.class);
Document thumbnails = snippet.get("thumbnails", Document.class);
ZonedDateTime uploadedAt = ZonedDateTime.parse(snippet.getString("publishedAt"));
EmbedBuilder embed = new EmbedBuilder();
embed.setColor(16711680);
embed.setDescription(snippet.getString("description"));
embed.setImage(thumbnails.getEmbedded(List.of("high", "url"), String.class));
embed.setTitle(snippet.getString("title"), this.getUrlFromId(id));
String kind = id.getString("kind");
if (kind.equals("youtube#channel")) {
embed.addField("Created At", uploadedAt.format(this.formatter), true);
} else if (kind.equals("youtube#video")) {
String state = snippet.getString("liveBroadcastContent");
embed.addField("Uploaded By", "[" + snippet.getString("channelTitle") + "](https://www.youtube.com/channel/" + snippet.getString("channelId") + ")", true);
embed.addField("Uploaded At", uploadedAt.format(this.formatter), true);
embed.addField("State", state.equals("live") ? "Live Now" : state.equals("upcoming") ? "Scheduled" : "Uploaded", true);
Request metaDataRequest = new Request.Builder().url("https://api.jockiemusic.com/v1/youtube/videos/" + id.getString("videoId") + "/metadata").build();
event.reply(embed.build()).queue(message -> {
event.getHttpClient().newCall(metaDataRequest).enqueue((HttpCallback) metaDataResponse -> {
if (metaDataResponse.code() == 404) {
return;
}
Document data = Document.parse(metaDataResponse.body().string()).get("data", Document.class);
Document metaData = data.get("metadata", Document.class);
Document rating = metaData.get("rating", Document.class);
long likes = rating.get("likes", Number.class).longValue(), dislikes = rating.get("dislikes", Number.class).longValue();
double ratingPercent = ((double) likes / (likes + dislikes)) * 100D;
embed.addField("Duration", TimeUtility.getMusicTimeString(metaData.get("length", Number.class).longValue(), TimeUnit.MILLISECONDS), true);
embed.addField("Views", String.format("%,d", metaData.get("views", Number.class).longValue()), true);
embed.addField("Likes/Dislikes", String.format("%,d \\\uD83D\uDC4D\n%,d \\\uD83D\uDC4E", likes, dislikes), true);
embed.addField("Rating", NumberUtility.DEFAULT_DECIMAL_FORMAT.format(ratingPercent) + "%", true);
embed.setFooter("Views and Ratings last updated");
embed.setTimestamp(Instant.ofEpochSecond(data.get("lastUpdated", Number.class).longValue()));
message.editMessageEmbeds(embed.build()).queue();
});
});
return;
} else {
embed.addField("Uploaded By", "[" + snippet.getString("channelTitle") + "](https://www.youtube.com/channel/" + snippet.getString("channelId") + ")", true);
embed.addField("Uploaded At", uploadedAt.format(this.formatter), true);
}
event.reply(embed.build()).queue();
});
paged.execute(event);
});
}
use of com.jockie.bot.core.option.Option in project Sx4 by sx4-discord-bot.
the class RoleCommand method add.
@Command(value = "add", description = "Add a role to a member")
@CommandId(250)
@Redirects({ "addrole", "add role", "ar" })
@Examples({ "role add @Shea#6653 Role", "role add Shea 345718366373150720", "role add @Role" })
@AuthorPermissions(permissions = { Permission.MANAGE_ROLES })
@BotPermissions(permissions = { Permission.MANAGE_ROLES })
public void add(Sx4CommandEvent event, @Argument(value = "user", nullDefault = true) @AlternativeOptions("all") Alternative<Member> option, @Argument(value = "role", endless = true) Role role) {
if (role.isManaged()) {
event.replyFailure("I cannot give managed roles").queue();
return;
}
if (role.isPublicRole()) {
event.replyFailure("I cannot give the @everyone role").queue();
return;
}
if (!event.getMember().canInteract(role)) {
event.replyFailure("You cannot give a role higher or equal than your top role").queue();
return;
}
if (!event.getSelfMember().canInteract(role)) {
event.replyFailure("I cannot give a role higher or equal than my top role").queue();
return;
}
if (option != null && option.isAlternative()) {
List<Member> members = event.getGuild().getMemberCache().applyStream(stream -> stream.filter(member -> !member.getRoles().contains(role)).collect(Collectors.toList()));
if (members.size() == 0) {
event.replyFailure("All users already have that role").queue();
return;
}
if (!this.pending.add(event.getGuild().getIdLong())) {
event.replyFailure("You can only have 1 concurrent role being added to all users").queue();
return;
}
event.replyFormat("Adding %s to **%,d** user%s, another message will be sent once this is done %s", role.getAsMention(), members.size(), members.size() == 1 ? "" : "s", event.getConfig().getSuccessEmote()).queue();
List<CompletableFuture<Integer>> futures = new ArrayList<>();
for (Member member : members) {
futures.add(event.getGuild().addRoleToMember(member, role).submit().handle((result, exception) -> exception == null ? 1 : 0));
}
FutureUtility.allOf(futures).whenComplete((completed, exception) -> {
this.pending.remove(event.getGuild().getIdLong());
int count = completed.stream().reduce(0, Integer::sum);
event.replyFormat("Successfully added the role %s to **%,d/%,d** user%s %s", role.getAsMention(), count, members.size(), count == 1 ? "" : "s", event.getConfig().getSuccessEmote()).queue();
});
} else {
Member effectiveMember = option == null ? event.getMember() : option.getValue();
event.getGuild().addRoleToMember(effectiveMember, role).flatMap($ -> event.replySuccess(role.getAsMention() + " has been added to **" + effectiveMember.getUser().getAsTag() + "**")).queue();
}
}
use of com.jockie.bot.core.option.Option in project Sx4 by sx4-discord-bot.
the class IGDBCommand method onCommand.
public void onCommand(Sx4CommandEvent event, @Argument(value = "game", endless = true, nullDefault = true) String game, @Option(value = "sort", description = "Sort results by `name` (default), `rating` and `release`") IGDBSort sort, @Option(value = "reverse", description = "Reverses sorting order") boolean reverse) {
IGDBParser parser = new IGDBParser().setFilter("category = 0").limit(500).addFields("name", "total_rating", "total_rating_count", "first_release_date", "genres.name", "url", "summary", "cover.image_id", "platforms.name");
if (game != null && sort == null && !reverse) {
parser.search(String.format("\"%s\"", game));
} else {
parser.sort(sort == null ? "name" : sort.getName(), !reverse).appendFilter(filter -> IGDBFilter.and(filter, (sort == null ? "name" : sort.getName()) + " != n"));
if (game != null) {
parser.appendFilter(filter -> IGDBFilter.and(filter, String.format("name ~ \"%s\"*", game)));
}
}
Request request = new Request.Builder().url("https://api.igdb.com/v4/games/").post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), parser.parse())).addHeader("Client-ID", event.getConfig().getTwitchClientId()).addHeader("Authorization", "Bearer " + event.getConfig().getTwitch()).build();
event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> {
String body = String.format("{\"data\":%s}", response.body().string());
List<Document> results = Document.parse(body).getList("data", Document.class);
if (results.isEmpty()) {
event.replyFailure("I could not find any games with that filter").queue();
return;
}
PagedResult<Document> paged = new PagedResult<>(event.getBot(), results).setAutoSelect(true).setIncreasedIndex(true).setAuthor("IGDB Search", null, "http://bit.ly/2NXGwMz").setDisplayFunction(data -> data.getString("name"));
paged.onSelect(select -> {
Document data = select.getSelected();
EmbedBuilder embed = new EmbedBuilder();
embed.setAuthor(data.getString("name"), data.getString("url"), "http://bit.ly/2NXGwMz");
embed.setDescription(StringUtility.limit(data.get("summary", "This game has no description :("), MessageEmbed.DESCRIPTION_MAX_LENGTH, "... [Read More](" + data.getString("url") + ")"));
embed.setThumbnail(data.containsKey("cover") ? String.format("https://images.igdb.com/igdb/image/upload/t_thumb/%s.jpg", data.getEmbedded(List.of("cover", "image_id"), String.class)) : null);
int ratings = data.get("total_rating_count", 0);
embed.addField("Rating", data.containsKey("total_rating") ? String.format("%.2f out of %,d rating%s", data.getDouble("total_rating"), ratings, ratings == 1 ? "" : "s") : "Unknown", true);
embed.addField("Release Date", data.containsKey("first_release_date") ? Instant.ofEpochSecond(data.getInteger("first_release_date")).atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("dd LLLL yyyy")) : "Unknown", true);
embed.addField("Genres", data.containsKey("genres") ? data.getList("genres", Document.class).stream().map(genre -> genre.getString("name")).collect(Collectors.joining("\n")) : "None", true);
embed.addField("Platforms", data.containsKey("platforms") ? data.getList("platforms", Document.class).stream().map(platform -> platform.getString("name")).collect(Collectors.joining("\n")) : "None", true);
event.reply(embed.build()).queue();
});
paged.execute(event);
});
}
use of com.jockie.bot.core.option.Option in project Sx4 by sx4-discord-bot.
the class GuessTheNumberCommand method onCommand.
public void onCommand(Sx4CommandEvent event, @Argument(value = "user", endless = true) Member member, @Option(value = "min", description = "Choose the minimum number of the range") @Limit(min = 1) @DefaultNumber(1) int min, @Option(value = "max", description = "Choose the maximum number of the range") @Limit(min = 2) @DefaultNumber(50) int max) {
User opponent = member.getUser();
if (opponent.isBot()) {
event.replyFailure("You cannot play against bots").queue();
return;
}
if (opponent.getIdLong() == event.getAuthor().getIdLong()) {
event.replyFailure("You cannot play against yourself").queue();
return;
}
List<Button> buttons = List.of(Button.success("yes", "Yes"), Button.danger("no", "No"));
event.reply(opponent.getAsMention() + ", do you want to play guess the number with **" + event.getAuthor().getName() + "**?").allowedMentions(EnumSet.of(Message.MentionType.USER)).setActionRow(buttons).submit().thenCompose(message -> {
return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, opponent)).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, opponent)).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
}).whenComplete((confirmEvent, confirmException) -> {
Throwable confirmCause = confirmException instanceof CompletionException ? confirmException.getCause() : confirmException;
if (confirmCause instanceof CancelException) {
GenericEvent cancelEvent = ((CancelException) confirmCause).getEvent();
if (cancelEvent != null) {
((ButtonClickEvent) cancelEvent).reply("Cancelled " + event.getConfig().getSuccessEmote()).queue();
}
return;
} else if (confirmCause instanceof TimeoutException) {
event.reply("Timed out :stopwatch:").queue();
return;
}
confirmEvent.deferEdit().queue();
CompletableFuture<MessageReceivedEvent> authorFuture = event.getAuthor().openPrivateChannel().submit().thenCompose(channel -> channel.sendMessage("Send a number between **" + min + "** and **" + max + "** or `cancel` to cancel").submit()).thenCompose(message -> {
return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setUnique(event.getAuthor().getIdLong(), message.getChannel().getIdLong()).setTimeout(30).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setPredicate(e -> {
int number;
try {
number = Integer.parseInt(e.getMessage().getContentRaw());
} catch (NumberFormatException exception) {
return false;
}
return number >= min && number <= max;
}).start();
});
CompletableFuture<MessageReceivedEvent> opponentFuture = opponent.openPrivateChannel().submit().thenCompose(channel -> channel.sendMessage("Send a number between **" + min + "** and **" + max + "** or `cancel` to cancel").submit()).thenCompose(message -> {
return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setUnique(opponent.getIdLong(), message.getChannel().getIdLong()).setTimeout(30).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setPredicate(e -> {
int number;
try {
number = Integer.parseInt(e.getMessage().getContentRaw());
} catch (NumberFormatException exception) {
return false;
}
return number >= min && number <= max;
}).start();
});
authorFuture.whenComplete((messageEvent, exception) -> {
Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
if (cause instanceof CancelException) {
opponentFuture.cancel(true);
if (((CancelException) cause).getType() == CancelType.USER) {
event.getAuthor().openPrivateChannel().flatMap(channel -> channel.sendMessage("Cancelled " + event.getConfig().getSuccessEmote())).queue();
}
event.replyFailure("**" + event.getAuthor().getAsTag() + "** cancelled their response").queue();
return;
} else if (cause instanceof TimeoutException) {
opponentFuture.cancel(true);
event.replyFailure("**" + event.getAuthor().getAsTag() + "** took too long to respond").queue();
return;
} else if (cause instanceof ErrorResponseException) {
opponentFuture.cancel(true);
event.replyFailure("I could not send a message to **" + event.getAuthor().getAsTag() + "**").queue();
return;
}
messageEvent.getChannel().sendMessage("Your number has been received, results will be sent in " + event.getTextChannel().getAsMention()).queue();
});
opponentFuture.whenComplete((messageEvent, exception) -> {
Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
if (cause instanceof CancelException) {
authorFuture.cancel(true);
if (((CancelException) cause).getType() == CancelType.USER) {
opponent.openPrivateChannel().flatMap(channel -> channel.sendMessage("Cancelled " + event.getConfig().getSuccessEmote())).queue();
}
event.replyFailure("**" + opponent.getAsTag() + "** cancelled their response").queue();
return;
} else if (cause instanceof TimeoutException) {
authorFuture.cancel(true);
event.replyFailure("**" + opponent.getAsTag() + "** took too long to respond").queue();
return;
} else if (cause instanceof ErrorResponseException) {
authorFuture.cancel(true);
event.replyFailure("I could not send a message to **" + opponent.getAsTag() + "**").queue();
return;
}
messageEvent.getChannel().sendMessage("Your number has been received, results will be sent in " + event.getTextChannel().getAsMention()).queue();
});
CompletableFuture.allOf(authorFuture, opponentFuture).whenComplete((result, exception) -> {
if (exception != null) {
return;
}
MessageReceivedEvent authorEvent = authorFuture.join(), opponentEvent = opponentFuture.join();
ObjectId gameId = ObjectId.get();
int authorNumber = Integer.parseInt(authorEvent.getMessage().getContentRaw());
int opponentNumber = Integer.parseInt(opponentEvent.getMessage().getContentRaw());
int randomNumber = event.getRandom().nextInt(max) + 1;
Document authorData = new Document("userId", event.getAuthor().getIdLong()).append("gameId", gameId).append("type", GameType.GUESS_THE_NUMBER.getId()).append("choice", authorNumber).append("answer", randomNumber);
Document opponentData = new Document("userId", opponent.getIdLong()).append("gameId", gameId).append("type", GameType.GUESS_THE_NUMBER.getId()).append("choice", authorNumber).append("answer", randomNumber);
int authorDifference = Math.abs(authorNumber - randomNumber), opponentDifference = Math.abs(opponentNumber - randomNumber);
StringBuilder content = new StringBuilder("The random number was **" + randomNumber + "**\n" + opponent.getName() + "'s number was **" + opponentNumber + "**\n" + event.getAuthor().getName() + "'s number was **" + authorNumber + "**\n\n");
if (authorDifference == opponentDifference) {
content.append("You both guessed the same number, It was a draw!");
authorData.append("state", GameState.DRAW.getId());
opponentData.append("state", GameState.DRAW.getId());
} else if (authorDifference > opponentDifference) {
content.append(opponent.getName()).append(" won! They were the closest to ").append(randomNumber);
authorData.append("state", GameState.LOSS.getId());
opponentData.append("state", GameState.WIN.getId());
} else {
content.append(event.getAuthor().getName()).append(" won! They were the closest to ").append(randomNumber);
authorData.append("state", GameState.WIN.getId());
opponentData.append("state", GameState.LOSS.getId());
}
event.reply(content.toString()).queue();
event.getMongo().insertManyGames(List.of(authorData, opponentData)).whenComplete(MongoDatabase.exceptionally());
});
});
}
use of com.jockie.bot.core.option.Option in project Sx4 by sx4-discord-bot.
the class CSGOSkinCommand method onCommand.
public void onCommand(Sx4CommandEvent event, @Argument(value = "skin name", endless = true) String query, @Option(value = "sort", description = "You can sort by `price`, `age`, `deal`, `popularity`, `wear or `discount`") Sort sort, @Option(value = "reverse", description = "Reverse the order of the sorting") boolean reverse, @Option(value = "wear", description = "What wear you would like to filter by, options are `fn`, `mw`, `ft`, `ww` and `bs`") Wear wear, @Option(value = "phase", description = "Filter by phase of a knife") @Lowercase String phase, @Option(value = "currency", description = "What currency to use for the prices of items") @Uppercase @DefaultString("GBP") String currency) {
SkinPortManager manager = event.getBot().getSkinPortManager();
String cookie = manager.getCSRFCookie();
double rate = manager.getCurrencyRate(currency);
if (rate == -1D) {
event.replyFailure("SkinPort does not support that currency").queue();
return;
}
FormBody body = new FormBody.Builder().add("prefix", query).add("_csrf", manager.getCSRFToken()).build();
Request suggestionRequest = new Request.Builder().url("https://skinport.com/api/suggestions/730").post(body).addHeader("Content-Type", "application/x-www-form-urlencoded").addHeader("Cookie", cookie).build();
event.getHttpClient().newCall(suggestionRequest).enqueue((HttpCallback) suggestionResponse -> {
Document data = Document.parse(suggestionResponse.body().string());
List<Document> variants = data.getList("suggestions", Document.class);
if (variants.isEmpty()) {
event.replyFailure("I could not find any skins from that query").queue();
return;
}
PagedResult<Document> suggestions = new PagedResult<>(event.getBot(), variants).setAuthor("SkinPort", null, "https://skinport.com/static/favicon-32x32.png").setDisplayFunction(suggestion -> {
String type = suggestion.getString("type");
return (type == null ? "" : type + " | ") + suggestion.getString("item");
}).setIndexed(true).setAutoSelect(true);
suggestions.onSelect(select -> {
Document selected = select.getSelected();
String type = selected.getString("type");
StringBuilder url = new StringBuilder("https://skinport.com/api/browse/730?cat=" + URLEncoder.encode(selected.getString("category"), StandardCharsets.UTF_8) + (type != null ? "&type=" + URLEncoder.encode(type, StandardCharsets.UTF_8) : "") + "&item=" + URLEncoder.encode(selected.getString("item"), StandardCharsets.UTF_8));
if (wear != null) {
url.append("&exterior=").append(wear.getId());
}
if (sort != null) {
url.append("&sort=").append(sort.getIdentifier()).append("&order=").append(reverse ? "desc" : "asc");
}
if (phase != null) {
int phaseId = this.phases.getOrDefault(phase, -1);
if (phaseId != -1) {
url.append("&phase=").append(phaseId);
}
}
Request request = new Request.Builder().url(url.toString()).addHeader("Cookie", cookie).build();
event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> {
Document skinData = Document.parse(response.body().string());
List<Document> items = skinData.getList("items", Document.class);
if (items.isEmpty()) {
event.replyFailure("There are no skins listed with those filters").queue();
return;
}
PagedResult<Document> skins = new PagedResult<>(event.getBot(), items).setPerPage(1).setSelect().setCustomFunction(page -> {
List<MessageEmbed> embeds = new ArrayList<>();
EmbedBuilder embed = new EmbedBuilder();
embed.setFooter("Skin " + page.getPage() + "/" + page.getMaxPage());
page.forEach((d, index) -> {
double steamPrice = (d.getInteger("suggestedPrice") / 100D) * rate;
double price = (d.getInteger("salePrice") / 100D) * rate;
double increase = steamPrice - price;
embed.setTitle(d.getString("marketName"), "https://skinport.com/item/" + d.getString("url") + "/" + d.getInteger("saleId"));
embed.setImage("https://community.cloudflare.steamstatic.com/economy/image/" + d.getString("image"));
embed.addField("Price", String.format("~~%,.2f %s~~ %,.2f %2$s (%s%.2f%%)", steamPrice, currency, price, increase > 0 ? "-" : "+", Math.abs((increase / steamPrice) * 100D)), true);
String exterior = d.getString("exterior");
if (exterior != null) {
embed.addField("Wear", exterior, true);
embed.addField("Float", String.format("%.3f", d.get("wear", Number.class).doubleValue()), true);
}
String lock = d.getString("lock");
embed.addField("Trade Locked", lock == null ? "No" : this.formatter.parse(Duration.between(OffsetDateTime.now(ZoneOffset.UTC), OffsetDateTime.parse(lock))), true);
embeds.add(embed.build());
if (d.getBoolean("canHaveScreenshots")) {
embed.setImage("https://cdn.skinport.com/images/screenshots/" + d.getInteger("assetId") + "/backside_512x384.png");
embeds.add(embed.build());
embed.setImage("https://cdn.skinport.com/images/screenshots/" + d.getInteger("assetId") + "/playside_512x384.png");
embeds.add(embed.build());
}
});
return new MessageBuilder().setEmbeds(embeds);
});
skins.execute(event);
});
});
suggestions.execute(event);
});
}
Aggregations