From d70fdcb3ab8ec7f8e9d31d901cf62e45fb6997da Mon Sep 17 00:00:00 2001 From: areteruhiro Date: Wed, 20 Nov 2024 15:32:34 +0900 Subject: [PATCH] =?UTF-8?q?Notif=5Finvalid=E3=80=80=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chipppppppppp/lime/LimeOptions.java | 6 +- .../io/github/chipppppppppp/lime/Main.java | 4 +- .../lime/hooks/EmbedOptions.java | 87 ++++++++ .../lime/hooks/Notif_invalid.java | 192 ++++++++++++++++++ app/src/main/res/values-ja/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/io/github/chipppppppppp/lime/hooks/Notif_invalid.java diff --git a/app/src/main/java/io/github/chipppppppppp/lime/LimeOptions.java b/app/src/main/java/io/github/chipppppppppp/lime/LimeOptions.java index f7197130..bcde8baf 100644 --- a/app/src/main/java/io/github/chipppppppppp/lime/LimeOptions.java +++ b/app/src/main/java/io/github/chipppppppppp/lime/LimeOptions.java @@ -39,6 +39,8 @@ public Option(String name, int id, boolean checked) { public Option callTone = new Option("call_tone", R.string.call_tone, false); public Option NaviColor = new Option("NaviColor", R.string.NaviColor, false); public Option ReadChecker = new Option("ReadChecker", R.string.ReadChecker, false); + public Option Notif_invalid = new Option("Notif_invalid", R.string.Notif_invalid, false); + public Option[] options = { removeVoom, @@ -66,6 +68,8 @@ public Option(String name, int id, boolean checked) { stopVersionCheck, outputCommunication, callTone, - NaviColor + NaviColor, + Notif_invalid + }; } diff --git a/app/src/main/java/io/github/chipppppppppp/lime/Main.java b/app/src/main/java/io/github/chipppppppppp/lime/Main.java index 613213e2..8834567e 100644 --- a/app/src/main/java/io/github/chipppppppppp/lime/Main.java +++ b/app/src/main/java/io/github/chipppppppppp/lime/Main.java @@ -23,6 +23,7 @@ import io.github.chipppppppppp.lime.hooks.ModifyRequest; import io.github.chipppppppppp.lime.hooks.ModifyResponse; import io.github.chipppppppppp.lime.hooks.NaviColor; +import io.github.chipppppppppp.lime.hooks.Notif_invalid; import io.github.chipppppppppp.lime.hooks.OutputRequest; import io.github.chipppppppppp.lime.hooks.OutputResponse; import io.github.chipppppppppp.lime.hooks.PreventMarkAsRead; @@ -73,7 +74,8 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou new UnsentCap(), new KeepUnreadLSpatch(), new NaviColor(), - new AutomaticBackup() + new AutomaticBackup(), + new Notif_invalid() }; public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { diff --git a/app/src/main/java/io/github/chipppppppppp/lime/hooks/EmbedOptions.java b/app/src/main/java/io/github/chipppppppppp/lime/hooks/EmbedOptions.java index 5f6370dd..d398c702 100644 --- a/app/src/main/java/io/github/chipppppppppp/lime/hooks/EmbedOptions.java +++ b/app/src/main/java/io/github/chipppppppppp/lime/hooks/EmbedOptions.java @@ -23,6 +23,13 @@ import android.widget.Switch; import android.widget.Toast; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -249,6 +256,19 @@ public void onClick(View v) { } }); + + Button MuteGroups_Button = new Button(context); + MuteGroups_Button.setLayoutParams(buttonParams); + MuteGroups_Button.setText("通知を無効にしているグループ"); + MuteGroups_Button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MuteGroups_Button(context); + } + }); + layout.addView(MuteGroups_Button); + + buttonLayout.addView(copyButton); Button pasteButton = new Button(context); @@ -302,6 +322,10 @@ public void onDismiss(DialogInterface dialog) { } }); + + + + AlertDialog dialog = builder.create(); Button button = new Button(context); @@ -394,4 +418,67 @@ public void onClick(View view) { } ); } + + + private void MuteGroups_Button(Context context) { + // ファイルパスを指定 + File dir = context.getFilesDir(); // 例えば内部ストレージのファイルディレクトリ + File file = new File(dir, "Notification.txt"); + + // ファイルが存在する場合、内容を読み込む + StringBuilder fileContent = new StringBuilder(); + if (file.exists()) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + fileContent.append(line).append("\n"); + } + } catch (IOException e) { + XposedBridge.log("Error reading the file: " + e.getMessage()); + } + } + + // 新しい内容を編集できるようにEditTextを表示する + final EditText editText = new EditText(context); + editText.setText(fileContent.toString()); + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + editText.setMinLines(10); // 適切な行数を設定 + editText.setGravity(Gravity.TOP); // 上から入力されるように設定 + + // ボタン用のレイアウトパラメータを設定 + LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + buttonParams.setMargins(16, 16, 16, 16); // 任意のマージン設定 + + // 保存ボタンを作成 + Button saveButton = new Button(context); + saveButton.setText("Save"); + saveButton.setLayoutParams(buttonParams); // レイアウトパラメータを設定 + saveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 編集した内容をファイルに保存 + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write(editText.getText().toString()); + XposedBridge.log("File saved successfully."); + } catch (IOException e) { + XposedBridge.log("Error saving the file: " + e.getMessage()); + } + } + }); + + // 編集画面を表示するためのLayoutに追加 + LinearLayout layout = new LinearLayout(context); + layout.setOrientation(LinearLayout.VERTICAL); + layout.addView(editText); + layout.addView(saveButton); + + // ダイアログを表示して編集画面を表示する + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle("通知を無効にしているグループ"); + builder.setView(layout); + builder.setNegativeButton("キャンセル", null); + builder.show(); + } + } diff --git a/app/src/main/java/io/github/chipppppppppp/lime/hooks/Notif_invalid.java b/app/src/main/java/io/github/chipppppppppp/lime/hooks/Notif_invalid.java new file mode 100644 index 00000000..c2b59e3d --- /dev/null +++ b/app/src/main/java/io/github/chipppppppppp/lime/hooks/Notif_invalid.java @@ -0,0 +1,192 @@ +package io.github.chipppppppppp.lime.hooks; + +import android.app.AndroidAppHelper; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Build; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.callbacks.XC_LoadPackage; +import io.github.chipppppppppp.lime.LimeOptions; + +public class Notif_invalid implements IHook { + @Override + public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { + if (!limeOptions.Notif_invalid.checked) return; + XposedBridge.hookAllMethods( + loadPackageParam.classLoader.loadClass(Constants.RESPONSE_HOOK.className), + Constants.RESPONSE_HOOK.methodName, + new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + String paramValue = param.args[1].toString(); + if (paramValue.contains("chatName:") && paramValue.contains("getChats_result")) { + String chatName = extractChatName(paramValue); + if (chatName != null) { + // XposedBridge.log("Extracted chatName: " + chatName); + Context moduleContext = AndroidAppHelper.currentApplication(); + File dir = moduleContext.getFilesDir(); + saveChatNameToFile(chatName, dir); + } + } + } + + private String extractChatName(String paramValue) { + String marker = "chatName:"; + int startIndex = paramValue.indexOf(marker); + if (startIndex != -1) { + startIndex += marker.length(); + int endIndex = paramValue.indexOf(',', startIndex); + if (endIndex != -1) { + return paramValue.substring(startIndex, endIndex).trim(); + } + } + return null; + } + + private void saveChatNameToFile(String chatName, File dir) { + if (!dir.exists() && !dir.mkdirs()) { + XposedBridge.log("Failed to create directory: " + dir.getPath()); + return; + } + + File file = new File(dir, "Notification.txt"); + + try { + if (!file.exists() && !file.createNewFile()) { + XposedBridge.log("Failed to create file: " + file.getPath()); + return; + } + + List existingChatNames = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + existingChatNames.add(line.trim()); + } + } catch (IOException e) { + XposedBridge.log("Error reading file: " + e.getMessage()); + } + + if (!existingChatNames.contains(chatName.trim())) { + try (FileWriter writer = new FileWriter(file, true)) { + writer.write(chatName + "\n"); + XposedBridge.log("Saved chatName: " + chatName); + } catch (IOException e) { + XposedBridge.log("Error writing to file: " + e.getMessage()); + } + } else { + XposedBridge.log("Chat name already exists: " + chatName); + } + } catch (IOException e) { + XposedBridge.log("Error accessing file: " + e.getMessage()); + } + } + }); + + XposedHelpers.findAndHookMethod(NotificationManager.class, "notify", + String.class, int.class, Notification.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + + int id = (int) param.args[1]; + Notification notification = (Notification) param.args[2]; + + logNotificationDetails("NotificationManager.notify (with tag)", id, notification); + String subText = notification.extras.getString(Notification.EXTRA_SUB_TEXT); + List chatNamesFromFile = loadNamesFromFile(); + for (String chatName : chatNamesFromFile) { + if (subText != null && subText.contains(chatName)) { + param.setResult(null); + return; + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelId = notification.getChannelId(); + NotificationManager manager = (NotificationManager) AndroidAppHelper.currentApplication().getSystemService(Context.NOTIFICATION_SERVICE); + NotificationChannel channel = manager.getNotificationChannel(channelId); + + if (channel != null) { + String channelName = channel.getName().toString(); + // XposedBridge.log("Notification Channel Name: " + channelName); + } + } + } + }); + + XposedHelpers.findAndHookMethod(Notification.Builder.class, "setContentTitle", + CharSequence.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + CharSequence title = (CharSequence) param.args[0]; + + List chatNamesFromFile = loadNamesFromFile(); + + for (String chatName : chatNamesFromFile) { + if (title != null && title.toString().contains(chatName)) { + //XposedBridge.log("Notification title contains chatName from file. Title: " + title); + param.setResult(null); // nullを返して通知を表示しない + return; + } + } + //XposedBridge.log("Notification title does not contain any chatName from file. Title: " + title); + } + }); + } + + // 通知の詳細をログに記録するヘルパーメソッド + private void logNotificationDetails(String method, int id, Notification notification) { + XposedBridge.log(method + " called. ID: " + id); + + if (notification.extras != null) { + + String title = notification.extras.getString(Notification.EXTRA_TITLE); // タイトル + String text = notification.extras.getString(Notification.EXTRA_TEXT); // メインのテキスト + String subText = notification.extras.getString(Notification.EXTRA_SUB_TEXT); // サブテキスト + + /* + XposedBridge.log("Notification Title: " + (title != null ? title : "No Title")); + XposedBridge.log("Notification Text: " + (text != null ? text : "No Text")); + XposedBridge.log("Notification SubText: " + (subText != null ? subText : "No SubText")); + + */ + } else { + // XposedBridge.log("Notification extras is null."); + } + //XposedBridge.log("Notification Icon: " + notification.icon); + } + + private List loadNamesFromFile() { + List names = new ArrayList<>(); + Context moduleContext = AndroidAppHelper.currentApplication(); + File dir = moduleContext.getFilesDir(); + File file = new File(dir, "Notification.txt"); + if (!file.exists()) { + return names; + } + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + names.add(line.trim()); + } + } catch (IOException e) { + // XposedBridge.log("Error reading names from file: " + e.getMessage()); + } + + return names; + } +} \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 64554764..e7f4f757 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -78,4 +78,5 @@ 何もバックアップされていません 正しく取得できませんでした。\nアプリを再起動してください 送信したメッセージの既読者の確認 + 登録しているグループの通知をオフに \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 6a1ea2ec..67049fad 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -42,4 +42,5 @@ 貼上 保持未讀 + 登録しているグループの通知をオフに \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 176608e3..b654055e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -78,4 +78,5 @@ Show \"Read as unread\" switch for LSPatch Set nav color to Black Check read friends + 登録しているグループの通知をオフに