webscout 7.6__py3-none-any.whl → 7.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webscout might be problematic. Click here for more details.

Files changed (124) hide show
  1. webscout/AIutel.py +2 -1
  2. webscout/Bard.py +14 -11
  3. webscout/DWEBS.py +431 -415
  4. webscout/Extra/autocoder/autocoder_utiles.py +183 -47
  5. webscout/Extra/autocoder/rawdog.py +848 -649
  6. webscout/Extra/gguf.py +682 -652
  7. webscout/Provider/AI21.py +1 -1
  8. webscout/Provider/AISEARCH/DeepFind.py +2 -2
  9. webscout/Provider/AISEARCH/ISou.py +2 -23
  10. webscout/Provider/AISEARCH/felo_search.py +6 -6
  11. webscout/Provider/AISEARCH/genspark_search.py +1 -1
  12. webscout/Provider/Aitopia.py +292 -0
  13. webscout/Provider/AllenAI.py +5 -22
  14. webscout/Provider/Andi.py +3 -3
  15. webscout/Provider/C4ai.py +1 -1
  16. webscout/Provider/ChatGPTClone.py +226 -0
  17. webscout/Provider/ChatGPTES.py +3 -5
  18. webscout/Provider/ChatGPTGratis.py +4 -4
  19. webscout/Provider/Chatify.py +2 -2
  20. webscout/Provider/Cloudflare.py +3 -2
  21. webscout/Provider/DARKAI.py +3 -2
  22. webscout/Provider/DeepSeek.py +2 -2
  23. webscout/Provider/Deepinfra.py +1 -1
  24. webscout/Provider/EDITEE.py +1 -1
  25. webscout/Provider/ElectronHub.py +178 -96
  26. webscout/Provider/ExaChat.py +310 -0
  27. webscout/Provider/Free2GPT.py +2 -2
  28. webscout/Provider/Gemini.py +5 -19
  29. webscout/Provider/GithubChat.py +1 -1
  30. webscout/Provider/Glider.py +12 -8
  31. webscout/Provider/Groq.py +3 -3
  32. webscout/Provider/HF_space/qwen_qwen2.py +1 -1
  33. webscout/Provider/HeckAI.py +1 -1
  34. webscout/Provider/HuggingFaceChat.py +1 -1
  35. webscout/Provider/Hunyuan.py +272 -0
  36. webscout/Provider/Jadve.py +3 -3
  37. webscout/Provider/Koboldai.py +3 -3
  38. webscout/Provider/LambdaChat.py +391 -0
  39. webscout/Provider/Llama.py +3 -5
  40. webscout/Provider/Llama3.py +4 -12
  41. webscout/Provider/Marcus.py +3 -3
  42. webscout/Provider/OLLAMA.py +260 -36
  43. webscout/Provider/Openai.py +7 -3
  44. webscout/Provider/PI.py +1 -1
  45. webscout/Provider/Perplexitylabs.py +1 -1
  46. webscout/Provider/Phind.py +1 -1
  47. webscout/Provider/PizzaGPT.py +1 -1
  48. webscout/Provider/QwenLM.py +4 -7
  49. webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +21 -46
  50. webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +37 -49
  51. webscout/Provider/TTI/ImgSys/__init__.py +23 -0
  52. webscout/Provider/TTI/ImgSys/async_imgsys.py +202 -0
  53. webscout/Provider/TTI/ImgSys/sync_imgsys.py +195 -0
  54. webscout/Provider/TTI/__init__.py +3 -1
  55. webscout/Provider/TTI/artbit/async_artbit.py +4 -33
  56. webscout/Provider/TTI/artbit/sync_artbit.py +4 -32
  57. webscout/Provider/TTI/fastflux/async_fastflux.py +6 -2
  58. webscout/Provider/TTI/fastflux/sync_fastflux.py +7 -2
  59. webscout/Provider/TTI/huggingface/async_huggingface.py +1 -1
  60. webscout/Provider/TTI/huggingface/sync_huggingface.py +1 -1
  61. webscout/Provider/TTI/pixelmuse/__init__.py +4 -0
  62. webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +249 -0
  63. webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +182 -0
  64. webscout/Provider/TTI/talkai/sync_talkai.py +1 -1
  65. webscout/Provider/TTS/utils.py +1 -1
  66. webscout/Provider/TeachAnything.py +1 -1
  67. webscout/Provider/TextPollinationsAI.py +4 -4
  68. webscout/Provider/TwoAI.py +1 -2
  69. webscout/Provider/Venice.py +4 -2
  70. webscout/Provider/VercelAI.py +234 -0
  71. webscout/Provider/WebSim.py +228 -0
  72. webscout/Provider/WiseCat.py +10 -12
  73. webscout/Provider/Youchat.py +1 -1
  74. webscout/Provider/__init__.py +22 -1
  75. webscout/Provider/ai4chat.py +1 -1
  76. webscout/Provider/aimathgpt.py +2 -6
  77. webscout/Provider/akashgpt.py +1 -1
  78. webscout/Provider/askmyai.py +4 -4
  79. webscout/Provider/asksteve.py +203 -0
  80. webscout/Provider/bagoodex.py +2 -2
  81. webscout/Provider/cerebras.py +1 -1
  82. webscout/Provider/chatglm.py +4 -4
  83. webscout/Provider/cleeai.py +1 -0
  84. webscout/Provider/copilot.py +427 -415
  85. webscout/Provider/elmo.py +1 -1
  86. webscout/Provider/flowith.py +14 -3
  87. webscout/Provider/freeaichat.py +57 -31
  88. webscout/Provider/gaurish.py +3 -5
  89. webscout/Provider/geminiprorealtime.py +1 -1
  90. webscout/Provider/granite.py +4 -4
  91. webscout/Provider/hermes.py +5 -5
  92. webscout/Provider/julius.py +1 -1
  93. webscout/Provider/koala.py +1 -1
  94. webscout/Provider/labyrinth.py +239 -0
  95. webscout/Provider/learnfastai.py +28 -15
  96. webscout/Provider/lepton.py +1 -1
  97. webscout/Provider/llama3mitril.py +4 -4
  98. webscout/Provider/llamatutor.py +1 -1
  99. webscout/Provider/llmchat.py +3 -3
  100. webscout/Provider/meta.py +1 -1
  101. webscout/Provider/multichat.py +10 -10
  102. webscout/Provider/promptrefine.py +1 -1
  103. webscout/Provider/searchchat.py +293 -0
  104. webscout/Provider/sonus.py +208 -0
  105. webscout/Provider/talkai.py +2 -2
  106. webscout/Provider/turboseek.py +1 -1
  107. webscout/Provider/tutorai.py +1 -1
  108. webscout/Provider/typegpt.py +6 -43
  109. webscout/Provider/uncovr.py +299 -0
  110. webscout/Provider/x0gpt.py +1 -1
  111. webscout/__init__.py +36 -36
  112. webscout/cli.py +293 -283
  113. webscout/litagent/agent.py +14 -9
  114. webscout/tempid.py +11 -11
  115. webscout/utils.py +2 -2
  116. webscout/version.py +1 -1
  117. webscout/webscout_search.py +1282 -1223
  118. webscout/webscout_search_async.py +813 -692
  119. {webscout-7.6.dist-info → webscout-7.8.dist-info}/METADATA +76 -44
  120. {webscout-7.6.dist-info → webscout-7.8.dist-info}/RECORD +124 -106
  121. {webscout-7.6.dist-info → webscout-7.8.dist-info}/LICENSE.md +0 -0
  122. {webscout-7.6.dist-info → webscout-7.8.dist-info}/WHEEL +0 -0
  123. {webscout-7.6.dist-info → webscout-7.8.dist-info}/entry_points.txt +0 -0
  124. {webscout-7.6.dist-info → webscout-7.8.dist-info}/top_level.txt +0 -0
