11#!/usr/bin/env python3
2- # Mirror.py
3- # Скачивание и сортировка прокси-ключей
4- # Требует: requests
2+ # Mirror.py — CLEAN MIRROR VERSION (with host:port:scheme de-dup)
53
64import os
5+ import shutil
76import requests
8- import base64
7+ import urllib . parse
98
10- # -------------------- Настройки --------------------
11- LOCAL_DIR = "githubmirror"
12- NEW_DIR = os .path .join (LOCAL_DIR , "new" )
13- CLEAN_DIR = os .path .join (LOCAL_DIR , "clean" )
9+ BASE_DIR = "githubmirror"
10+ NEW_DIR = os .path .join (BASE_DIR , "new" )
11+ CLEAN_DIR = os .path .join (BASE_DIR , "clean" )
1412
15- # Протоколы
16- PROTOCOLS = ["vless" , "vmess" , "trojan" , "ss" , "hysteria" , "hysteria2" , "hy2" , "tuic" ]
13+ PROTOCOLS = [
14+ "vless" , "vmess" , "trojan" , "ss" ,
15+ "hysteria" , "hysteria2" , "hy2" , "tuic"
16+ ]
1717
18- # Источники
1918URLS = [
2019 "https://github.com/sakha1370/OpenRay/raw/refs/heads/main/output/all_valid_proxies.txt" ,
2120 "https://raw.githubusercontent.com/sevcator/5ubscrpt10n/main/protocols/vl.txt" ,
5352 "https://raw.githubusercontent.com/MrMohebi/xray-proxy-grabber-telegram/master/collected-proxies/row-url/all.txt" ,
5453]
5554
56- # -------------------- Функции --------------------
57- def is_valid_proxy (line ):
58- line = line .strip ().lower ()
59- return any (line .startswith (p + "://" ) for p in PROTOCOLS )
55+ def clean_start ():
56+ if os .path .exists (BASE_DIR ):
57+ shutil .rmtree (BASE_DIR )
58+ os .makedirs (NEW_DIR )
59+ os .makedirs (CLEAN_DIR )
6060
61- def get_protocol (line ):
62- line = line .strip ().lower ()
61+ def protocol_of (line : str ):
6362 for p in PROTOCOLS :
6463 if line .startswith (p + "://" ):
6564 return p
66- return "other"
65+ return None
66+
67+ def extract_host_port_scheme (line : str ):
68+ try :
69+ u = urllib .parse .urlparse (line )
70+ return u .hostname , u .port , u .scheme
71+ except Exception :
72+ return None , None , None
73+
74+ def main ():
75+ clean_start ()
76+
77+ all_keys = []
6778
68- def download_sources ():
69- all_lines = []
7079 print ("Скачиваем источники..." )
7180 for i , url in enumerate (URLS , 1 ):
7281 try :
7382 r = requests .get (url , timeout = 15 )
7483 r .raise_for_status ()
75- lines = r .text .splitlines ()
76- all_lines .extend ([l .strip () for l in lines if l .strip ()])
84+ for line in r .text .splitlines ():
85+ line = line .strip ()
86+ if protocol_of (line ):
87+ all_keys .append (line )
7788 print (f"{ i } /{ len (URLS )} ОК" )
7889 except Exception as e :
79- print (f"{ i } /{ len (URLS )} ошибка: { e } " )
80- return all_lines
81-
82- def save_new (all_lines ):
83- os .makedirs (NEW_DIR , exist_ok = True )
84- new_file = os .path .join (NEW_DIR , "new_keys.txt" )
85- with open (new_file , "w" , encoding = "utf-8" ) as f :
86- f .write ("\n " .join (all_lines ))
87- print (f"\n Сохранено { len (all_lines )} новых ключей в '{ NEW_DIR } '" )
88-
89- def save_clean (all_lines ):
90- os .makedirs (CLEAN_DIR , exist_ok = True )
91- clean_counts = {p : 0 for p in PROTOCOLS + ["other" ]}
92- unique_lines = list (dict .fromkeys (all_lines )) # удаляем дубли
93- for line in unique_lines :
94- proto = get_protocol (line )
95- path = os .path .join (CLEAN_DIR , proto )
96- os .makedirs (path , exist_ok = True )
97- fname = os .path .join (path , "clean_keys.txt" )
98- with open (fname , "a" , encoding = "utf-8" ) as f :
99- f .write (line + "\n " )
100- clean_counts [proto ] += 1
101- print ("\n Сортировка и очистка завершены:" )
102- for p , c in clean_counts .items ():
103- print (f"{ p } : { c } ключей" )
104-
105- # -------------------- Основная логика --------------------
106- def main ():
107- all_lines = download_sources ()
108- all_lines = [l for l in all_lines if is_valid_proxy (l )]
109- save_new (all_lines )
110- save_clean (all_lines )
111- print ("\n ✅ Готово. Новые ключи в 'new', чистые по протоколам в 'clean'." )
90+ print (f"{ i } /{ len (URLS )} ошибка" )
91+
92+ # NEW (сырые ключи)
93+ with open (os .path .join (NEW_DIR , "all_new.txt" ), "w" , encoding = "utf-8" ) as f :
94+ f .write ("\n " .join (all_keys ))
95+
96+ # Анти-дубликат по host:port:scheme
97+ seen_ip = set ()
98+ clean_keys = []
99+
100+ for line in all_keys :
101+ host , port , scheme = extract_host_port_scheme (line )
102+ if not host or not port or not scheme :
103+ continue
104+ key = (host , port , scheme )
105+ if key in seen_ip :
106+ continue
107+ seen_ip .add (key )
108+ clean_keys .append (line )
109+
110+ # CLEAN
111+ unique = list (dict .fromkeys (clean_keys ))
112+ buckets = {p : [] for p in PROTOCOLS }
113+
114+ for k in unique :
115+ p = protocol_of (k )
116+ if p :
117+ buckets [p ].append (k )
118+
119+ for p , items in buckets .items ():
120+ with open (os .path .join (CLEAN_DIR , f"{ p } .txt" ), "w" , encoding = "utf-8" ) as f :
121+ f .write ("\n " .join (items ))
122+ print (f"{ p } : { len (items )} " )
123+
124+ print ("\n ГОТОВО. githubmirror пересобран с нуля." )
112125
113126if __name__ == "__main__" :
114127 main ()
@@ -124,3 +137,4 @@ def main():
124137
125138
126139
140+
0 commit comments