jerry vor 3 Wochen
Ursprung
Commit
c9f083d010

+ 6 - 10
booker_builtin.py

@@ -11,7 +11,6 @@ from vs_types import GroupConfig, VSPlgConfig, Task, VSQueryResult, AppointmentT
 from vs_plg_factory import VSPlgFactory 
 from toolkit.thread_pool import ThreadPool 
 from toolkit.vs_cloud_api import VSCloudApi
-from toolkit.proxy_manager import ProxyManager
 from toolkit.backoff import ExponentialBackoff
 
 class BuiltinBookerGCO:
@@ -274,17 +273,13 @@ class BuiltinBookerGCO:
                 plg_cfg.session_max_life = self.m_cfg.session_max_life
 
                 if self.m_cfg.need_account:
-                    acc = VSCloudApi.Instance().get_next_account(self.m_cfg.booker.account_pool_id, self.m_cfg.booker.account_cd * 60)
-                    if not acc:
-                        return
+                    acc = VSCloudApi.Instance().get_next_account(self.m_cfg.booker.account_pool_id, self.m_cfg.booker.account_cd)
                     plg_cfg.account.id = acc['id']
                     plg_cfg.account.username = acc['username']
                     plg_cfg.account.password = acc['password']
 
                 if self.m_cfg.need_proxy:
-                    proxy = ProxyManager.Instance().next(self.m_cfg.proxy_pool, lock_duration=self.m_cfg.proxy_lock_interval)
-                    if not proxy:
-                        return
+                    proxy = VSCloudApi.Instance().get_next_proxy(self.m_cfg.proxy_pool, self.m_cfg.proxy_cd)
                     plg_cfg.proxy.id = proxy['id']
                     plg_cfg.proxy.ip = proxy['ip']
                     plg_cfg.proxy.port = proxy['port']
@@ -317,11 +312,12 @@ class BuiltinBookerGCO:
                 self._log(f"+++ Built-in Booker spawned: {plg_cfg.account.username}")
             except Exception as e:
                 err_str = str(e)
-                account_not_found_indicators = [
+                resource_not_found_indicators = [
                     "40401" in err_str,
-                    "Account not found" in err_str
+                    "Account not found" in err_str,
+                    "Proxy not found" in err_str,
                 ]
-                if any(account_not_found_indicators):
+                if any(resource_not_found_indicators):
                     return
                 
                 self._log(f"Spawn failed: {e}")

+ 8 - 9
booker_order.py

@@ -11,7 +11,6 @@ from vs_types import GroupConfig, VSPlgConfig, Task, VSQueryResult, AppointmentT
 from vs_plg_factory import VSPlgFactory 
 from toolkit.thread_pool import ThreadPool 
 from toolkit.vs_cloud_api import VSCloudApi
-from toolkit.proxy_manager import ProxyManager
 from toolkit.backoff import ExponentialBackoff
 
 class OrderBookerGCO:
@@ -286,8 +285,9 @@ class OrderBookerGCO:
                 user_inputs = task_data.get('user_inputs', {})
                 
                 plg_cfg = VSPlgConfig()
-                plg_cfg.debug = self.m_cfg.debug; plg_cfg.free_config = self.m_cfg.free_config; plg_cfg.session_max_life = self.m_cfg.session_max_life
-                
+                plg_cfg.debug = self.m_cfg.debug
+                plg_cfg.free_config = self.m_cfg.free_config
+                plg_cfg.session_max_life = self.m_cfg.session_max_life
                 plg_cfg.account.username = user_inputs.get("username", "")
                 plg_cfg.account.password = user_inputs.get("password", "")
                 if not plg_cfg.account.username:
@@ -295,9 +295,7 @@ class OrderBookerGCO:
                 
                 acceptable_keys = [target_routing_key]
                 if self.m_cfg.need_proxy:
-                    proxy = ProxyManager.Instance().next(self.m_cfg.proxy_pool, lock_duration=self.m_cfg.proxy_lock_interval)
-                    if not proxy:
-                        return
+                    proxy = VSCloudApi.Instance().get_next_proxy(self.m_cfg.proxy_pool, self.m_cfg.proxy_cd)
                     plg_cfg.proxy.id = proxy['id']
                     plg_cfg.proxy.ip = proxy['ip']
                     plg_cfg.proxy.port = proxy['port']
@@ -328,11 +326,12 @@ class OrderBookerGCO:
                 self._log(f"+++ Order Booker spawned: {plg_cfg.account.username} (Target: {acceptable_keys})")
             except Exception as e:
                 err_str = str(e)
-                order_not_found_indicators = [
+                resource_not_found_indicators = [
                     "40401" in err_str,
-                    "Account not found" in err_str
+                    "Account not found" in err_str,
+                    "Proxy not found" in err_str
                 ]
-                if any(order_not_found_indicators):
+                if any(resource_not_found_indicators):
                     return
                 
                 self._log(f"Order Booker spawn failed: {e}")

+ 106 - 106
config/config.json

@@ -12,21 +12,21 @@
             "enable": true,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.nl.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.nl.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 300,
                 "max_bookings_per_account": 8
             },
@@ -78,21 +78,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "sg.fr.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "sg.fr.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -144,21 +144,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "au.fr.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "au.fr.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -226,21 +226,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.it.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.it.booker",
                 "target_instances": 0,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -308,21 +308,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.nl.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.nl.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -390,21 +390,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.no.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.no.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -456,21 +456,21 @@
             "enable": true,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.at.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.at.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 300,
                 "max_bookings_per_account": 8
             },
