Pārlūkot izejas kodu

Merge branch 'main' of https://git.port.run/puge/pythonTest

PUGE 3 nedēļas atpakaļ
vecāks
revīzija
504b6423a8
2 mainītis faili ar 306 papildinājumiem un 13 dzēšanām
  1. 2 2
      天龙八部拍卖行.py
  2. 304 11
      自动匹配上架图片.py

+ 2 - 2
天龙八部拍卖行.py

@@ -379,7 +379,7 @@ class AuctionBot:
         
         self.log(f"识别到价格: {price}, 目标价格: {target_price}")
         
-        if price <= target_price and price > 0.5:
+        if price <= target_price and price > 1.1:
             self.log(f"价格 {price} <= {target_price},执行购买!")
             
             # 选择购买项
@@ -421,7 +421,7 @@ class AuctionBot:
         
         # 查找窗口
         self.log("查找新天龙八部窗口...")
-        window_list = self.get_hwnds_by_title_contains("0.08.2611")
+        window_list = self.get_hwnds_by_title_contains("天龙八部")
         
         if not window_list:
             self.log("未找到新天龙八部窗口!")

+ 304 - 11
自动匹配上架图片.py

@@ -20,16 +20,52 @@ from io import BytesIO
 class AmazonImageUploader:
     """亚马逊图片上传类"""
     
-    def __init__(self):
-        self.client_id = "amzn1.application-oa2-client.9f775d35077a4c7598116e5a89b60222"
-        self.client_secret = "amzn1.oa2-cs.v1.6909777baa82b796555a431cd23709342e8e01434abcad1f8b59cadf048b51c3"
-        self.refresh_token = "Atzr|IwEBICh_fojh7qAfrePzSjOZhQxTnHRZCYOuWNvSAHGaBs1WfkjR4qjC1Dmv0uK3oyq_L-R9SRKK4cYmPwF1MQXQdqKlpzOAGItWeXnNzh-SyhHHISv0_vCt3D6hluVmIEmF2kA7ro_XF-PslD41g3Eq6bv0Qq4y4pQbkDj-9dudDuz7nku8UL-nc4EWgJCrHCJTAs8TK48Yvrfi3E35uv97tYhs6qb8D9d4dR9C7daaC49eoDqP88qyUHThQV1Kqon8xukx4AT2_wLqWNcabpADzuK-5w7D-vvFFtvzfkbmtfzoPeEdHPulG6scc59BPFTyBlGU7a3d1JSFg2ROHIlrljRm"
-        self.aws_access_key = "AKIA24CLQSVTW2K4S6RP"
-        self.aws_secret_key = "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"
-        self.aws_region = "us-east-1"
-        self.seller_id = "A1H50Z0WYYLEGQ"
-        self.marketplace_id = "ATVPDKIKX0DER"
-        self.product_type = "TABLE"
+    def __init__(self, config=None):
+        # 默认配置
+        defaults = {
+            "client_id": "amzn1.application-oa2-client.9f775d35077a4c7598116e5a89b60222",
+            "client_secret": "amzn1.oa2-cs.v1.6909777baa82b796555a431cd23709342e8e01434abcad1f8b59cadf048b51c3",
+            "refresh_token": "Atzr|IwEBICh_fojh7qAfrePzSjOZhQxTnHRZCYOuWNvSAHGaBs1WfkjR4qjC1Dmv0uK3oyq_L-R9SRKK4cYmPwF1MQXQdqKlpzOAGItWeXnNzh-SyhHHISv0_vCt3D6hluVmIEmF2kA7ro_XF-PslD41g3Eq6bv0Qq4y4pQbkDj-9dudDuz7nku8UL-nc4EWgJCrHCJTAs8TK48Yvrfi3E35uv97tYhs6qb8D9d4dR9C7daaC49eoDqP88qyUHThQV1Kqon8xukx4AT2_wLqWNcabpADzuK-5w7D-vvFFtvzfkbmtfzoPeEdHPulG6scc59BPFTyBlGU7a3d1JSFg2ROHIlrljRm",
+            "aws_access_key": "AKIA24CLQSVTW2K4S6RP",
+            "aws_secret_key": "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",
+            "aws_region": "us-east-1",
+            "seller_id": "A1H50Z0WYYLEGQ",
+            "marketplace_id": "ATVPDKIKX0DER",
+            "product_type": "TABLE",
+        }
+        if config:
+            defaults.update(config)
+        
+        self.client_id = defaults["client_id"]
+        self.client_secret = defaults["client_secret"]
+        self.refresh_token = defaults["refresh_token"]
+        self.aws_access_key = defaults["aws_access_key"]
+        self.aws_secret_key = defaults["aws_secret_key"]
+        self.aws_region = defaults["aws_region"]
+        self.seller_id = defaults["seller_id"]
+        self.marketplace_id = defaults["marketplace_id"]
+        self.product_type = defaults["product_type"]
+    
+    def update_config(self, config):
+        """更新配置"""
+        if "client_id" in config:
+            self.client_id = config["client_id"]
+        if "client_secret" in config:
+            self.client_secret = config["client_secret"]
+        if "refresh_token" in config:
+            self.refresh_token = config["refresh_token"]
+        if "aws_access_key" in config:
+            self.aws_access_key = config["aws_access_key"]
+        if "aws_secret_key" in config:
+            self.aws_secret_key = config["aws_secret_key"]
+        if "aws_region" in config:
+            self.aws_region = config["aws_region"]
+        if "seller_id" in config:
+            self.seller_id = config["seller_id"]
+        if "marketplace_id" in config:
+            self.marketplace_id = config["marketplace_id"]
+        if "product_type" in config:
+            self.product_type = config["product_type"]
         
     def sha256_hash(self, data):
         return hashlib.sha256(data.encode("utf-8")).hexdigest()
