coidada commited on
Commit
f6f8acc
·
verified ·
1 Parent(s): 466bd89

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -67
app.py CHANGED
@@ -1,81 +1,48 @@
1
  import gradio as gr
2
  import subprocess
3
  import tempfile
4
- import shutil
5
  import os
6
- import zipfile
7
 
8
- def build_stub_jar(zip_file) -> tuple[str, str | None]:
9
- if zip_file is None:
10
- return "⚠️ Пожалуйста, загрузите .zip архив с .java файлами.", None
11
 
12
- workdir = tempfile.mkdtemp(prefix="stub_builder_")
13
  log_lines = []
14
 
15
  try:
16
- src_dir = os.path.join(workdir, "src")
17
- classes_dir = os.path.join(workdir, "classes")
18
- os.makedirs(src_dir, exist_ok=True)
19
- os.makedirs(classes_dir, exist_ok=True)
20
 
21
- log_lines.append("📦 Распаковка архива...")
22
- with zipfile.ZipFile(zip_file.name, 'r') as zf:
23
- zf.extractall(src_dir)
24
-
25
- # Ищем все .java файлы (включая подпапки)
26
- java_files = []
27
- for root, dirs, files in os.walk(src_dir):
28
- for file in files:
29
- if file.endswith(".java"):
30
- java_files.append(os.path.join(root, file))
31
-
32
- if not java_files:
33
- log_lines.append("❌ В архиве не найдено .java файлов!")
34
- return "\n".join(log_lines), None
35
-
36
- log_lines.append(f"🔍 Найдено .java файлов: {len(java_files)}")
37
 
38
- # Создаем файл со списком исходников (чтобы не упереться в лимит длины команды)
39
- sources_list_path = os.path.join(workdir, "sources.txt")
40
- with open(sources_list_path, "w", encoding="utf-8") as f:
41
- for jf in java_files:
42
- f.write(f'"{jf}"\n')
43
-
44
- # ─── ШАГ 1: Компиляция (javac) ──────────────────────────────
45
- log_lines.append("\n⚙️ Компиляция Java исходников...")
46
- javac_cmd = [
47
- "javac",
48
- "-encoding", "UTF-8",
49
- "-g:none", # Убираем отладочную инфу для уменьшения веса
50
- "-nowarn", # Игнорируем варнинги
51
- "-d", classes_dir,
52
- f"@{sources_list_path}"
53
  ]
54
 
55
- result = subprocess.run(javac_cmd, capture_output=True, text=True)
 
 
 
 
 
56
  if result.stdout: log_lines.append(result.stdout)
57
  if result.stderr: log_lines.append(result.stderr)
58
 
59
- if result.returncode != 0:
60
- log_lines.append(f"\n❌ Ошибка компиляции (код {result.returncode})")
61
  return "\n".join(log_lines), None
62
 
63
- log_lines.append("✅ Успешно скомпилировано в .class файлы")
64
-
65
- # ─── ШАГ 2: Упаковка в JAR ─────────────────────────────────
66
- out_jar = os.path.join(workdir, "custom_stubs.jar")
67
- log_lines.append("\n📦 Упаковка в JAR...")
68
-
69
- jar_cmd = ["jar", "cf", out_jar, "-C", classes_dir, "."]
70
- result2 = subprocess.run(jar_cmd, capture_output=True, text=True)
71
-
72
- if result2.returncode != 0:
73
- log_lines.append(f"\n❌ Ошибка создания JAR (код {result2.returncode})")
74
- if result2.stderr: log_lines.append(result2.stderr)
75
- return "\n".join(log_lines), None
76
-
77
  jar_size = os.path.getsize(out_jar)
78
- log_lines.append(f"🎉 Готово! custom_stubs.jar ({jar_size:,} bytes)")
 
79
 
80
  return "\n".join(log_lines), out_jar
81
 
@@ -85,23 +52,23 @@ def build_stub_jar(zip_file) -> tuple[str, str | None]:
85
 
86
  CSS = """
87
  @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Space+Grotesk:wght@400;600;700&display=swap');
88
- :root { --bg: #0d0e14; --surface: #13141e; --border: #22253a; --accent: #3ecf8e; --text: #e2e4f0; }
89
  body, .gradio-container { background: var(--bg) !important; font-family: 'Space Grotesk', sans-serif !important; color: var(--text) !important; }
90
  .gr-panel, .gr-box, .gr-form { background: var(--surface) !important; border: 1px solid var(--border) !important; border-radius: 12px !important; }
91
  """
92
 
