webscout 8.2.7__py3-none-any.whl → 8.2.9__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.
Files changed (281) hide show
  1. webscout/AIauto.py +33 -15
  2. webscout/AIbase.py +96 -37
  3. webscout/AIutel.py +703 -250
  4. webscout/Bard.py +441 -323
  5. webscout/Extra/Act.md +309 -0
  6. webscout/Extra/GitToolkit/__init__.py +10 -0
  7. webscout/Extra/GitToolkit/gitapi/README.md +110 -0
  8. webscout/Extra/GitToolkit/gitapi/__init__.py +12 -0
  9. webscout/Extra/GitToolkit/gitapi/repository.py +195 -0
  10. webscout/Extra/GitToolkit/gitapi/user.py +96 -0
  11. webscout/Extra/GitToolkit/gitapi/utils.py +62 -0
  12. webscout/Extra/YTToolkit/README.md +375 -0
  13. webscout/Extra/YTToolkit/YTdownloader.py +957 -0
  14. webscout/Extra/YTToolkit/__init__.py +3 -0
  15. webscout/Extra/YTToolkit/transcriber.py +476 -0
  16. webscout/Extra/YTToolkit/ytapi/README.md +44 -0
  17. webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
  18. webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
  19. webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
  20. webscout/Extra/YTToolkit/ytapi/extras.py +118 -0
  21. webscout/Extra/YTToolkit/ytapi/https.py +88 -0
  22. webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
  23. webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
  24. webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
  25. webscout/Extra/YTToolkit/ytapi/query.py +40 -0
  26. webscout/Extra/YTToolkit/ytapi/stream.py +63 -0
  27. webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
  28. webscout/Extra/YTToolkit/ytapi/video.py +232 -0
  29. webscout/Extra/__init__.py +7 -0
  30. webscout/Extra/autocoder/__init__.py +9 -0
  31. webscout/Extra/autocoder/autocoder.py +1105 -0
  32. webscout/Extra/autocoder/autocoder_utiles.py +332 -0
  33. webscout/Extra/gguf.md +430 -0
  34. webscout/Extra/gguf.py +684 -0
  35. webscout/Extra/tempmail/README.md +488 -0
  36. webscout/Extra/tempmail/__init__.py +28 -0
  37. webscout/Extra/tempmail/async_utils.py +141 -0
  38. webscout/Extra/tempmail/base.py +161 -0
  39. webscout/Extra/tempmail/cli.py +187 -0
  40. webscout/Extra/tempmail/emailnator.py +84 -0
  41. webscout/Extra/tempmail/mail_tm.py +361 -0
  42. webscout/Extra/tempmail/temp_mail_io.py +292 -0
  43. webscout/Extra/weather.md +281 -0
  44. webscout/Extra/weather.py +194 -0
  45. webscout/Extra/weather_ascii.py +76 -0
  46. webscout/Litlogger/README.md +10 -0
  47. webscout/Litlogger/__init__.py +15 -0
  48. webscout/Litlogger/formats.py +4 -0
  49. webscout/Litlogger/handlers.py +103 -0
  50. webscout/Litlogger/levels.py +13 -0
  51. webscout/Litlogger/logger.py +92 -0
  52. webscout/Provider/AI21.py +177 -0
  53. webscout/Provider/AISEARCH/DeepFind.py +254 -0
  54. webscout/Provider/AISEARCH/Perplexity.py +333 -0
  55. webscout/Provider/AISEARCH/README.md +279 -0
  56. webscout/Provider/AISEARCH/__init__.py +9 -0
  57. webscout/Provider/AISEARCH/felo_search.py +202 -0
  58. webscout/Provider/AISEARCH/genspark_search.py +324 -0
  59. webscout/Provider/AISEARCH/hika_search.py +186 -0
  60. webscout/Provider/AISEARCH/iask_search.py +410 -0
  61. webscout/Provider/AISEARCH/monica_search.py +220 -0
  62. webscout/Provider/AISEARCH/scira_search.py +298 -0
  63. webscout/Provider/AISEARCH/webpilotai_search.py +255 -0
  64. webscout/Provider/Aitopia.py +316 -0
  65. webscout/Provider/AllenAI.py +440 -0
  66. webscout/Provider/Andi.py +228 -0
  67. webscout/Provider/Blackboxai.py +791 -0
  68. webscout/Provider/ChatGPTClone.py +237 -0
  69. webscout/Provider/ChatGPTGratis.py +194 -0
  70. webscout/Provider/ChatSandbox.py +342 -0
  71. webscout/Provider/Cloudflare.py +324 -0
  72. webscout/Provider/Cohere.py +208 -0
  73. webscout/Provider/Deepinfra.py +340 -0
  74. webscout/Provider/ExaAI.py +261 -0
  75. webscout/Provider/ExaChat.py +358 -0
  76. webscout/Provider/Flowith.py +217 -0
  77. webscout/Provider/FreeGemini.py +250 -0
  78. webscout/Provider/Gemini.py +169 -0
  79. webscout/Provider/GithubChat.py +369 -0
  80. webscout/Provider/GizAI.py +295 -0
  81. webscout/Provider/Glider.py +225 -0
  82. webscout/Provider/Groq.py +801 -0
  83. webscout/Provider/HF_space/__init__.py +0 -0
  84. webscout/Provider/HF_space/qwen_qwen2.py +206 -0
  85. webscout/Provider/HeckAI.py +375 -0
  86. webscout/Provider/HuggingFaceChat.py +469 -0
  87. webscout/Provider/Hunyuan.py +283 -0
  88. webscout/Provider/Jadve.py +291 -0
  89. webscout/Provider/Koboldai.py +384 -0
  90. webscout/Provider/LambdaChat.py +411 -0
  91. webscout/Provider/Llama3.py +259 -0
  92. webscout/Provider/MCPCore.py +315 -0
  93. webscout/Provider/Marcus.py +198 -0
  94. webscout/Provider/Nemotron.py +218 -0
  95. webscout/Provider/Netwrck.py +270 -0
  96. webscout/Provider/OLLAMA.py +396 -0
  97. webscout/Provider/OPENAI/BLACKBOXAI.py +766 -0
  98. webscout/Provider/OPENAI/Cloudflare.py +378 -0
  99. webscout/Provider/OPENAI/FreeGemini.py +283 -0
  100. webscout/Provider/OPENAI/NEMOTRON.py +232 -0
  101. webscout/Provider/OPENAI/Qwen3.py +283 -0
  102. webscout/Provider/OPENAI/README.md +952 -0
  103. webscout/Provider/OPENAI/TwoAI.py +357 -0
  104. webscout/Provider/OPENAI/__init__.py +40 -0
  105. webscout/Provider/OPENAI/ai4chat.py +293 -0
  106. webscout/Provider/OPENAI/api.py +969 -0
  107. webscout/Provider/OPENAI/base.py +249 -0
  108. webscout/Provider/OPENAI/c4ai.py +373 -0
  109. webscout/Provider/OPENAI/chatgpt.py +556 -0
  110. webscout/Provider/OPENAI/chatgptclone.py +494 -0
  111. webscout/Provider/OPENAI/chatsandbox.py +173 -0
  112. webscout/Provider/OPENAI/copilot.py +242 -0
  113. webscout/Provider/OPENAI/deepinfra.py +322 -0
  114. webscout/Provider/OPENAI/e2b.py +1414 -0
  115. webscout/Provider/OPENAI/exaai.py +417 -0
  116. webscout/Provider/OPENAI/exachat.py +444 -0
  117. webscout/Provider/OPENAI/flowith.py +162 -0
  118. webscout/Provider/OPENAI/freeaichat.py +359 -0
  119. webscout/Provider/OPENAI/glider.py +326 -0
  120. webscout/Provider/OPENAI/groq.py +364 -0
  121. webscout/Provider/OPENAI/heckai.py +308 -0
  122. webscout/Provider/OPENAI/llmchatco.py +335 -0
  123. webscout/Provider/OPENAI/mcpcore.py +389 -0
  124. webscout/Provider/OPENAI/multichat.py +376 -0
  125. webscout/Provider/OPENAI/netwrck.py +357 -0
  126. webscout/Provider/OPENAI/oivscode.py +287 -0
  127. webscout/Provider/OPENAI/opkfc.py +496 -0
  128. webscout/Provider/OPENAI/pydantic_imports.py +172 -0
  129. webscout/Provider/OPENAI/scirachat.py +477 -0
  130. webscout/Provider/OPENAI/sonus.py +304 -0
  131. webscout/Provider/OPENAI/standardinput.py +433 -0
  132. webscout/Provider/OPENAI/textpollinations.py +339 -0
  133. webscout/Provider/OPENAI/toolbaz.py +413 -0
  134. webscout/Provider/OPENAI/typefully.py +355 -0
  135. webscout/Provider/OPENAI/typegpt.py +364 -0
  136. webscout/Provider/OPENAI/uncovrAI.py +463 -0
  137. webscout/Provider/OPENAI/utils.py +318 -0
  138. webscout/Provider/OPENAI/venice.py +431 -0
  139. webscout/Provider/OPENAI/wisecat.py +387 -0
  140. webscout/Provider/OPENAI/writecream.py +163 -0
  141. webscout/Provider/OPENAI/x0gpt.py +365 -0
  142. webscout/Provider/OPENAI/yep.py +382 -0
  143. webscout/Provider/OpenGPT.py +209 -0
  144. webscout/Provider/Openai.py +496 -0
  145. webscout/Provider/PI.py +429 -0
  146. webscout/Provider/Perplexitylabs.py +415 -0
  147. webscout/Provider/QwenLM.py +254 -0
  148. webscout/Provider/Reka.py +214 -0
  149. webscout/Provider/StandardInput.py +290 -0
  150. webscout/Provider/TTI/README.md +82 -0
  151. webscout/Provider/TTI/__init__.py +7 -0
  152. webscout/Provider/TTI/aiarta.py +365 -0
  153. webscout/Provider/TTI/artbit.py +0 -0
  154. webscout/Provider/TTI/base.py +64 -0
  155. webscout/Provider/TTI/fastflux.py +200 -0
  156. webscout/Provider/TTI/magicstudio.py +201 -0
  157. webscout/Provider/TTI/piclumen.py +203 -0
  158. webscout/Provider/TTI/pixelmuse.py +225 -0
  159. webscout/Provider/TTI/pollinations.py +221 -0
  160. webscout/Provider/TTI/utils.py +11 -0
  161. webscout/Provider/TTS/README.md +192 -0
  162. webscout/Provider/TTS/__init__.py +10 -0
  163. webscout/Provider/TTS/base.py +159 -0
  164. webscout/Provider/TTS/deepgram.py +156 -0
  165. webscout/Provider/TTS/elevenlabs.py +111 -0
  166. webscout/Provider/TTS/gesserit.py +128 -0
  167. webscout/Provider/TTS/murfai.py +113 -0
  168. webscout/Provider/TTS/openai_fm.py +129 -0
  169. webscout/Provider/TTS/parler.py +111 -0
  170. webscout/Provider/TTS/speechma.py +580 -0
  171. webscout/Provider/TTS/sthir.py +94 -0
  172. webscout/Provider/TTS/streamElements.py +333 -0
  173. webscout/Provider/TTS/utils.py +280 -0
  174. webscout/Provider/TeachAnything.py +229 -0
  175. webscout/Provider/TextPollinationsAI.py +308 -0
  176. webscout/Provider/TwoAI.py +475 -0
  177. webscout/Provider/TypliAI.py +305 -0
  178. webscout/Provider/UNFINISHED/ChatHub.py +209 -0
  179. webscout/Provider/UNFINISHED/Youchat.py +330 -0
  180. webscout/Provider/UNFINISHED/liner_api_request.py +263 -0
  181. webscout/Provider/UNFINISHED/puterjs.py +635 -0
  182. webscout/Provider/UNFINISHED/test_lmarena.py +119 -0
  183. webscout/Provider/Venice.py +258 -0
  184. webscout/Provider/VercelAI.py +253 -0
  185. webscout/Provider/WiseCat.py +233 -0
  186. webscout/Provider/WrDoChat.py +370 -0
  187. webscout/Provider/Writecream.py +246 -0
  188. webscout/Provider/WritingMate.py +269 -0
  189. webscout/Provider/__init__.py +174 -0
  190. webscout/Provider/ai4chat.py +174 -0
  191. webscout/Provider/akashgpt.py +335 -0
  192. webscout/Provider/asksteve.py +220 -0
  193. webscout/Provider/cerebras.py +290 -0
  194. webscout/Provider/chatglm.py +215 -0
  195. webscout/Provider/cleeai.py +213 -0
  196. webscout/Provider/copilot.py +425 -0
  197. webscout/Provider/elmo.py +283 -0
  198. webscout/Provider/freeaichat.py +285 -0
  199. webscout/Provider/geminiapi.py +208 -0
  200. webscout/Provider/granite.py +235 -0
  201. webscout/Provider/hermes.py +266 -0
  202. webscout/Provider/julius.py +223 -0
  203. webscout/Provider/koala.py +170 -0
  204. webscout/Provider/learnfastai.py +325 -0
  205. webscout/Provider/llama3mitril.py +215 -0
  206. webscout/Provider/llmchat.py +258 -0
  207. webscout/Provider/llmchatco.py +306 -0
  208. webscout/Provider/lmarena.py +198 -0
  209. webscout/Provider/meta.py +801 -0
  210. webscout/Provider/multichat.py +364 -0
  211. webscout/Provider/oivscode.py +309 -0
  212. webscout/Provider/samurai.py +224 -0
  213. webscout/Provider/scira_chat.py +299 -0
  214. webscout/Provider/scnet.py +243 -0
  215. webscout/Provider/searchchat.py +292 -0
  216. webscout/Provider/sonus.py +258 -0
  217. webscout/Provider/talkai.py +194 -0
  218. webscout/Provider/toolbaz.py +353 -0
  219. webscout/Provider/turboseek.py +266 -0
  220. webscout/Provider/typefully.py +202 -0
  221. webscout/Provider/typegpt.py +289 -0
  222. webscout/Provider/uncovr.py +368 -0
  223. webscout/Provider/x0gpt.py +299 -0
  224. webscout/Provider/yep.py +389 -0
  225. webscout/__init__.py +4 -2
  226. webscout/cli.py +3 -28
  227. webscout/client.py +70 -0
  228. webscout/conversation.py +35 -35
  229. webscout/litagent/Readme.md +276 -0
  230. webscout/litagent/__init__.py +29 -0
  231. webscout/litagent/agent.py +455 -0
  232. webscout/litagent/constants.py +60 -0
  233. webscout/litprinter/__init__.py +59 -0
  234. webscout/optimizers.py +419 -419
  235. webscout/scout/README.md +404 -0
  236. webscout/scout/__init__.py +8 -0
  237. webscout/scout/core/__init__.py +7 -0
  238. webscout/scout/core/crawler.py +210 -0
  239. webscout/scout/core/scout.py +607 -0
  240. webscout/scout/core/search_result.py +96 -0
  241. webscout/scout/core/text_analyzer.py +63 -0
  242. webscout/scout/core/text_utils.py +277 -0
  243. webscout/scout/core/web_analyzer.py +52 -0
  244. webscout/scout/element.py +478 -0
  245. webscout/scout/parsers/__init__.py +69 -0
  246. webscout/scout/parsers/html5lib_parser.py +172 -0
  247. webscout/scout/parsers/html_parser.py +236 -0
  248. webscout/scout/parsers/lxml_parser.py +178 -0
  249. webscout/scout/utils.py +37 -0
  250. webscout/swiftcli/Readme.md +323 -0
  251. webscout/swiftcli/__init__.py +95 -0
  252. webscout/swiftcli/core/__init__.py +7 -0
  253. webscout/swiftcli/core/cli.py +297 -0
  254. webscout/swiftcli/core/context.py +104 -0
  255. webscout/swiftcli/core/group.py +241 -0
  256. webscout/swiftcli/decorators/__init__.py +28 -0
  257. webscout/swiftcli/decorators/command.py +221 -0
  258. webscout/swiftcli/decorators/options.py +220 -0
  259. webscout/swiftcli/decorators/output.py +252 -0
  260. webscout/swiftcli/exceptions.py +21 -0
  261. webscout/swiftcli/plugins/__init__.py +9 -0
  262. webscout/swiftcli/plugins/base.py +135 -0
  263. webscout/swiftcli/plugins/manager.py +269 -0
  264. webscout/swiftcli/utils/__init__.py +59 -0
  265. webscout/swiftcli/utils/formatting.py +252 -0
  266. webscout/swiftcli/utils/parsing.py +267 -0
  267. webscout/version.py +1 -1
  268. webscout/webscout_search.py +2 -182
  269. webscout/webscout_search_async.py +1 -179
  270. webscout/zeroart/README.md +89 -0
  271. webscout/zeroart/__init__.py +135 -0
  272. webscout/zeroart/base.py +66 -0
  273. webscout/zeroart/effects.py +101 -0
  274. webscout/zeroart/fonts.py +1239 -0
  275. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/METADATA +262 -83
  276. webscout-8.2.9.dist-info/RECORD +289 -0
  277. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/WHEEL +1 -1
  278. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/entry_points.txt +1 -0
  279. webscout-8.2.7.dist-info/RECORD +0 -26
  280. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/licenses/LICENSE.md +0 -0
  281. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,221 @@
