Giter Club home page Giter Club logo

Comments (10)

Chipppppppppp avatar Chipppppppppp commented on June 1, 2024 2

すみません、忙しくて追えていませんでした
データベースをいじることで新たな道が開けそうですね!

from lime.

Chipppppppppp avatar Chipppppppppp commented on June 1, 2024 1

わかりました。

from lime.

Chipppppppppp avatar Chipppppppppp commented on June 1, 2024 1

できたら Pull Request にしてお願いします (完成していなくても Pull Request にして作業したほうがいいかもしれません)

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

方法がうまいこと、思い浮かばなくて、特定してくれたom5.cクラスの取り消された際の返り値が、一定なのを利用して、以下のコードで一応ログに残すことはできそう、、
使用方法はresultList に追加された、二個目の値がサーバーidになるので、SQlitemanagerでdata/data/jp.naver.line.android/database/naver.lien

のchat_historyで特定するって方法が一応あります、、、

// 結果を保持するリスト
List resultList = new ArrayList<>();

// 最後の値が0であるか
final boolean[] isLastValueZero = {false};

    hookTarget = lparam.classLoader.loadClass("om5.c");
    XposedHelpers.findAndHookMethod(hookTarget, "u", new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            Object result = param.getResult();
            
            if (result.toString().matches("[A-Za-z0-9]{33}")) {
                resultList.add(result);
                isLastValueZero[0] = false;
            }
     
            else if (result.toString().matches("\\d{18}")) {
                resultList.add(result);
                isLastValueZero[0] = false;
            }
            else if (result.equals("0") && resultList.size() == 2 && isLastValueZero[0] == false) {
                resultList.add(result);

                
                StringBuilder sb = new StringBuilder();
                for (Object obj : resultList) {
                    sb.append(obj.toString()).append(" ");
                }
                XposedBridge.log("削除されたメッセージ: " + sb.toString());

                resultList.clear();
                isLastValueZero[0] = false;
            }

            else {
                resultList.clear();
                isLastValueZero[0] = false;
            }
        }
    })

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

sqlite3を利用してます。
端末が対応していない場合は
https://github.com/rojenzaman/sqlite3-magisk-module
などで、sqlite3を導入しなければいけません。

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

そうですね!

ADBコマンドでは、以下のサイトの改変の仕方でメッセージ内容を変更できたのですが、

root権限(su)の与え方が悪いのか
モジュール上でコマンドを実行すると、data/dataファイルが見つかりません
とエラーが発生します、、

https://kajindowsxp.com/line/

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

一応訂正版です、
アプリを開いていないとメッセージが取得できないかもです

   hookTarget = lparam.classLoader.loadClass("org.apache.thrift.n");
        XposedBridge.hookAllMethods(hookTarget, "a", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                String paramValue = param.args[1].toString();

// DUMMY を含む場合のみログを表示
                if (paramValue.contains("type:DUMMY,")) {
                    // param1 と param2 の値を取得
                    String[] parts = paramValue.split(",");
                    String serverId = null;
                    String talkId = null;
                    for (String part : parts) {
                        if (part.trim().startsWith("param1:")) {
                            talkId  = part.trim().substring("param1:".length());

                        } else if (part.trim().startsWith("param2:")) {
                            serverId = part.trim().substring("param2:".length());
                        }
                    }

                        // 保存したserverIdとtalkIdを使用してcontentを取得して編集する
                        String content = getContentFromServerId(serverId);
                        String image_check = image_check(serverId);
                        String gruop_name = get_group_name(talkId);
                        String talk_name = talk_name(talkId);


                            List<String> pastValues = new ArrayList<>();

                            if (content != null && (gruop_name != null || talk_name != null)) {
                                String A = (gruop_name != null ? gruop_name : "") + (talk_name != null ? talk_name : "") + ":" + content + image_check;
                                XposedBridge.log("削除されたメッセージ: " + A);
// ログに残すファイルを指定
                                
                                String filePath = "/storage/emulated/0/Download/Test.txt";

// pastValues リストの内容を改行区切りでファイルに書き込むコマンド
                                String command = "su -c echo \"" + String.join("\n", A) + "\" >> " + filePath;

                                try {
             
                                    Process process = Runtime.getRuntime().exec(command);
                                    process.waitFor();
                                } catch (IOException | InterruptedException e) {
                                    e.printStackTrace();
                                }


                            }


                    }
                }

        });



    }
    int retryCount = 2;
    int retryInterval = 100;
    private String getContentFromServerId(String serverId) {
        String content = null;

        for (int i = 0; i < retryCount; i++) {
            try {
                String command = "su -c sqlite3 /data_mirror/data_ce/null/0/jp.naver.line.android/databases/naver_line " +
                        "\"SELECT content FROM chat_history WHERE server_id='" + serverId + "';\"";
                content = executeSQLite3Command(command);

                if (content != null) {
                    break;
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }try {Thread.sleep(retryInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return content;
    }
    private String get_group_name(String talkId) {
        String gruop_name = null;


        for (int i = 0; i < retryCount; i++) {
            try {
                String command = "su -c sqlite3 /data_mirror/data_ce/null/0/jp.naver.line.android/databases/naver_line " +
                        "\"SELECT name FROM groups WHERE id='" + talkId + "';\"";
                gruop_name = executeSQLite3Command(command);

                if (gruop_name != null) {
                    break;
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }


            try {
                Thread.sleep(retryInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();

            }}
        return gruop_name;
    }
    private String talk_name(String talkId) {
        String talk_name = null;


        for (int i = 0; i < retryCount; i++) {
            try {
                String command = "su -c sqlite3 /data_mirror/data_ce/null/0/jp.naver.line.android/databases/naver_line " +
                        "\"SELECT name FROM contacts WHERE m_id='" + talkId + "';\"";
                talk_name = executeSQLite3Command(command);

                if (talk_name != null) {
                    break;
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }


            try {
                Thread.sleep(retryInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        return talk_name;
    }


    private String image_check(String serverId) {
        String image_check = null;

        for (int i = 0; i < retryCount; i++) {
            try {
                String command = "su -c sqlite3 /data_mirror/data_ce/null/0/jp.naver.line.android/databases/naver_line " +
                        "\"SELECT attachement_image FROM chat_history WHERE server_id='" + serverId + "';\"";
                image_check = executeSQLite3Command(command);
                if ("1".equals(image_check)) {
                    image_check = "画像が削除されました";
                    break;
                }
                if ("0".equals(image_check)) {
                    image_check = " ";
                    break;
                }


            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(retryInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return  image_check;
    }


    // SQLite3コマンドを実行する
    private String executeSQLite3Command(String command) throws IOException, InterruptedException {
        try {
            java.lang.Process process = getRuntime().exec(command);
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuilder contentBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                contentBuilder.append(line);
            }
            process.waitFor();
            return contentBuilder.toString();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return null;
        }
    }

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

一応個人的には、ギリギリ実用的なところまで出来たので、この機能については後はお任せいたします(より良い方法が見つかった場合は再オープンさせてもらいます)。参考にもならない煩雑なものですがご自由にどうぞ

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

わかりました。

chathistoryのActivity見てますけど実装めんどくさい感じしますね
Micro-Gみたいに不可能って感じはしないですが、

色々また試してみます

from lime.

areteruhiro avatar areteruhiro commented on June 1, 2024

できたら Pull Request にしてお願いします (完成していなくても Pull Request にして作業したほうがいいかもしれません)

わかりました。

from lime.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.