93
- with gr.Blocks(css=CSS, title="Java Stub Generator") as demo:
94
- gr.HTML("<h1 style='text-align:center; padding:20px;'>☕ Java ZIP → Stub JAR</h1>")
95
 
96
  with gr.Row():
97
  with gr.Column():
98
- zip_input = gr.File(label="Загрузите ZIP с .java файлами", file_types=[".zip"])
99
- build_btn = gr.Button("⚙️ Сгенерировать JAR", variant="primary")
100
  with gr.Column():
101
- log_output = gr.Textbox(label="Лог сборки", lines=10, interactive=False)
102
- jar_output = gr.File(label="Скачать готовый .jar", interactive=False)
103
 
104
- build_btn.click(fn=build_stub_jar, inputs=[zip_input], outputs=[log_output, jar_output])
105
 
106
  if __name__ == "__main__":
107
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import gradio as gr
2
  import subprocess
3
  import tempfile
 
4
  import os
5
+ import shutil
6
 
7
+ def convert_apk_to_jar(file_obj) -> tuple[str, str | None]:
8
+ if file_obj is None:
9
+ return "⚠️ Пожалуйста, загрузите .apk или .dex файл.", None
10
 
11
+ workdir = tempfile.mkdtemp(prefix="dex2jar_")
12
  log_lines = []
13
 
14
  try:
15
+ out_jar = os.path.join(workdir, "app_stubs.jar")
16
+ file_name = os.path.basename(file_obj.name)
 
 
17
 
18
+ log_lines.append(f"📦 Файл загружен: {file_name}")
19
+ log_lines.append("⚙️ Запуск dex2jar (конвертация Dalvik -> JVM)...")
20
+ log_lines.append("⏳ Это может занять 1-3 минуты для больших приложений (например, Telegram).")
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ # Запускаем d2j-dex2jar
23
+ cmd = [
24
+ "d2j-dex2jar",
25
+ file_obj.name,
26
+ "-o", out_jar,
27
+ "--force"
 
 
 
 
 
 
 
 
 
28
  ]
29
 
30
+ # Увеличиваем лимит памяти для Java, так как Telegram огромный
31
+ env = os.environ.copy()
32
+ env["JAVA_OPTS"] = "-Xmx2048m"
33
+
34
+ result = subprocess.run(cmd, capture_output=True, text=True, env=env)
35
+
36
  if result.stdout: log_lines.append(result.stdout)
37
  if result.stderr: log_lines.append(result.stderr)
38
 
39
+ if not os.path.exists(out_jar) or result.returncode != 0:
40
+ log_lines.append(f"\n❌ Ошибка конвертации (код {result.returncode})")
41
  return "\n".join(log_lines), None
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  jar_size = os.path.getsize(out_jar)
44
+ log_lines.append(f"\n✅ Готово! app_stubs.jar ({jar_size // 1024 // 1024} MB)")
45
+ log_lines.append("🚀 Теперь загрузи этот JAR во второе поле твоего Kotlin-компилятора!")
46
 
47
  return "\n".join(log_lines), out_jar
48
 
 
52
 
53
  CSS = """
54
  @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Space+Grotesk:wght@400;600;700&display=swap');
55
+ :root { --bg: #0d0e14; --surface: #13141e; --border: #22253a; --accent: #ff4757; --text: #e2e4f0; }
56
  body, .gradio-container { background: var(--bg) !important; font-family: 'Space Grotesk', sans-serif !important; color: var(--text) !important; }
57
  .gr-panel, .gr-box, .gr-form { background: var(--surface) !important; border: 1px solid var(--border) !important; border-radius: 12px !important; }
58
  """
59
 
60
+ with gr.Blocks(css=CSS, title="APK to Stub Generator") as demo:
61
+ gr.HTML("<h1 style='text-align:center; padding:20px;'>🤖 APK/DEX → Stub JAR</h1><p style='text-align:center; color:#888;'>Генератор стабов для Xposed-модулей без декомпиляции в Java</p>")
62
 
63
  with gr.Row():
64
  with gr.Column():
65
+ file_input = gr.File(label="Загрузите .apk или .dex файл", file_types=[".apk", ".dex"])
66
+ build_btn = gr.Button("⚙️ Создать JAR", variant="primary")
67
  with gr.Column():
68
+ log_output = gr.Textbox(label="Лог конвертации", lines=12, interactive=False)
69
+ jar_output = gr.File(label="Скачать готовый .jar стаб", interactive=False)
70
 
71
+ build_btn.click(fn=convert_apk_to_jar, inputs=[file_input], outputs=[log_output, jar_output])
72
 
73
  if __name__ == "__main__":
74
  demo.launch(server_name="0.0.0.0", server_port=7860)