1
+ import requests
2
+ from typing import Optional, List, Dict, Any, Union
3
+ from pathlib import Path
4
+ from requests.exceptions import RequestException
5
+ from webscout.Provider.TTI.utils import ImageData, ImageResponse
6
+ from webscout.Provider.TTI.base import TTICompatibleProvider, BaseImages
7
+ from io import BytesIO
8
+ import os
9
+ import tempfile
10
+ from webscout.litagent import LitAgent
11
+ import time
12
+ import json
13
+ import random
14
+
15
+ try:
16
+ from PIL import Image
17
+ except ImportError:
18
+ Image = None
19
+
20
+ class Images(BaseImages):
21
+ def __init__(self, client):
22
+ self._client = client
23
+
24
+ def create(
25
+ self,
26
+ *,
27
+ model: str,
28
+ prompt: str,
29
+ n: int = 1,
30
+ size: str = "1024x1024",
31
+ response_format: str = "url",
32
+ user: Optional[str] = None,
33
+ style: str = "none",
34
+ aspect_ratio: str = "1:1",
35
+ timeout: int = 60,
36
+ image_format: str = "png",
37
+ seed: Optional[int] = None,
38
+ **kwargs
39
+ ) -> ImageResponse:
40
+ """
41
+ image_format: "png" or "jpeg"
42
+ seed: Optional random seed for reproducibility. If not provided, a random seed is used.
43
+ """
44
+ if Image is None:
45
+ raise ImportError("Pillow (PIL) is required for image format conversion.")
46
+
47
+ images = []
48
+ urls = []
49
+
50
+ def upload_file_with_retry(img_bytes, image_format, max_retries=3):
51
+ ext = "jpg" if image_format.lower() == "jpeg" else "png"
52
+ for attempt in range(max_retries):
53
+ tmp_path = None
54
+ try:
55
+ with tempfile.NamedTemporaryFile(suffix=f".{ext}", delete=False) as tmp:
56
+ tmp.write(img_bytes)
57
+ tmp.flush()
58
+ tmp_path = tmp.name
59
+ with open(tmp_path, 'rb') as f:
60
+ files = {
61
+ 'fileToUpload': (f'image.{ext}', f, f'image/{ext}')
62
+ }
63
+ data = {
64
+ 'reqtype': 'fileupload',
65
+ 'json': 'true'
66
+ }
67
+ headers = {'User-Agent': LitAgent().random()}
68
+ if attempt > 0:
69
+ headers['Connection'] = 'close'
70
+ resp = requests.post("https://catbox.moe/user/api.php", files=files, data=data, headers=headers, timeout=timeout)
71
+ if resp.status_code == 200 and resp.text.strip():
72
+ text = resp.text.strip()
73
+ if text.startswith('http'):
74
+ return text
75
+ try:
76
+ result = resp.json()
77
+ if "url" in result:
78
+ return result["url"]
79
+ except json.JSONDecodeError:
80
+ if 'http' in text:
81
+ return text
82
+ except Exception:
83
+ if attempt < max_retries - 1:
84
+ time.sleep(1 * (attempt + 1))
85
+ finally:
86
+ if tmp_path and os.path.isfile(tmp_path):
87
+ try:
88
+ os.remove(tmp_path)
89
+ except Exception:
90
+ pass
91
+ return None
92
+
93
+ def upload_file_alternative(img_bytes, image_format):
94
+ try:
95
+ ext = "jpg" if image_format.lower() == "jpeg" else "png"
96
+ with tempfile.NamedTemporaryFile(suffix=f".{ext}", delete=False) as tmp:
97
+ tmp.write(img_bytes)
98
+ tmp.flush()
99
+ tmp_path = tmp.name
100
+ try:
101
+ if not os.path.isfile(tmp_path):
102
+ return None
103
+ with open(tmp_path, 'rb') as img_file:
104
+ files = {'file': img_file}
105
+ response = requests.post('https://0x0.st', files=files)
106
+ response.raise_for_status()
107
+ image_url = response.text.strip()
108
+ if not image_url.startswith('http'):
109
+ return None
110
+ return image_url
111
+ except Exception:
112
+ return None
113
+ finally:
114
+ try:
115
+ os.remove(tmp_path)
116
+ except Exception:
117
+ pass
118
+ except Exception:
119
+ return None
120
+
121
+ for i in range(n):
122
+ # Prepare parameters for Pollinations API
123
+ params = {
124
+ "model": model,
125
+ "width": int(size.split("x")[0]) if "x" in size else 1024,
126
+ "height": int(size.split("x")[1]) if "x" in size else 1024,
127
+ "seed": seed if seed is not None else random.randint(0, 2**32 - 1),
128
+ }
129
+ # Build the API URL
130
+ base_url = f"https://image.pollinations.ai/prompt/{prompt}"
131
+ # Compose query string
132
+ query = "&".join(f"{k}={v}" for k, v in params.items())
133
+ url = f"{base_url}?{query}"
134
+ try:
135
+ resp = self._client.session.get(url, timeout=timeout)
136
+ resp.raise_for_status()
137
+ img_bytes = resp.content
138
+ except RequestException as e:
139
+ raise RuntimeError(f"Failed to fetch image from Pollinations API: {e}")
140
+
141
+ # Convert to png or jpeg in memory
142
+ with BytesIO(img_bytes) as input_io:
143
+ with Image.open(input_io) as im:
144
+ out_io = BytesIO()
145
+ if image_format.lower() == "jpeg":
146
+ im = im.convert("RGB")
147
+ im.save(out_io, format="JPEG")
148
+ else:
149
+ im.save(out_io, format="PNG")
150
+ img_bytes = out_io.getvalue()
151
+
152
+ images.append(img_bytes)
153
+
154
+ if response_format == "url":
155
+ uploaded_url = upload_file_with_retry(img_bytes, image_format)
156
+ if not uploaded_url:
157
+ uploaded_url = upload_file_alternative(img_bytes, image_format)
158
+ if uploaded_url:
159
+ urls.append(uploaded_url)
160
+ else:
161
+ raise RuntimeError("Failed to upload image to catbox.moe using all available methods")
162
+
163
+ result_data = []
164
+ if response_format == "url":
165
+ for url in urls:
166
+ result_data.append(ImageData(url=url))
167
+ elif response_format == "b64_json":
168
+ import base64
169
+ for img in images:
170
+ b64 = base64.b64encode(img).decode("utf-8")
171
+ result_data.append(ImageData(b64_json=b64))
172
+ else:
173
+ raise ValueError("response_format must be 'url' or 'b64_json'")
174
+
175
+ from time import time as _time
176
+ return ImageResponse(
177
+ created=int(_time()),
178
+ data=result_data
179
+ )
180
+
181
+ class PollinationsAI(TTICompatibleProvider):
182
+ AVAILABLE_MODELS = [
183
+ "flux",
184
+ "turbo",
185
+ "gptimage"
186
+ ]
187
+
188
+ def __init__(self):
189
+ self.api_endpoint = "https://image.pollinations.ai/prompt"
190
+ self.session = requests.Session()
191
+ self.user_agent = LitAgent().random()
192
+ self.headers = {
193
+ "accept": "*/*",
194
+ "accept-language": "en-US,en;q=0.9",
195
+ "content-type": "application/json",
196
+ "origin": "https://image.pollinations.ai",
197
+ "referer": "https://image.pollinations.ai/",
198
+ "user-agent": self.user_agent,
199
+ }
200
+ self.session.headers.update(self.headers)
201
+ self.images = Images(self)
202
+
203
+ @property
204
+ def models(self):
205
+ class _ModelList:
206
+ def list(inner_self):
207
+ return type(self).AVAILABLE_MODELS
208
+ return _ModelList()
209
+
210
+ if __name__ == "__main__":
211
+ from rich import print
212
+ client = PollinationsAI()
213
+ response = client.images.create(
214
+ model="flux",
215
+ prompt="a japanese waifu in short kimono clothes",
216
+ response_format="url",
217
+ n=4,
218
+ timeout=30,
219
+ seed=None # You can set a specific seed for reproducibility
220
+ )
221
+ print(response)
@@ -0,0 +1,11 @@
1
+ from typing import List, Optional
2
+ from pydantic import BaseModel, Field
3
+ import time
4
+
5
+ class ImageData(BaseModel):
6
+ url: Optional[str] = None
7
+ b64_json: Optional[str] = None
8
+
9
+ class ImageResponse(BaseModel):
10
+ created: int = Field(default_factory=lambda: int(time.time()))
11
+ data: List[ImageData]
@@ -0,0 +1,192 @@
1
+ # 🎙️ Webscout Text-to-Speech (TTS) Providers
2
+
3
+ ## Overview
4
+
5
+ Webscout's TTS Providers offer a versatile and powerful text-to-speech conversion library with support for multiple providers and advanced features.
6
+
7
+ ## 🌟 Features
8
+
9
+ - **Multiple TTS Providers**: Support for various text-to-speech services
10
+ - **Concurrent Audio Generation**: Efficiently process long texts
11
+ - **Flexible Voice Selection**: Choose from a wide range of voices
12
+ - **Robust Error Handling**: Comprehensive logging and error management
13
+ - **Temporary File Management**: Automatically manages temporary audio files
14
+ - **Cross-Platform Compatibility**: Works seamlessly across different environments
15
+ - **Custom Save Locations**: Save audio files to specific destinations
16
+ - **Audio Streaming**: Stream audio data in chunks for real-time applications
17
+
18
+ ## 📦 Supported TTS Providers
19
+
20
+ 1. **ElevenlabsTTS**
21
+ 2. **GesseritTTS**
22
+ 3. **MurfAITTS**
23
+ 4. **ParlerTTS**
24
+ 5. **DeepgramTTS**
25
+ 6. **StreamElementsTTS**
26
+ 7. **SpeechMaTTS**
27
+ 8. **SthirTTS**
28
+ ## 🚀 Installation
29
+
30
+ ```bash
31
+ pip install webscout
32
+ ```
33
+
34
+ ## 💻 Basic Usage
35
+
36
+ ```python
37
+ from webscout.Provider.TTS import ElevenlabsTTS
38
+
39
+ # Initialize the TTS provider
40
+ tts = ElevenlabsTTS()
41
+
42
+ # Generate speech from text
43
+ text = "Hello, this is a test of text-to-speech conversion."
44
+ audio_file = tts.tts(text, voice="Brian")
45
+
46
+ # Save the audio to a specific location
47
+ saved_path = tts.save_audio(audio_file, destination="my_speech.mp3")
48
+ print(f"Audio saved to: {saved_path}")
49
+
50
+ # Stream audio in chunks
51
+ for chunk in tts.stream_audio(text, voice="Brian"):
52
+ # Process each chunk (e.g., send to a websocket, write to a stream, etc.)
53
+ process_audio_chunk(chunk)
54
+ ```
55
+
56
+ ## 🎛️ Advanced Configuration
57
+
58
+ ### Voice Selection
59
+
60
+ Each TTS provider offers multiple voices:
61
+
62
+ ```python
63
+ # List available voices
64
+ print(tts.all_voices.keys())
65
+
66
+ # Select a specific voice
67
+ audio_file = tts.tts(text, voice="Alice")
68
+ ```
69
+
70
+ ### Verbose Logging
71
+
72
+ Enable detailed logging for debugging:
73
+
74
+ ```python
75
+ audio_file = tts.tts(text, verbose=True)
76
+ ```
77
+
78
+ ## 🔧 Provider-Specific Details
79
+
80
+ ### ElevenlabsTTS
81
+
82
+ - Supports multiple English voices
83
+ - Multilingual text-to-speech
84
+
85
+ ### GesseritTTS
86
+
87
+ - Offers unique voice characteristics
88
+ - Supports voice description customization
89
+
90
+ ### MurfAITTS
91
+
92
+ - Provides specific voice models
93
+ - Supports custom voice descriptions
94
+
95
+ ### ParlerTTS
96
+
97
+ - Uses Gradio Client for TTS generation
98
+ - Supports large and small model variants
99
+
100
+ ### DeepgramTTS
101
+
102
+ - Multiple voice options
103
+ - Advanced voice selection
104
+
105
+ ### StreamElementsTTS
106
+
107
+ - Wide range of international voices
108
+
109
+ ### SpeechMaTTS
110
+
111
+ - Multilingual voices (Ava, Emma, Andrew, Brian)
112
+ - Adjustable pitch and speech rate
113
+ - Fast audio generation
114
+
115
+ ## 🛡️ Error Handling
116
+
117
+ ```python
118
+ try:
119
+ audio_file = tts.tts(text)
120
+ except exceptions.FailedToGenerateResponseError as e:
121
+ print(f"TTS generation failed: {e}")
122
+ ```
123
+
124
+ ## 🌐 Proxy Support
125
+
126
+ ```python
127
+ # Use with proxy
128
+ tts = ElevenlabsTTS(proxies={
129
+ 'http': 'http://proxy.example.com:8080',
130
+ 'https': 'https://proxy.example.com:8080'
131
+ })
132
+ ```
133
+
134
+ ## 💾 Custom Audio Saving
135
+
136
+ Save generated audio to a specific location:
137
+
138
+ ```python
139
+ # Generate speech
140
+ audio_file = tts.tts(text, voice="Brian")
141
+
142
+ # Save to a specific file
143
+ tts.save_audio(audio_file, destination="path/to/output.mp3")
144
+
145
+ # Save to a specific directory with default filename
146
+ tts.save_audio(audio_file, destination="path/to/directory/")
147
+
148
+ # Save with default location (current directory with timestamp)
149
+ saved_path = tts.save_audio(audio_file)
150
+ print(f"Saved to: {saved_path}")
151
+ ```
152
+
153
+ ## 📼 Audio Streaming
154
+
155
+ Stream audio data in chunks for real-time applications:
156
+
157
+ ```python
158
+ # Stream audio in chunks
159
+ for chunk in tts.stream_audio(text, voice="Brian", chunk_size=2048):
160
+ # Example: Send to a websocket
161
+ websocket.send(chunk)
162
+
163
+ # Example: Write to an audio stream
164
+ audio_stream.write(chunk)
165
+
166
+ # Example: Process in real-time
167
+ process_audio_data(chunk)
168
+ ```
169
+
170
+ ## ⏱️ Async Support
171
+
172
+ Use the async versions for non-blocking operations:
173
+
174
+ ```python
175
+ from webscout.Provider.TTS import AsyncElevenlabsTTS
176
+ import asyncio
177
+
178
+ async def main():
179
+ tts = AsyncElevenlabsTTS()
180
+
181
+ # Generate speech
182
+ audio_file = await tts.tts(text, voice="Brian")
183
+
184
+ # Save to a specific location
185
+ saved_path = await tts.save_audio(audio_file, destination="output.mp3")
186
+
187
+ # Stream audio
188
+ async for chunk in tts.stream_audio(text, voice="Brian"):
189
+ await process_chunk(chunk)
190
+
191
+ asyncio.run(main())
192
+ ```
@@ -0,0 +1,10 @@
1
+ from .base import BaseTTSProvider, AsyncBaseTTSProvider
2
+ from .streamElements import *
3
+ from .parler import *
4
+ from .deepgram import *
5
+ from .elevenlabs import *
6
+ from .murfai import *
7
+ from .gesserit import *
8
+ from .speechma import *
9
+ from .sthir import *
10
+ from .openai_fm import *
@@ -0,0 +1,159 @@
1
+ """
2
+ Base class for TTS providers with common functionality.
3
+ """
4
+ import os
5
+ import tempfile
6
+ from pathlib import Path
7
+ from typing import Generator, Optional
8
+ from webscout.AIbase import TTSProvider
9
+
10
+ class BaseTTSProvider(TTSProvider):
11
+ """
12
+ Base class for TTS providers with common functionality.
13
+
14
+ This class implements common methods like save_audio and stream_audio
15
+ that can be used by all TTS providers.
16
+ """
17
+
18
+ def __init__(self):
19
+ """Initialize the base TTS provider."""
20
+ self.temp_dir = tempfile.mkdtemp(prefix="webscout_tts_")
21
+
22
+ def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
23
+ """
24
+ Save audio to a specific destination.
25
+
26
+ Args:
27
+ audio_file (str): Path to the source audio file
28
+ destination (str, optional): Destination path. Defaults to current directory with timestamp.
29
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
30
+
31
+ Returns:
32
+ str: Path to the saved audio file
33
+
34
+ Raises:
35
+ FileNotFoundError: If the audio file doesn't exist
36
+ """
37
+ import shutil
38
+ import time
39
+
40
+ source_path = Path(audio_file)
41
+
42
+ if not source_path.exists():
43
+ raise FileNotFoundError(f"Audio file not found: {audio_file}")
44
+
45
+ if destination is None:
46
+ # Create a default destination with timestamp in current directory
47
+ timestamp = int(time.time())
48
+ destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
49
+
50
+ # Ensure the destination directory exists
51
+ os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
52
+
53
+ # Copy the file
54
+ shutil.copy2(source_path, destination)
55
+
56
+ if verbose:
57
+ print(f"[debug] Audio saved to {destination}")
58
+
59
+ return destination
60
+
61
+ def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> Generator[bytes, None, None]:
62
+ """
63
+ Stream audio in chunks.
64
+
65
+ Args:
66
+ text (str): The text to convert to speech
67
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
68
+ chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
69
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
70
+
71
+ Yields:
72
+ Generator[bytes, None, None]: Audio data chunks
73
+ """
74
+ # Generate the audio file
75
+ audio_file = self.tts(text, voice=voice, verbose=verbose)
76
+
77
+ # Stream the file in chunks
78
+ with open(audio_file, 'rb') as f:
79
+ while chunk := f.read(chunk_size):
80
+ yield chunk
81
+
82
+
83
+ class AsyncBaseTTSProvider:
84
+ """
85
+ Base class for async TTS providers with common functionality.
86
+
87
+ This class implements common async methods like save_audio and stream_audio
88
+ that can be used by all async TTS providers.
89
+ """
90
+
91
+ def __init__(self):
92
+ """Initialize the async base TTS provider."""
93
+ self.temp_dir = tempfile.mkdtemp(prefix="webscout_tts_")
94
+
95
+ async def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
96
+ """
97
+ Save audio to a specific destination asynchronously.
98
+
99
+ Args:
100
+ audio_file (str): Path to the source audio file
101
+ destination (str, optional): Destination path. Defaults to current directory with timestamp.
102
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
103
+
104
+ Returns:
105
+ str: Path to the saved audio file
106
+
107
+ Raises:
108
+ FileNotFoundError: If the audio file doesn't exist
109
+ """
110
+ import shutil
111
+ import time
112
+ import asyncio
113
+
114
+ source_path = Path(audio_file)
115
+
116
+ if not source_path.exists():
117
+ raise FileNotFoundError(f"Audio file not found: {audio_file}")
118
+
119
+ if destination is None:
120
+ # Create a default destination with timestamp in current directory
121
+ timestamp = int(time.time())
122
+ destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
123
+
124
+ # Ensure the destination directory exists
125
+ os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
126
+
127
+ # Copy the file using asyncio to avoid blocking
128
+ await asyncio.to_thread(shutil.copy2, source_path, destination)
129
+
130
+ if verbose:
131
+ print(f"[debug] Audio saved to {destination}")
132
+
133
+ return destination
134
+
135
+ async def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False):
136
+ """
137
+ Stream audio in chunks asynchronously.
138
+
139
+ Args:
140
+ text (str): The text to convert to speech
141
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
142
+ chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
143
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
144
+
145
+ Yields:
146
+ AsyncGenerator[bytes, None]: Audio data chunks
147
+ """
148
+ try:
149
+ import aiofiles
150
+ except ImportError:
151
+ raise ImportError("The 'aiofiles' package is required for async streaming. Install it with 'pip install aiofiles'.")
152
+
153
+ # Generate the audio file
154
+ audio_file = await self.tts(text, voice=voice, verbose=verbose)
155
+
156
+ # Stream the file in chunks
157
+ async with aiofiles.open(audio_file, 'rb') as f:
158
+ while chunk := await f.read(chunk_size):
159
+ yield chunk