@@ -14,11 +14,93 @@ import * as openpgp from 'openpgp'
1414import os from 'node:os'
1515import CONET_Guardian_NodeInfo_ABI from './CONET_Guardian_NodeInfo_ABI.json'
1616import { runUpdater , readUpdateInfo } from './updateProcess'
17+ import allNodes from './nodes.json'
1718import fs from 'node:fs'
1819import { LayerMinus } from './layerMinus'
1920
21+
2022const ver = '0.1.5'
2123
24+ const deleteNodeFromList = ( node : nodes_info ) => {
25+ const index = allNodes . findIndex ( n => n . ip_addr === node . ip_addr )
26+ if ( index > - 1 ) {
27+ allNodes . splice ( index , 1 )
28+ }
29+ }
30+
31+ export const postToEndpoint = async < T = any > (
32+ url : string ,
33+ post : boolean ,
34+ jsonData ?: any ,
35+ timeoutMs = 5 * 1000
36+ ) : Promise < "" | boolean | T > => {
37+ const ac = new AbortController ( ) ;
38+
39+
40+ try {
41+ const timer = setTimeout ( ( ) => ac . abort ( 'TimeoutError' ) , timeoutMs ) ;
42+ const res = await fetch ( url , {
43+ method : post ? "POST" : "GET" ,
44+ headers :
45+ post && jsonData !== undefined
46+ ? { "Content-Type" : "application/json;charset=UTF-8" }
47+ : undefined ,
48+ body : post ? ( jsonData ? JSON . stringify ( jsonData ) : "" ) : undefined ,
49+ signal : ac . signal ,
50+ } ) ;
51+
52+ // 200 → resolve(false)
53+ if ( res . status < 200 || res . status >= 300 ) {
54+ return false ;
55+ }
56+ clearTimeout ( timer ) ;
57+ const text = await res . text ( ) ;
58+ if ( ! text . length ) {
59+ return "" ;
60+ }
61+
62+ // 优先依据 Content-Type
63+ const ct = ( res . headers . get ( "Content-Type" ) || "" ) . toLowerCase ( ) ;
64+ if ( ct . includes ( "application/json" ) || ct . includes ( "+json" ) ) {
65+ return JSON . parse ( text ) as T ;
66+ }
67+
68+ // 回落:尝试 JSON 解析;失败时保持原规则(POST→"",GET→true)
69+ try {
70+ return JSON . parse ( text ) as T ;
71+ } catch {
72+ return ( post ? "" : true ) as any ;
73+ }
74+ } catch ( err ) {
75+ // AbortError/网络错误 → reject
76+ throw err ;
77+ }
78+ }
79+
80+
81+ const testNode = ( node : nodes_info ) : Promise < boolean > => new Promise ( async executor => {
82+ try {
83+ const url = `http://${ node . ip_addr } `
84+ await postToEndpoint ( url , false , false , 1000 )
85+ // 只有在“计入结果”的时候才判断是否够数
86+ executor ( true )
87+ } catch ( e ) {
88+ // 失败再次测试
89+ deleteNodeFromList ( node )
90+ executor ( false )
91+ }
92+ } )
93+
94+ const getRandomNode = async ( ) => {
95+ const index = Math . floor ( Math . random ( ) * allNodes . length )
96+ const node = allNodes [ index ]
97+ const isWorking = await testNode ( node )
98+ if ( ! isWorking ) {
99+ return await getRandomNode ( )
100+ }
101+ return node
102+
103+ }
22104const getLocalNetworkIpaddress = ( ) => {
23105 const interfaceAll = os . networkInterfaces ( )
24106 let ipv4 : string [ ] = [ ]
@@ -179,7 +261,7 @@ const startSilentPass = (vpnObj: Native_StartVPNObj, currentVer: UpdateInfo, rea
179261 const layerMinus = new LayerMinus ( vpnObj . entryNodes , vpnObj . exitNode , vpnObj . privateKey )
180262 _proxyServer = new ProxyServer ( 3002 , layerMinus )
181263 _proxyServer . start ( )
182- runUpdater ( vpnObj . entryNodes , currentVer , reactFolder , restart )
264+ // runUpdater(vpnObj.entryNodes, currentVer, reactFolder, restart)
183265 return _proxyServer
184266}
185267
@@ -223,6 +305,15 @@ type filterRule = {
223305}
224306
225307
308+ const checkUpdateProcess = async ( currentVer : UpdateInfo , reactFolder : string , restart : ( ) => Promise < void > ) => {
309+ const node = await getRandomNode ( )
310+ await runUpdater ( node , currentVer , reactFolder , restart )
311+ setTimeout ( ( ) => {
312+ checkUpdateProcess ( currentVer , reactFolder , restart )
313+ } , 1000 * 60 * 10 )
314+ }
315+
316+
226317export class Daemon {
227318 private logsPool : proxyLogs [ ] = [ ]
228319
@@ -279,7 +370,10 @@ export class Daemon {
279370 if ( ! this . currentVer ) {
280371 staticFolder = defaultPath
281372 logger ( Colors . red ( `updatedPath ERROR, go back to defaultPath ${ defaultPath } ` ) )
282- }
373+ } else {
374+ // start check update process
375+ checkUpdateProcess ( this . currentVer , this . reactBuildFolder , this . restart )
376+ }
283377
284378 // --- 关键逻辑结束 ---
285379
@@ -563,6 +657,8 @@ export class Daemon {
563657 { 'Serving files from' : staticFolder }
564658 ] )
565659 } )
660+
661+
566662 }
567663
568664 // 将 restart 方法改为箭头函数属性
0 commit comments