@@ -6,8 +6,8 @@ Examples:
6
6
  >>> import asyncio
7
7
  >>>
8
8
  >>> async def example():
9
- ... # Initialize with logging
10
- ... provider = AsyncArtbitImager(logging=True)
9
+ ... # Initialize provider
10
+ ... provider = AsyncArtbitImager()
11
11
  ...
12
12
  ... # Generate a single image
13
13
  ... images = await provider.generate("Cool art")
@@ -31,29 +31,21 @@ import aiohttp
31
31
  import aiofiles
32
32
  import asyncio
33
33
  import os
34
- from typing import List
34
+ from typing import Union, List
35
35
  from webscout.AIbase import AsyncImageProvider
36
- from webscout.Litlogger import Logger, LogFormat
37
36
  from webscout.litagent import LitAgent
38
37
 
39
- # Initialize our fire logger and agent 🔥
40
- logger = Logger(
41
- "AsyncArtbit",
42
- format=LogFormat.MODERN_EMOJI,
43
-
44
- )
45
38
  agent = LitAgent()
46
39
 
47
40
  class AsyncArtbitImager(AsyncImageProvider):
48
41
  """Your go-to async provider for generating fire images with Artbit! ⚡"""
49
42
 
50
- def __init__(self, timeout: int = 60, proxies: dict = {}, logging: bool = True):
43
+ def __init__(self, timeout: int = 60, proxies: dict = {}):
51
44
  """Initialize your async Artbit provider with custom settings! ⚙️
52
45
 
53
46
  Args:
54
47
  timeout (int): Request timeout in seconds (default: 60)
55
48
  proxies (dict): Proxy settings for requests (default: {})
56
- logging (bool): Enable fire logging (default: True)
57
49
  """
