use of com.sx4.bot.http.HttpCallback 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.http.HttpCallback in project Sx4 by sx4-discord-bot.
the class GoogleSearchCache method retrieveResultsByQuery.
public CompletableFuture<List<GoogleSearchResult>> retrieveResultsByQuery(String query, boolean imageSearch, boolean includeNSFW) {
CompletableFuture<List<GoogleSearchResult>> future = new CompletableFuture<>();
Map<Boolean, Map<String, List<GoogleSearchResult>>> cache = imageSearch ? this.imageCache : this.cache;
Map<String, List<GoogleSearchResult>> actualCache = cache.get(includeNSFW);
if (actualCache != null && actualCache.containsKey(query)) {
future.complete(actualCache.get(query));
} else {
Request request = new Request.Builder().url("https://www.googleapis.com/customsearch/v1?key=" + this.bot.getConfig().getGoogle() + "&cx=014023765838117903829:mm334tqd3kg" + (imageSearch ? "&searchType=image" : "") + "&safe=" + (includeNSFW ? "off" : "active") + "&q=" + query).build();
this.bot.getHttpClient().newCall(request).enqueue((HttpCallback) response -> {
Document json = Document.parse(response.body().string());
if (json.containsKey("error")) {
Document error = json.get("error", Document.class);
int code = error.getInteger("code");
if (code == 429) {
future.completeExceptionally(new ForbiddenException("Daily quota reached (100)"));
} else {
future.completeExceptionally(new HttpException(error.get("message", "Unknown error occurred with status " + code)));
}
return;
}
List<Document> items = json.getList("items", Document.class, Collections.emptyList());
List<GoogleSearchResult> results = items.stream().map(GoogleSearchResult::new).collect(Collectors.toList());
cache.compute(includeNSFW, (key, value) -> {
if (value == null) {
Map<String, List<GoogleSearchResult>> newCache = new HashMap<>();
newCache.put(query, results);
return newCache;
} else {
value.put(query, results);
return value;
}
});
future.complete(results);
});
}
return future;
}
use of com.sx4.bot.http.HttpCallback 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.sx4.bot.http.HttpCallback 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.sx4.bot.http.HttpCallback in project Sx4 by sx4-discord-bot.
the class SteamCommand method compare.
@Command(value = "compare", description = "Compare what games 2 steam accounts have in common")
@CommandId(279)
@Examples({ "steam compare dog cat", "steam compare https://steamcommunity.com/id/dog https://steamcommunity.com/id/cat" })
@BotPermissions(permissions = { Permission.MESSAGE_EMBED_LINKS })
public void compare(Sx4CommandEvent event, @Argument(value = "first profile") String firstQuery, @Argument(value = "second profile", endless = true) String secondQuery) {
String firstUrl = this.getProfileUrl(firstQuery), secondUrl = this.getProfileUrl(secondQuery);
Request firstRequest = new Request.Builder().url(firstUrl + "games/?tab=all&xml=1").build();
Request secondRequest = new Request.Builder().url(secondUrl + "games/?tab=all&xml=1").build();
event.getHttpClient().newCall(firstRequest).enqueue((HttpCallback) firstResponse -> {
JSONObject firstData = XML.toJSONObject(firstResponse.body().string()).getJSONObject("gamesList");
if (firstData.has("error")) {
event.replyFailure("The steam profile <https://steamcommunity.com/profiles/" + firstData.getLong("steamID64") + "> is private").queue();
return;
}
event.getHttpClient().newCall(secondRequest).enqueue((HttpCallback) secondResponse -> {
JSONObject secondData = XML.toJSONObject(secondResponse.body().string()).getJSONObject("gamesList");
if (secondData.has("error")) {
event.replyFailure("The steam profile <https://steamcommunity.com/profiles/" + secondData.getLong("steamID64") + "> is private").queue();
return;
}
JSONArray firstGames = firstData.getJSONObject("games").getJSONArray("game"), secondGames = secondData.getJSONObject("games").getJSONArray("game");
Map<Integer, String> commonGames = new HashMap<>();
for (int x = 0; x < firstGames.length(); x++) {
for (int y = 0; y < secondGames.length(); y++) {
JSONObject firstGame = firstGames.getJSONObject(x), secondGame = secondGames.getJSONObject(y);
if (firstGame.getInt("appID") == secondGame.getInt("appID")) {
commonGames.put(firstGame.getInt("appID"), firstGame.getString("name"));
}
}
}
PagedResult<Map.Entry<Integer, String>> paged = new PagedResult<>(event.getBot(), new ArrayList<>(commonGames.entrySet())).setAuthor("Games In Common (" + commonGames.size() + ")", null, "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Steam_icon_logo.svg/2000px-Steam_icon_logo.svg.png").setPerPage(15).setIncreasedIndex(true).setDisplayFunction(d -> "[" + d.getValue() + "](https://store.steampowered.com/app/" + d.getKey() + ")");
paged.execute(event);
});
});
}
Aggregations