mirror of
https://github.com/areteruhiro/LIME-beta-hiro.git
synced 2025-02-11 07:51:37 +09:00
既読者機能の修正
This commit is contained in:
parent
87f45c7961
commit
64a87bbce8
@ -42,6 +42,9 @@ public class LimeOptions {
|
|||||||
public Option removeAllServices = new Option("remove_Services", R.string.RemoveService, false);
|
public Option removeAllServices = new Option("remove_Services", R.string.RemoveService, false);
|
||||||
public Option calltone = new Option("calltone", R.string.calltone, false);
|
public Option calltone = new Option("calltone", R.string.calltone, false);
|
||||||
public Option ReadChecker = new Option("ReadChecker", R.string.ReadChecker, false);
|
public Option ReadChecker = new Option("ReadChecker", R.string.ReadChecker, false);
|
||||||
|
public Option MySendMessage = new Option("MySendMessage", R.string.MySendMessage, false);
|
||||||
|
|
||||||
|
|
||||||
public Option RemoveNotification = new Option("RemoveNotification", R.string.removeNotification, false);
|
public Option RemoveNotification = new Option("RemoveNotification", R.string.removeNotification, false);
|
||||||
public Option DarkColor = new Option("DarkColor", R.string.DarkColor, false);
|
public Option DarkColor = new Option("DarkColor", R.string.DarkColor, false);
|
||||||
public Option NoMuteMessage = new Option("NoMuteMessage", R.string.NoMuteMessage, false);
|
public Option NoMuteMessage = new Option("NoMuteMessage", R.string.NoMuteMessage, false);
|
||||||
@ -69,7 +72,7 @@ public class LimeOptions {
|
|||||||
preventUnsendMessage,
|
preventUnsendMessage,
|
||||||
sendMuteMessage,
|
sendMuteMessage,
|
||||||
Archived,
|
Archived,
|
||||||
ReadChecker,
|
ReadChecker,MySendMessage,
|
||||||
removeKeepUnread,
|
removeKeepUnread,
|
||||||
KeepUnreadLSpatch,
|
KeepUnreadLSpatch,
|
||||||
blockTracking,
|
blockTracking,
|
||||||
@ -83,4 +86,5 @@ public class LimeOptions {
|
|||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ import io.github.hiro.lime.hooks.RemoveIcons;
|
|||||||
import io.github.hiro.lime.hooks.RemoveNotification;
|
import io.github.hiro.lime.hooks.RemoveNotification;
|
||||||
import io.github.hiro.lime.hooks.RemoveReplyMute;
|
import io.github.hiro.lime.hooks.RemoveReplyMute;
|
||||||
import io.github.hiro.lime.hooks.RemoveVoiceRecord;
|
import io.github.hiro.lime.hooks.RemoveVoiceRecord;
|
||||||
|
import io.github.hiro.lime.hooks.Resend;
|
||||||
import io.github.hiro.lime.hooks.Ringtone;
|
import io.github.hiro.lime.hooks.Ringtone;
|
||||||
import io.github.hiro.lime.hooks.SendMuteMessage;
|
import io.github.hiro.lime.hooks.SendMuteMessage;
|
||||||
import io.github.hiro.lime.hooks.SpoofAndroidId;
|
import io.github.hiro.lime.hooks.SpoofAndroidId;
|
||||||
@ -45,6 +46,7 @@ import io.github.hiro.lime.hooks.UnsentRec;
|
|||||||
import io.github.hiro.lime.hooks.Archived;
|
import io.github.hiro.lime.hooks.Archived;
|
||||||
import io.github.hiro.lime.hooks.ReadChecker;
|
import io.github.hiro.lime.hooks.ReadChecker;
|
||||||
import io.github.hiro.lime.hooks.DarkColor;
|
import io.github.hiro.lime.hooks.DarkColor;
|
||||||
|
import io.github.hiro.lime.hooks.test;
|
||||||
|
|
||||||
|
|
||||||
public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResources, IXposedHookZygoteInit {
|
public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResources, IXposedHookZygoteInit {
|
||||||
@ -86,7 +88,7 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
|
|||||||
new RemoveNotification(),
|
new RemoveNotification(),
|
||||||
new Disabled_Group_notification(),
|
new Disabled_Group_notification(),
|
||||||
new PhotoAddNotification(),
|
new PhotoAddNotification(),
|
||||||
new RemoveVoiceRecord()
|
new RemoveVoiceRecord(),
|
||||||
};
|
};
|
||||||
|
|
||||||
public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
package io.github.hiro.lime.hooks;
|
package io.github.hiro.lime.hooks;
|
||||||
|
|
||||||
|
|
||||||
import android.app.AndroidAppHelper;
|
import android.app.AndroidAppHelper;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -18,18 +21,20 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
import de.robv.android.xposed.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XposedBridge;
|
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||||
import io.github.hiro.lime.LimeOptions;
|
import io.github.hiro.lime.LimeOptions;
|
||||||
|
|
||||||
|
|
||||||
public class KeepUnread implements IHook {
|
public class KeepUnread implements IHook {
|
||||||
static boolean keepUnread = true;
|
static boolean keepUnread = false;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
||||||
if (limeOptions.removeKeepUnread.checked) return;
|
if (limeOptions.removeKeepUnread.checked) return;
|
||||||
|
|
||||||
|
|
||||||
XposedHelpers.findAndHookMethod(
|
XposedHelpers.findAndHookMethod(
|
||||||
"com.linecorp.line.chatlist.view.fragment.ChatListFragment",
|
"com.linecorp.line.chatlist.view.fragment.ChatListFragment",
|
||||||
loadPackageParam.classLoader,
|
loadPackageParam.classLoader,
|
||||||
@ -41,28 +46,38 @@ public class KeepUnread implements IHook {
|
|||||||
View rootView = (View) param.getResult();
|
View rootView = (View) param.getResult();
|
||||||
Context appContext = rootView.getContext();
|
Context appContext = rootView.getContext();
|
||||||
|
|
||||||
|
|
||||||
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
|
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
|
||||||
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
||||||
|
|
||||||
|
|
||||||
RelativeLayout layout = new RelativeLayout(appContext);
|
RelativeLayout layout = new RelativeLayout(appContext);
|
||||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
|
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
|
||||||
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||||
layout.setLayoutParams(layoutParams);
|
layout.setLayoutParams(layoutParams);
|
||||||
|
|
||||||
|
|
||||||
keepUnread = readStateFromFile(appContext);
|
keepUnread = readStateFromFile(appContext);
|
||||||
ImageView imageView = new ImageView(appContext);
|
ImageView imageView = new ImageView(appContext);
|
||||||
updateSwitchImage(imageView, keepUnread, moduleContext);
|
updateSwitchImage(imageView, keepUnread, moduleContext);
|
||||||
|
|
||||||
DisplayMetrics displayMetrics = appContext.getResources().getDisplayMetrics();
|
|
||||||
int screenWidth = displayMetrics.widthPixels;
|
|
||||||
int screenHeight = displayMetrics.heightPixels;
|
|
||||||
|
|
||||||
int horizontalMargin = (int) (screenWidth * 0.5);
|
Resources resources = appContext.getResources();
|
||||||
int verticalMargin = (int) (screenHeight * 0.015);
|
Configuration configuration = resources.getConfiguration();
|
||||||
|
int smallestWidthDp = configuration.smallestScreenWidthDp;
|
||||||
|
|
||||||
|
|
||||||
|
float density = resources.getDisplayMetrics().density;
|
||||||
|
|
||||||
|
|
||||||
|
int horizontalMarginPx = (int) ((smallestWidthDp * 0.5) * density);
|
||||||
|
int verticalMarginPx = (int) (15 * density);
|
||||||
|
|
||||||
|
|
||||||
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(
|
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(
|
||||||
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||||
imageParams.setMargins(horizontalMargin, verticalMargin, 0, 0); // 動的に計算されたマージンを設定
|
imageParams.setMargins(horizontalMarginPx, verticalMarginPx, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
imageView.setOnClickListener(v -> {
|
imageView.setOnClickListener(v -> {
|
||||||
keepUnread = !keepUnread;
|
keepUnread = !keepUnread;
|
||||||
@ -70,23 +85,40 @@ public class KeepUnread implements IHook {
|
|||||||
saveStateToFile(appContext, keepUnread);
|
saveStateToFile(appContext, keepUnread);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
layout.addView(imageView, imageParams);
|
layout.addView(imageView, imageParams);
|
||||||
|
|
||||||
|
|
||||||
if (rootView instanceof ViewGroup) {
|
if (rootView instanceof ViewGroup) {
|
||||||
ViewGroup rootViewGroup = (ViewGroup) rootView;
|
ViewGroup rootViewGroup = (ViewGroup) rootView;
|
||||||
if (rootViewGroup.getChildCount() > 0 && rootViewGroup.getChildAt(0) instanceof ListView) {
|
|
||||||
ListView listView = (ListView) rootViewGroup.getChildAt(0);
|
|
||||||
|
boolean added = false;
|
||||||
|
for (int i = 0; i < rootViewGroup.getChildCount(); i++) {
|
||||||
|
View child = rootViewGroup.getChildAt(i);
|
||||||
|
if (child instanceof ListView) {
|
||||||
|
ListView listView = (ListView) child;
|
||||||
listView.addFooterView(layout);
|
listView.addFooterView(layout);
|
||||||
} else {
|
added = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!added) {
|
||||||
rootViewGroup.addView(layout);
|
rootViewGroup.addView(layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateSwitchImage(ImageView imageView, boolean isOn, Context moduleContext) {
|
private void updateSwitchImage(ImageView imageView, boolean isOn, Context moduleContext) {
|
||||||
|
|
||||||
|
|
||||||
String imageName = isOn ? "switch_on" : "switch_off";
|
String imageName = isOn ? "switch_on" : "switch_off";
|
||||||
int imageResource = moduleContext.getResources().getIdentifier(imageName, "drawable", "io.github.hiro.lime");
|
int imageResource = moduleContext.getResources().getIdentifier(imageName, "drawable", "io.github.hiro.lime");
|
||||||
|
|
||||||
|
|
||||||
if (imageResource != 0) {
|
if (imageResource != 0) {
|
||||||
Drawable drawable = moduleContext.getResources().getDrawable(imageResource, null);
|
Drawable drawable = moduleContext.getResources().getDrawable(imageResource, null);
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
@ -96,12 +128,14 @@ public class KeepUnread implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Drawable scaleDrawable(Drawable drawable, int width, int height) {
|
private Drawable scaleDrawable(Drawable drawable, int width, int height) {
|
||||||
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||||
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
|
||||||
return new BitmapDrawable(scaledBitmap);
|
return new BitmapDrawable(scaledBitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void saveStateToFile(Context context, boolean state) {
|
private void saveStateToFile(Context context, boolean state) {
|
||||||
String filename = "keep_unread_state.txt";
|
String filename = "keep_unread_state.txt";
|
||||||
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {
|
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {
|
||||||
@ -110,6 +144,7 @@ public class KeepUnread implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean readStateFromFile(Context context) {
|
private boolean readStateFromFile(Context context) {
|
||||||
String filename = "keep_unread_state.txt";
|
String filename = "keep_unread_state.txt";
|
||||||
try (FileInputStream fis = context.openFileInput(filename)) {
|
try (FileInputStream fis = context.openFileInput(filename)) {
|
||||||
@ -126,6 +161,7 @@ public class KeepUnread implements IHook {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
XposedHelpers.findAndHookMethod(
|
XposedHelpers.findAndHookMethod(
|
||||||
loadPackageParam.classLoader.loadClass(Constants.MARK_AS_READ_HOOK.className),
|
loadPackageParam.classLoader.loadClass(Constants.MARK_AS_READ_HOOK.className),
|
||||||
Constants.MARK_AS_READ_HOOK.methodName,
|
Constants.MARK_AS_READ_HOOK.methodName,
|
||||||
@ -138,19 +174,6 @@ public class KeepUnread implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XposedBridge.hookAllMethods(
|
|
||||||
loadPackageParam.classLoader.loadClass(Constants.RESPONSE_HOOK.className),
|
|
||||||
Constants.RESPONSE_HOOK.methodName,
|
|
||||||
new XC_MethodHook() {
|
|
||||||
@Override
|
|
||||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
|
||||||
if (param.args[0] != null && param.args[0].toString().equals("sendChatChecked")) {
|
|
||||||
param.setResult(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package io.github.hiro.lime.hooks;
|
package io.github.hiro.lime.hooks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import static io.github.hiro.lime.Main.limeOptions;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.AndroidAppHelper;
|
import android.app.AndroidAppHelper;
|
||||||
@ -49,6 +53,8 @@ public class ReadChecker implements IHook {
|
|||||||
private SQLiteDatabase db4 = null;
|
private SQLiteDatabase db4 = null;
|
||||||
private boolean shouldHookOnCreate = false;
|
private boolean shouldHookOnCreate = false;
|
||||||
private String currentGroupId = null;
|
private String currentGroupId = null;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
|
||||||
if (!limeOptions.ReadChecker.checked) return;
|
if (!limeOptions.ReadChecker.checked) return;
|
||||||
@ -57,6 +63,7 @@ public class ReadChecker implements IHook {
|
|||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
Application appContext = (Application) param.thisObject;
|
Application appContext = (Application) param.thisObject;
|
||||||
|
|
||||||
|
|
||||||
if (appContext == null) {
|
if (appContext == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -68,14 +75,19 @@ public class ReadChecker implements IHook {
|
|||||||
SQLiteDatabase.OpenParams dbParams1 = builder1.build();
|
SQLiteDatabase.OpenParams dbParams1 = builder1.build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SQLiteDatabase.OpenParams.Builder builder2 = new SQLiteDatabase.OpenParams.Builder();
|
SQLiteDatabase.OpenParams.Builder builder2 = new SQLiteDatabase.OpenParams.Builder();
|
||||||
builder2.addOpenFlags(SQLiteDatabase.OPEN_READWRITE);
|
builder2.addOpenFlags(SQLiteDatabase.OPEN_READWRITE);
|
||||||
SQLiteDatabase.OpenParams dbParams2 = builder2.build();
|
SQLiteDatabase.OpenParams dbParams2 = builder2.build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db3 = SQLiteDatabase.openDatabase(dbFile3, dbParams1);
|
db3 = SQLiteDatabase.openDatabase(dbFile3, dbParams1);
|
||||||
db4 = SQLiteDatabase.openDatabase(dbFile4, dbParams2);
|
db4 = SQLiteDatabase.openDatabase(dbFile4, dbParams2);
|
||||||
|
|
||||||
|
|
||||||
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
|
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
|
||||||
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
||||||
initializeLimeDatabase(appContext);
|
initializeLimeDatabase(appContext);
|
||||||
@ -85,12 +97,14 @@ public class ReadChecker implements IHook {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Class<?> chatHistoryRequestClass = XposedHelpers.findClass("com.linecorp.line.chat.request.ChatHistoryRequest", loadPackageParam.classLoader);
|
Class<?> chatHistoryRequestClass = XposedHelpers.findClass("com.linecorp.line.chat.request.ChatHistoryRequest", loadPackageParam.classLoader);
|
||||||
XposedHelpers.findAndHookMethod(chatHistoryRequestClass, "getChatId", new XC_MethodHook() {
|
XposedHelpers.findAndHookMethod(chatHistoryRequestClass, "getChatId", new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
String chatId = (String) param.getResult();
|
String chatId = (String) param.getResult();
|
||||||
//XposedBridge.log(chatId);
|
////XposedBridge.log(chatId);
|
||||||
if (isGroupExists(chatId)) {
|
if (isGroupExists(chatId)) {
|
||||||
shouldHookOnCreate = true;
|
shouldHookOnCreate = true;
|
||||||
currentGroupId = chatId;
|
currentGroupId = chatId;
|
||||||
@ -102,10 +116,13 @@ public class ReadChecker implements IHook {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Class<?> chatHistoryActivityClass = XposedHelpers.findClass("jp.naver.line.android.activity.chathistory.ChatHistoryActivity", loadPackageParam.classLoader);
|
Class<?> chatHistoryActivityClass = XposedHelpers.findClass("jp.naver.line.android.activity.chathistory.ChatHistoryActivity", loadPackageParam.classLoader);
|
||||||
XposedHelpers.findAndHookMethod(chatHistoryActivityClass, "onCreate", Bundle.class, new XC_MethodHook() {
|
XposedHelpers.findAndHookMethod(chatHistoryActivityClass, "onCreate", Bundle.class, new XC_MethodHook() {
|
||||||
Context moduleContext;
|
Context moduleContext;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
if (moduleContext == null) {
|
if (moduleContext == null) {
|
||||||
@ -113,22 +130,25 @@ public class ReadChecker implements IHook {
|
|||||||
Context systemContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext");
|
Context systemContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext");
|
||||||
moduleContext = systemContext.createPackageContext("io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
moduleContext = systemContext.createPackageContext("io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
XposedBridge.log("Failed to get module context: " + e.getMessage());
|
//XposedBridge.log("Failed to get module context: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
if (moduleContext == null) {
|
if (moduleContext == null) {
|
||||||
XposedBridge.log("Module context is null. Skipping hook.");
|
//XposedBridge.log("Module context is null. Skipping hook.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (shouldHookOnCreate && currentGroupId != null) {
|
if (shouldHookOnCreate && currentGroupId != null) {
|
||||||
if (!isNoGroup(currentGroupId)) {
|
if (!isNoGroup(currentGroupId)) {
|
||||||
Activity activity = (Activity) param.thisObject;
|
Activity activity = (Activity) param.thisObject;
|
||||||
|
|
||||||
|
|
||||||
addButton(activity, moduleContext);
|
addButton(activity, moduleContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,11 +156,14 @@ public class ReadChecker implements IHook {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isGroupExists(String groupId) {
|
private boolean isGroupExists(String groupId) {
|
||||||
if (limeDatabase == null) {
|
if (limeDatabase == null) {
|
||||||
// //XposedBridge.log("Database is not initialized.");
|
// ////XposedBridge.log("Database is not initialized.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String query = "SELECT 1 FROM group_messages WHERE group_id = ?";
|
String query = "SELECT 1 FROM group_messages WHERE group_id = ?";
|
||||||
@ -150,9 +173,10 @@ public class ReadChecker implements IHook {
|
|||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isNoGroup(String groupId) {
|
private boolean isNoGroup(String groupId) {
|
||||||
if (limeDatabase == null) {
|
if (limeDatabase == null) {
|
||||||
// //XposedBridge.log("Database is not initialized.");
|
// ////XposedBridge.log("Database is not initialized.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String query = "SELECT group_name FROM group_messages WHERE group_id = ?";
|
String query = "SELECT group_name FROM group_messages WHERE group_id = ?";
|
||||||
@ -163,17 +187,21 @@ public class ReadChecker implements IHook {
|
|||||||
noGroup = groupName == null || groupName.isEmpty();
|
noGroup = groupName == null || groupName.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cursor.close();
|
cursor.close();
|
||||||
return noGroup;
|
return noGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addButton(Activity activity, Context moduleContext) {
|
private void addButton(Activity activity, Context moduleContext) {
|
||||||
Button button = new Button(activity);
|
Button button = new Button(activity);
|
||||||
button.setText("R");
|
button.setText("R");
|
||||||
button.setBackgroundColor(Color.BLACK);
|
button.setBackgroundColor(Color.BLACK);
|
||||||
|
|
||||||
|
|
||||||
button.setTextColor(Color.WHITE);
|
button.setTextColor(Color.WHITE);
|
||||||
|
|
||||||
|
|
||||||
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
|
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
FrameLayout.LayoutParams.WRAP_CONTENT
|
||||||
@ -182,6 +210,7 @@ public class ReadChecker implements IHook {
|
|||||||
frameParams.topMargin = 150;
|
frameParams.topMargin = 150;
|
||||||
button.setLayoutParams(frameParams);
|
button.setLayoutParams(frameParams);
|
||||||
|
|
||||||
|
|
||||||
button.setOnClickListener(new View.OnClickListener() {
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -191,28 +220,36 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ViewGroup layout = activity.findViewById(android.R.id.content);
|
ViewGroup layout = activity.findViewById(android.R.id.content);
|
||||||
layout.addView(button);
|
layout.addView(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showDataForGroupId(Activity activity, String groupId, Context moduleContext) {
|
private void showDataForGroupId(Activity activity, String groupId, Context moduleContext) {
|
||||||
|
|
||||||
|
|
||||||
if (limeDatabase == null) {
|
if (limeDatabase == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String query = "SELECT server_id, content, created_time FROM group_messages WHERE group_id=? ORDER BY created_time ASC";
|
String query = "SELECT server_id, content, created_time FROM group_messages WHERE group_id=? ORDER BY created_time ASC";
|
||||||
Cursor cursor = limeDatabase.rawQuery(query, new String[]{groupId});
|
Cursor cursor = limeDatabase.rawQuery(query, new String[]{groupId});
|
||||||
|
|
||||||
|
|
||||||
Map<String, DataItem> dataItemMap = new HashMap<>();
|
Map<String, DataItem> dataItemMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
String serverId = cursor.getString(0);
|
String serverId = cursor.getString(0);
|
||||||
String content = cursor.getString(1);
|
String content = cursor.getString(1);
|
||||||
String createdTime = cursor.getString(2);
|
String createdTime = cursor.getString(2);
|
||||||
|
|
||||||
|
|
||||||
List<String> user_nameList = getuser_namesForServerId(serverId);
|
List<String> user_nameList = getuser_namesForServerId(serverId);
|
||||||
|
|
||||||
|
|
||||||
if (dataItemMap.containsKey(serverId)) {
|
if (dataItemMap.containsKey(serverId)) {
|
||||||
DataItem existingItem = dataItemMap.get(serverId);
|
DataItem existingItem = dataItemMap.get(serverId);
|
||||||
existingItem.user_names.addAll(user_nameList);
|
existingItem.user_names.addAll(user_nameList);
|
||||||
@ -224,16 +261,26 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
|
|
||||||
|
|
||||||
List<DataItem> sortedDataItems = new ArrayList<>(dataItemMap.values());
|
List<DataItem> sortedDataItems = new ArrayList<>(dataItemMap.values());
|
||||||
Collections.sort(sortedDataItems, Comparator.comparing(item -> item.createdTime));
|
Collections.sort(sortedDataItems, Comparator.comparing(item -> item.createdTime));
|
||||||
|
|
||||||
|
|
||||||
StringBuilder resultBuilder = new StringBuilder();
|
StringBuilder resultBuilder = new StringBuilder();
|
||||||
for (DataItem item : sortedDataItems) {
|
for (DataItem item : sortedDataItems) {
|
||||||
resultBuilder.append("Content: ").append(item.content != null ? item.content : "Media").append("\n");
|
resultBuilder.append("Content: ").append(item.content != null ? item.content : "Media").append("\n");
|
||||||
resultBuilder.append("Created Time: ").append(item.createdTime).append("\n");
|
resultBuilder.append("Created Time: ").append(item.createdTime).append("\n");
|
||||||
|
|
||||||
|
|
||||||
if (!item.user_names.isEmpty()) {
|
if (!item.user_names.isEmpty()) {
|
||||||
resultBuilder.append(moduleContext.getResources().getString(R.string.Reader)+" (").append(item.user_names.size()).append("):\n");
|
|
||||||
|
|
||||||
|
int newlineCount = 0;
|
||||||
|
for (String user_name : item.user_names) {
|
||||||
|
newlineCount += countNewlines(user_name);
|
||||||
|
}
|
||||||
|
resultBuilder.append(moduleContext.getResources().getString(R.string.Reader))
|
||||||
|
.append(" (").append(item.user_names.size() + newlineCount).append("):\n");
|
||||||
for (String user_name : item.user_names) {
|
for (String user_name : item.user_names) {
|
||||||
resultBuilder.append("- ").append(user_name).append("\n");
|
resultBuilder.append("- ").append(user_name).append("\n");
|
||||||
}
|
}
|
||||||
@ -243,23 +290,31 @@ public class ReadChecker implements IHook {
|
|||||||
resultBuilder.append("\n");
|
resultBuilder.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TextView textView = new TextView(activity);
|
TextView textView = new TextView(activity);
|
||||||
textView.setText(resultBuilder.toString());
|
textView.setText(resultBuilder.toString());
|
||||||
textView.setPadding(20, 20, 20, 20);
|
textView.setPadding(20, 20, 20, 20);
|
||||||
|
|
||||||
|
|
||||||
ScrollView scrollView = new ScrollView(activity);
|
ScrollView scrollView = new ScrollView(activity);
|
||||||
scrollView.addView(textView);
|
scrollView.addView(textView);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setTitle("READ Data");
|
builder.setTitle("READ Data");
|
||||||
builder.setView(scrollView);
|
builder.setView(scrollView);
|
||||||
|
|
||||||
|
|
||||||
builder.setPositiveButton("OK", null);
|
builder.setPositiveButton("OK", null);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
builder.setNegativeButton(moduleContext.getResources().getString(R.string.Delete), (dialog, which) -> {
|
builder.setNegativeButton(moduleContext.getResources().getString(R.string.Delete), (dialog, which) -> {
|
||||||
|
|
||||||
|
|
||||||
new AlertDialog.Builder(activity)
|
new AlertDialog.Builder(activity)
|
||||||
.setTitle(moduleContext.getResources().getString(R.string.check))
|
.setTitle(moduleContext.getResources().getString(R.string.check))
|
||||||
.setMessage(moduleContext.getResources().getString(R.string.really_delete))
|
.setMessage(moduleContext.getResources().getString(R.string.really_delete))
|
||||||
@ -268,46 +323,69 @@ public class ReadChecker implements IHook {
|
|||||||
.show();
|
.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
scrollView.post(() -> scrollView.fullScroll(View.FOCUS_DOWN));
|
scrollView.post(() -> scrollView.fullScroll(View.FOCUS_DOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void deleteGroupData(String groupId, Activity activity, Context moduleContext) {
|
private void deleteGroupData(String groupId, Activity activity, Context moduleContext) {
|
||||||
if (limeDatabase == null) {
|
if (limeDatabase == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String deleteQuery = "DELETE FROM group_messages WHERE group_id=?";
|
String deleteQuery = "DELETE FROM group_messages WHERE group_id=?";
|
||||||
limeDatabase.execSQL(deleteQuery, new String[]{groupId});
|
limeDatabase.execSQL(deleteQuery, new String[]{groupId});
|
||||||
Toast.makeText(activity, moduleContext.getResources().getString(R.string.Reader_Data_Delete_Success), Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, moduleContext.getResources().getString(R.string.Reader_Data_Delete_Success), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> getuser_namesForServerId(String serverId) {
|
private List<String> getuser_namesForServerId(String serverId) {
|
||||||
if (limeDatabase == null) {
|
if (limeDatabase == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
String query = "SELECT user_name FROM group_messages WHERE server_id=?";
|
||||||
// user_name のすべてのエントリを取得する
|
|
||||||
String query = "SELECT user_name FROM group_messages WHERE server_id=? ORDER BY created_time ASC";
|
|
||||||
Cursor cursor = limeDatabase.rawQuery(query, new String[]{serverId});
|
Cursor cursor = limeDatabase.rawQuery(query, new String[]{serverId});
|
||||||
List<String> userNames = new ArrayList<>();
|
List<String> user_names = new ArrayList<>();
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
String userNameStr = cursor.getString(0);
|
String userNameStr = cursor.getString(0);
|
||||||
if (userNameStr != null) {
|
if (userNameStr != null) {
|
||||||
// user_nameをそのままリストに追加
|
|
||||||
userNames.add(userNameStr);
|
|
||||||
|
String[] names = userNameStr.split("\n");
|
||||||
|
Collections.addAll(user_names, names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
return userNames;
|
return user_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int countNewlines(String text) {
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
for (char c : text.toCharArray()) {
|
||||||
|
if (c == '\n') {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class DataItem {
|
private static class DataItem {
|
||||||
String serverId;
|
String serverId;
|
||||||
String content;
|
String content;
|
||||||
String createdTime;
|
String createdTime;
|
||||||
Set<String> user_names;
|
Set<String> user_names;
|
||||||
|
|
||||||
|
|
||||||
DataItem(String serverId, String content, String createdTime) {
|
DataItem(String serverId, String content, String createdTime) {
|
||||||
this.serverId = serverId;
|
this.serverId = serverId;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
@ -315,6 +393,8 @@ public class ReadChecker implements IHook {
|
|||||||
this.user_names = new HashSet<>();
|
this.user_names = new HashSet<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void catchNotification(XC_LoadPackage.LoadPackageParam loadPackageParam, SQLiteDatabase db3, SQLiteDatabase db4, Context appContext, Context moduleContext) {
|
private void catchNotification(XC_LoadPackage.LoadPackageParam loadPackageParam, SQLiteDatabase db3, SQLiteDatabase db4, Context appContext, Context moduleContext) {
|
||||||
try {
|
try {
|
||||||
XposedBridge.hookAllMethods(
|
XposedBridge.hookAllMethods(
|
||||||
@ -324,12 +404,12 @@ public class ReadChecker implements IHook {
|
|||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
String paramValue = param.args[0].toString();
|
String paramValue = param.args[0].toString();
|
||||||
//XposedBridge.log(paramValue);
|
|
||||||
if (appContext == null) {
|
if (appContext == null) {
|
||||||
//XposedBridge.log("appContext is null!");
|
//
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Context moduleContext;
|
Context moduleContext;
|
||||||
try {
|
try {
|
||||||
moduleContext = appContext.createPackageContext(
|
moduleContext = appContext.createPackageContext(
|
||||||
@ -339,6 +419,7 @@ public class ReadChecker implements IHook {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (paramValue != null && paramValue.contains("type:NOTIFIED_READ_MESSAGE")) {
|
if (paramValue != null && paramValue.contains("type:NOTIFIED_READ_MESSAGE")) {
|
||||||
List<String> messages = extractMessages(paramValue);
|
List<String> messages = extractMessages(paramValue);
|
||||||
for (String message : messages) {
|
for (String message : messages) {
|
||||||
@ -353,21 +434,26 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> extractMessages(String paramValue) {
|
private List<String> extractMessages(String paramValue) {
|
||||||
List<String> messages = new ArrayList<>();
|
List<String> messages = new ArrayList<>();
|
||||||
Pattern pattern = Pattern.compile("type:NOTIFIED_READ_MESSAGE.*?(?=type:|$)");
|
Pattern pattern = Pattern.compile("type:NOTIFIED_READ_MESSAGE.*?(?=type:|$)");
|
||||||
Matcher matcher = pattern.matcher(paramValue);
|
Matcher matcher = pattern.matcher(paramValue);
|
||||||
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
messages.add(matcher.group().trim());
|
messages.add(matcher.group().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void fetchDataAndSave(SQLiteDatabase db3, SQLiteDatabase db4, String paramValue, Context context, Context moduleContext) {
|
private void fetchDataAndSave(SQLiteDatabase db3, SQLiteDatabase db4, String paramValue, Context context, Context moduleContext) {
|
||||||
File dbFile = new File(context.getFilesDir(), "data_log.txt");
|
File dbFile = new File(context.getFilesDir(), "data_log.txt");
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String serverId = extractServerId(paramValue, context);
|
String serverId = extractServerId(paramValue, context);
|
||||||
String checkedUser = extractCheckedUser(paramValue);
|
String checkedUser = extractCheckedUser(paramValue);
|
||||||
@ -375,6 +461,7 @@ public class ReadChecker implements IHook {
|
|||||||
writeToFile(dbFile, "Missing parameters: serverId=" + serverId + ", checkedUser=" + checkedUser);
|
writeToFile(dbFile, "Missing parameters: serverId=" + serverId + ", checkedUser=" + checkedUser);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String SendUser = queryDatabase(db3, "SELECT from_mid FROM chat_history WHERE server_id=?", serverId);
|
||||||
String groupId = queryDatabase(db3, "SELECT chat_id FROM chat_history WHERE server_id=?", serverId);
|
String groupId = queryDatabase(db3, "SELECT chat_id FROM chat_history WHERE server_id=?", serverId);
|
||||||
String groupName = queryDatabase(db3, "SELECT name FROM groups WHERE id=?", groupId);
|
String groupName = queryDatabase(db3, "SELECT name FROM groups WHERE id=?", groupId);
|
||||||
String content = queryDatabase(db3, "SELECT content FROM chat_history WHERE server_id=?", serverId);
|
String content = queryDatabase(db3, "SELECT content FROM chat_history WHERE server_id=?", serverId);
|
||||||
@ -400,15 +487,17 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String finalContent = (content != null && !content.isEmpty()) ? content : (!mediaDescription.isEmpty() ? mediaDescription : "No content:" + serverId);
|
String finalContent = (content != null && !content.isEmpty()) ? content : (!mediaDescription.isEmpty() ? mediaDescription : "No content:" + serverId);
|
||||||
saveData(groupId, serverId, checkedUser, groupName, finalContent, user_name, timeFormatted, context);
|
saveData(SendUser, groupId, serverId, checkedUser, groupName, finalContent, user_name, timeFormatted, context);
|
||||||
// markPreviousMessagesAsRead(groupId, checkedUser, timeEpochStr, context);
|
// markPreviousMessagesAsRead(groupId, checkedUser, timeEpochStr, context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void markPreviousMessagesAsRead(String groupId, String checkedUser, String timeEpochStr, Context context) {
|
private void markPreviousMessagesAsRead(String groupId, String checkedUser, String timeEpochStr, Context context) {
|
||||||
initializeLimeDatabase(context);
|
initializeLimeDatabase(context);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String query = "SELECT server_id, content, created_time, user_name FROM group_messages " +
|
String query = "SELECT server_id, content, created_time, user_name FROM group_messages " +
|
||||||
"WHERE group_id=? AND created_time<? AND user_name NOT LIKE ?";
|
"WHERE group_id=? AND created_time<? AND user_name NOT LIKE ?";
|
||||||
@ -423,10 +512,12 @@ public class ReadChecker implements IHook {
|
|||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put("user_name", updatedUserName);
|
values.put("user_name", updatedUserName);
|
||||||
|
|
||||||
|
|
||||||
limeDatabase.update("group_messages", values, "group_id=? AND server_id=?",
|
limeDatabase.update("group_messages", values, "group_id=? AND server_id=?",
|
||||||
new String[]{groupId, previousServerId});
|
new String[]{groupId, previousServerId});
|
||||||
|
|
||||||
// //XposedBridge.log("Marked as read in lime_data.db: Group_id: " + groupId + ", Server_id: " + previousServerId + ", Updated user_name: " + updatedUserName);
|
|
||||||
|
// ////XposedBridge.log("Marked as read in lime_data.db: Group_id: " + groupId + ", Server_id: " + previousServerId + ", Updated user_name: " + updatedUserName);
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -434,6 +525,7 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void writeToFile(File file, String text) {
|
private void writeToFile(File file, String text) {
|
||||||
try (FileWriter writer = new FileWriter(file, true)) {
|
try (FileWriter writer = new FileWriter(file, true)) {
|
||||||
writer.write(text + "\n");
|
writer.write(text + "\n");
|
||||||
@ -441,6 +533,7 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String formatMessageTime(String timeEpochStr) {
|
private String formatMessageTime(String timeEpochStr) {
|
||||||
if (timeEpochStr == null) return null;
|
if (timeEpochStr == null) return null;
|
||||||
long timeEpoch = Long.parseLong(timeEpochStr);
|
long timeEpoch = Long.parseLong(timeEpochStr);
|
||||||
@ -448,43 +541,55 @@ public class ReadChecker implements IHook {
|
|||||||
return sdf.format(new Date(timeEpoch));
|
return sdf.format(new Date(timeEpoch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String extractCheckedUser(String paramValue) {
|
private String extractCheckedUser(String paramValue) {
|
||||||
Pattern pattern = Pattern.compile("param2:([a-zA-Z0-9]+)");
|
Pattern pattern = Pattern.compile("param2:([a-zA-Z0-9]+)");
|
||||||
Matcher matcher = pattern.matcher(paramValue);
|
Matcher matcher = pattern.matcher(paramValue);
|
||||||
|
|
||||||
|
|
||||||
return matcher.find() ? matcher.group(1) : null;
|
return matcher.find() ? matcher.group(1) : null;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String extractServerId(String paramValue, Context context) {
|
private String extractServerId(String paramValue, Context context) {
|
||||||
Pattern pattern = Pattern.compile("param3:([0-9]+)");
|
Pattern pattern = Pattern.compile("param3:([0-9]+)");
|
||||||
Matcher matcher = pattern.matcher(paramValue);
|
Matcher matcher = pattern.matcher(paramValue);
|
||||||
|
//XposedBridge.log(paramValue);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
saveParamToFile(paramValue, context);
|
saveParamToFile(paramValue, context);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void saveParamToFile(String paramValue, Context context) {
|
private void saveParamToFile(String paramValue, Context context) {
|
||||||
try {
|
try {
|
||||||
File logFile = new File(context.getFilesDir(), "missing_param_values.txt");
|
File logFile = new File(context.getFilesDir(), "missing_param_values.txt");
|
||||||
|
|
||||||
|
|
||||||
if (!logFile.exists()) {
|
if (!logFile.exists()) {
|
||||||
logFile.createNewFile();
|
logFile.createNewFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FileWriter writer = new FileWriter(logFile, true);
|
FileWriter writer = new FileWriter(logFile, true);
|
||||||
writer.append("Missing serverId in paramValue:").append(paramValue).append("\n");
|
writer.append("Missing serverId in paramValue:").append(paramValue).append("\n");
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
// //XposedBridge.log("Error writing paramValue to file: " + e.getMessage());
|
// ////XposedBridge.log("Error writing paramValue to file: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String queryDatabase(SQLiteDatabase db, String query, String... selectionArgs) {
|
private String queryDatabase(SQLiteDatabase db, String query, String... selectionArgs) {
|
||||||
if (db == null) {
|
if (db == null) {
|
||||||
// //XposedBridge.log("Database is not initialized.");
|
// ////XposedBridge.log("Database is not initialized.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Cursor cursor = db.rawQuery(query, selectionArgs);
|
Cursor cursor = db.rawQuery(query, selectionArgs);
|
||||||
@ -496,21 +601,24 @@ public class ReadChecker implements IHook {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initializeLimeDatabase(Context context) {
|
private void initializeLimeDatabase(Context context) {
|
||||||
|
|
||||||
|
|
||||||
File oldDbFile = new File(context.getFilesDir(), "lime_data.db");
|
File oldDbFile = new File(context.getFilesDir(), "lime_data.db");
|
||||||
if (oldDbFile.exists()) {
|
if (oldDbFile.exists()) {
|
||||||
boolean deleted = oldDbFile.delete();
|
boolean deleted = oldDbFile.delete();
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
//XposedBridge.log("Old database file lime_data.db deleted.");
|
////XposedBridge.log("Old database file lime_data.db deleted.");
|
||||||
} else {
|
} else {
|
||||||
//XposedBridge.log("Failed to delete old database file lime_data.db.");
|
////XposedBridge.log("Failed to delete old database file lime_data.db.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 新しいデータベースファイルの初期化
|
// 新しいデータベースファイルの初期化
|
||||||
File dbFile = new File(context.getFilesDir(), "lime_checked_data.db");
|
File dbFile = new File(context.getFilesDir(), "lime_checked_data.db");
|
||||||
limeDatabase = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
|
limeDatabase = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
|
||||||
|
|
||||||
|
|
||||||
String createGroupTable = "CREATE TABLE IF NOT EXISTS group_messages (" +
|
String createGroupTable = "CREATE TABLE IF NOT EXISTS group_messages (" +
|
||||||
"group_id TEXT NOT NULL, " +
|
"group_id TEXT NOT NULL, " +
|
||||||
"server_id TEXT NOT NULL, " +
|
"server_id TEXT NOT NULL, " +
|
||||||
@ -522,12 +630,16 @@ public class ReadChecker implements IHook {
|
|||||||
"PRIMARY KEY(group_id, server_id, checked_user)" +
|
"PRIMARY KEY(group_id, server_id, checked_user)" +
|
||||||
");";
|
");";
|
||||||
|
|
||||||
|
|
||||||
limeDatabase.execSQL(createGroupTable);
|
limeDatabase.execSQL(createGroupTable);
|
||||||
// //XposedBridge.log("Database initialized and group_messages table created.");
|
// ////XposedBridge.log("Database initialized and group_messages table created.");
|
||||||
}
|
}
|
||||||
private void saveData(String groupId, String serverId, String checkedUser, String groupName, String content, String user_name, String createdTime, Context context) {
|
|
||||||
|
|
||||||
|
private void saveData( String SendUser, String groupId, String serverId, String checkedUser, String groupName, String content, String user_name, String createdTime, Context context) {
|
||||||
if (groupName == null) {
|
if (groupName == null) {
|
||||||
Log.w("saveData", "group_name is null. Skipping save operation.");
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
@ -539,22 +651,23 @@ public class ReadChecker implements IHook {
|
|||||||
String existingUserName = cursor.getString(1);
|
String existingUserName = cursor.getString(1);
|
||||||
String currentTime = getCurrentTime();
|
String currentTime = getCurrentTime();
|
||||||
|
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
if (!existingUserName.contains(user_name)) {
|
if (!existingUserName.contains(user_name)) {
|
||||||
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
|
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put("user_name", updatedUserName);
|
values.put("user_name", updatedUserName);
|
||||||
limeDatabase.update("group_messages", values, "server_id=? AND checked_user=?", new String[]{serverId, checkedUser});
|
limeDatabase.update("group_messages", values, "server_id=? AND checked_user=?", new String[]{serverId, checkedUser});
|
||||||
// //XposedBridge.log("User name updated for server_id: " + serverId + ", checked_user: " + checkedUser);
|
// ////XposedBridge.log("User name updated for server_id: " + serverId + ", checked_user: " + checkedUser);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
insertNewRecord(groupId, serverId, checkedUser, groupName, content, "-" + user_name + " [" + currentTime + "]", createdTime);
|
insertNewRecord(SendUser, groupId, serverId, checkedUser, groupName, content, "-" + user_name + " [" + currentTime + "]", createdTime);
|
||||||
}
|
}
|
||||||
updateOtherRecordsUserNames(groupId, user_name, currentTime);
|
updateOtherRecordsUserNames(groupId, user_name, currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("saveData", "Error during data existence check or update:", e);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
@ -562,23 +675,27 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateOtherRecordsUserNames(String groupId, String user_name, String currentTime) {
|
private void updateOtherRecordsUserNames(String groupId, String user_name, String currentTime) {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
String selectOtherQuery = "SELECT server_id, user_name FROM group_messages WHERE group_id=? AND user_name NOT LIKE ?";
|
String selectOtherQuery = "SELECT server_id, user_name FROM group_messages WHERE group_id=? AND user_name NOT LIKE ?";
|
||||||
cursor = limeDatabase.rawQuery(selectOtherQuery, new String[]{groupId, "%-" + user_name + "%"});
|
cursor = limeDatabase.rawQuery(selectOtherQuery, new String[]{groupId, "%-" + user_name + "%"});
|
||||||
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
String serverId = cursor.getString(cursor.getColumnIndexOrThrow("server_id"));
|
String serverId = cursor.getString(cursor.getColumnIndexOrThrow("server_id"));
|
||||||
String existingUserName = cursor.getString(cursor.getColumnIndexOrThrow("user_name"));
|
String existingUserName = cursor.getString(cursor.getColumnIndexOrThrow("user_name"));
|
||||||
|
|
||||||
|
|
||||||
if (!existingUserName.contains(user_name)) {
|
if (!existingUserName.contains(user_name)) {
|
||||||
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
|
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put("user_name", updatedUserName);
|
values.put("user_name", updatedUserName);
|
||||||
|
|
||||||
|
|
||||||
limeDatabase.update("group_messages", values, "group_id=? AND server_id=?", new String[]{groupId, serverId});
|
limeDatabase.update("group_messages", values, "group_id=? AND server_id=?", new String[]{groupId, serverId});
|
||||||
// //XposedBridge.log("Updated user_name for other records in group_id: " + groupId + ", server_id: " + serverId);
|
// ////XposedBridge.log("Updated user_name for other records in group_id: " + groupId + ", server_id: " + serverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -590,18 +707,32 @@ public class ReadChecker implements IHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getCurrentTime() {
|
private String getCurrentTime() {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
||||||
return sdf.format(new Date());
|
return sdf.format(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertNewRecord(String groupId, String serverId, String checkedUser, String groupName, String content, String user_name, String createdTime) {
|
|
||||||
try {
|
private void insertNewRecord(String SendUser, String groupId, String serverId, String checkedUser, String groupName, String content, String user_name, String createdTime) {
|
||||||
String insertQuery = "INSERT INTO group_messages(group_id, server_id, checked_user, group_name, content, user_name, created_time)" +
|
String insertQuery = "INSERT INTO group_messages(group_id, server_id, checked_user, group_name, content, user_name, created_time)" +
|
||||||
" VALUES(?, ?, ?, ?, ?, ?, ?);";
|
" VALUES(?, ?, ?, ?, ?, ?, ?);";
|
||||||
|
if (!limeOptions.MySendMessage.checked) {
|
||||||
limeDatabase.execSQL(insertQuery, new Object[]{groupId, serverId, checkedUser, groupName, content, user_name, createdTime});
|
limeDatabase.execSQL(insertQuery, new Object[]{groupId, serverId, checkedUser, groupName, content, user_name, createdTime});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SendUser == null) {
|
||||||
|
try {
|
||||||
|
limeDatabase.beginTransaction();
|
||||||
|
limeDatabase.execSQL(insertQuery, new Object[]{groupId, serverId, checkedUser, groupName, content, user_name, createdTime});
|
||||||
|
limeDatabase.setTransactionSuccessful();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
limeDatabase.endTransaction();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 451 KiB After Width: | Height: | Size: 20 KiB |
@ -131,4 +131,8 @@
|
|||||||
<string name="AutomaticBackup">定期的にバックアップ</string>
|
<string name="AutomaticBackup">定期的にバックアップ</string>
|
||||||
<string name="set_id">Set ID</string>
|
<string name="set_id">Set ID</string>
|
||||||
<string name="RemoveVoiceRecord">音声ボタンを無効化</string>
|
<string name="RemoveVoiceRecord">音声ボタンを無効化</string>
|
||||||
|
<string name="MySendMessage">(既読機能)自分以外のメッセージを保存しない</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -125,4 +125,6 @@
|
|||||||
<string name="AutomaticBackup">將您訂閱的群組的通知靜音</string>
|
<string name="AutomaticBackup">將您訂閱的群組的通知靜音</string>
|
||||||
<string name="RemoveVoiceRecord">禁用音訊按鈕</string>
|
<string name="RemoveVoiceRecord">禁用音訊按鈕</string>
|
||||||
|
|
||||||
|
<string name="MySendMessage">(讀取功能)請勿儲存您自己以外的信息</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -134,4 +134,9 @@
|
|||||||
<string name="Talk_Auto_Back_up_Error">Error occurred during automatic backup</string>
|
<string name="Talk_Auto_Back_up_Error">Error occurred during automatic backup</string>
|
||||||
<string name="Talk_Picture_Back_up_Success">The talk picture folder was successfully backed up</string>
|
<string name="Talk_Picture_Back_up_Success">The talk picture folder was successfully backed up</string>
|
||||||
<string name="RemoveVoiceRecord">Enable audio button</string>
|
<string name="RemoveVoiceRecord">Enable audio button</string>
|
||||||
|
|
||||||
|
<string name="MySendMessage">(Read function) Do not save messages other than your own</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user