coidada commited on
Commit
6f4c9db
·
verified ·
1 Parent(s): 1f6e2c3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -0
app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import subprocess
4
+ import zipfile
5
+ import tempfile
6
+ import shutil
7
+
8
+ def decompile_file(file_obj):
9
+ if not file_obj:
10
+ return (
11
+ gr.update(visible=False), # code_view
12
+ gr.update(visible=False), # zip_info
13
+ gr.update(visible=False, value=None) # download_btn
14
+ )
15
+
16
+ file_path = file_obj.name
17
+ ext = os.path.splitext(file_path)[1].lower()
18
+
19
+ if ext == '.pyc':
20
+ # --- Обработка одиночного .pyc ---
21
+ # Декомпилируем через pycdc
22
+ result = subprocess.run(['pycdc', file_path], capture_output=True, text=True)
23
+ code = result.stdout
24
+ if result.stderr:
25
+ code += f"\n\n# ВНИМАНИЕ: Ошибки декомпилятора:\n# {result.stderr.replace('=', '')}"
26
+
27
+ # Сохраняем в .py для скачивания
28
+ temp_dir = tempfile.mkdtemp()
29
+ base_name = os.path.basename(file_path)
30
+ out_name = base_name[:-1] if base_name.endswith('c') else base_name + ".py"
31
+ out_path = os.path.join(temp_dir, out_name)
32
+
33
+ with open(out_path, "w", encoding="utf-8") as f:
34
+ f.write(code)
35
+
36
+ return (
37
+ gr.update(visible=True, value=code),
38
+ gr.update(visible=False),
39
+ gr.update(visible=True, value=out_path)
40
+ )
41
+
42
+ elif ext == '.zip':
43
+ # --- Обработка .zip архива ---
44
+ temp_dir = tempfile.mkdtemp()
45
+ extract_dir = os.path.join(temp_dir, "extracted")
46
+ out_zip_dir = os.path.join(temp_dir, "output")
47
+ os.makedirs(extract_dir)
48
+ os.makedirs(out_zip_dir)
49
+
50
+ out_zip_path = os.path.join(out_zip_dir, "decompiled_source.zip")
51
+
52
+ # Распаковываем
53
+ with zipfile.ZipFile(file_path, 'r') as zip_ref:
54
+ zip_ref.extractall(extract_dir)
55
+
56
+ # Рекурсивно ищем и декомпилируем .pyc
57
+ pyc_count = 0
58
+ for root, dirs, files in os.walk(extract_dir):
59
+ for file in files:
60
+ if file.lower().endswith('.pyc'):
61
+ pyc_count += 1
62
+ full_path = os.path.join(root, file)
63
+
64
+ # Декомпилируем
65
+ result = subprocess.run(['pycdc', full_path], capture_output=True, text=True)
66
+
67
+ # Сохраняем как .py
68
+ out_py = full_path[:-1]
69
+ with open(out_py, "w", encoding="utf-8") as f:
70
+ f.write(result.stdout)
71
+ if result.stderr:
72
+ f.write(f"\n# Errors:\n# {result.stderr}")
73
+
74
+ # Удаляем исходный .pyc
75
+ os.remove(full_path)
76
+
77
+ # Запаковываем обратно сохраняя структуру
78
+ shutil.make_archive(out_zip_path[:-4], 'zip', extract_dir)
79
+
80
+ zip_msg = f"## 📦 Архив успешно обработан!\n**Найдено и декомпилировано `.pyc` файлов:** {pyc_count}\n\n*Структура папок полностью сохранена.*"
81
+
82
+ return (
83
+ gr.update(visible=False),
84
+ gr.update(visible=True, value=zip_msg),
85
+ gr.update(visible=True, value=out_zip_path)
86
+ )
87
+
88
+ # --- Настройка UI ---
89
+ with gr.Blocks(title="PyLingual Docker Edition", theme=gr.themes.Monochrome()) as demo:
90
+ gr.Markdown("# 🐍 Python Bytecode Decompiler (.pyc / .zip)")
91
+
92
+ with gr.Row():
93
+ # ЛЕВАЯ КОЛОНКА (Drag & Drop)
94
+ with gr.Column(scale=1):
95
+ file_input = gr.File(
96
+ label="Закинь сюда .pyc или .zip файл",
97
+ file_types=[".pyc", ".zip"],
98
+ type="filepath",
99
+ file_count="single"
100
+ )
101
+
102
+ # ПРАВАЯ КОЛОНКА (Результаты)
103
+ with gr.Column(scale=1):
104
+ # Просмотр кода (только для .pyc)
105
+ code_view = gr.Code(
106
+ label="Декомпилированный код",
107
+ language="python",
108
+ interactive=False,
109
+ visible=False
110
+ )
111
+
112
+ # Инфо об архиве (только для .zip)
113
+ zip_info = gr.Markdown(
114
+ value="",
115
+ visible=False
116
+ )
117
+
118
+ # Кнопка скачивания (общая)
119
+ download_btn = gr.File(
120
+ label="📥 Скачать результат",
121
+ interactive=False,
122
+ visible=False
123
+ )
124
+
125
+ # Логика
126
+ file_input.change(
127
+ fn=decompile_file,
128
+ inputs=file_input,
129
+ outputs=[code_view, zip_info, download_btn]
130
+ )
131
+
132
+ if __name__ == "__main__":
133
+ demo.launch(server_name="0.0.0.0", server_port=7860)