diff --git a/.androidide/editor/openedFiles.json b/.androidide/editor/openedFiles.json index 0a67edd..ae4c51b 100644 --- a/.androidide/editor/openedFiles.json +++ b/.androidide/editor/openedFiles.json @@ -4,29 +4,14 @@ "file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java", "selection": { "end": { - "column": 30, - "index": 4201, - "line": 112 + "column": 101, + "index": 9409, + "line": 222 }, "start": { - "column": 30, - "index": 4201, - "line": 112 - } - } - }, - { - "file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/res/xml/config.xml", - "selection": { - "end": { - "column": 27, - "index": 461, - "line": 13 - }, - "start": { - "column": 27, - "index": 461, - "line": 13 + "column": 101, + "index": 9409, + "line": 222 } } }, @@ -44,7 +29,37 @@ "line": 14 } } + }, + { + "file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java", + "selection": { + "end": { + "column": 8, + "index": 2261, + "line": 57 + }, + "start": { + "column": 8, + "index": 2261, + "line": 57 + } + } + }, + { + "file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/res/xml/config.xml", + "selection": { + "end": { + "column": 48, + "index": 2950, + "line": 86 + }, + "start": { + "column": 25, + "index": 2927, + "line": 86 + } + } } ], - "selectedFile": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/build.gradle" + "selectedFile": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java" } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9e5ea72..07b5b4d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "io.github.moonleeeaf.fuckmaonemo" minSdk 21 targetSdk 33 - versionCode 16000 - versionName "1.6.0" + versionCode 17000 + versionName "1.7.0" vectorDrawables { useSupportLibrary true diff --git a/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java b/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java index dc2e3b6..fe98e49 100644 --- a/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java +++ b/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/ConfigActivity.java @@ -6,6 +6,7 @@ import android.os.Bundle; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.view.ViewGroup; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.Toast; @@ -43,6 +44,23 @@ public class ConfigActivity extends PreferenceActivity { return false; }); + findPreference("set_newest_works_filter").setOnPreferenceClickListener((p) -> { + EditText edit = new EditText(this); + + edit.setText(getPreferenceManager().getSharedPreferences().getString("newest_works_filter_rule_shared", "userId 823651139")); + + new AlertDialog.Builder(this) + .setTitle("最新作品过滤规则") + .setView(edit) + .setPositiveButton("保存", (d, w) -> { + getPreferenceManager().getSharedPreferences().edit().putString("newest_works_filter_rule_shared", edit.getText().toString()).apply(); + }) + .setNegativeButton("取消", (d, w) -> {}) + .show(); + + return false; + }); + try { FileOutputStream fos = openFileOutput("fuck_miao.txt", MODE_WORLD_READABLE); String s = new String(getAssets().open("屏蔽词.txt").readAllBytes()); diff --git a/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java b/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java index bb13c95..a54b07f 100644 --- a/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java +++ b/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java @@ -7,6 +7,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.AssetManager; import android.content.res.loader.AssetsProvider; +import android.net.Uri; import android.os.Bundle; import android.text.InputFilter; import android.text.Spanned; @@ -23,6 +24,7 @@ import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.net.Proxy; import java.util.ArrayList; @@ -30,6 +32,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; public class Hook implements IXposedHookLoadPackage { private static boolean isHooked = false; @@ -134,6 +137,21 @@ public class Hook implements IXposedHookLoadPackage { c.startActivity(new Intent().setComponent(new ComponentName("io.github.moonleeeaf.fuckmaonemo", ConfigActivity.class.getName()))); return false; }); + m.add("打开内置浏览器").setOnMenuItemClickListener((mm) -> { + EditText edit = new EditText(c); + new AlertDialog.Builder(c) + .setTitle("打开内置浏览器") + .setIcon(android.R.drawable.ic_dialog_info) + .setView(edit) + .setPositiveButton("打开", (d, w) -> { + c.startActivity(new Intent().setData(Uri.parse("nemo://com.codemao.nemo/openwith?type=5&url=" + edit.getText()))); + }) + .setNegativeButton("取消", (d, w) -> {}) + .create() + .show(); + + return false; + }); pop.show(); mp.setResult(null); @@ -198,6 +216,64 @@ public class Hook implements IXposedHookLoadPackage { )); }); + // 最新作品过滤 + load("newest_works_filter", () -> { + XposedBridge.log("[FuckMaoNemo] Hook_最新作品过滤"); + + final String[] rules = xsp.getString("newest_works_filter_rule_shared", "userId 823651139").split("\n"); + + final ArrayList filters = new ArrayList(); + + for (String s : rules) { + String type = s.split(" ")[0]; + String value = s.split(" ")[1]; + + NewestWorksFilter nwf = new NewestWorksFilter(type, value); + + filters.add(nwf); + } + + XposedBridge.hookMethod( + getMethod( + XposedHelpers.findClass("com.codemao.nemo.bean.LatestWorks", classLoader), + "getItems", + null + ), + new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam mp) throws Throwable { + List ls = (List) XposedHelpers.getObjectField(mp.thisObject, "items"); + + ArrayList al = new ArrayList(); + + for (Object o : ls) { + String workName = (String) XposedHelpers.getObjectField(o, "work_name"); + String userId = "" + XposedHelpers.getLongField(o, "user_id"); + + boolean disadd = false; + + for (NewestWorksFilter filter : filters) { + if (filter.matches(userId, workName)) { + disadd = true; + break; + } + } + + if (disadd) { + XposedBridge.log("[FuckMaoNemo] 过滤用户 " + userId + " 的作品 " + workName); + + continue; + } + + al.add(o); + } + + return al; + } + } + ); + }); + // 修复KN作品播放 load("fix_kn_player", () -> { XposedBridge.log("[FuckMaoNemo] Hook_修复KN作品播放"); @@ -278,19 +354,64 @@ public class Hook implements IXposedHookLoadPackage { load("fuck_box3recommend", () -> { XposedBridge.log("[FuckMaoNemo] Hook_岛3我推荐你吗"); - Object mgr = XposedHelpers.findClass("com.giu.xzz.http.RetrofitManager",classLoader).getDeclaredMethod("get", null).invoke(null, null); - Object example = mgr.getClass().getDeclaredMethod("create", new Class[] { Class.class }).invoke(mgr, XposedHelpers.findClass("com.codemao.nemo.retrofit.api.DiscoveryService", classLoader)); - - XposedBridge.hookAllMethods( - example.getClass(), - "getRecommendBoxData", - new XC_MethodReplacement() { + XposedBridge.hookMethod( + getMethod( + XposedHelpers.findClass("retrofit2.Retrofit$1", classLoader), + "invoke", + new Class[] { + Object.class, + Method.class, + Object[].class + } + ), + new XC_MethodHook() { @Override - protected Object replaceHookedMethod(MethodHookParam mp) throws Throwable { - return XposedHelpers.findClass("io.reactivex.Observable", classLoader).getConstructor(null).newInstance(null); + protected void beforeHookedMethod(MethodHookParam mp) throws Throwable { + switch (((Method) mp.args[1]).getName()) { + case "getRecommendBoxData": + mp.setResult(XposedHelpers.callMethod(mp.args[0], "getRecommendPageData", new Object[] {})); + break; + } } } ); + + /* + XposedBridge.hookMethod( + getMethod( + XposedHelpers.findClass("com.giu.xzz.http.RetrofitManager",classLoader), + "create", + Class.class + ), + new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam mp) throws Throwable { + Object s = mp.getResult(); + + XposedBridge.hookAllMethods( + s.getClass(), + "getRecommendBoxData", + new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable { + InvocationHandler handler = new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { + return null; + } + } + return java.lang.reflect.Proxy.newProxyInstance( + classLoader, + new Class[] { XposedHelpers.findClass("io.reactivex.Observable", classLoader) }, + hanlder + ); + } + } + ); + } + } + ); + */ }); // 强制显示再创作按钮 @@ -480,4 +601,25 @@ public class Hook implements IXposedHookLoadPackage { } } + public static class NewestWorksFilter { + private String type; + private String value; + + public NewestWorksFilter(String type, String value) { + this.type = type; + this.value = value; + } + + public boolean matches(String userId, String workName) { + if ("workName".equals(this.type)) { + return Pattern.matches(value, workName); + } else if ("userId".equals(this.type)) { + return userId.equals(value); + } + + return false; + } + + } + } diff --git a/app/src/main/res/xml/config.xml b/app/src/main/res/xml/config.xml index 0e682c2..a64b2f5 100644 --- a/app/src/main/res/xml/config.xml +++ b/app/src/main/res/xml/config.xml @@ -77,6 +77,16 @@ android:key="fuck_fcm" android:title="绕过防沉迷" android:summary="滞空防沉迷检测方法的调用实现无伤速通破解防沉迷,无需 Player 链接,不支持叽叽猫砸进里面的岛3,不支持内嵌社区网页的防沉迷,那不属于我的能力范围" /> + + + +