Skip to content

Commit b484165

Browse files
authored
Update mirror.py
Signed-off-by: саня <109840177+kort0881@users.noreply.github.com>
1 parent 9a8a1ab commit b484165

1 file changed

Lines changed: 74 additions & 54 deletions

File tree

mirror.py

Lines changed: 74 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22
# mirror_with_sni.py
3-
# Зеркалирование источников + SNI-фильтрация + создание подписок
3+
# Зеркалирование источников + создание компактных подписок
44
# Требует: requests, PyGithub
55
# ENV: MY_TOKEN (GitHub token)
66

@@ -13,7 +13,7 @@
1313
import time
1414
from requests.adapters import HTTPAdapter
1515
from urllib3.util.retry import Retry
16-
from github import Github, Auth, GithubException
16+
from github import Github, Auth, GithubException, InputGitTreeElement
1717
from datetime import datetime
1818
import zoneinfo
1919

@@ -30,7 +30,6 @@
3030
RETRIES = 2
3131
REQUESTS_POOL = 10
3232
GITHUB_DELAY = 1.5
33-
MAX_KEYS_PER_FILE = 1000 # Максимум ключей в одном файле
3433

3534
CHROME_UA = (
3635
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
@@ -68,8 +67,6 @@
6867
"https://raw.githubusercontent.com/Argh94/V2RayAutoConfig/refs/heads/main/configs/Vless.txt",
6968
"https://raw.githubusercontent.com/Argh94/V2RayAutoConfig/refs/heads/main/configs/Hysteria2.txt",
7069
"https://raw.githubusercontent.com/mahdibland/V2RayAggregator/master/sub/sub_list.json",
71-
72-
# ----- НОВЫЕ ИСТОЧНИКИ -----
7370
"https://raw.githubusercontent.com/NiREvil/vless/main/sub/SSTime",
7471
"https://raw.githubusercontent.com/ndsphonemy/proxy-sub/main/speed.txt",
7572
"https://raw.githubusercontent.com/Mahdi0024/ProxyCollector/master/sub/proxies.txt",
@@ -185,6 +182,50 @@ def upload_file_if_changed(local_path: str, remote_path: str):
185182
else:
186183
raise
187184

185+
def upload_large_file_via_git(local_path: str, remote_path: str):
186+
"""Загрузка больших файлов через Git API"""
187+
try:
188+
with open(local_path, "rb") as f:
189+
content = f.read()
190+
191+
# Создаём blob
192+
time.sleep(GITHUB_DELAY)
193+
blob = repo.create_git_blob(content.decode('utf-8'), 'utf-8')
194+
195+
# Получаем текущий коммит main
196+
time.sleep(GITHUB_DELAY)
197+
ref = repo.get_git_ref('heads/main')
198+
commit = repo.get_git_commit(ref.object.sha)
199+
200+
# Создаём tree element
201+
element = InputGitTreeElement(
202+
path=remote_path,
203+
mode='100644',
204+
type='blob',
205+
sha=blob.sha
206+
)
207+
208+
# Создаём новый tree
209+
time.sleep(GITHUB_DELAY)
210+
base_tree = repo.get_git_tree(commit.tree.sha)
211+
new_tree = repo.create_git_tree([element], base_tree)
212+
213+
# Создаём коммит
214+
time.sleep(GITHUB_DELAY)
215+
new_commit = repo.create_git_commit(
216+
f"Update {remote_path} | {now_moscow()}",
217+
new_tree,
218+
[commit]
219+
)
220+
221+
# Обновляем референс
222+
time.sleep(GITHUB_DELAY)
223+
ref.edit(new_commit.sha)
224+
225+
print(f"{remote_path} загружен через Git API")
226+
except Exception as e:
227+
print(f"Ошибка загрузки {remote_path}: {e}")
228+
188229
def is_valid_proxy(line: str) -> bool:
189230
"""Проверка, является ли строка валидным прокси-ключом"""
190231
protocols = ['vless://', 'vmess://', 'trojan://', 'ss://',
@@ -211,19 +252,14 @@ def create_filtered_file():
211252
f.write("\n".join(out))
212253
return final_file
213254

214-
def split_into_chunks(items, chunk_size):
215-
"""Разбивает список на части"""
216-
for i in range(0, len(items), chunk_size):
217-
yield items[i:i + chunk_size]
218-
219255
def create_subscriptions():
220-
"""Создаёт подписки из всех собранных ключей"""
256+
"""Создаёт ТОЛЬКО 4 основных файла подписок"""
221257
print("\n" + "="*60)
222258
print("Создание подписок...")
223259

224260
all_keys = []
225261

226-
# Собираем все ключи из файлов 1.txt - N.txt
262+
# Собираем все ключи
227263
total = len(URLS)
228264
for i in range(1, total + 1):
229265
p = os.path.join(LOCAL_DIR, f"{i}.txt")
@@ -241,45 +277,24 @@ def create_subscriptions():
241277
all_keys = list(dict.fromkeys(all_keys))
242278
print(f"Всего уникальных ключей: {len(all_keys)}")
243279

280+
# Создаём ТОЛЬКО 4 файла
244281
subscriptions = []
245282

246-
# Разбиваем на части, если больше MAX_KEYS_PER_FILE
247-
if len(all_keys) > MAX_KEYS_PER_FILE:
248-
chunks = list(split_into_chunks(all_keys, MAX_KEYS_PER_FILE))
249-
print(f"Файл слишком большой, разбиваем на {len(chunks)} частей")
250-
251-
# Создаём части (raw)
252-
for idx, chunk in enumerate(chunks, 1):
253-
filename = f"all_part{idx}.txt"
254-
filepath = os.path.join(SUBSCRIPTIONS_DIR, filename)
255-
with open(filepath, "w", encoding="utf-8") as f:
256-
f.write("\n".join(chunk))
257-
subscriptions.append((filename, len(chunk)))
258-
259-
# Создаём части (base64)
260-
for idx, chunk in enumerate(chunks, 1):
261-
filename = f"all_part{idx}_base64.txt"
262-
filepath = os.path.join(SUBSCRIPTIONS_DIR, filename)
263-
with open(filepath, "w", encoding="utf-8") as f:
264-
content = "\n".join(chunk)
265-
encoded = base64.b64encode(content.encode('utf-8')).decode('utf-8')
266-
f.write(encoded)
267-
subscriptions.append((filename, len(chunk)))
268-
else:
269-
# Если меньше лимита, создаём один файл
270-
all_raw = os.path.join(SUBSCRIPTIONS_DIR, "all.txt")
271-
with open(all_raw, "w", encoding="utf-8") as f:
272-
f.write("\n".join(all_keys))
273-
subscriptions.append(("all.txt", len(all_keys)))
274-
275-
all_b64 = os.path.join(SUBSCRIPTIONS_DIR, "all_base64.txt")
276-
with open(all_b64, "w", encoding="utf-8") as f:
277-
content = "\n".join(all_keys)
278-
encoded = base64.b64encode(content.encode('utf-8')).decode('utf-8')
279-
f.write(encoded)
280-
subscriptions.append(("all_base64.txt", len(all_keys)))
283+
# 1. Все ключи (raw) - через Git API
284+
all_raw = os.path.join(SUBSCRIPTIONS_DIR, "all.txt")
285+
with open(all_raw, "w", encoding="utf-8") as f:
286+
f.write("\n".join(all_keys))
287+
subscriptions.append(("all.txt", len(all_keys), True))
288+
289+
# 2. Все ключи (base64) - через Git API
290+
all_b64 = os.path.join(SUBSCRIPTIONS_DIR, "all_base64.txt")
291+
with open(all_b64, "w", encoding="utf-8") as f:
292+
content = "\n".join(all_keys)
293+
encoded = base64.b64encode(content.encode('utf-8')).decode('utf-8')
294+
f.write(encoded)
295+
subscriptions.append(("all_base64.txt", len(all_keys), True))
281296

282-
# SNI-фильтрованные (из файла N+1.txt)
297+
# 3. SNI-фильтрованные
283298
sni_file = os.path.join(LOCAL_DIR, f"{total + 1}.txt")
284299
if os.path.exists(sni_file):
285300
with open(sni_file, "r", encoding="utf-8") as f:
@@ -290,23 +305,28 @@ def create_subscriptions():
290305
sni_raw = os.path.join(SUBSCRIPTIONS_DIR, "sni_filtered.txt")
291306
with open(sni_raw, "w", encoding="utf-8") as f:
292307
f.write("\n".join(sni_keys))
293-
subscriptions.append(("sni_filtered.txt", len(sni_keys)))
308+
subscriptions.append(("sni_filtered.txt", len(sni_keys), False))
294309

295310
# SNI base64
296311
sni_b64 = os.path.join(SUBSCRIPTIONS_DIR, "sni_filtered_base64.txt")
297312
with open(sni_b64, "w", encoding="utf-8") as f:
298313
content = "\n".join(sni_keys)
299314
encoded = base64.b64encode(content.encode('utf-8')).decode('utf-8')
300315
f.write(encoded)
301-
subscriptions.append(("sni_filtered_base64.txt", len(sni_keys)))
316+
subscriptions.append(("sni_filtered_base64.txt", len(sni_keys), False))
302317

303318
# Загружаем на GitHub
304319
print("\nЗагрузка подписок на GitHub...")
305-
for filename, count in subscriptions:
320+
for filename, count, use_git_api in subscriptions:
306321
try:
307322
local_path = os.path.join(SUBSCRIPTIONS_DIR, filename)
308323
remote_path = f"{SUBSCRIPTIONS_DIR}/{filename}"
309-
upload_file_if_changed(local_path, remote_path)
324+
325+
if use_git_api:
326+
upload_large_file_via_git(local_path, remote_path)
327+
else:
328+
upload_file_if_changed(local_path, remote_path)
329+
310330
except Exception as e:
311331
print(f"Ошибка загрузки {filename}: {e}")
312332

@@ -315,11 +335,11 @@ def create_subscriptions():
315335
print("✅ Подписки созданы!")
316336
print("="*60)
317337
print("\nСтатистика:")
318-
for filename, count in subscriptions:
338+
for filename, count, _ in subscriptions:
319339
print(f" {filename}: {count} ключей")
320340

321341
print(f"\n📌 Ссылки на подписки:")
322-
for filename, _ in subscriptions:
342+
for filename, _, _ in subscriptions:
323343
print(f"https://raw.githubusercontent.com/{REPO_NAME}/main/{SUBSCRIPTIONS_DIR}/{filename}")
324344
print("="*60 + "\n")
325345

0 commit comments

Comments
 (0)