wangzhibo
2025-07-30 25087cbe79c8c4992551477d55d9db8bbea2202e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import requests
import urllib.parse
import datetime
import random
import os
from io import BytesIO
 
from  auto_media_publisher.config.conf_base import (
    TRANSLATE_API_TEMPLATE,
    POLLINATIONS_API_TEMPLATE,
    POLLINATIONS_DEFAULT_WIDTH ,
    POLLINATIONS_DEFAULT_HEIGHT ,
    POLLINATIONS_DEFAULT_MODEL,
)
 
 
class Text2ImageGenerator:
    def __init__(self, width=POLLINATIONS_DEFAULT_WIDTH, height=POLLINATIONS_DEFAULT_HEIGHT, model=POLLINATIONS_DEFAULT_MODEL):
        self.width = width
        self.height = height
        self.model = model
 
    def translate_prompt(self, prompt: str) -> str:
        """
        使用 MyMemory API 将中文提示词翻译为英文,失败则返回原文。
        """
        
        encoded_prompt = urllib.parse.quote(prompt)
        api_url = TRANSLATE_API_TEMPLATE.format(prompt=encoded_prompt)
        try:
            res = requests.get(api_url, timeout=30)
            res.raise_for_status()
            data = res.json()
            if data.get("responseStatus") == 200 and "translatedText" in data.get("responseData", {}):
                translated = data["responseData"]["translatedText"]
                print(f"[✓] 翻译成功: {translated}")
                return translated
        except Exception as e:
            print(f"[!] 翻译失败,使用原文: {e}")
        return prompt
 
    def build_url(self, prompt: str) -> str:
        """
        构建 Pollinations 图片生成 URL。
        """
        seed = random.randint(1, 1_000_000)
        encoded_prompt = urllib.parse.quote(prompt)
        return POLLINATIONS_API_TEMPLATE.format(
            prompt=encoded_prompt,
            width=self.width,
            height=self.height,
            seed=seed,
            model=self.model
        )
    
    def _fetch_with_retry(self, url: str, max_retries: int = 3):
        """
        最多尝试 max_retries 次请求 URL,成功则返回 response.content,否则返回 None。
        """
        for attempt in range(1, max_retries + 1):
            try:
                response = requests.get(url, timeout=30)
                response.raise_for_status()
                return response.content
            except Exception as e:
                print(f"[!] 请求第 {attempt} 次失败:{e}")
        return None
 
    def generate_image(self, prompt: str, filename: str = None) -> str:
        if not prompt.strip():
            raise ValueError("提示词不能为空")
 
        translated_prompt = self.translate_prompt(prompt)
        url = self.build_url(translated_prompt)
 
        content = self._fetch_with_retry(url)
        if content is None:
            return None
 
        if not filename:
            now = datetime.datetime.now()
            filename = now.strftime("%Y%m%d%H%M%S") + ".png"
        if not filename.lower().endswith(".png"):
            filename += ".png"
 
        with open(filename, "wb") as f:
            f.write(content)
 
        abs_path = os.path.abspath(filename)
        print(f"[✓] 图片已保存:{abs_path}")
        return abs_path
    
    def generate_image_to_stream(self, prompt: str) -> BytesIO:
        if not prompt.strip():
            raise ValueError("提示词不能为空")
 
        translated_prompt = self.translate_prompt(prompt)
        url = self.build_url(translated_prompt)
 
        content = self._fetch_with_retry(url)
        if content is None:
            return None
 
        image_stream = BytesIO(content)
        return image_stream