@@ -258,6 +294,11 @@ class ImageMatcherApp:
         self.notebook.add(self.tab_detail, text="亚马逊详情图更换")
         self.create_detail_tab()
         
+        # 选项卡4: 设置
+        self.tab_settings = ttk.Frame(self.notebook)
+        self.notebook.add(self.tab_settings, text="设置")
+        self.create_settings_tab()
+        
         # 状态栏
         self.status_var = tk.StringVar()
         self.status_var.set("就绪")
@@ -424,6 +465,253 @@ class ImageMatcherApp:
         progress_label = ttk.Label(tab, textvariable=self.detail_progress_var, relief=tk.SUNKEN, anchor=tk.W)
         progress_label.grid(row=10, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5)
         
+    def create_settings_tab(self):
+        """创建设置选项卡"""
+        tab = self.tab_settings
+        tab.columnconfigure(0, weight=1)
+        tab.rowconfigure(1, weight=1)
+        
+        # 标题
+        title_label = ttk.Label(tab, text="亚马逊 API 设置", font=("Arial", 14, "bold"))
+        title_label.grid(row=0, column=0, pady=10, sticky=tk.W, padx=10)
+        
+        # 创建一个可滚动的Frame来容纳所有设置项
+        canvas = tk.Canvas(tab)
+        scrollbar = ttk.Scrollbar(tab, orient="vertical", command=canvas.yview)
+        scrollable_frame = ttk.Frame(canvas)
+        
+        scrollable_frame.bind(
+            "<Configure>",
+            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
+        )
+        
+        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
+        canvas.configure(yscrollcommand=scrollbar.set)
+        
+        canvas.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=10)
+        scrollbar.grid(row=1, column=1, sticky=(tk.N, tk.S))
+        
+        scrollable_frame.columnconfigure(1, weight=1)
+        
+        # 设置项
+        row = 0
+        
+        # Client ID
+        ttk.Label(scrollable_frame, text="Client ID:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_client_id = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_client_id, width=80).grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # Client Secret
+        ttk.Label(scrollable_frame, text="Client Secret:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_client_secret = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_client_secret, width=80, show="*").grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # Refresh Token
+        ttk.Label(scrollable_frame, text="Refresh Token:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_refresh_token = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_refresh_token, width=80).grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # AWS Access Key
+        ttk.Label(scrollable_frame, text="AWS Access Key:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_aws_access_key = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_aws_access_key, width=80).grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # AWS Secret Key
+        ttk.Label(scrollable_frame, text="AWS Secret Key:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_aws_secret_key = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_aws_secret_key, width=80, show="*").grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # AWS Region
+        ttk.Label(scrollable_frame, text="AWS Region:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_aws_region = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_aws_region, width=30).grid(row=row, column=1, sticky=tk.W, pady=5, padx=5)
+        row += 1
+        
+        # Seller ID
+        ttk.Label(scrollable_frame, text="Seller ID:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_seller_id = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_seller_id, width=80).grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # Marketplace ID
+        ttk.Label(scrollable_frame, text="Marketplace ID:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_marketplace_id = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_marketplace_id, width=80).grid(row=row, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
+        row += 1
+        
+        # Product Type
+        ttk.Label(scrollable_frame, text="Product Type:").grid(row=row, column=0, sticky=tk.W, pady=5, padx=5)
+        self.setting_product_type = tk.StringVar()
+        ttk.Entry(scrollable_frame, textvariable=self.setting_product_type, width=30).grid(row=row, column=1, sticky=tk.W, pady=5, padx=5)
+        row += 1
+        
+        # 分隔线
+        ttk.Separator(scrollable_frame, orient=tk.HORIZONTAL).grid(row=row, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=15)
+        row += 1
+        
+        # 按钮框架
+        button_frame = ttk.Frame(scrollable_frame)
+        button_frame.grid(row=row, column=0, columnspan=2, pady=15)
+        
+        ttk.Button(button_frame, text="保存设置", command=self.save_settings, width=15).pack(side=tk.LEFT, padx=5)
+        ttk.Button(button_frame, text="重置为默认值", command=self.reset_settings, width=15).pack(side=tk.LEFT, padx=5)
+        ttk.Button(button_frame, text="测试连接", command=self.test_connection, width=15).pack(side=tk.LEFT, padx=5)
+        
+        row += 1
+        
+        # 设置日志框
+        log_frame = ttk.LabelFrame(scrollable_frame, text="设置日志", padding="5")
+        log_frame.grid(row=row, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10, padx=5)
+        log_frame.columnconfigure(0, weight=1)
+        log_frame.rowconfigure(0, weight=1)
+        
+        self.settings_log_text = scrolledtext.ScrolledText(log_frame, height=8, width=80, wrap=tk.WORD)
+        self.settings_log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
+        
+        # 初始化设置值
+        self.init_settings_values()
+        
+    def init_settings_values(self):
+        """初始化设置值"""
+        self.setting_client_id.set(self.amazon_uploader.client_id)
+        self.setting_client_secret.set(self.amazon_uploader.client_secret)
+        self.setting_refresh_token.set(self.amazon_uploader.refresh_token)
+        self.setting_aws_access_key.set(self.amazon_uploader.aws_access_key)
+        self.setting_aws_secret_key.set(self.amazon_uploader.aws_secret_key)
+        self.setting_aws_region.set(self.amazon_uploader.aws_region)
+        self.setting_seller_id.set(self.amazon_uploader.seller_id)
+        self.setting_marketplace_id.set(self.amazon_uploader.marketplace_id)
+        self.setting_product_type.set(self.amazon_uploader.product_type)
+        
+    def settings_log(self, message):
+        """在设置选项卡日志框中添加消息"""
+        self.settings_log_text.insert(tk.END, f"{message}\n")
+        self.settings_log_text.see(tk.END)
+        self.root.update_idletasks()
+        
+    def get_settings_config_path(self):
+        """获取设置配置文件路径"""
+        return os.path.join(os.path.dirname(os.path.abspath(__file__)), "amazon_settings.json")
+        
+    def save_settings(self):
+        """保存设置"""
+        config = {
+            "client_id": self.setting_client_id.get(),
+            "client_secret": self.setting_client_secret.get(),
+            "refresh_token": self.setting_refresh_token.get(),
+            "aws_access_key": self.setting_aws_access_key.get(),
+            "aws_secret_key": self.setting_aws_secret_key.get(),
+            "aws_region": self.setting_aws_region.get(),
+            "seller_id": self.setting_seller_id.get(),
+            "marketplace_id": self.setting_marketplace_id.get(),
+            "product_type": self.setting_product_type.get(),
+        }
+        try:
+            with open(self.get_settings_config_path(), 'w', encoding='utf-8') as f:
+                json.dump(config, f, ensure_ascii=False, indent=2)
+            
+            # 更新亚马逊上传器配置
+            self.amazon_uploader.update_config(config)
+            
+            self.settings_log("✅ 设置已保存并应用")
+            messagebox.showinfo("成功", "设置已保存!")
+        except Exception as e:
+            self.settings_log(f"❌ 保存设置失败: {str(e)}")
+            messagebox.showerror("错误", f"保存设置失败: {str(e)}")
+            
+    def reset_settings(self):
+        """重置为默认值"""
+        if not messagebox.askyesno("确认", "确定要重置为默认值吗?"):
+            return
+            
+        defaults = {
+            "client_id": "amzn1.application-oa2-client.9f775d35077a4c7598116e5a89b60222",
+            "client_secret": "amzn1.oa2-cs.v1.6909777baa82b796555a431cd23709342e8e01434abcad1f8b59cadf048b51c3",
+            "refresh_token": "Atzr|IwEBICh_fojh7qAfrePzSjOZhQxTnHRZCYOuWNvSAHGaBs1WfkjR4qjC1Dmv0uK3oyq_L-R9SRKK4cYmPwF1MQXQdqKlpzOAGItWeXnNzh-SyhHHISv0_vCt3D6hluVmIEmF2kA7ro_XF-PslD41g3Eq6bv0Qq4y4pQbkDj-9dudDuz7nku8UL-nc4EWgJCrHCJTAs8TK48Yvrfi3E35uv97tYhs6qb8D9d4dR9C7daaC49eoDqP88qyUHThQV1Kqon8xukx4AT2_wLqWNcabpADzuK-5w7D-vvFFtvzfkbmtfzoPeEdHPulG6scc59BPFTyBlGU7a3d1JSFg2ROHIlrljRm",
+            "aws_access_key": "AKIA24CLQSVTW2K4S6RP",
+            "aws_secret_key": "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",
+            "aws_region": "us-east-1",
+            "seller_id": "A1H50Z0WYYLEGQ",
+            "marketplace_id": "ATVPDKIKX0DER",
+            "product_type": "TABLE",
+        }
+        
+        self.setting_client_id.set(defaults["client_id"])
+        self.setting_client_secret.set(defaults["client_secret"])
+        self.setting_refresh_token.set(defaults["refresh_token"])
+        self.setting_aws_access_key.set(defaults["aws_access_key"])
+        self.setting_aws_secret_key.set(defaults["aws_secret_key"])
+        self.setting_aws_region.set(defaults["aws_region"])
+        self.setting_seller_id.set(defaults["seller_id"])
+        self.setting_marketplace_id.set(defaults["marketplace_id"])
+        self.setting_product_type.set(defaults["product_type"])
+        
+        self.settings_log("✅ 已重置为默认值")
+        
+    def test_connection(self):
+        """测试连接"""
+        self.settings_log("🔍 测试连接...")
+        
+        # 先保存设置
+        self.save_settings()
+        
+        try:
+            # 测试获取Access Token
+            self.settings_log("  🔑 获取Access Token...")
+            token = self.amazon_uploader.get_access_token()
+            self.settings_log(f"  ✅ Token获取成功 (长度: {len(token)})")
+            
+            # 测试SP-API连接(获取marketplace参与信息)
+            self.settings_log("  🌐 测试SP-API连接...")
+            resp = self.amazon_uploader.spapi_request(
+                "GET",
+                "/sellers/v1/marketplaceParticipations",
+                "",
+                access_token=token
+            )
+            
+            if resp.status_code == 200:
+                self.settings_log("  ✅ SP-API连接成功")
+                data = resp.json()
+                self.settings_log(f"  参与市场数量: {len(data.get('payload', []))}")
+            else:
+                self.settings_log(f"  ⚠️ SP-API返回状态码: {resp.status_code}")
+                self.settings_log(f"  响应: {resp.text[:200]}")
+                
+            self.settings_log("✅ 连接测试完成")
+            
+        except Exception as e:
+            self.settings_log(f"❌ 连接测试失败: {str(e)}")
+            messagebox.showerror("连接失败", f"连接测试失败:\n{str(e)}")
+            
+    def load_settings(self):
+        """加载设置"""
+        try:
+            config_path = self.get_settings_config_path()
+            if os.path.exists(config_path):
+                with open(config_path, 'r', encoding='utf-8') as f:
+                    config = json.load(f)
+                
+                self.setting_client_id.set(config.get("client_id", self.amazon_uploader.client_id))
+                self.setting_client_secret.set(config.get("client_secret", self.amazon_uploader.client_secret))
+                self.setting_refresh_token.set(config.get("refresh_token", self.amazon_uploader.refresh_token))
+                self.setting_aws_access_key.set(config.get("aws_access_key", self.amazon_uploader.aws_access_key))
+                self.setting_aws_secret_key.set(config.get("aws_secret_key", self.amazon_uploader.aws_secret_key))
+                self.setting_aws_region.set(config.get("aws_region", self.amazon_uploader.aws_region))
+                self.setting_seller_id.set(config.get("seller_id", self.amazon_uploader.seller_id))
+                self.setting_marketplace_id.set(config.get("marketplace_id", self.amazon_uploader.marketplace_id))
+                self.setting_product_type.set(config.get("product_type", self.amazon_uploader.product_type))
+                
+                # 更新上传器配置
+                self.amazon_uploader.update_config(config)
+        except Exception:
+            pass
+
     def select_template(self):
         filename = filedialog.askopenfilename(
             title="选择模板文件",
@@ -568,7 +856,8 @@ class ImageMatcherApp:
             self.detail_log(f"❌ 加载配置失败: {str(e)}")
             
     def load_config(self):
-        """启动时自动加载亚马逊配置"""
+        """启动时自动加载所有配置"""
+        # 加载亚马逊上传配置
         try:
             config_path = self.get_config_path()
             if os.path.exists(config_path):
@@ -581,6 +870,7 @@ class ImageMatcherApp:
                     self.amazon_template_path.set(config.get("template_path"))
         except Exception:
             pass
+        
         # 加载详情图配置
         try:
             config_path = self.get_detail_config_path()
@@ -597,6 +887,9 @@ class ImageMatcherApp:
                     self.detail_template_path.set(config.get("template_path"))
         except Exception:
             pass
+        
+        # 加载设置配置
+        self.load_settings()
 
     def start_matching(self):
         """开始匹配处理"""