Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 43 additions & 19 deletions src/main/java/com/rarchives/ripme/ripper/rippers/RedgifsRipper.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public JSONObject getFirstPage() throws IOException {

@Override
public void downloadURL(URL url, int index) {
// redgifs is easy to trigger rate limit, so be a little cautious
// redgifs is easy to trigger rate limit, so be a little cautious
sleep(3000);
addURLToDownload(url, getPrefix(index));
}
Expand Down Expand Up @@ -276,34 +276,45 @@ private static List<String> getURLsForGallery(String galleryID, String gifID) {
*/
public static String getVideoURL(URL url) throws IOException, URISyntaxException {
logger.info("Retrieving " + url.toExternalForm());

var m = SINGLETON_PATTERN.matcher(url.toExternalForm());
if (!m.matches()) {
throw new IOException(String.format("Cannot fetch redgif url %s", url.toExternalForm()));
}

var gid = m.group(1).split("-")[0];
var gifDetailsURL = String.format(GIFS_DETAIL_ENDPOINT, gid);

if (authToken == null || authToken.isBlank()) {
fetchAuthToken();
}
var gid = m.group(1).split("-")[0];
var gifDetailsURL = String.format(GIFS_DETAIL_ENDPOINT, gid);
var json = Http.url(gifDetailsURL).header("Authorization", "Bearer " + authToken).getJSON();

try {
return fetchGifUrl(gifDetailsURL, url);
} catch (org.jsoup.HttpStatusException e) {
if (e.getStatusCode() == 401) {
logger.warn("RedGIFs token expired, refreshing token and retrying...");
fetchAuthToken();
return fetchGifUrl(gifDetailsURL, url);
}
throw e;
}
}

private static String fetchGifUrl(String gifDetailsURL, URL originalUrl)
throws IOException, URISyntaxException {

var json = Http.url(gifDetailsURL)
.header("Authorization", "Bearer " + authToken)
.getJSON();

var gif = json.getJSONObject("gif");

if (!gif.isNull("gallery")) {
// TODO check how to handle a image gallery
throw new IOException(String.format("Multiple images found for url %s", url));
throw new IOException(String.format("Multiple images found for url %s", originalUrl));
}
return gif.getJSONObject("urls").getString("hd");
}

/**
* Fetch a temorary auth token for the rip
*
* @throws IOException
*/
private static void fetchAuthToken() throws IOException {
var json = Http.url(TEMPORARY_AUTH_ENDPOINT).getJSON();
var token = json.getString("token");
authToken = token;
logger.info("Incase of redgif 401 errors, please restart the app to refresh the auth token");
return gif.getJSONObject("urls").getString("hd");
}

/**
Expand All @@ -318,6 +329,19 @@ private static void fetchAuthToken() throws IOException {
*
* @return Search or tags endpoint url
*/
/**
* Fetch a temporary authentication token from RedGIFs API
*/
private static void fetchAuthToken() throws IOException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this method back to where it was to minimize the diff in this PR. As a practical issue, moving this method to this location also split the doc comment for getSearchOrTagsURL() away from the getSearchOrTagsURL method implementation.

try {
var json = Http.url(TEMPORARY_AUTH_ENDPOINT).getJSON();
authToken = json.getString("token");
} catch (IOException e) {
logger.error("Failed to fetch RedGIFs authentication token", e);
throw e;
}
}

private URL getSearchOrTagsURL() throws IOException, URISyntaxException {
URIBuilder uri;
Map<String, String> endpointQueryParams = new HashMap<>();
Expand Down Expand Up @@ -390,4 +414,4 @@ private URL getSearchOrTagsURL() throws IOException, URISyntaxException {

return uri.build().toURL();
}
}
}