@@ -522,21 +522,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.dk.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.dk.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -588,21 +588,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.fi.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.fi.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -654,21 +654,21 @@
             "enable": true,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.hu.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.hu.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 180,
                 "max_bookings_per_account": 8
             },
@@ -720,21 +720,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.is.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.is.booker",
                 "target_instances": 0,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -786,21 +786,21 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.at.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.at.booker",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 8
             },
@@ -852,20 +852,20 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 60,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 3600,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.es.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
                 "target_instances": 0,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 1
             },
@@ -913,20 +913,20 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "iproyal",
-            "proxy_cd": 5,
-            "session_max_life": 60,
+            "proxy_pool": ["iproyal"],
+            "proxy_cd": 300,
+            "session_max_life": 3600,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.es.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
-                "target_instances": 1,
-                "account_cd": 180,
+                "target_instances": 0,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 1
             },
@@ -971,23 +971,23 @@
         {
             "identifier": "tls.gb.fr",
             "debug": false,
-            "enable": false,
+            "enable": true,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "gb.fr.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 1800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 1800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 1
             },
@@ -1036,20 +1036,20 @@
             "enable": false,
             "need_account": false,
             "need_proxy": true,
-            "proxy_pool": "local",
-            "proxy_cd": 5,
-            "session_max_life": 30,
+            "proxy_pool": ["local"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "cn.cng.fr.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 1800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 1800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 1
             },
