feat: `tiktok-feed-filter` , `tiktok-settings` and `tiktok-force-login` patch (#142)

This commit is contained in:
d4rkk3y 2022-09-22 03:59:50 +07:00 committed by GitHub
parent cf2d6b955a
commit c3f79eb27b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 550 additions and 0 deletions

View File

@ -0,0 +1,39 @@
package app.revanced.tiktok.feedfilter;
import com.ss.android.ugc.aweme.feed.model.Aweme;
import com.ss.android.ugc.aweme.feed.model.FeedItemList;
import java.util.Iterator;
import java.util.List;
import app.revanced.tiktok.settings.SettingsEnum;
public class FeedItemsFilter {
public static void filter(FeedItemList feedItemList) {
if (SettingsEnum.TIK_REMOVE_ADS.getBoolean()) removeAds(feedItemList);
if (SettingsEnum.TIK_HIDE_LIVE.getBoolean()) removeLive(feedItemList);
}
private static void removeAds(FeedItemList feedItemList) {
List<Aweme> items = feedItemList.items;
Iterator<Aweme> it = items.iterator();
while (it.hasNext()) {
Aweme item = it.next();
if (item != null && (item.isAd() || item.isWithPromotionalMusic())) {
it.remove();
}
}
}
private static void removeLive(FeedItemList feedItemList) {
List<Aweme> items = feedItemList.items;
Iterator<Aweme> it = items.iterator();
while (it.hasNext()) {
Aweme item = it.next();
if (item != null && (item.isLive() || item.isLiveReplay())) {
it.remove();
}
}
}
}

View File

@ -0,0 +1,5 @@
package app.revanced.tiktok.settings;
public enum ReturnType {
BOOLEAN, INTEGER, STRING, LONG, FLOAT
}

View File

@ -0,0 +1,148 @@
package app.revanced.tiktok.settings;
import android.content.Context;
import android.util.Log;
import app.revanced.tiktok.utils.LogHelper;
import app.revanced.tiktok.utils.ReVancedUtils;
import app.revanced.tiktok.utils.SharedPrefHelper;
public enum SettingsEnum {
//TikTok Settings
TIK_REMOVE_ADS("tik-remove-ads", true, SharedPrefHelper.SharedPrefNames.TIKTOK_PREFS, ReturnType.BOOLEAN, true),
TIK_HIDE_LIVE("tik-hide-live", false, SharedPrefHelper.SharedPrefNames.TIKTOK_PREFS, ReturnType.BOOLEAN, true),
TIK_DEBUG("tik_debug", false, SharedPrefHelper.SharedPrefNames.TIKTOK_PREFS, ReturnType.BOOLEAN);
static {
load();
}
private final String path;
private final Object defaultValue;
private final SharedPrefHelper.SharedPrefNames sharedPref;
private final ReturnType returnType;
private final boolean rebootApp;
private Object value = null;
SettingsEnum(String path, Object defaultValue, ReturnType returnType) {
this.path = path;
this.defaultValue = defaultValue;
this.sharedPref = SharedPrefHelper.SharedPrefNames.TIKTOK_PREFS;
this.returnType = returnType;
this.rebootApp = false;
}
SettingsEnum(String path, Object defaultValue, SharedPrefHelper.SharedPrefNames prefName, ReturnType returnType) {
this.path = path;
this.defaultValue = defaultValue;
this.sharedPref = prefName;
this.returnType = returnType;
this.rebootApp = false;
}
SettingsEnum(String path, Object defaultValue, SharedPrefHelper.SharedPrefNames prefName, ReturnType returnType, Boolean rebootApp) {
this.path = path;
this.defaultValue = defaultValue;
this.sharedPref = prefName;
this.returnType = returnType;
this.rebootApp = rebootApp;
}
private static void load() {
Context context = ReVancedUtils.getAppContext();
if (context == null) {
Log.e("revanced: SettingsEnum", "Context returned null! Setings NOT initialized");
} else {
try {
for (SettingsEnum setting : values()) {
Object value = setting.getDefaultValue();
//LogHelper is not initialized here
Log.d("revanced: SettingsEnum", "Loading Setting: " + setting.name());
switch (setting.getReturnType()) {
case FLOAT:
value = SharedPrefHelper.getFloat(context, setting.sharedPref, setting.getPath(), (float) setting.getDefaultValue());
break;
case LONG:
value = SharedPrefHelper.getLong(context, setting.sharedPref, setting.getPath(), (long) setting.getDefaultValue());
break;
case BOOLEAN:
value = SharedPrefHelper.getBoolean(context, setting.sharedPref, setting.getPath(), (boolean) setting.getDefaultValue());
break;
case INTEGER:
value = SharedPrefHelper.getInt(context, setting.sharedPref, setting.getPath(), (int) setting.getDefaultValue());
break;
case STRING:
value = SharedPrefHelper.getString(context, setting.sharedPref, setting.getPath(), (String) setting.getDefaultValue());
break;
default:
LogHelper.printException(SettingsEnum.class, "Setting does not have a valid Type. Name is: " + setting.name());
break;
}
setting.setValue(value);
//LogHelper is not initialized here
Log.d("revanced: SettingsEnum", "Loaded Setting: " + setting.name() + " Value: " + value);
}
} catch (Throwable th) {
LogHelper.printException(SettingsEnum.class, "Error during load()!", th);
}
}
}
public void setValue(Object newValue) {
this.value = newValue;
}
public void saveValue(Object newValue) {
Context context = ReVancedUtils.getAppContext();
if (context != null) {
if (returnType == ReturnType.BOOLEAN) {
SharedPrefHelper.saveBoolean(context, sharedPref, path, (Boolean) newValue);
} else {
SharedPrefHelper.saveString(context, sharedPref, path, newValue + "");
}
value = newValue;
} else {
LogHelper.printException(SettingsEnum.class, "Context on SaveValue is null!");
}
}
public int getInt() {
return (int) value;
}
public String getString() {
return (String) value;
}
public boolean getBoolean() {
return (Boolean) value;
}
public Long getLong() {
return (Long) value;
}
public Float getFloat() {
return (Float) value;
}
public Object getDefaultValue() {
return defaultValue;
}
public String getPath() {
return path;
}
public ReturnType getReturnType() {
return returnType;
}
public boolean shouldRebootOnChange() {
return rebootApp;
}
}

View File

@ -0,0 +1,134 @@
package app.revanced.tiktok.settingsmenu;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Process;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import androidx.annotation.Nullable;
import com.ss.android.ugc.aweme.splash.SplashActivity;
import app.revanced.tiktok.settings.SettingsEnum;
import app.revanced.tiktok.utils.ReVancedUtils;
import app.revanced.tiktok.utils.SharedPrefHelper;
public class ReVancedSettingsFragment extends PreferenceFragment {
private boolean Registered = false;
private boolean settingsInitialized = false;
SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
for (SettingsEnum setting : SettingsEnum.values()) {
if (!setting.getPath().equals(str)) continue;
if (ReVancedUtils.getAppContext() != null && this.settingsInitialized && setting.shouldRebootOnChange()) {
rebootDialog(getActivity());
}
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(SharedPrefHelper.SharedPrefNames.TIKTOK_PREFS.getName());
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this.listener);
this.Registered = true;
final Activity context = this.getActivity();
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
setPreferenceScreen(preferenceScreen);
//Feed filter
if (SettingsStatus.feedFilter) {
PreferenceCategory feedFilter = new PreferenceCategory(context);
feedFilter.setTitle("Feed filter");
preferenceScreen.addPreference(feedFilter);
//Remove ads toggle
{
SwitchPreference preference = new SwitchPreference(context);
feedFilter.addPreference(preference);
preference.setKey(SettingsEnum.TIK_REMOVE_ADS.getPath());
preference.setDefaultValue(SettingsEnum.TIK_REMOVE_ADS.getDefaultValue());
preference.setChecked(SettingsEnum.TIK_REMOVE_ADS.getBoolean());
preference.setTitle("Remove feed ads");
preference.setSummary("Remove ads from feed.");
preference.setOnPreferenceChangeListener((pref, newValue) -> {
final boolean value = (Boolean) newValue;
SettingsEnum.TIK_REMOVE_ADS.saveValue(value);
return true;
});
}
//Hide LiveStreams toggle
{
SwitchPreference preference = new SwitchPreference(context);
feedFilter.addPreference(preference);
preference.setKey(SettingsEnum.TIK_HIDE_LIVE.getPath());
preference.setDefaultValue(SettingsEnum.TIK_HIDE_LIVE.getDefaultValue());
preference.setChecked(SettingsEnum.TIK_HIDE_LIVE.getBoolean());
preference.setTitle("Hide livestreams");
preference.setSummary("Hide livestreams from feed.");
preference.setOnPreferenceChangeListener((pref, newValue) -> {
final boolean value = (Boolean) newValue;
SettingsEnum.TIK_HIDE_LIVE.saveValue(value);
return true;
});
}
}
//Integration
PreferenceCategory integration = new PreferenceCategory(context);
integration.setTitle("Integration");
preferenceScreen.addPreference(integration);
//Enable DebugLog toggle
{
SwitchPreference preference = new SwitchPreference(context);
integration.addPreference(preference);
preference.setKey(SettingsEnum.TIK_DEBUG.getPath());
preference.setDefaultValue(SettingsEnum.TIK_DEBUG.getDefaultValue());
preference.setChecked(SettingsEnum.TIK_DEBUG.getBoolean());
preference.setTitle("Enable debug log");
preference.setSummary("Show integration debug log.");
preference.setOnPreferenceChangeListener((pref, newValue) -> {
final boolean value = (Boolean) newValue;
SettingsEnum.TIK_DEBUG.saveValue(value);
return true;
});
}
this.settingsInitialized = true;
}
@Override // android.preference.PreferenceFragment, android.app.Fragment
public void onDestroy() {
if (this.Registered) {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this.listener);
this.Registered = false;
}
super.onDestroy();
}
private void reboot(Activity activity) {
int intent;
intent = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE;
((AlarmManager) activity.getSystemService(Context.ALARM_SERVICE)).setExact(AlarmManager.ELAPSED_REALTIME, 1500L, PendingIntent.getActivity(activity, 0, new Intent(activity, SplashActivity.class), intent));
Process.killProcess(Process.myPid());
}
private void rebootDialog(final Activity activity) {
new AlertDialog.Builder(activity).
setMessage("Refresh and restart").
setPositiveButton("RESTART", (dialog, i) -> reboot(activity))
.setNegativeButton("CANCEL", null)
.show();
}
}