58
50
  self.url = "https://artbit.ai/api/generateImage"
59
51
  self.headers = {
@@ -65,9 +57,6 @@ class AsyncArtbitImager(AsyncImageProvider):
65
57
  self.proxies = proxies
66
58
  self.prompt: str = "AI-generated image - webscout"
67
59
  self.image_extension: str = "png"
68
- self.logging = logging
69
- if self.logging:
70
- logger.info("AsyncArtbit provider initialized! 🚀")
71
60
 
72
61
  async def generate(
73
62
  self,
@@ -96,9 +85,6 @@ class AsyncArtbitImager(AsyncImageProvider):
96
85
  self.prompt = prompt
97
86
  response: List[str] = []
98
87
 
99
- if self.logging:
100
- logger.info(f"Generating {amount} images with {caption_model}... 🎨")
101
-
102
88
  payload = {
103
89
  "captionInput": prompt,
104
90
  "captionModel": caption_model,
@@ -113,18 +99,10 @@ class AsyncArtbitImager(AsyncImageProvider):
113
99
  resp.raise_for_status()
114
100
  response_data = await resp.json()
115
101
  imgs = response_data.get("imgs", [])
116
-
117
102
  if imgs:
118
103
  response.extend(imgs)
119
- if self.logging:
120
- logger.success("Images generated successfully! 🎉")
121
- else:
122
- if self.logging:
123
- logger.warning("No images found in the response 😢")
124
104
 
125
105
  except aiohttp.ClientError as e:
126
- if self.logging:
127
- logger.error(f"Failed to generate images: {e} 😢")
128
106
  raise
129
107
 
130
108
  return response
@@ -153,9 +131,6 @@ class AsyncArtbitImager(AsyncImageProvider):
153
131
  filenames = []
154
132
  count = 0
155
133
 
156
- if self.logging:
157
- logger.info(f"Saving {len(response)} images... 💾")
158
-
159
134
  async with aiohttp.ClientSession(headers=self.headers) as session:
160
135
  for img_url in response:
161
136
  def complete_path():
@@ -175,10 +150,6 @@ class AsyncArtbitImager(AsyncImageProvider):
175
150
  await fh.write(await resp.read())
176
151
 
177
152
  except aiohttp.ClientError as e:
178
- if self.logging:
179
- logger.error(f"Failed to save image from {img_url}: {e} 😢")
180
153
  raise
181
154
 
182
- if self.logging:
183
- logger.success(f"Images saved successfully! Check {dir} 🎉")
184
155
  return filenames
@@ -4,8 +4,8 @@ ArtbitImager - Your go-to provider for generating fire images with Artbit! 🔥
4
4
  Examples:
5
5
  >>> from webscout import ArtbitImager
6
6
  >>>
7
- >>> # Initialize with logging
8
- >>> provider = ArtbitImager(logging=True)
7
+ >>> # Initialize provider
8
+ >>> provider = ArtbitImager()
9
9
  >>>
10
10
  >>> # Generate a single image
11
11
  >>> images = provider.generate("Cool art")
@@ -25,29 +25,21 @@ Examples:
25
25
  import cloudscraper
26
26
  import os
27
27
  import requests
28
- from typing import List
28
+ from typing import Union, List
29
29
  from webscout.AIbase import ImageProvider
30
- from webscout.Litlogger import Logger, LogFormat
31
30
  from webscout.litagent import LitAgent
32
31
 
33
- # Initialize our fire logger and agent 🔥
34
- logger = Logger(
35
- "Artbit",
36
- format=LogFormat.MODERN_EMOJI,
37
-
38
- )
39
32
  agent = LitAgent()
40
33
 
41
34
  class ArtbitImager(ImageProvider):
42
35
  """Your go-to provider for generating fire images with Artbit! 🔥"""
43
36
 
44
- def __init__(self, timeout: int = 60, proxies: dict = {}, logging: bool = True):
37
+ def __init__(self, timeout: int = 60, proxies: dict = {}):
45
38
  """Initialize your Artbit provider with custom settings! ⚙️
46
39
 
47
40
  Args:
48
41
  timeout (int): Request timeout in seconds (default: 60)
49
42
  proxies (dict): Proxy settings for requests (default: {})
50
- logging (bool): Enable fire logging (default: True)
51
43
  """
52
44
  self.url = "https://artbit.ai/api/generateImage"
53
45
  self.scraper = cloudscraper.create_scraper()
@@ -56,9 +48,6 @@ class ArtbitImager(ImageProvider):
56
48
  self.timeout = timeout
57
49
  self.prompt: str = "AI-generated image - webscout"
58
50
  self.image_extension: str = "png"
59
- self.logging = logging
60
- if self.logging:
61
- logger.info("Artbit provider initialized! 🚀")
62
51
 
63
52
  def generate(
64
53
  self,
@@ -87,9 +76,6 @@ class ArtbitImager(ImageProvider):
87
76
  self.prompt = prompt
88
77
  response: List[str] = []
89
78
 
90
- if self.logging:
91
- logger.info(f"Generating {amount} images with {caption_model}... 🎨")
92
-
93
79
  payload = {
94
80
  "captionInput": prompt,
95
81
  "captionModel": caption_model,
@@ -107,15 +93,8 @@ class ArtbitImager(ImageProvider):
107
93
 
108
94
  if imgs:
109
95
  response.extend(imgs)
110
- if self.logging:
111
- logger.success("Images generated successfully! 🎉")
112
- else:
113
- if self.logging:
114
- logger.warning("No images found in the response 😢")
115
96
 
116
97
  except requests.RequestException as e:
117
- if self.logging:
118
- logger.error(f"Failed to generate images: {e} 😢")
119
98
  raise
120
99
 
121
100
  return response
@@ -144,9 +123,6 @@ class ArtbitImager(ImageProvider):
144
123
  filenames = []
145
124
  count = 0
146
125
 
147
- if self.logging:
148
- logger.info(f"Saving {len(response)} images... 💾")
149
-
150
126
  for img_url in response:
151
127
  def complete_path():
152
128
  count_value = "" if count == 0 else f"_{count}"
@@ -167,10 +143,6 @@ class ArtbitImager(ImageProvider):
167
143
  fh.write(chunk)
168
144
 
169
145
  except requests.exceptions.RequestException as e:
170
- if self.logging:
171
- logger.error(f"Failed to save image from {img_url}: {e} 😢")
172
146
  raise
173
147
 
174
- if self.logging:
175
- logger.success(f"Images saved successfully! Check {dir} 🎉")
176
148
  return filenames
@@ -26,7 +26,6 @@ import aiofiles
26
26
  from webscout.AIbase import AsyncImageProvider
27
27
  from webscout.litagent import LitAgent
28
28
 
29
-
30
29
  class AsyncFastFluxImager(AsyncImageProvider):
31
30
  """Your go-to async provider for generating fire images with FastFlux! ⚡
32
31
 
@@ -55,7 +54,11 @@ class AsyncFastFluxImager(AsyncImageProvider):
55
54
  "sana_1_6b" # SANA 1.6B model
56
55
  ]
57
56
 
58
-
57
+ AVAILABLE_SIZES = [
58
+ "1_1",
59
+ "16_9",
60
+ "4_3",
61
+ ]
59
62
 
60
63
  def __init__(self, timeout: int = 60, proxies: dict = None):
61
64
  """Initialize your async FastFluxImager provider with custom settings ⚙️
@@ -81,6 +84,7 @@ class AsyncFastFluxImager(AsyncImageProvider):
81
84
  self.proxies = proxies
82
85
  self.prompt: str = "AI-generated image - webscout"
83
86
  self.image_extension: str = "png"
87
+ self.logging = True
84
88
 
85
89
 
86
90
  async def generate(
@@ -55,7 +55,12 @@ class FastFluxImager(ImageProvider):
55
55
  "flux_1_dev", # Developer model
56
56
  "sana_1_6b" # SANA 1.6B model
57
57
  ]
58
-
58
+
59
+ AVAILABLE_SIZES = [
60
+ "1_1",
61
+ "16_9",
62
+ "4_3",
63
+ ]
59
64
 
60
65
  def __init__(self, timeout: int = 60, proxies: dict = None):
61
66
  """Initialize your FastFluxImager provider with custom settings
@@ -84,7 +89,7 @@ class FastFluxImager(ImageProvider):
84
89
  self.timeout = timeout
85
90
  self.prompt: str = "AI-generated image - webscout"
86
91
  self.image_extension: str = "png"
87
-
92
+ self.logging = True
88
93
 
89
94
  def generate(
90
95
  self,
@@ -34,7 +34,7 @@ import os
34
34
  import aiohttp
35
35
  import aiofiles
36
36
  import asyncio
37
- from typing import Any, List, Optional, Dict
37
+ from typing import Union, Any, List, Optional, Dict
38
38
  from webscout.AIbase import AsyncImageProvider
39
39
  from webscout.Litlogger import Logger, LogFormat
40
40
  from webscout.litagent import LitAgent
@@ -29,7 +29,7 @@ import os
29
29
  import requests
30
30
  import io
31
31
  from PIL import Image
32
- from typing import Any, List, Optional, Dict
32
+ from typing import Union, Any, List, Optional, Dict
33
33
  from webscout.AIbase import ImageProvider
34
34
  from webscout.Litlogger import Logger, LogFormat
35
35
  from webscout.litagent import LitAgent
@@ -0,0 +1,4 @@
1
+ from .sync_pixelmuse import PixelMuseImager
2
+ from .async_pixelmuse import AsyncPixelMuseImager
3
+
4
+ __all__ = ['PixelMuseImager', 'AsyncPixelMuseImager']
@@ -0,0 +1,249 @@
1
+ import aiohttp
2
+ import asyncio
3
+ import os
4
+ import time
5
+ from typing import List, Optional, Union, AsyncGenerator
6
+ from string import punctuation
7
+ from random import choice
8
+ from aiohttp import ClientError
9
+ from pathlib import Path
10
+
11
+ from webscout.AIbase import AsyncImageProvider
12
+ from webscout.litagent import LitAgent
13
+
14
+ agent = LitAgent()
15
+
16
+ class AsyncPixelMuseImager(AsyncImageProvider):
17
+ """Your go-to async provider for generating fire images with PixelMuse! ⚡
18
+
19
+ Examples:
20
+ >>> # Basic usage
21
+ >>> provider = AsyncPixelMuseImager()
22
+ >>> async def example():
23
+ ... images = await provider.generate("Cool art")
24
+ ... paths = await provider.save(images)
25
+ >>>
26
+ >>> # Advanced usage
27
+ >>> provider = AsyncPixelMuseImager(timeout=120)
28
+ >>> async def example():
29
+ ... images = await provider.generate(
30
+ ... prompt="Epic dragon",
31
+ ... amount=3,
32
+ ... model="flux-schnell",
33
+ ... style="none",
34
+ ... aspect_ratio="1:1"
35
+ ... )
36
+ ... paths = await provider.save(images, name="dragon", dir="my_art")
37
+ """
38
+
39
+ AVAILABLE_MODELS = [
40
+ "flux-schnell",
41
+ "imagen-3-fast",
42
+ "imagen-3",
43
+ "recraft-v3"
44
+ ]
45
+
46
+ def __init__(self, timeout: int = 60, proxies: dict = {}):
47
+ """Initialize your async PixelMuse provider with custom settings! ⚙️
48
+
49
+ Args:
50
+ timeout (int): Request timeout in seconds (default: 60)
51
+ proxies (dict): Proxy settings for requests (default: {})
52
+ """
53
+ self.api_endpoint = "https://www.pixelmuse.studio/api/predictions"
54
+ self.headers = {
55
+ "accept": "*/*",
56
+ "accept-language": "en-US,en;q=0.9",
57
+ "content-type": "application/json",
58
+ "origin": "https://www.pixelmuse.studio",
59
+ "referer": "https://www.pixelmuse.studio/",
60
+ "sec-ch-ua": '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
61
+ "sec-ch-ua-mobile": "?0",
62
+ "sec-ch-ua-platform": '"Windows"',
63
+ "sec-fetch-dest": "empty",
64
+ "sec-fetch-mode": "cors",
65
+ "sec-fetch-site": "same-origin",
66
+ "user-agent": agent.random(),
67
+ }
68
+ self.timeout = timeout
69
+ self.proxies = proxies
70
+ self.prompt: str = "AI-generated image - webscout"
71
+ self.image_extension: str = "webp"
72
+
73
+ async def generate(
74
+ self,
75
+ prompt: str,
76
+ amount: int = 1,
77
+ max_retries: int = 3,
78
+ retry_delay: int = 5,
79
+ model: str = "flux-schnell",
80
+ style: str = "none",
81
+ aspect_ratio: str = "1:1"
82
+ ) -> List[bytes]:
83
+ """Generate some amazing images from your prompt asynchronously! ⚡
84
+
85
+ Examples:
86
+ >>> provider = AsyncPixelMuseImager()
87
+ >>> async def example():
88
+ ... # Basic usage
89
+ ... images = await provider.generate("Cool art")
90
+ ... # Advanced usage
91
+ ... images = await provider.generate(
92
+ ... prompt="Epic dragon",
93
+ ... amount=3,
94
+ ... model="flux-schnell"
95
+ ... )
96
+
97
+ Args:
98
+ prompt (str): Your creative prompt
99
+ amount (int): How many images to generate
100
+ max_retries (int): Max retry attempts if generation fails
101
+ retry_delay (int): Seconds to wait between retries
102
+ model (str): Model to use - check AVAILABLE_MODELS (default: "flux-schnell")
103
+ style (str): Style to apply (default: "none")
104
+ aspect_ratio (str): Aspect ratio (default: "1:1")
105
+
106
+ Returns:
107
+ List[bytes]: Your generated images
108
+
109
+ Raises:
110
+ ValueError: If the inputs ain't valid
111
+ ClientError: If the API calls fail after retries
112
+ """
113
+ assert bool(prompt), "Prompt cannot be null"
114
+ assert isinstance(amount, int), f"Amount should be an integer only not {type(amount)}"
115
+ assert amount > 0, "Amount should be greater than 0"
116
+ assert model in self.AVAILABLE_MODELS, f"Model should be one of {self.AVAILABLE_MODELS}"
117
+
118
+ self.prompt = prompt
119
+ response = []
120
+
121
+ async with aiohttp.ClientSession(headers=self.headers) as session:
122
+ for _ in range(amount):
123
+ for attempt in range(max_retries):
124
+ try:
125
+ # First request to get the prediction
126
+ async with session.post(
127
+ self.api_endpoint,
128
+ json=self._create_payload(prompt, model, style, aspect_ratio),
129
+ timeout=self.timeout,
130
+ proxy=self.proxies.get('http')
131
+ ) as resp:
132
+ resp.raise_for_status()
133
+ data = await resp.json()
134
+
135
+ if 'output' in data and len(data['output']) > 0:
136
+ image_url = data['output'][0]
137
+ # Get the image data from the URL
138
+ async with session.get(
139
+ image_url,
140
+ timeout=self.timeout,
141
+ proxy=self.proxies.get('http')
142
+ ) as img_resp:
143
+ img_resp.raise_for_status()
144
+ response.append(await img_resp.read())
145
+ break
146
+ else:
147
+ print(f"Warning: No image data in response: {data}")
148
+ if attempt == max_retries - 1:
149
+ raise Exception("No image data received after all retries")
150
+
151
+ except ClientError as e:
152
+ if attempt == max_retries - 1:
153
+ raise
154
+ else:
155
+ await asyncio.sleep(retry_delay)
156
+
157
+ return response
158
+
159
+ def _create_payload(self, prompt: str, model: str, style: str, aspect_ratio: str) -> dict:
160
+ """Create the API request payload 📦
161
+
162
+ Args:
163
+ prompt (str): The image generation prompt
164
+ model (str): Model to use
165
+ style (str): Style to apply
166
+ aspect_ratio (str): Aspect ratio
167
+
168
+ Returns:
169
+ dict: API request payload
170
+ """
171
+ return {
172
+ "prompt": prompt,
173
+ "model": model,
174
+ "style": style,
175
+ "aspect_ratio": aspect_ratio
176
+ }
177
+
178
+ async def save(
179
+ self,
180
+ response: Union[AsyncGenerator[bytes, None], List[bytes]],
181
+ name: Optional[str] = None,
182
+ dir: Optional[Union[str, Path]] = None,
183
+ filenames_prefix: str = "",
184
+ ) -> List[str]:
185
+ """Save your amazing images asynchronously! 💾
186
+
187
+ Examples:
188
+ >>> provider = AsyncPixelMuseImager()
189
+ >>> async def example():
190
+ ... images = await provider.generate("Cool art")
191
+ ... # Save with default settings
192
+ ... paths = await provider.save(images)
193
+ ... # Save with custom name and directory
194
+ ... paths = await provider.save(
195
+ ... images,
196
+ ... name="my_art",
197
+ ... dir="my_images",
198
+ ... filenames_prefix="test_"
199
+ ... )
200
+
201
+ Args:
202
+ response (Union[AsyncGenerator[bytes, None], List[bytes]]): Your generated images
203
+ name (Optional[str]): Custom name for your images
204
+ dir (Optional[Union[str, Path]]): Where to save the images (default: current directory)
205
+ filenames_prefix (str): Prefix for your image files
206
+
207
+ Returns:
208
+ List[str]: Paths to your saved images
209
+ """
210
+ save_dir = dir if dir else os.getcwd()
211
+ if not os.path.exists(save_dir):
212
+ os.makedirs(save_dir)
213
+
214
+ name = self.prompt if name is None else name
215
+ saved_paths = []
216
+ timestamp = int(time.time())
217
+
218
+ async def save_single_image(image_bytes: bytes, index: int) -> str:
219
+ filename = f"{filenames_prefix}{name}_{index}.{self.image_extension}"
220
+ filepath = os.path.join(save_dir, filename)
221
+
222
+ # Write file using asyncio
223
+ async with asyncio.Lock():
224
+ with open(filepath, "wb") as f:
225
+ f.write(image_bytes)
226
+
227
+ return filepath
228
+
229
+ # Handle both List[bytes] and AsyncGenerator
230
+ if isinstance(response, list):
231
+ image_list = response
232
+ else:
233
+ image_list = [chunk async for chunk in response]
234
+
235
+ tasks = [save_single_image(img, i) for i, img in enumerate(image_list)]
236
+ saved_paths = await asyncio.gather(*tasks)
237
+ return saved_paths
238
+
239
+ if __name__ == "__main__":
240
+ async def main():
241
+ bot = AsyncPixelMuseImager()
242
+ try:
243
+ resp = await bot.generate("A magical forest with glowing mushrooms and fairy lights", 1)
244
+ paths = await bot.save(resp)
245
+ print(paths)
246
+ except Exception as e:
247
+ print(f"An error occurred: {e}")
248
+
249
+ asyncio.run(main())