mirror of
https://github.com/Docile-Alligator/Infinity-For-Reddit.git
synced 2025-10-29 11:35:08 +00:00
Use the solution provided by @edgan to fix the redgifs issue.
This commit is contained in:
parent
ab20643fdb
commit
bbc7c368e2
@ -215,7 +215,7 @@ abstract class NetworkModule {
|
||||
return new RedgifsAccessTokenAuthenticator(currentAccountSharedPreferences);
|
||||
}
|
||||
|
||||
/*@Provides
|
||||
@Provides
|
||||
@Named("redgifs")
|
||||
@Singleton
|
||||
static Retrofit provideRedgifsRetrofit(@Named("RedgifsAccessTokenAuthenticator") Interceptor accessTokenAuthenticator,
|
||||
@ -236,16 +236,16 @@ abstract class NetworkModule {
|
||||
.baseUrl(APIUtils.REDGIFS_API_BASE_URI)
|
||||
.client(okHttpClientBuilder.build())
|
||||
.build();
|
||||
}*/
|
||||
}
|
||||
|
||||
@Provides
|
||||
/*@Provides
|
||||
@Named("redgifs")
|
||||
@Singleton
|
||||
static Retrofit provideRedgifsRetrofit(@Named("base") Retrofit retrofit) {
|
||||
return retrofit.newBuilder()
|
||||
.baseUrl(APIUtils.OH_MY_DL_BASE_URI)
|
||||
.build();
|
||||
}
|
||||
}*/
|
||||
|
||||
@Provides
|
||||
@Named("imgur")
|
||||
|
||||
@ -18,4 +18,7 @@ public interface RedgifsAPI {
|
||||
@FormUrlEncoded
|
||||
@POST("/v2/oauth/client")
|
||||
Call<String> getRedgifsAccessToken(@FieldMap Map<String, String> params);
|
||||
|
||||
@GET("/v2/auth/temporary")
|
||||
Call<String> getRedgifsTemporaryToken();
|
||||
}
|
||||
|
||||
@ -1,27 +1,6 @@
|
||||
package ml.docilealligator.infinityforreddit.network;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.apis.RedgifsAPI;
|
||||
import ml.docilealligator.infinityforreddit.utils.APIUtils;
|
||||
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Response;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
public class RedgifsAccessTokenAuthenticator implements Interceptor {
|
||||
/*public class RedgifsAccessTokenAuthenticator implements Interceptor {
|
||||
private final SharedPreferences mCurrentAccountSharedPreferences;
|
||||
|
||||
public RedgifsAccessTokenAuthenticator(SharedPreferences currentAccountSharedPreferences) {
|
||||
@ -57,6 +36,98 @@ public class RedgifsAccessTokenAuthenticator implements Interceptor {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
Response response = chain.proceed(chain.request());
|
||||
if (response.code() == 401 || response.code() == 400) {
|
||||
String accessTokenHeader = response.request().header(APIUtils.AUTHORIZATION_KEY);
|
||||
if (accessTokenHeader == null) {
|
||||
return response;
|
||||
}
|
||||
|
||||
String accessToken = accessTokenHeader.substring(APIUtils.AUTHORIZATION_BASE.length() - 1).trim();
|
||||
synchronized (this) {
|
||||
String accessTokenFromSharedPreferences = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, "");
|
||||
if (accessToken.equals(accessTokenFromSharedPreferences)) {
|
||||
String newAccessToken = refreshAccessToken();
|
||||
if (!newAccessToken.equals("")) {
|
||||
response.close();
|
||||
return chain.proceed(response.request().newBuilder().headers(Headers.of(APIUtils.getRedgifsOAuthHeader(newAccessToken))).build());
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
} else {
|
||||
response.close();
|
||||
return chain.proceed(response.request().newBuilder().headers(Headers.of(APIUtils.getRedgifsOAuthHeader(accessTokenFromSharedPreferences))).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}*/
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.apis.RedgifsAPI;
|
||||
import ml.docilealligator.infinityforreddit.utils.APIUtils;
|
||||
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Response;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
public class RedgifsAccessTokenAuthenticator implements Interceptor {
|
||||
private final SharedPreferences mCurrentAccountSharedPreferences;
|
||||
|
||||
public RedgifsAccessTokenAuthenticator(SharedPreferences currentAccountSharedPreferences) {
|
||||
this.mCurrentAccountSharedPreferences = currentAccountSharedPreferences;
|
||||
}
|
||||
|
||||
private String refreshAccessToken() {
|
||||
// Check if existing token is valid
|
||||
APIUtils.RedgifsAuthToken currentToken = APIUtils.REDGIFS_TOKEN.get();
|
||||
if (currentToken.isValid()) {
|
||||
return currentToken.token;
|
||||
}
|
||||
|
||||
// Get new token from API
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl(APIUtils.REDGIFS_API_BASE_URI)
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.build();
|
||||
RedgifsAPI api = retrofit.create(RedgifsAPI.class);
|
||||
|
||||
Call<String> accessTokenCall = api.getRedgifsTemporaryToken();
|
||||
try {
|
||||
retrofit2.Response<String> response = accessTokenCall.execute();
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String newAccessToken = new JSONObject(response.body()).getString("token");
|
||||
|
||||
// Update both the atomic reference and shared preferences
|
||||
APIUtils.RedgifsAuthToken newToken = APIUtils.RedgifsAuthToken.expireIn1day(newAccessToken);
|
||||
APIUtils.REDGIFS_TOKEN.set(newToken);
|
||||
mCurrentAccountSharedPreferences.edit().putString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, newAccessToken).apply();
|
||||
|
||||
return newAccessToken;
|
||||
}
|
||||
return "";
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
|
||||
@ -10,12 +10,9 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.FetchVideoLinkListener;
|
||||
import ml.docilealligator.infinityforreddit.apis.OhMyDlAPI;
|
||||
import ml.docilealligator.infinityforreddit.apis.RedgifsAPI;
|
||||
import ml.docilealligator.infinityforreddit.utils.APIUtils;
|
||||
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
|
||||
@ -31,6 +28,41 @@ public class FetchRedgifsVideoLinks {
|
||||
FetchVideoLinkListener fetchVideoLinkListener) {
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
// Get valid token
|
||||
String accessToken = getValidAccessToken(redgifsRetrofit, currentAccountSharedPreferences);
|
||||
if (accessToken.isEmpty()) {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
return;
|
||||
}
|
||||
|
||||
Response<String> response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(APIUtils.getRedgifsOAuthHeader(accessToken),
|
||||
redgifsId, APIUtils.USER_AGENT)
|
||||
.execute();
|
||||
if (response.isSuccessful()) {
|
||||
parseRedgifsVideoLinks(handler, response.body(), fetchVideoLinkListener);
|
||||
} else if (response.code() == 401) {
|
||||
// Token expired, try once more with new token
|
||||
accessToken = refreshAccessToken(redgifsRetrofit, currentAccountSharedPreferences);
|
||||
if (!accessToken.isEmpty()) {
|
||||
response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(
|
||||
APIUtils.getRedgifsOAuthHeader(accessToken),
|
||||
redgifsId, APIUtils.USER_AGENT)
|
||||
.execute();
|
||||
if (response.isSuccessful()) {
|
||||
parseRedgifsVideoLinks(handler, response.body(), fetchVideoLinkListener);
|
||||
} else {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}
|
||||
} else {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}
|
||||
} else {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}
|
||||
/*Response<String> response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(
|
||||
@ -43,7 +75,7 @@ public class FetchRedgifsVideoLinks {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}*/
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
/*Map<String, String> params = new HashMap<>();
|
||||
params.put(APIUtils.PLATFORM_KEY, "redgifs");
|
||||
params.put(APIUtils.URL_KEY, "https://www.redgifs.com/watch/" + redgifsId);
|
||||
|
||||
@ -55,7 +87,7 @@ public class FetchRedgifsVideoLinks {
|
||||
parseRedgifsVideoLinks(handler, response.body(), fetchVideoLinkListener);
|
||||
} else {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}
|
||||
}*/
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
@ -69,7 +101,39 @@ public class FetchRedgifsVideoLinks {
|
||||
SharedPreferences currentAccountSharedPreferences,
|
||||
String redgifsId) {
|
||||
try {
|
||||
// Get valid token
|
||||
String accessToken = getValidAccessToken(redgifsRetrofit, currentAccountSharedPreferences);
|
||||
if (accessToken.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Response<String> response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(APIUtils.getRedgifsOAuthHeader(accessToken),
|
||||
redgifsId, APIUtils.USER_AGENT)
|
||||
.execute();
|
||||
if (response.isSuccessful()) {
|
||||
return parseRedgifsVideoLinks(response.body());
|
||||
} else if (response.code() == 401) {
|
||||
// Token expired, try once more with new token
|
||||
accessToken = refreshAccessToken(redgifsRetrofit, currentAccountSharedPreferences);
|
||||
if (!accessToken.isEmpty()) {
|
||||
response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(
|
||||
APIUtils.getRedgifsOAuthHeader(accessToken),
|
||||
redgifsId, APIUtils.USER_AGENT)
|
||||
.execute();
|
||||
if (response.isSuccessful()) {
|
||||
return parseRedgifsVideoLinks(response.body());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*Response<String> response = redgifsRetrofit
|
||||
.create(RedgifsAPI.class)
|
||||
.getRedgifsData(
|
||||
APIUtils.getRedgifsOAuthHeader(currentAccountSharedPreferences.getString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, "")),
|
||||
@ -79,7 +143,7 @@ public class FetchRedgifsVideoLinks {
|
||||
return parseRedgifsVideoLinks(response.body());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
@ -106,31 +170,101 @@ public class FetchRedgifsVideoLinks {
|
||||
|
||||
private static void parseRedgifsVideoLinks(Handler handler, String response,
|
||||
FetchVideoLinkListener fetchVideoLinkListener) {
|
||||
try {
|
||||
/*String mp4 = new JSONObject(response).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.URLS_KEY)
|
||||
/*try {
|
||||
*//*String mp4 = new JSONObject(response).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.URLS_KEY)
|
||||
.getString(JSONUtils.HD_KEY);
|
||||
if (mp4.contains("-silent")) {
|
||||
mp4 = mp4.substring(0, mp4.indexOf("-silent")) + ".mp4";
|
||||
}
|
||||
final String mp4Name = mp4;
|
||||
handler.post(() -> fetchVideoLinkListener.onFetchRedgifsVideoLinkSuccess(mp4Name, mp4Name));*/
|
||||
handler.post(() -> fetchVideoLinkListener.onFetchRedgifsVideoLinkSuccess(mp4Name, mp4Name));*//*
|
||||
|
||||
String mp4 = new JSONObject(response).getString(JSONUtils.VIDEO_DOWNLOAD_URL);
|
||||
handler.post(() -> fetchVideoLinkListener.onFetchRedgifsVideoLinkSuccess(mp4, mp4));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}*/
|
||||
|
||||
try {
|
||||
JSONObject jsonResponse = new JSONObject(response);
|
||||
JSONObject gif = jsonResponse.getJSONObject(JSONUtils.GIF_KEY);
|
||||
JSONObject urls = gif.getJSONObject(JSONUtils.URLS_KEY);
|
||||
|
||||
// Try HD first, fall back to SD if not available
|
||||
String mp4;
|
||||
if (urls.has(JSONUtils.HD_KEY)) {
|
||||
mp4 = urls.getString(JSONUtils.HD_KEY);
|
||||
} else if (urls.has("sd")) {
|
||||
mp4 = urls.getString("sd");
|
||||
} else {
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mp4.contains("-silent")) {
|
||||
mp4 = mp4.substring(0, mp4.indexOf("-silent")) + ".mp4";
|
||||
}
|
||||
final String mp4Name = mp4;
|
||||
handler.post(() -> fetchVideoLinkListener.onFetchRedgifsVideoLinkSuccess(mp4Name, mp4Name));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
handler.post(() -> fetchVideoLinkListener.failed(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String parseRedgifsVideoLinks(String response) {
|
||||
try {
|
||||
return new JSONObject(response).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.URLS_KEY)
|
||||
.getString(JSONUtils.HD_KEY);
|
||||
/*return new JSONObject(response).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.URLS_KEY)
|
||||
.getString(JSONUtils.HD_KEY);*/
|
||||
JSONObject jsonResponse = new JSONObject(response);
|
||||
JSONObject gif = jsonResponse.getJSONObject(JSONUtils.GIF_KEY);
|
||||
JSONObject urls = gif.getJSONObject(JSONUtils.URLS_KEY);
|
||||
|
||||
// Try HD first, fall back to SD if not available
|
||||
if (urls.has(JSONUtils.HD_KEY)) {
|
||||
return urls.getString(JSONUtils.HD_KEY);
|
||||
} else if (urls.has("sd")) {
|
||||
return urls.getString("sd");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getValidAccessToken(Retrofit redgifsRetrofit, SharedPreferences currentAccountSharedPreferences) {
|
||||
// Check if existing token is valid
|
||||
APIUtils.RedgifsAuthToken currentToken = APIUtils.REDGIFS_TOKEN.get();
|
||||
if (currentToken.isValid()) {
|
||||
return currentToken.token;
|
||||
}
|
||||
|
||||
// Get new token if current one is invalid
|
||||
return refreshAccessToken(redgifsRetrofit, currentAccountSharedPreferences);
|
||||
}
|
||||
|
||||
private static String refreshAccessToken(Retrofit redgifsRetrofit, SharedPreferences currentAccountSharedPreferences) {
|
||||
try {
|
||||
RedgifsAPI api = redgifsRetrofit.create(RedgifsAPI.class);
|
||||
retrofit2.Response<String> response = api.getRedgifsTemporaryToken().execute();
|
||||
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String newAccessToken = new JSONObject(response.body()).getString("token");
|
||||
|
||||
// Update both the atomic reference and shared preferences
|
||||
APIUtils.RedgifsAuthToken newToken = APIUtils.RedgifsAuthToken.expireIn1day(newAccessToken);
|
||||
APIUtils.REDGIFS_TOKEN.set(newToken);
|
||||
currentAccountSharedPreferences.edit().putString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, newAccessToken).apply();
|
||||
|
||||
return newAccessToken;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
package ml.docilealligator.infinityforreddit.utils;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.BuildConfig;
|
||||
import ml.docilealligator.infinityforreddit.account.Account;
|
||||
@ -166,4 +170,28 @@ public class APIUtils {
|
||||
params.put(APIUtils.USER_AGENT_KEY, APIUtils.USER_AGENT);
|
||||
return params;
|
||||
}
|
||||
|
||||
// RedGifs token management
|
||||
public static final AtomicReference<RedgifsAuthToken> REDGIFS_TOKEN = new AtomicReference<>(new RedgifsAuthToken("", 0));
|
||||
|
||||
public static class RedgifsAuthToken {
|
||||
@NonNull
|
||||
public final String token;
|
||||
private final long expireAt;
|
||||
|
||||
private RedgifsAuthToken(@NonNull String token, final long expireAt) {
|
||||
this.token = token;
|
||||
this.expireAt = expireAt;
|
||||
}
|
||||
|
||||
public static RedgifsAuthToken expireIn1day(@NonNull String token) {
|
||||
// 23 not 24 to give an hour leeway
|
||||
long expireTime = 1000 * 60 * 60 * 23;
|
||||
return new RedgifsAuthToken(token, SystemClock.uptimeMillis() + expireTime);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return !token.isEmpty() && expireAt > SystemClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user