View File

@ -0,0 +1,44 @@
package app.revanced.tiktok.settingsmenu;
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceFragment;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization.AdPersonalizationActivity;
import app.revanced.tiktok.utils.LogHelper;
import app.revanced.tiktok.utils.ReVancedUtils;
public class SettingsMenu {
public static void initializeSettings(AdPersonalizationActivity base) {
SettingsStatus.load();
LinearLayout linearLayout = new LinearLayout(base);
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(-1, -1));
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setFitsSystemWindows(true);
linearLayout.setTransitionGroup(true);
FrameLayout fragment = new FrameLayout(base);
fragment.setLayoutParams(new FrameLayout.LayoutParams(-1, -1));
int fragmentId = View.generateViewId();
fragment.setId(fragmentId);
linearLayout.addView(fragment);
base.setContentView(linearLayout);
PreferenceFragment preferenceFragment = new ReVancedSettingsFragment();
base.getFragmentManager().beginTransaction().replace(fragmentId, preferenceFragment).commit();
}
public static void startSettingsActivity() {
Context appContext = ReVancedUtils.getAppContext();
if (appContext != null) {
Intent intent = new Intent(appContext, AdPersonalizationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(intent);
} else {
LogHelper.debug(SettingsMenu.class, "ReVancedUtils.getAppContext() return null");
}
}
}

