1
0
mirror of https://github.com/areteruhiro/LIME-beta-hiro.git synced 2025-02-06 05:21:37 +09:00

既読者機能の修正

This commit is contained in:
areteruhiro 2024-12-25 02:22:46 +09:00
parent 87f45c7961
commit 64a87bbce8
9 changed files with 245 additions and 74 deletions

View File

@ -42,6 +42,9 @@ public class LimeOptions {
public Option removeAllServices = new Option("remove_Services", R.string.RemoveService, false);
public Option calltone = new Option("calltone", R.string.calltone, 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 DarkColor = new Option("DarkColor", R.string.DarkColor, false);
public Option NoMuteMessage = new Option("NoMuteMessage", R.string.NoMuteMessage, false);
@ -69,7 +72,7 @@ public class LimeOptions {
preventUnsendMessage,
sendMuteMessage,
Archived,
ReadChecker,
ReadChecker,MySendMessage,
removeKeepUnread,
KeepUnreadLSpatch,
blockTracking,
@ -83,4 +86,5 @@ public class LimeOptions {
};
}

View File

@ -37,6 +37,7 @@ import io.github.hiro.lime.hooks.RemoveIcons;
import io.github.hiro.lime.hooks.RemoveNotification;
import io.github.hiro.lime.hooks.RemoveReplyMute;
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.SendMuteMessage;
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.ReadChecker;
import io.github.hiro.lime.hooks.DarkColor;
import io.github.hiro.lime.hooks.test;
public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResources, IXposedHookZygoteInit {
@ -86,7 +88,7 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
new RemoveNotification(),
new Disabled_Group_notification(),
new PhotoAddNotification(),
new RemoveVoiceRecord()
new RemoveVoiceRecord(),
};
public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

View File

@ -1,11 +1,14 @@
package io.github.hiro.lime.hooks;
import android.app.AndroidAppHelper;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -18,18 +21,20 @@ import java.io.FileOutputStream;
import java.io.IOException;
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.hiro.lime.LimeOptions;
public class KeepUnread implements IHook {
static boolean keepUnread = true;
static boolean keepUnread = false;
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (limeOptions.removeKeepUnread.checked) return;
XposedHelpers.findAndHookMethod(
"com.linecorp.line.chatlist.view.fragment.ChatListFragment",
loadPackageParam.classLoader,
@ -41,28 +46,38 @@ public class KeepUnread implements IHook {
View rootView = (View) param.getResult();
Context appContext = rootView.getContext();
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
RelativeLayout layout = new RelativeLayout(appContext);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layout.setLayoutParams(layoutParams);
keepUnread = readStateFromFile(appContext);
ImageView imageView = new ImageView(appContext);
updateSwitchImage(imageView, keepUnread, moduleContext);
DisplayMetrics displayMetrics = appContext.getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
int horizontalMargin = (int) (screenWidth * 0.5);
int verticalMargin = (int) (screenHeight * 0.015);
Resources resources = appContext.getResources();
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.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
imageParams.setMargins(horizontalMargin, verticalMargin, 0, 0); // 動的に計算されたマージンを設定
imageParams.setMargins(horizontalMarginPx, verticalMarginPx, 0, 0);
imageView.setOnClickListener(v -> {
keepUnread = !keepUnread;
@ -70,23 +85,40 @@ public class KeepUnread implements IHook {
saveStateToFile(appContext, keepUnread);
});
layout.addView(imageView, imageParams);
if (rootView instanceof ViewGroup) {
ViewGroup rootViewGroup = (ViewGroup) rootView;
if (rootViewGroup.getChildCount() > 0 && rootViewGroup.getChildAt(0) instanceof ListView) {
ListView listView = (ListView) rootViewGroup.getChildAt(0);
listView.addFooterView(layout);
} else {
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);
added = true;
break;
}
}
if (!added) {
rootViewGroup.addView(layout);
}
}
}
private void updateSwitchImage(ImageView imageView, boolean isOn, Context moduleContext) {
String imageName = isOn ? "switch_on" : "switch_off";
int imageResource = moduleContext.getResources().getIdentifier(imageName, "drawable", "io.github.hiro.lime");
if (imageResource != 0) {
Drawable drawable = moduleContext.getResources().getDrawable(imageResource, null);
if (drawable != null) {
@ -96,12 +128,14 @@ public class KeepUnread implements IHook {
}
}
private Drawable scaleDrawable(Drawable drawable, int width, int height) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
return new BitmapDrawable(scaledBitmap);
}
private void saveStateToFile(Context context, boolean state) {
String filename = "keep_unread_state.txt";
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {
@ -110,6 +144,7 @@ public class KeepUnread implements IHook {
}
}
private boolean readStateFromFile(Context context) {
String filename = "keep_unread_state.txt";
try (FileInputStream fis = context.openFileInput(filename)) {
@ -126,6 +161,7 @@ public class KeepUnread implements IHook {
}
);
XposedHelpers.findAndHookMethod(
loadPackageParam.classLoader.loadClass(Constants.MARK_AS_READ_HOOK.className),
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);
}
}
}
);
}
}