@@ -1088,12 +1088,12 @@
         {
             "identifier": "e-konsulat.ie.pl",
             "debug": false,
-            "enable": false,
+            "enable": true,
             "need_account": false,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 15,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "",
                 "account_pool_id": "",
@@ -1142,9 +1142,9 @@
             "enable": false,
             "need_account": false,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 10000000,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 1800,
             "sentinel": {
                 "account_source": "",
                 "account_pool_id": "",
@@ -1193,14 +1193,14 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "local",
-            "proxy_cd": 5,
-            "session_max_life": 10000000,
+            "proxy_pool": ["local"],
+            "proxy_cd": 300,
+            "session_max_life": 10800,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.be.sentinel",
                 "target_instances": 1,
-                "account_cd": 0,
+                "account_cd": 3600,
                 "signal_ttl": 30
             },
             "booker": {
@@ -1242,9 +1242,9 @@
             "enable": false,
             "need_account": false,
             "need_proxy": true,
-            "proxy_pool": "iproyal",
-            "proxy_cd": 5,
-            "session_max_life": 15,
+            "proxy_pool": ["iproyal"],
+            "proxy_cd": 300,
+            "session_max_life": 900,
             "sentinel": {
                 "account_source": "",
                 "account_pool_id": "",
@@ -1293,20 +1293,20 @@
             "enable": false,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 15,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 900,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.it.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 10,
                 "max_bookings_per_account": 1
             },
@@ -1342,20 +1342,20 @@
             "enable": true,
             "need_account": true,
             "need_proxy": true,
-            "proxy_pool": "isp_all",
-            "proxy_cd": 5,
-            "session_max_life": 1440,
+            "proxy_pool": ["isp_all"],
+            "proxy_cd": 300,
+            "session_max_life": 86400,
             "sentinel": {
                 "account_source": "built-in",
                 "account_pool_id": "ie.gr.sentinel",
                 "target_instances": 1,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "signal_ttl": 30
             },
             "booker": {
                 "account_source": "order",
                 "target_instances": 10,
-                "account_cd": 180,
+                "account_cd": 10800,
                 "booking_cooldown": 30,
                 "max_bookings_per_account": 1
             },

+ 1 - 1
plugins/bel_plugin.py

@@ -104,7 +104,7 @@ class BelPlugin(IVSPlg):
         except:
             return False
         if self.config.session_max_life > 0:
-            if time.time() - self.session_create_time > self.config.session_max_life * 60:
+            if time.time() - self.session_create_time > self.config.session_max_life:
                 self._log("Session expired.")
                 return False
         return True

+ 1 - 1
plugins/bls_plugin.py

@@ -91,7 +91,7 @@ class BlsPlugin(IVSPlg):
         if self.config.session_max_life > 0:
             current_time = time.time()
             elapsed_time = current_time - self.session_create_time
-            if elapsed_time > self.config.session_max_life * 60:
+            if elapsed_time > self.config.session_max_life:
                 self._log(f"Session expired.")
                 return False
         return True

+ 1 - 1
plugins/de_plugin.py

@@ -113,7 +113,7 @@ class DePlugin(IVSPlg):
         except:
             return False
         if self.config.session_max_life > 0:
-            if time.time() - self.session_create_time > self.config.session_max_life * 60:
+            if time.time() - self.session_create_time > self.config.session_max_life:
                 self._log("Session expired.")
                 return False
         return True

+ 1 - 1
plugins/grc_plugin.py

@@ -66,7 +66,7 @@ class GrcPlugin(IVSPlg):
         if self.config.session_max_life > 0:
             current_time = time.time()
             elapsed_time = current_time - self.session_create_time
-            if elapsed_time > self.config.session_max_life * 60:
+            if elapsed_time > self.config.session_max_life:
                 self._log(f"Session Life ({int(elapsed_time)}s) out of max life limit ({self.config.session_max_life * 60}s), mark as unhealth session")
                 return False
         return True

+ 1 - 1
plugins/ita_plugin.py

@@ -102,7 +102,7 @@ class ItaPlugin(IVSPlg):
         except:
             return False
         if self.config.session_max_life > 0:
-            if time.time() - self.session_create_time > self.config.session_max_life * 60:
+            if time.time() - self.session_create_time > self.config.session_max_life:
                 self._log("Session expired.")
                 return False
         return True

+ 1 - 1
plugins/pol_plugin.py

@@ -104,7 +104,7 @@ class PolPlugin(IVSPlg):
         except:
             return False
         if self.config.session_max_life > 0:
-            if time.time() - self.session_create_time > self.config.session_max_life * 60:
+            if time.time() - self.session_create_time > self.config.session_max_life:
                 self._log("Session expired.")
                 return False
         return True

+ 1 - 1
plugins/tls_plugin.py

@@ -108,7 +108,7 @@ class TlsPlugin(IVSPlg):
         if self.config.session_max_life > 0:
             current_time = time.time()
             elapsed_time = current_time - self.session_create_time
-            if elapsed_time > self.config.session_max_life * 60:
+            if elapsed_time > self.config.session_max_life:
                 self._log(f"Session expired.")
                 return False
         return True

+ 1 - 1
plugins/tls_plugin2.py

@@ -191,7 +191,7 @@ class TlsPlugin(IVSPlg):
         if self.config.session_max_life > 0:
             current_time = time.time()
             elapsed_time = current_time - self.session_create_time
-            if elapsed_time > self.config.session_max_life * 60:
+            if elapsed_time > self.config.session_max_life:
                 self._log(f"Session expired.")
                 return False
         return True

+ 1 - 1
plugins/vfs_plugin.py

@@ -191,7 +191,7 @@ class VfsPlugin(IVSPlg):
         if self.config.session_max_life > 0:
             current_time = time.time()
             elapsed_time = current_time - self.session_create_time
-            if elapsed_time > self.config.session_max_life * 60:
+            if elapsed_time > self.config.session_max_life:
                 self._log(f"Session expired.")
                 return False
         return True

+ 75 - 0
proxy_uploader.py

@@ -0,0 +1,75 @@
+import json
+import requests
+from datetime import datetime, timezone
+
+# --- 配置部分 ---
+API_URL = 'http://localhost:8888/api/proxy/create'
+BEARER_TOKEN = 'tok_5d84b9ecddfa4386a995bf8996901828' # 替换为你的真实 Token
+FILE_PATH = 'config/proxies.json'
+
+headers = {
+    'accept': 'application/json',
+    'Authorization': f'Bearer {BEARER_TOKEN}',
+    'Content-Type': 'application/json'
+}
+
+def main():
+    # 1. 读取 JSON 文件
+    try:
+        with open(FILE_PATH, 'r', encoding='utf-8') as f:
+            data = json.load(f)
+    except FileNotFoundError:
+        print(f"错误: 找不到文件 {FILE_PATH}")
+        return
+    except json.JSONDecodeError:
+        print(f"错误: {FILE_PATH} 不是有效的 JSON 格式")
+        return
+
+    proxies = data.get('isp_all', [])
+    if not proxies:
+        print("没有在 JSON 中找到 'isp_all' 列表。")
+        return
+
+    print(f"共读取到 {len(proxies)} 个代理,准备开始上传...\n")
+
+    # 2. 遍历列表并发送请求
+    success_count = 0
+    fail_count = 0
+
+    for index, proxy in enumerate(proxies, start=1):
+        # 字段映射转换
+        payload = {
+            "pool_name": "isp_all",                  # 你可以根据需要自定义这个代理池名称
+            "proto": proxy.get("scheme", "http"),    # scheme 映射到 proto
+            "ip": proxy.get("ip"),
+            "port": proxy.get("port"),
+            "username": proxy.get("username", ""),
+            "password": proxy.get("password", ""),
+            # 设置一个默认的下次使用时间(这里使用当前UTC时间)
+            "next_use_time": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
+            "status": "active"                       # 设定初始状态,例如 "active" 或 "ready"
+        }
+
+        # 3. 发送 POST 请求
+        try:
+            response = requests.post(API_URL, headers=headers, json=payload, timeout=10)
+            
+            # 判断响应状态码 (200 或 201 通常表示创建成功)
+            if response.status_code in (200, 201):
+                print(f"[{index}/{len(proxies)}] 成功: 上传 {payload['ip']}:{payload['port']}")
+                success_count += 1
+            else:
+                print(f"[{index}/{len(proxies)}] 失败: {payload['ip']}:{payload['port']} | HTTP状态码: {response.status_code} | 详情: {response.text}")
+                fail_count += 1
+                
+        except requests.exceptions.RequestException as e:
+            print(f"[{index}/{len(proxies)}] 请求异常: {payload['ip']}:{payload['port']} | 错误: {e}")
+            fail_count += 1
+
+    # 打印最终统计
+    print("\n--- 上传完成 ---")
+    print(f"成功: {success_count} 条")
+    print(f"失败: {fail_count} 条")
+
+if __name__ == "__main__":
+    main()

+ 6 - 9
sentinel.py

@@ -10,7 +10,6 @@ from vs_types import GroupConfig, VSPlgConfig, Task, QueryWaitMode
 from vs_plg_factory import VSPlgFactory 
 from toolkit.thread_pool import ThreadPool 
 from toolkit.vs_cloud_api import VSCloudApi
-from toolkit.proxy_manager import ProxyManager
 from toolkit.backoff import ExponentialBackoff
 
 class SentinelGCO:
@@ -145,16 +144,13 @@ class SentinelGCO:
                     plg_cfg.account.id = 0
                     plg_cfg.account.username = "Guest"
                 else:
-                    acc = VSCloudApi.Instance().get_next_account(self.m_cfg.sentinel.account_pool_id, self.m_cfg.sentinel.account_cd * 60)
-                    if not acc: return
+                    acc = VSCloudApi.Instance().get_next_account(self.m_cfg.sentinel.account_pool_id, self.m_cfg.sentinel.account_cd)
                     plg_cfg.account.id = acc['id']
                     plg_cfg.account.username = acc['username']
                     plg_cfg.account.password = acc['password']
                 
                 if self.m_cfg.need_proxy:
-                    proxy = ProxyManager.Instance().next(self.m_cfg.proxy_pool, lock_duration=self.m_cfg.proxy_lock_interval)
-                    if not proxy:
-                        return
+                    proxy = VSCloudApi.Instance().get_next_proxy(self.m_cfg.proxy_pool, self.m_cfg.proxy_cd)
                     plg_cfg.proxy.id = proxy['id']
                     plg_cfg.proxy.ip = proxy['ip']
                     plg_cfg.proxy.port = proxy['port']
@@ -178,11 +174,12 @@ class SentinelGCO:
 
             except Exception as e:
                 err_str = str(e)
-                account_not_found_indicators = [
+                resource_not_found_indicators = [
                     "40401" in err_str,
-                    "Account not found" in err_str
+                    "Account not found" in err_str,
+                    "Proxy not found" in err_str,
                 ]
-                if any(account_not_found_indicators):
+                if any(resource_not_found_indicators):
                     return
                 
                 self._log(f"Spawn failed: {e}")

+ 0 - 223
toolkit/proxy_manager.py

@@ -1,223 +0,0 @@
-import threading
-import time
-import json
-import os
-import random
-from typing import List, Optional, Dict, Any
-from vs_log_macros import VSC_DEBUG, VSC_WARN, VSC_INFO, VSC_ERROR
-
-class ProxyManager:
-    """
-    代理管理器 (支持数据落盘持久化 + 代理池隔离)
-    - 静态配置: config/proxies.json
-    - 动态状态: data/proxy_states.json
-    """
-    _instance = None
-    _lock = threading.RLock()
-
-    def __new__(cls):
-        with cls._lock:
-            if cls._instance is None:
-                cls._instance = super().__new__(cls)
-                cls._instance._init_data()
-            return cls._instance
-
-    @staticmethod
-    def Instance():
-        return ProxyManager()
-
-    def _init_data(self):
-        # 静态数据: pool_name -> List[Dict]
-        self._proxies: Dict[str, List[Dict]] = {}
-        
-        # 动态锁定状态: "pool_name::proxy_id" -> lock_until_timestamp
-        self._lock_states: Dict[str, float] = {}
-        
-        self._proxy_lock = threading.RLock()
-        
-        # 路径配置
-        self._config_path = "config/proxies.json"
-        self._state_path = "data/proxy_states.json"
-        
-        # 确保 data 目录存在
-        os.makedirs(os.path.dirname(self._state_path), exist_ok=True)
-        
-        self.reload_config()
-
-    def _get_state_key(self, pool_name: str, proxy_id: Any) -> str:
-        """
-        生成唯一的锁定状态 Key (组合键)
-        格式: pool_name::proxy_id
-        """
-        return f"{pool_name}::{proxy_id}"
-
-    def reload_config(self):
-        """(重新)加载本地配置文件,并恢复锁定状态"""
-        if not os.path.exists(self._config_path):
-            VSC_WARN("proxy_mgr", f"Config file not found: {self._config_path}. Proxy pools are empty.")
-            return
-
-        try:
-            # 1. 先加载磁盘上的锁定状态
-            self._load_state_from_disk()
-
-            # 2. 加载静态配置
-            with open(self._config_path, 'r', encoding='utf-8') as f:
-                data = json.load(f)
-            
-            count = 0
-            with self._proxy_lock:
-                self._proxies.clear()
-                for pool_name, proxy_list in data.items():
-                    processed_list = []
-                    for p in proxy_list:
-                        # 校验必要字段
-                        if "id" not in p or "ip" not in p or "port" not in p:
-                            continue
-                        
-                        # 初始化默认字段
-                        p.setdefault('scheme', 'http')
-                        p.setdefault('username', '')
-                        p.setdefault('password', '')
-                        
-                        # 恢复锁定状态
-                        proxy_id = p["id"]
-                        state_key = self._get_state_key(pool_name, proxy_id)
-                        
-                        # 从全局状态中获取该池子下该代理的锁定时间
-                        saved_lock = self._lock_states.get(state_key, 0)
-                        p['lock_until'] = saved_lock
-                        
-                        processed_list.append(p)
-                        count += 1
-                    
-                    self._proxies[pool_name] = processed_list
-                    
-            VSC_INFO("proxy_mgr", f"Loaded {count} proxies. Lock states restored from {self._state_path}")
-            
-        except json.JSONDecodeError:
-            VSC_ERROR("proxy_mgr", f"Invalid JSON format in {self._config_path}")
-        except Exception as e:
-            VSC_ERROR("proxy_mgr", f"Failed to load proxy config: {e}")
-
-    def _load_state_from_disk(self):
-        """从磁盘读取状态文件"""
-        with self._proxy_lock:
-            self._lock_states.clear()
-            if not os.path.exists(self._state_path):
-                return
-            try:
-                with open(self._state_path, 'r', encoding='utf-8') as f:
-                    data = json.load(f)
-                    for k, v in data.items():
-                        self._lock_states[str(k)] = float(v)
-            except Exception as e:
-                VSC_WARN("proxy_mgr", f"Failed to load state file: {e}. Starting fresh.")
-
-    def _save_state_to_disk(self):
-        """
-        将当前内存中的锁定状态写入磁盘
-        只保存未来还会被锁定的记录,减少文件大小
-        """
-        try:
-            now = time.time()
-            active_states = {
-                k: v for k, v in self._lock_states.items() 
-                if v > now
-            }
-            
-            # 更新内存缓存
-            self._lock_states = active_states
-
-            with open(self._state_path, 'w', encoding='utf-8') as f:
-                json.dump(active_states, f, indent=4)
-                
-        except Exception as e:
-            VSC_ERROR("proxy_mgr", f"Failed to save state to disk: {e}")
-
-    def next(self, pool_name: str, lock_duration: float = 0.0) -> Optional[Dict[str, Any]]:
-        """
-        从指定池中获取下一个可用代理,并锁定指定时长。
-        
-        @param pool_name: 代理池名称
-        @param lock_duration: 锁定时间(秒)。
-                              注意:如果不传或传0,则不锁定(仅获取),适合无状态请求。
-                              如果为了限制频率,请传入大于0的值。
-        """
-        with self._proxy_lock:
-            proxies = self._proxies.get(pool_name, [])
-            if not proxies:
-                # VSC_WARN("proxy_mgr", "No proxies found in pool '%s'", pool_name)
-                return None
-            
-            now = time.time()
-            available = []
-
-            # 筛选可用代理
-            for p in proxies:
-                proxy_id = p["id"]
-                state_key = self._get_state_key(pool_name, proxy_id)
-                
-                # 检查隔离的锁定状态
-                current_lock = self._lock_states.get(state_key, 0)
-                
-                if current_lock <= now:
-                    available.append(p)
-            
-            if not available:
-                # VSC_WARN("proxy_mgr", "Pool '%s' has proxies but all are locked/busy.", pool_name)
-                return None
-            
-            # 随机选择
-            selected = random.choice(available)
-            proxy_id = selected["id"]
-            
-            # === 如果需要锁定,更新全局状态并落盘 ===
-            if lock_duration > 0:
-                new_lock_until = now + lock_duration
-                state_key = self._get_state_key(pool_name, proxy_id)
-                
-                # 1. 更新状态
-                self._lock_states[state_key] = new_lock_until
-                selected["lock_until"] = new_lock_until
-                
-                # 2. 立即落盘
-                self._save_state_to_disk()
-                
-                VSC_DEBUG("proxy_mgr", "Selected proxy ID %s (Pool: %s), locked for %.0fs", 
-                          proxy_id, pool_name, lock_duration)
-            else:
-                VSC_DEBUG("proxy_mgr", "Selected proxy ID %s (Pool: %s) without lock", 
-                          proxy_id, pool_name)
-
-            return selected.copy()
-
-    def lock(self, pool_name: str, proxy_id: int, duration_seconds: int):
-        """
-        手动锁定指定代理 (支持数据落盘)
-        通常用于在请求失败(如429)时紧急调用
-        """
-        with self._proxy_lock:
-            proxies = self._proxies.get(pool_name, [])
-            target_proxy = None
-            
-            for p in proxies:
-                if p["id"] == proxy_id:
-                    target_proxy = p
-                    break
-            
-            if target_proxy:
-                state_key = self._get_state_key(pool_name, proxy_id)
-                new_lock_until = time.time() + duration_seconds
-                
-                # 更新状态
-                self._lock_states[state_key] = new_lock_until
-                target_proxy["lock_until"] = new_lock_until
-                
-                # 立即落盘
-                self._save_state_to_disk()
-                
-                VSC_INFO("proxy_mgr", "Manually locked proxy ID %d in pool '%s' for %ds",
-                         proxy_id, pool_name, duration_seconds)
-            else:
-                VSC_WARN("proxy_mgr", "Proxy ID %d not found in pool '%s' for locking", proxy_id, pool_name)

+ 24 - 5
toolkit/vs_cloud_api.py

@@ -4,7 +4,7 @@ import json
 import time
 import urllib.parse
 from datetime import datetime
-from typing import Dict, Any, Optional
+from typing import Dict, Any, List, Optional
 from vs_types import NotFoundError, PermissionDeniedError, RateLimiteddError, SessionExpiredOrInvalidError, BizLogicError 
 from vs_log_macros import VSC_ERROR, VSC_INFO, VSC_WARN, VSC_DEBUG
 
@@ -315,20 +315,39 @@ class VSCloudApi:
     def get_next_account(
         self,
         pool_name: str,
-        lock_duration: float = 60
+        account_cd: int = 60
     ):
         url = f'{self.base_url}/api/account/next'
-        params = {
+        payload = {
             "pool_name": pool_name,
-            "lock_duration": lock_duration
+            "account_cd": account_cd
+        }
+        headers = self._get_headers()
+        resp = self._perform_request('POST', url, headers=headers, json_data=payload)
+        result = resp.json()
+        if result.get("code") == 0:
+            return result.get("data", {})
+        else:
+            raise BizLogicError(message=f"Get next account biz error: {result.get('message')}")
+        
+    def get_next_proxy(
+        self,
+        pools: List[str],
+        proxy_cd: int = 60
+    ):
+        url = f'{self.base_url}/api/proxy/next-ip'
+        payload = {
+            "pools": pools,
+            "proxy_cd": proxy_cd
         }
         headers = self._get_headers()
-        resp = self._perform_request('GET', url, headers=headers, params=params)
+        resp = self._perform_request('POST', url, headers=headers, json_data=payload)
         result = resp.json()
         if result.get("code") == 0:
             return result.get("data", {})
         else:
             raise BizLogicError(message=f"Get next account biz error: {result.get('message')}")
+    
 
     def slot_snapshot_report(
         self,

+ 7 - 9
vs_types.py

@@ -85,7 +85,7 @@ class SentinelConfig(BaseModel):
     account_source: str = "built-in"
     account_pool_id: str = ""
     target_instances: int = 1
-    account_cd: int = 180           # 单位 分钟
+    account_cd: int = 180*60        # 单位 秒
     signal_ttl: int = 180           # 单位 秒
 
 # === Booker配置 ===
@@ -93,8 +93,8 @@ class BookerConfig(BaseModel):
     account_source: str = "built-in" # "built-in" 或 "order"
     account_pool_id: str = ""        # 仅在 built-in 模式下使用
     target_instances: int = 1        # built-in下为全局限制; order下为单队列限制
-    account_cd: int = 180
-    booking_cooldown: float = 10.0   # 触发冷却
+    account_cd: int = 180*60         # 单位 秒
+    booking_cooldown: float = 10.0   # 单位 秒
     max_bookings_per_account: int = 1
 
 class GroupConfig(BaseModel):
@@ -103,9 +103,9 @@ class GroupConfig(BaseModel):
     enable: bool = False
     need_account: bool = False
     need_proxy: bool = False
-    proxy_pool: str = ""
-    proxy_lock_interval: int = 5
-    session_max_life: int = 30
+    proxy_pool: List[str] = Field(default_factory=list)
+    proxy_cd: int = 5*60                # 单位 秒
+    session_max_life: int = 30*60       # 单位 秒
     
     sentinel: SentinelConfig = Field(default_factory=SentinelConfig)
     booker: BookerConfig = Field(default_factory=BookerConfig)
@@ -125,7 +125,6 @@ class VSAccount(BaseModel):
     id: int = 0
     username: str = ""
     password: str = ""
-    lock_until: float = 0.0 
 
 class VSProxy(BaseModel):
     id: int = 0
@@ -134,14 +133,13 @@ class VSProxy(BaseModel):
     port: int = 0
     username: str = ""
     password: str = ""
-    lock_until: float = 0.0 
 
 class VSPlgConfig(BaseModel):
     debug: bool = False
     account: VSAccount = Field(default_factory=VSAccount)
     proxy: VSProxy = Field(default_factory=VSProxy)
     free_config: dict = Field(default_factory=dict)
-    session_max_life: int = 15
+    session_max_life: int = 30*60       # 单位 秒
 
 class TimeSlot(BaseModel):
     time: str = ""     # "hh:mm"