View File

@ -0,0 +1,11 @@
package app.revanced.tiktok.settingsmenu;
public class SettingsStatus {
public static boolean feedFilter = false;
public static void enableFeedFilter() {
feedFilter = true;
}
public static void load() {
}
}

View File

@ -0,0 +1,28 @@
package app.revanced.tiktok.utils;
import android.util.Log;
import app.revanced.tiktok.settings.SettingsEnum;
public class LogHelper {
//ToDo: Get Calling classname using Reflection
public static void debug(Class clazz, String message) {
if (SettingsEnum.TIK_DEBUG.getBoolean()) {
Log.d("revanced: " + (clazz != null ? clazz.getSimpleName() : ""), message);
}
}
public static void printException(Class clazz, String message, Throwable ex) {
Log.e("revanced: " + (clazz != null ? clazz.getSimpleName() : ""), message, ex);
}
public static void printException(Class clazz, String message) {
Log.e("revanced: " + (clazz != null ? clazz.getSimpleName() : ""), message);
}
public static void info(Class clazz, String message) {
Log.i("revanced: " + (clazz != null ? clazz.getSimpleName() : ""), message);
}
}

View File

@ -0,0 +1,18 @@
package app.revanced.tiktok.utils;
import android.content.Context;
public class ReVancedUtils {
//Used by TiktokIntegrations patch
public static Context context;
//Used by TiktokIntegrations patch
public static Context getAppContext() {
if (context != null) {
return context;
}
LogHelper.printException(ReVancedUtils.class, "Context is null!");
return null;
}
}