View File

@ -1,6 +1,10 @@
package io.github.hiro.lime.hooks;
import static io.github.hiro.lime.Main.limeOptions;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AndroidAppHelper;
@ -49,6 +53,8 @@ public class ReadChecker implements IHook {
private SQLiteDatabase db4 = null;
private boolean shouldHookOnCreate = false;
private String currentGroupId = null;
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!limeOptions.ReadChecker.checked) return;
@ -57,6 +63,7 @@ public class ReadChecker implements IHook {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Application appContext = (Application) param.thisObject;
if (appContext == null) {
return;
}
@ -68,29 +75,36 @@ public class ReadChecker implements IHook {
SQLiteDatabase.OpenParams dbParams1 = builder1.build();
SQLiteDatabase.OpenParams.Builder builder2 = new SQLiteDatabase.OpenParams.Builder();
builder2.addOpenFlags(SQLiteDatabase.OPEN_READWRITE);
SQLiteDatabase.OpenParams dbParams2 = builder2.build();
db3 = SQLiteDatabase.openDatabase(dbFile3, dbParams1);
db4 = SQLiteDatabase.openDatabase(dbFile4, dbParams2);
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
initializeLimeDatabase(appContext);
catchNotification(loadPackageParam, db3, db4, appContext,moduleContext);
catchNotification(loadPackageParam, db3, db4, appContext, moduleContext);
}
}
});
Class<?> chatHistoryRequestClass = XposedHelpers.findClass("com.linecorp.line.chat.request.ChatHistoryRequest", loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(chatHistoryRequestClass, "getChatId", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String chatId = (String) param.getResult();
//XposedBridge.log(chatId);
////XposedBridge.log(chatId);
if (isGroupExists(chatId)) {
shouldHookOnCreate = true;
currentGroupId = chatId;
@ -102,10 +116,13 @@ public class ReadChecker implements IHook {
});
Class<?> chatHistoryActivityClass = XposedHelpers.findClass("jp.naver.line.android.activity.chathistory.ChatHistoryActivity", loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(chatHistoryActivityClass, "onCreate", Bundle.class, new XC_MethodHook() {
Context moduleContext;
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (moduleContext == null) {
@ -113,22 +130,25 @@ public class ReadChecker implements IHook {
Context systemContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext");
moduleContext = systemContext.createPackageContext("io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
} catch (Exception e) {
XposedBridge.log("Failed to get module context: " + e.getMessage());
//XposedBridge.log("Failed to get module context: " + e.getMessage());
}
}
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (moduleContext == null) {
XposedBridge.log("Module context is null. Skipping hook.");
//XposedBridge.log("Module context is null. Skipping hook.");
return;
}
if (shouldHookOnCreate && currentGroupId != null) {
if (!isNoGroup(currentGroupId)) {
Activity activity = (Activity) param.thisObject;
addButton(activity, moduleContext);
}
}
@ -136,11 +156,14 @@ public class ReadChecker implements IHook {
});
}
private boolean isGroupExists(String groupId) {
if (limeDatabase == null) {
// //XposedBridge.log("Database is not initialized.");
// ////XposedBridge.log("Database is not initialized.");
return false;
}
String query = "SELECT 1 FROM group_messages WHERE group_id = ?";
@ -150,9 +173,10 @@ public class ReadChecker implements IHook {
return exists;
}
private boolean isNoGroup(String groupId) {
if (limeDatabase == null) {
// //XposedBridge.log("Database is not initialized.");
// ////XposedBridge.log("Database is not initialized.");
return true;
}
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();
}
cursor.close();
return noGroup;
}
private void addButton(Activity activity,Context moduleContext) {
private void addButton(Activity activity, Context moduleContext) {
Button button = new Button(activity);
button.setText("R");
button.setBackgroundColor(Color.BLACK);
button.setTextColor(Color.WHITE);
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
@ -182,37 +210,46 @@ public class ReadChecker implements IHook {
frameParams.topMargin = 150;
button.setLayoutParams(frameParams);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (currentGroupId != null) {
showDataForGroupId(activity, currentGroupId,moduleContext);
showDataForGroupId(activity, currentGroupId, moduleContext);
}
}
});
ViewGroup layout = activity.findViewById(android.R.id.content);
layout.addView(button);
}
private void showDataForGroupId(Activity activity, String groupId,Context moduleContext) {
private void showDataForGroupId(Activity activity, String groupId, Context moduleContext) {
if (limeDatabase == null) {
return;
}
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});
Map<String, DataItem> dataItemMap = new HashMap<>();
while (cursor.moveToNext()) {
String serverId = cursor.getString(0);
String content = cursor.getString(1);
String createdTime = cursor.getString(2);
List<String> user_nameList = getuser_namesForServerId(serverId);
if (dataItemMap.containsKey(serverId)) {
DataItem existingItem = dataItemMap.get(serverId);
existingItem.user_names.addAll(user_nameList);
@ -224,16 +261,26 @@ public class ReadChecker implements IHook {
}
cursor.close();
List<DataItem> sortedDataItems = new ArrayList<>(dataItemMap.values());
Collections.sort(sortedDataItems, Comparator.comparing(item -> item.createdTime));
StringBuilder resultBuilder = new StringBuilder();
for (DataItem item : sortedDataItems) {
resultBuilder.append("Content: ").append(item.content != null ? item.content : "Media").append("\n");
resultBuilder.append("Created Time: ").append(item.createdTime).append("\n");
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) {
resultBuilder.append("- ").append(user_name).append("\n");
}
@ -243,71 +290,102 @@ public class ReadChecker implements IHook {
resultBuilder.append("\n");
}
TextView textView = new TextView(activity);
textView.setText(resultBuilder.toString());
textView.setPadding(20, 20, 20, 20);
ScrollView scrollView = new ScrollView(activity);
scrollView.addView(textView);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("READ Data");
builder.setView(scrollView);
builder.setPositiveButton("OK", null);
builder.setNegativeButton(moduleContext.getResources().getString(R.string.Delete), (dialog, which) -> {
new AlertDialog.Builder(activity)
.setTitle(moduleContext.getResources().getString(R.string.check))
.setMessage(moduleContext.getResources().getString(R.string.really_delete))
.setPositiveButton(moduleContext.getResources().getString(R.string.yes), (confirmDialog, confirmWhich) -> deleteGroupData(groupId,activity,moduleContext))
.setPositiveButton(moduleContext.getResources().getString(R.string.yes), (confirmDialog, confirmWhich) -> deleteGroupData(groupId, activity, moduleContext))
.setNegativeButton(moduleContext.getResources().getString(R.string.no), null)
.show();
});
AlertDialog dialog = builder.create();
dialog.show();
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) {
return;
}
String deleteQuery = "DELETE FROM group_messages WHERE group_id=?";
limeDatabase.execSQL(deleteQuery, new String[]{groupId});
Toast.makeText(activity, moduleContext.getResources().getString(R.string.Reader_Data_Delete_Success), Toast.LENGTH_SHORT).show();
}
private List<String> getuser_namesForServerId(String serverId) {
if (limeDatabase == null) {
return Collections.emptyList();
}
// user_name のすべてのエントリを取得する
String query = "SELECT user_name FROM group_messages WHERE server_id=? ORDER BY created_time ASC";
String query = "SELECT user_name FROM group_messages WHERE server_id=?";
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);
if (userNameStr != null) {
// user_nameをそのままリストに追加
userNames.add(userNameStr);
String[] names = userNameStr.split("\n");
Collections.addAll(user_names, names);
}
}
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 {
String serverId;
String content;
String createdTime;
Set<String> user_names;
DataItem(String serverId, String content, String createdTime) {
this.serverId = serverId;
this.content = content;
@ -315,7 +393,9 @@ public class ReadChecker implements IHook {
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 {
XposedBridge.hookAllMethods(
loadPackageParam.classLoader.loadClass(Constants.NOTIFICATION_READ_HOOK.className),
@ -324,21 +404,22 @@ public class ReadChecker implements IHook {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String paramValue = param.args[0].toString();
//XposedBridge.log(paramValue);
if (appContext == null) {
//XposedBridge.log("appContext is null!");
//
return;
}
Context moduleContext;
try {
moduleContext = appContext.createPackageContext(
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
// //XposedBridge.log("Failed to create package context: " + e.getMessage());
////XposedBridge.log("Failed to create package context: " + e.getMessage());
return;
}
if (paramValue != null && paramValue.contains("type:NOTIFIED_READ_MESSAGE")) {
List<String> messages = extractMessages(paramValue);
for (String message : messages) {
@ -353,21 +434,26 @@ public class ReadChecker implements IHook {
}
}
private List<String> extractMessages(String paramValue) {
List<String> messages = new ArrayList<>();
Pattern pattern = Pattern.compile("type:NOTIFIED_READ_MESSAGE.*?(?=type:|$)");
Matcher matcher = pattern.matcher(paramValue);
while (matcher.find()) {
messages.add(matcher.group().trim());
}
return messages;
}
private void fetchDataAndSave(SQLiteDatabase db3, SQLiteDatabase db4, String paramValue, Context context, Context moduleContext) {
File dbFile = new File(context.getFilesDir(), "data_log.txt");
try {
String serverId = extractServerId(paramValue, context);
String checkedUser = extractCheckedUser(paramValue);
@ -375,6 +461,7 @@ public class ReadChecker implements IHook {
writeToFile(dbFile, "Missing parameters: serverId=" + serverId + ", checkedUser=" + checkedUser);
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 groupName = queryDatabase(db3, "SELECT name FROM groups WHERE id=?", groupId);
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);
saveData(groupId, serverId, checkedUser, groupName, finalContent, user_name, timeFormatted, context);
// markPreviousMessagesAsRead(groupId, checkedUser, timeEpochStr, context);
saveData(SendUser, groupId, serverId, checkedUser, groupName, finalContent, user_name, timeFormatted, context);
// markPreviousMessagesAsRead(groupId, checkedUser, timeEpochStr, context);
} catch (Exception e) {
}
}
private void markPreviousMessagesAsRead(String groupId, String checkedUser, String timeEpochStr, Context context) {
initializeLimeDatabase(context);
try {
String query = "SELECT server_id, content, created_time, user_name FROM group_messages " +
"WHERE group_id=? AND created_time<? AND user_name NOT LIKE ?";
@ -423,10 +512,12 @@ public class ReadChecker implements IHook {
ContentValues values = new ContentValues();
values.put("user_name", updatedUserName);
limeDatabase.update("group_messages", values, "group_id=? AND server_id=?",
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();
} catch (Exception e) {
@ -434,6 +525,7 @@ public class ReadChecker implements IHook {
}
}
private void writeToFile(File file, String text) {
try (FileWriter writer = new FileWriter(file, true)) {
writer.write(text + "\n");
@ -441,6 +533,7 @@ public class ReadChecker implements IHook {
}
}
private String formatMessageTime(String timeEpochStr) {
if (timeEpochStr == null) return null;
long timeEpoch = Long.parseLong(timeEpochStr);
@ -448,43 +541,55 @@ public class ReadChecker implements IHook {
return sdf.format(new Date(timeEpoch));
}
private String extractCheckedUser(String paramValue) {
Pattern pattern = Pattern.compile("param2:([a-zA-Z0-9]+)");
Matcher matcher = pattern.matcher(paramValue);
return matcher.find() ? matcher.group(1) : null;
}
private String extractServerId(String paramValue, Context context) {
Pattern pattern = Pattern.compile("param3:([0-9]+)");
Matcher matcher = pattern.matcher(paramValue);
//XposedBridge.log(paramValue);
if (matcher.find()) {
return matcher.group(1);
} else {
saveParamToFile(paramValue, context);
return null;
}
}
private void saveParamToFile(String paramValue, Context context) {
try {
File logFile = new File(context.getFilesDir(), "missing_param_values.txt");
if (!logFile.exists()) {
logFile.createNewFile();
}
FileWriter writer = new FileWriter(logFile, true);
writer.append("Missing serverId in paramValue:").append(paramValue).append("\n");
writer.close();
} 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) {
if (db == null) {
// //XposedBridge.log("Database is not initialized.");
// ////XposedBridge.log("Database is not initialized.");
return null;
}
Cursor cursor = db.rawQuery(query, selectionArgs);
@ -496,21 +601,24 @@ public class ReadChecker implements IHook {
return result;
}
private void initializeLimeDatabase(Context context) {
File oldDbFile = new File(context.getFilesDir(), "lime_data.db");
if (oldDbFile.exists()) {
boolean deleted = oldDbFile.delete();
if (deleted) {
//XposedBridge.log("Old database file lime_data.db deleted.");
////XposedBridge.log("Old database file lime_data.db deleted.");
} 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");
limeDatabase = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
String createGroupTable = "CREATE TABLE IF NOT EXISTS group_messages (" +
"group_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)" +
");";
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) {
Log.w("saveData", "group_name is null. Skipping save operation.");
return;
}
Cursor cursor = null;
@ -539,22 +651,23 @@ public class ReadChecker implements IHook {
String existingUserName = cursor.getString(1);
String currentTime = getCurrentTime();
if (count > 0) {
if (!existingUserName.contains(user_name)) {
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
ContentValues values = new ContentValues();
values.put("user_name", updatedUserName);
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 {
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);
}
} catch (Exception e) {
Log.e("saveData", "Error during data existence check or update:", e);
} finally {
if (cursor != null) {
cursor.close();
@ -562,23 +675,27 @@ public class ReadChecker implements IHook {
}
}
private void updateOtherRecordsUserNames(String groupId, String user_name, String currentTime) {
Cursor cursor = null;
try {
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 + "%"});
while (cursor.moveToNext()) {
String serverId = cursor.getString(cursor.getColumnIndexOrThrow("server_id"));
String existingUserName = cursor.getString(cursor.getColumnIndexOrThrow("user_name"));
if (!existingUserName.contains(user_name)) {
String updatedUserName = existingUserName + (existingUserName.isEmpty() ? "" : "\n") + "-" + user_name + " [" + currentTime + "]";
ContentValues values = new ContentValues();
values.put("user_name", updatedUserName);
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) {
@ -590,18 +707,32 @@ public class ReadChecker implements IHook {
}
}
private String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return sdf.format(new Date());
}
private void insertNewRecord(String groupId, String serverId, String checkedUser, String groupName, String content, String user_name, String createdTime) {
try {
String insertQuery = "INSERT INTO group_messages(group_id, server_id, checked_user, group_name, content, user_name, created_time)" +
"VALUES(?, ?, ?, ?, ?, ?, ?);";
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)" +
" VALUES(?, ?, ?, ?, ?, ?, ?);";
if (!limeOptions.MySendMessage.checked) {
limeDatabase.execSQL(insertQuery, new Object[]{groupId, serverId, checkedUser, groupName, content, user_name, createdTime});
} catch (Exception e) {
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) {
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

View File

@ -131,4 +131,8 @@
<string name="AutomaticBackup">定期的にバックアップ</string>
<string name="set_id">Set ID</string>
<string name="RemoveVoiceRecord">音声ボタンを無効化</string>
<string name="MySendMessage">(既読機能)自分以外のメッセージを保存しない</string>
</resources>

View File

@ -125,4 +125,6 @@
<string name="AutomaticBackup">將您訂閱的群組的通知靜音</string>
<string name="RemoveVoiceRecord">禁用音訊按鈕</string>
<string name="MySendMessage">(讀取功能)請勿儲存您自己以外的信息</string>
</resources>

View File

@ -134,4 +134,9 @@
<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="RemoveVoiceRecord">Enable audio button</string>
<string name="MySendMessage">(Read function) Do not save messages other than your own</string>
</resources>