Skip to content

Commit b92259f

Browse files
authored
Retry RedGIFs API calls once on 401 (expired auth token) (#2170)
Reworked to address metaprime's review: fetchAuthToken() stays in its original location, and the 401-retry now covers all authenticated call sites (getFirstPage, getNextPage, getURLsForGallery, getVideoURL) via a shared getAuthenticatedJSON() helper. Verified live against a 16-item RedGIFs profile with cleared history — all files downloaded.
1 parent ec7e4e1 commit b92259f

1 file changed

Lines changed: 32 additions & 16 deletions

File tree

src/main/java/com/rarchives/ripme/ripper/rippers/RedgifsRipper.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,12 @@ public Matcher isSingleton() {
104104
@Override
105105
public JSONObject getFirstPage() throws IOException {
106106
try {
107-
if (authToken == null || authToken.isBlank()) {
108-
fetchAuthToken();
109-
}
110-
111107
if (isSingleton().matches()) {
112108
maxPages = 1;
113109
String gifDetailsURL = String.format(GIFS_DETAIL_ENDPOINT, getGID(url));
114-
return Http.url(gifDetailsURL).header("Authorization", "Bearer " + authToken).getJSON();
110+
return getAuthenticatedJSON(gifDetailsURL);
115111
} else if (isSearch().matches() || isTags().matches()) {
116-
var json = Http.url(getSearchOrTagsURL()).header("Authorization", "Bearer " + authToken).getJSON();
112+
var json = getAuthenticatedJSON(getSearchOrTagsURL());
117113
maxPages = json.getInt("pages");
118114
return json;
119115
} else {
@@ -122,7 +118,7 @@ public JSONObject getFirstPage() throws IOException {
122118
uri.addParameter("order", "new");
123119
uri.addParameter("count", Integer.toString(count));
124120
uri.addParameter("page", Integer.toString(currentPage));
125-
var json = Http.url(uri.build().toURL()).header("Authorization", "Bearer " + authToken).getJSON();
121+
var json = getAuthenticatedJSON(uri.build().toURL());
126122
maxPages = json.getInt("pages");
127123
return json;
128124
}
@@ -194,7 +190,7 @@ public JSONObject getNextPage(JSONObject doc) throws IOException, URISyntaxExcep
194190
}
195191
currentPage++;
196192
if (isSearch().matches() || isTags().matches()) {
197-
var json = Http.url(getSearchOrTagsURL()).header("Authorization", "Bearer " + authToken).getJSON();
193+
var json = getAuthenticatedJSON(getSearchOrTagsURL());
198194
// Handle rare maxPages change during a rip
199195
maxPages = json.getInt("pages");
200196
return json;
@@ -203,7 +199,7 @@ public JSONObject getNextPage(JSONObject doc) throws IOException, URISyntaxExcep
203199
uri.addParameter("order", "new");
204200
uri.addParameter("count", Integer.toString(count));
205201
uri.addParameter("page", Integer.toString(currentPage));
206-
var json = Http.url(uri.build().toURL()).header("Authorization", "Bearer " + authToken).getJSON();
202+
var json = getAuthenticatedJSON(uri.build().toURL());
207203
// Handle rare maxPages change during a rip
208204
maxPages = json.getInt("pages");
209205
return json;
@@ -254,8 +250,7 @@ private static List<String> getURLsForGallery(String galleryID, String gifID) {
254250
return list;
255251
}
256252
try {
257-
var json = Http.url(String.format(GALLERY_ENDPOINT, galleryID))
258-
.header("Authorization", "Bearer " + authToken).getJSON();
253+
var json = getAuthenticatedJSON(String.format(GALLERY_ENDPOINT, galleryID));
259254
for (var gif : json.getJSONArray("gifs")) {
260255
var hdURL = ((JSONObject) gif).getJSONObject("urls").getString("hd");
261256
list.add(hdURL);
@@ -280,12 +275,9 @@ public static String getVideoURL(URL url) throws IOException, URISyntaxException
280275
if (!m.matches()) {
281276
throw new IOException(String.format("Cannot fetch redgif url %s", url.toExternalForm()));
282277
}
283-
if (authToken == null || authToken.isBlank()) {
284-
fetchAuthToken();
285-
}
286278
var gid = m.group(1).split("-")[0];
287279
var gifDetailsURL = String.format(GIFS_DETAIL_ENDPOINT, gid);
288-
var json = Http.url(gifDetailsURL).header("Authorization", "Bearer " + authToken).getJSON();
280+
var json = getAuthenticatedJSON(gifDetailsURL);
289281
var gif = json.getJSONObject("gif");
290282
if (!gif.isNull("gallery")) {
291283
// TODO check how to handle a image gallery
@@ -303,7 +295,31 @@ private static void fetchAuthToken() throws IOException {
303295
var json = Http.url(TEMPORARY_AUTH_ENDPOINT).getJSON();
304296
var token = json.getString("token");
305297
authToken = token;
306-
logger.info("Incase of redgif 401 errors, please restart the app to refresh the auth token");
298+
}
299+
300+
/**
301+
* Performs an authenticated GET against the RedGIFs API. The auth token is a
302+
* temporary, expiring credential (see fetchAuthToken()); on a 401 (expired
303+
* token) this fetches a fresh one and retries once before giving up.
304+
*/
305+
private static JSONObject getAuthenticatedJSON(String requestUrl) throws IOException {
306+
if (authToken == null || authToken.isBlank()) {
307+
fetchAuthToken();
308+
}
309+
try {
310+
return Http.url(requestUrl).header("Authorization", "Bearer " + authToken).getJSON();
311+
} catch (org.jsoup.HttpStatusException e) {
312+
if (e.getStatusCode() != 401) {
313+
throw e;
314+
}
315+
logger.warn("RedGIFs auth token expired, fetching a new one and retrying: " + requestUrl);
316+
fetchAuthToken();
317+
return Http.url(requestUrl).header("Authorization", "Bearer " + authToken).getJSON();
318+
}
319+
}
320+
321+
private static JSONObject getAuthenticatedJSON(URL requestUrl) throws IOException {
322+
return getAuthenticatedJSON(requestUrl.toExternalForm());
307323
}
308324

309325
/**

0 commit comments

Comments
 (0)