View File

@ -0,0 +1,82 @@
package app.revanced.tiktok.utils;
import android.content.Context;
import android.content.SharedPreferences;
public class SharedPrefHelper {
public static void saveString(Context context, SharedPrefNames prefName, String key, String value) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
sharedPreferences.edit().putString(key, value).apply();
}
public static void saveBoolean(Context context, SharedPrefNames prefName, String key, Boolean value) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
sharedPreferences.edit().putBoolean(key, value).apply();
}
public static String getString(Context context, SharedPrefNames prefName, String key, String _default) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
return (sharedPreferences.getString(key, _default));
}
public static Boolean getBoolean(Context context, SharedPrefNames prefName, String key, Boolean _default) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
return (sharedPreferences.getBoolean(key, _default));
}
public static Long getLong(Context context, SharedPrefNames prefName, String key, Long _default) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
try {
return Long.valueOf(sharedPreferences.getString(key, _default + ""));
} catch (ClassCastException ex) {
return sharedPreferences.getLong(key, _default);
}
}
public static Float getFloat(Context context, SharedPrefNames prefName, String key, Float _default) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
try {
return Float.valueOf(sharedPreferences.getString(key, _default + ""));
} catch (ClassCastException ex) {
return sharedPreferences.getFloat(key, _default);
}
}
public static Integer getInt(Context context, SharedPrefNames prefName, String key, Integer _default) {
SharedPreferences sharedPreferences = getPreferences(context, prefName);
try {
return Integer.valueOf(sharedPreferences.getString(key, _default + ""));
} catch (ClassCastException ex) {
return sharedPreferences.getInt(key, _default);
}
}
public static SharedPreferences getPreferences(Context context, SharedPrefNames name) {
if (context == null) return null;
return context.getSharedPreferences(name.getName(), Context.MODE_PRIVATE);
}
public static SharedPreferences getPreferences(Context context, String name) {
if (context == null) return null;
return context.getSharedPreferences(name, Context.MODE_PRIVATE);
}
public enum SharedPrefNames {
TIKTOK_PREFS("tiktok_revanced");
private final String name;
SharedPrefNames(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
}

View File

@ -0,0 +1,6 @@
package com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization;
import android.app.Activity;
//Dummy class
public class AdPersonalizationActivity extends Activity { }

View File

@ -0,0 +1,18 @@
package com.ss.android.ugc.aweme.feed.model;
//Dummy class
public class Aweme {
public boolean isAd() {
return true;
}
public boolean isLive() {
return true;
}
public boolean isLiveReplay() {
return true;
}
public boolean isWithPromotionalMusic() {
return true;
}
}

View File

@ -0,0 +1,8 @@
package com.ss.android.ugc.aweme.feed.model;
import java.util.List;
//Dummy class
public class FeedItemList {
public List<Aweme> items;
}

View File

@ -0,0 +1,9 @@
package com.ss.android.ugc.aweme.splash;
import android.annotation.SuppressLint;
import android.app.Activity;
//Dummy class
@SuppressLint("CustomSplashScreen")
public class SplashActivity extends Activity {
}