jerry 3 hónapja
szülő
commit
3a3fdf5b7a
3 módosított fájl, 131 hozzáadás és 226 törlés
  1. 71 221
      main.py
  2. 7 0
      plugins/vfs_plugin2.py
  3. 53 5
      vfs_registration_bot.py

+ 71 - 221
main.py

@@ -5,163 +5,93 @@ import json
 import logging
 
 # 导入必要模块
-from vs_types import GroupConfig, QueryWaitMode, PluginConfig, QueryWaitConfig
-from gco import GCO
+from vs_types import VSPlgConfig, AppointmentType
+from plugins.vfs_plugin2 import VfsPlugin2
 from vs_log_macros import VSC_INFO, VSC_ERROR
 
 def vfs_test():
-    # 0. 检查目录结构
-    if not os.path.exists("plugins/vfs_plugin.py"):
-        print("[ERROR] 找不到插件文件 'plugins/vfs_plugin.py'")
-        print("请将上一条回答中的代码保存为该文件。")
-        return
-
     # 1. 准备 VFS 业务配置 (free_config)
     # 这部分 JSON 对应 VfsPlugin 中读取的配置
-    vfs_config = {
-        "verbose": 0,
-        "missionCode": "fra",
-        "missionName": "France",
-        "countryCode": "sgp",
-        "countryName": "Singapore",
-        "cultureCode": "en-US",
-        "language": "en",
-        "website": "https://visa.vfsglobal.com/sgp/en/fra/login",
-        "appointmentType": [
-            {
-                "id": 538,
-                "routing_key": "slot.vfs.sin.fr.tourist",
-                "centerName": "France Visa Application Center, Singapore",
-                "city": "Singapore",
-                "country": "France",
-                "visa_type": "Tourist",
-                "address": "79 Anson Road #15-01 Singapore 079906",
-                "vacCode": "FRSN",
-                "categoryName": "Short Stay",
-                "categoryCode": "02",
-                "subcategoryName": "Short Stay Tourist, Family Visit",
-                "subcategoryCode": "Six",
-                "fee": None,
-                "currency": None
+    
+    cfg_dict = {
+        "debug": False,
+        "account": {
+            "username": "ie_is_cwwyxz@gmail-app.com",
+            "password": "Or1duEJc5@"
+        },
+        "proxy": {
+            "scheme": "http",
+            "ip": "127.0.0.1",
+            "port": 7890
+        },
+        "free_config": {
+            "mission_code": "isl",
+            "mission_name": "Iceland",
+            "country_code": "irl",
+            "country_name": "Ireland",
+            "culture_code": "en-US",
+            "language": "en",
+            "apt_configs": {
+                "slot.dub.is.tourist": {
+                    "center_name": "Iceland Visa Application Center- Dublin",
+                    "address": "Cunningham House, 130 Francis Street, Dublin, Ireland- DO8 H48R",
+                    "vac_code": "DUB",
+                    "category_name": "C-Visa",
+                    "category_code": "CVI",
+                    "subcategory_name": "Tourism",
+                    "subcategory_code": "OTT"
+                }
             }
-        ]
+        },
+        "session_max_life": 30
     }
-
-    # 2. 构造查询策略配置
-    query_wait_config = QueryWaitConfig(
-        mode=QueryWaitMode.Random,
-        random_min=5,  # 最小间隔 5秒
-        random_max=10  # 最大间隔 10秒
-    )
-
-    # 3. 构造插件加载配置
-    # 注意:plugin_name="vfs_plugin" 会被自动推导为类名 "VfsPlugin"
-    plugin_config = PluginConfig(
-        lib_path="plugins",             
-        plugin_name="vfs_plugin", 
-        plugin_bin="vfs_plugin.py",
-        plugin_proto="IVSPlg"
-    )
     
-    # 4. 构造任务组配置
-    group_config = GroupConfig(
-        identifier="Singapore_France_Visas", # 组名
-        enable=True,                    # 启用
-        need_account=True,              # 需要登录账号
-        account_pool="ie_nl",           # 使用 AccountManager 中的 fr_pool (在 account_manager.py 中预设)
-        need_proxy=True,                # 需要代理
-        proxy_pool="global_proxy",      # 使用 ProxyManager 中的 global_proxy
-        need_ip_bind=False,             # 不强制 IP 绑定
-        account_login_interval=10,      # 登录失败/成功后锁定账号 10 分钟
-        target_instances=1,             # 启动 2 个并发实例 (线程)
-        query_wait=query_wait_config,
-        plugin_config=plugin_config,
-        free_config=json.dumps(vfs_config) # 将业务配置转为 JSON 字符串
-    )
-
-    # 5. 创建协调器
-    gco = GCO(group_config)
-    # 7. 启动
-    try:
-        VSC_INFO("main", "========================================")
-        VSC_INFO("main", "   VFS Python Plugin Tester      ")
-        VSC_INFO("main", "========================================")
-        
-        gco.start()
-        
-        time.sleep(3600)
-    except KeyboardInterrupt:
-        VSC_INFO("main", "Ctrl+C detected. Stopping...")
-    except Exception as e:
-        VSC_ERROR("main", "Unexpected Error: %s", str(e))
-    finally:
-        # 8. 停止
-        gco.stop()
-        VSC_INFO("main", "Program finished.")
-        
-        
-def tls_test():
-    # 0. 检查目录结构
-    if not os.path.exists("plugins/tls_plugin.py"):
-        print("[ERROR] 找不到插件文件 'plugins/tls_plugin.py'")
-        print("请将上一条回答中的代码保存为该文件。")
-        return
-
-    # 1. 准备 VFS 业务配置 (free_config)
-    # 这部分 JSON 对应 TlsPlugin 中读取的配置
-    tls_config = {
-        "verbose": 0,
-        "embassy_code": "gbLON2fr",
-        "country_code": "gb",
-        "mission_code": "fr",
-        "city": "london",
-        "capsolver_key": "CAP-5441DD341DD3CC2FAEF0BE6FE493EE9A",
-        "interest_month": "01-2026",
-        "target_labels": ["", "pta"],
-        'website': 'https://visas-fr.tlscontact.com/country/gb/vac/gbLON2fr/'
+    apt_type_dict =  {
+        "weight": 10,
+        "routing_key": "slot.dub.is.tourist",
+        "city": "Dublin",
+        "visa_type": "Tourist",
+        "country": "Iceland"
+    }
+    
+    user_inputs = {
+        "email": "hujiarui8@gmail.com",
+        "phone": "07843900464",
+        "gender": "female",
+        "birthday": "1995-12-15",
+        "last_name": "Hu",
+        "first_name": "Jiarui",
+        "nationality": "China",
+        "passport_no": "EP9863641",
+        "_admin_bypass": {
+            "at": "2026-02-08T14:52:59.454636",
+            "by": "usr-db8f814c",
+            "reason": "admin manual order",
+            "enabled": True
+        },
+        "expected_end_date": "2023-03-15",
+        "phone_country_code": "44",
+        "expected_start_date": "2023-02-25",
+        "passport_expiry_date": "2035-09-17",
+        "social_media_account": "淘宝-yayale95778240"
     }
-
-    # 2. 构造查询策略配置
-    query_wait_config = QueryWaitConfig(
-        mode=QueryWaitMode.Random,
-        random_min=60,  # 最小间隔 5秒
-        random_max=300  # 最大间隔 10秒
-    )
-
-    # 3. 构造插件加载配置
-    # 注意:plugin_name="tls_plugin" 会被自动推导为类名 "TlsPlugin"
-    plugin_config = PluginConfig(
-        lib_path="plugins",             
-        plugin_name="tls_plugin", 
-        plugin_bin="tls_plugin.py",
-        plugin_proto="IVSPlg"
-    )
     
-    # 4. 构造任务组配置
-    group_config = GroupConfig(
-        identifier="London_France_Visas", # 组名
-        enable=True,                    # 启用
-        need_account=True,              # 需要登录账号
-        account_pool="gb_fr",           # 使用 AccountManager 中的 uk_pool (在 account_manager.py 中预设)
-        need_proxy=True,                # 需要代理
-        proxy_pool="global_proxy",      # 使用 ProxyManager 中的 global_proxy
-        need_ip_bind=False,             # 不强制 IP 绑定
-        account_login_interval=10,      # 登录失败/成功后锁定账号 10 分钟
-        target_instances=1,             # 启动 2 个并发实例 (线程)
-        query_wait=query_wait_config,
-        plugin_config=plugin_config,
-        free_config=json.dumps(tls_config) # 将业务配置转为 JSON 字符串
-    )
+    apt_type = AppointmentType(**apt_type_dict)
+
+    config = VSPlgConfig(**cfg_dict)
 
-    # 5. 创建协调器
-    gco = GCO(group_config)
     # 7. 启动
     try:
         VSC_INFO("main", "========================================")
-        VSC_INFO("main", "    TLS Python Plugin Tester      ")
+        VSC_INFO("main", "   VFS Python Plugin Tester      ")
         VSC_INFO("main", "========================================")
         
-        gco.start()
+        vfs_plg = VfsPlugin2("test")
+        vfs_plg.set_config(config)
+        vfs_plg.create_session()
+        slot_info = vfs_plg.query(apt_type)
+        slot_info.apt_type = apt_type
+        vfs_plg.book(slot_info, user_inputs)
         
         time.sleep(3600)
     except KeyboardInterrupt:
@@ -170,88 +100,8 @@ def tls_test():
         VSC_ERROR("main", "Unexpected Error: %s", str(e))
     finally:
         # 8. 停止
-        gco.stop()
         VSC_INFO("main", "Program finished.")
         
-def bls_test():
-    # 0. 环境检查
-    if not os.path.exists("plugins/bls_plugin.py"):
-        print("[ERROR] 找不到插件文件 'plugins/bls_plugin.py'")
-        return
-
-    # 2. 准备 BLS 业务配置 (Free Config)
-    # 这些字段会被 BlsPlugin 读取并用于填表和逻辑判断
-    bls_config = {
-        "domain": "ireland.blsspainglobal.com", # 目标域名
-        "ocr_service_url": "http://127.0.0.1:8085/predict/vfcode?model=pytorch", # OCR 服务地址
-        
-        # 签证参数 (根据实际网站下拉框的值填写)
-        "location": "Dublin",
-        "jurisdiction": None,
-        "visaType": "Schengen Visa/ Short Term Visa",
-        "visaSubType": "Tourist Visa",
-        "appointmentCategory": "Normal",
-        
-        # 申请人信息 (用于 book 阶段)
-        "user_info": {
-            "first_name": "John",
-            "last_name": "Doe",
-            "passport_no": "E12345678",
-            "passport_issue_date": "2020-01-01",
-            "passport_expiry_date": "2030-01-01",
-            "birthday": "1990-01-01",
-            "phone_no": "447700900000",
-            "nationality": "India",
-            "gender": "Male",
-            "passport_image_url": "https://via.placeholder.com/600x400.jpg" # 模拟图片URL
-        }
-    }
-
-    # 3. 构造查询策略
-    query_wait_config = QueryWaitConfig(
-        mode=QueryWaitMode.Fixed,
-        fixed_wait=10 # 每次查询间隔 10 秒
-    )
-
-    # 4. 构造插件配置
-    # plugin_name="bls_plugin" -> 自动推导类名 "BlsPlugin"
-    plugin_config = PluginConfig(
-        lib_path="plugins",             
-        plugin_name="bls_plugin", 
-        plugin_bin="bls_plugin.py",
-        plugin_proto="IVSPlg"
-    )
     
-    # 5. 构造任务组配置
-    group_config = GroupConfig(
-        identifier="Dublin_Spain_Visas",  # 任务组 ID
-        enable=True,
-        need_account=True,
-        account_pool="ie_es",           # 使用刚才注入的池子
-        need_proxy=True,
-        proxy_pool="local",      # 使用默认代理池
-        target_instances=1,             # 启动 1 个实例
-        account_login_interval=5,       # 登录间隔/锁定时间
-        query_wait=query_wait_config,
-        plugin_config=plugin_config,
-        free_config=json.dumps(bls_config)
-    )
-
-    # 6. 创建协调器
-    gco = GCO(group_config)
-    # 8. 启动运行
-    try:
-        VSC_INFO("main", ">>> Starting BLS Plugin Test...")
-        gco.start()
-        
-        time.sleep(3600)
-    except KeyboardInterrupt:
-        VSC_INFO("main", "Ctrl+C detected.")
-    except Exception as e:
-        VSC_ERROR("main", f"Unexpected Error: {e}")
-    finally:
-        gco.stop()
-        VSC_INFO("main", "Test Finished.")
-
 if __name__ == "__main__":
     vfs_test()

+ 7 - 0
plugins/vfs_plugin2.py

@@ -134,6 +134,8 @@ class VfsPlugin2(IVSPlg):
         self.category_conf: Dict = {}
         self.subcategory_conf: Dict = {}
         
+        self.booking_wait_applied = False
+        
         self.public_key = serialization.load_pem_public_key(
             VFS_PUBLIC_KEY_PEM.encode(),
             backend=default_backend()
@@ -954,6 +956,11 @@ class VfsPlugin2(IVSPlg):
         final_urn = None
         is_waitlist = (slot_info.availability_status == AvailabilityStatus.Waitlist)
         
+        if not self.booking_wait_applied:
+            self._log("pre-booking wait: sleeping 20s before booking to avoid risk control")
+            time.sleep(20)
+            self.booking_wait_applied = True
+        
         # 重试机制:添加申请人有时候会因为并发冲突失败
         MAX_RETRY = 3
         for i in range(MAX_RETRY):

+ 53 - 5
vfs_registration_bot.py

@@ -6,6 +6,7 @@ import time
 import string
 import logging
 import base64
+import requests
 from datetime import datetime, timezone
 from urllib.parse import urlparse, urlencode
 
@@ -38,6 +39,52 @@ t92towriKoH75BhiazY0mghm4LjmAWrV0u/GNpV3tk9bxbtHEXGaFmxCJqjg+7x6
 GQIDAQAB
 -----END PUBLIC KEY-----"""
 
+def upload_account_to_server(account):
+    """
+    将注册成功的账号上报到中心服务器
+    """
+    api_url = 'https://visafly.top/api/account/add'
+    api_token = 'tok_e946329a60ff45ba807f3f41b0e8b7fc'  # 你的 Bearer Token
+
+    # 构造请求头
+    headers = {
+        'accept': 'application/json',
+        'Authorization': f'Bearer {api_token}',
+        'Content-Type': 'application/json'
+    }
+
+    # 构造 extra_data (存放 VFS 特有的国家、领区、手机号信息)
+    extra_payload = {
+        "country_code": account.get("country_code"),
+        "mission_code": account.get("mission_code"),
+        "phone_country_code": account.get("phone_country_code"),
+        "phone_number": account.get("phone_number"),
+        "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+    }
+
+    # 构造主 Payload
+    payload = {
+        "pool_name": account.get("pool_name", "default_pool"),
+        "username": account.get("username"),
+        "password": account.get("password"),
+        "extra_data": extra_payload
+    }
+
+    try:
+        logger.info(f"Uploading account {account['username']} to server...")
+        resp = requests.post(api_url, json=payload, headers=headers, timeout=10)
+        
+        if resp.status_code == 200:
+            logger.info(f"✅ [API Upload Success] Server responded: {resp.text}")
+            return True
+        else:
+            logger.error(f"❌ [API Upload Failed] Status: {resp.status_code}, Body: {resp.text}")
+            return False
+    except Exception as e:
+        logger.error(f"❌ [API Upload Error]: {e}")
+        return False
+
+
 class VFSHelper:
     """工具方法的静态类"""
     
@@ -252,7 +299,7 @@ class VFSRegistrationBot:
             logger.error(f"Turnstile refresh failed: {e}")
         return None
 
-    def _wait_for_activation_link(self, username, max_wait_sec=300):
+    def _wait_for_activation_link(self, username, max_wait_sec=60):
         """轮询获取激活链接"""
         logger.info(f"Waiting for email to {username}...")
         start_time = time.time()
@@ -377,7 +424,7 @@ class VFSRegistrationBot:
                 headers=headers, 
                 json_data=post_data
             )
-            
+            logger.info(f"Registration response: {resp.text}")
             resp_data = resp.json()
             if resp_data.get("code") == "200":
                 logger.info("Registration API success. Waiting for email...")
@@ -449,15 +496,15 @@ def generate_account_details(config, pool_name):
 def main():
     # 配置
     config = {
-        "pool_name": "ie_fi",
+        "pool_name": "ie_dk",
         "email_domain": "gmail-app", 
         "master_email": "visafly666@gmail.com",
         "proxy_url": "http://127.0.0.1:7890",
         "target_count": 30,
         "phone_country_code": 353,
         "country_code": "irl",
-        "mission_code": "fin",
-        "website": "https://visa.vfsglobal.com/irl/en/fin/register",
+        "mission_code": "dnk",
+        "website": "https://visa.vfsglobal.com/irl/en/dnk/register",
     }
     
     bot = VFSRegistrationBot(config)
@@ -475,6 +522,7 @@ def main():
             success_accounts.append(account)
             logger.info(f"Progress: {len(success_accounts)}/{config['target_count']}")
             
+            upload_account_to_server(account)
             # 保存结果到文件,防止中途退出丢失
             with open("registered_accounts.json", "w", encoding='utf-8') as f:
                 json.dump(success_accounts, f, indent=4, ensure_ascii=False)