webscout 8.2.6__py3-none-any.whl → 8.2.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 (150) hide show
  1. webscout/AIauto.py +1 -1
  2. webscout/AIutel.py +298 -239
  3. webscout/Extra/Act.md +309 -0
  4. webscout/Extra/GitToolkit/gitapi/README.md +110 -0
  5. webscout/Extra/YTToolkit/README.md +375 -0
  6. webscout/Extra/YTToolkit/ytapi/README.md +44 -0
  7. webscout/Extra/YTToolkit/ytapi/extras.py +92 -19
  8. webscout/Extra/autocoder/autocoder.py +309 -114
  9. webscout/Extra/autocoder/autocoder_utiles.py +15 -15
  10. webscout/Extra/gguf.md +430 -0
  11. webscout/Extra/tempmail/README.md +488 -0
  12. webscout/Extra/weather.md +281 -0
  13. webscout/Litlogger/Readme.md +175 -0
  14. webscout/Provider/AISEARCH/DeepFind.py +41 -37
  15. webscout/Provider/AISEARCH/README.md +279 -0
  16. webscout/Provider/AISEARCH/__init__.py +0 -1
  17. webscout/Provider/AISEARCH/genspark_search.py +228 -86
  18. webscout/Provider/AISEARCH/hika_search.py +11 -11
  19. webscout/Provider/AISEARCH/scira_search.py +324 -322
  20. webscout/Provider/AllenAI.py +7 -14
  21. webscout/Provider/Blackboxai.py +518 -74
  22. webscout/Provider/Cloudflare.py +0 -1
  23. webscout/Provider/Deepinfra.py +23 -21
  24. webscout/Provider/Flowith.py +217 -0
  25. webscout/Provider/FreeGemini.py +250 -0
  26. webscout/Provider/GizAI.py +15 -5
  27. webscout/Provider/Glider.py +11 -8
  28. webscout/Provider/HeckAI.py +80 -52
  29. webscout/Provider/Koboldai.py +7 -4
  30. webscout/Provider/LambdaChat.py +2 -2
  31. webscout/Provider/Marcus.py +10 -18
  32. webscout/Provider/OPENAI/BLACKBOXAI.py +735 -0
  33. webscout/Provider/OPENAI/Cloudflare.py +378 -0
  34. webscout/Provider/OPENAI/FreeGemini.py +282 -0
  35. webscout/Provider/OPENAI/NEMOTRON.py +244 -0
  36. webscout/Provider/OPENAI/README.md +1253 -0
  37. webscout/Provider/OPENAI/__init__.py +8 -0
  38. webscout/Provider/OPENAI/ai4chat.py +293 -286
  39. webscout/Provider/OPENAI/api.py +810 -0
  40. webscout/Provider/OPENAI/base.py +217 -14
  41. webscout/Provider/OPENAI/c4ai.py +373 -367
  42. webscout/Provider/OPENAI/chatgpt.py +7 -0
  43. webscout/Provider/OPENAI/chatgptclone.py +7 -0
  44. webscout/Provider/OPENAI/chatsandbox.py +172 -0
  45. webscout/Provider/OPENAI/deepinfra.py +30 -20
  46. webscout/Provider/OPENAI/e2b.py +6 -0
  47. webscout/Provider/OPENAI/exaai.py +7 -0
  48. webscout/Provider/OPENAI/exachat.py +6 -0
  49. webscout/Provider/OPENAI/flowith.py +162 -0
  50. webscout/Provider/OPENAI/freeaichat.py +359 -352
  51. webscout/Provider/OPENAI/glider.py +323 -316
  52. webscout/Provider/OPENAI/groq.py +361 -354
  53. webscout/Provider/OPENAI/heckai.py +30 -64
  54. webscout/Provider/OPENAI/llmchatco.py +8 -0
  55. webscout/Provider/OPENAI/mcpcore.py +7 -0
  56. webscout/Provider/OPENAI/multichat.py +8 -0
  57. webscout/Provider/OPENAI/netwrck.py +356 -350
  58. webscout/Provider/OPENAI/opkfc.py +8 -0
  59. webscout/Provider/OPENAI/scirachat.py +471 -462
  60. webscout/Provider/OPENAI/sonus.py +9 -0
  61. webscout/Provider/OPENAI/standardinput.py +9 -1
  62. webscout/Provider/OPENAI/textpollinations.py +339 -329
  63. webscout/Provider/OPENAI/toolbaz.py +7 -0
  64. webscout/Provider/OPENAI/typefully.py +355 -0
  65. webscout/Provider/OPENAI/typegpt.py +358 -346
  66. webscout/Provider/OPENAI/uncovrAI.py +7 -0
  67. webscout/Provider/OPENAI/utils.py +103 -7
  68. webscout/Provider/OPENAI/venice.py +12 -0
  69. webscout/Provider/OPENAI/wisecat.py +19 -19
  70. webscout/Provider/OPENAI/writecream.py +7 -0
  71. webscout/Provider/OPENAI/x0gpt.py +7 -0
  72. webscout/Provider/OPENAI/yep.py +50 -21
  73. webscout/Provider/OpenGPT.py +1 -1
  74. webscout/Provider/TTI/AiForce/README.md +159 -0
  75. webscout/Provider/TTI/FreeAIPlayground/README.md +99 -0
  76. webscout/Provider/TTI/ImgSys/README.md +174 -0
  77. webscout/Provider/TTI/MagicStudio/README.md +101 -0
  78. webscout/Provider/TTI/Nexra/README.md +155 -0
  79. webscout/Provider/TTI/PollinationsAI/README.md +146 -0
  80. webscout/Provider/TTI/README.md +128 -0
  81. webscout/Provider/TTI/aiarta/README.md +134 -0
  82. webscout/Provider/TTI/artbit/README.md +100 -0
  83. webscout/Provider/TTI/fastflux/README.md +129 -0
  84. webscout/Provider/TTI/huggingface/README.md +114 -0
  85. webscout/Provider/TTI/piclumen/README.md +161 -0
  86. webscout/Provider/TTI/pixelmuse/README.md +79 -0
  87. webscout/Provider/TTI/talkai/README.md +139 -0
  88. webscout/Provider/TTS/README.md +192 -0
  89. webscout/Provider/TTS/__init__.py +2 -1
  90. webscout/Provider/TTS/speechma.py +500 -100
  91. webscout/Provider/TTS/sthir.py +94 -0
  92. webscout/Provider/TeachAnything.py +3 -7
  93. webscout/Provider/TextPollinationsAI.py +4 -2
  94. webscout/Provider/{aimathgpt.py → UNFINISHED/ChatHub.py} +88 -68
  95. webscout/Provider/UNFINISHED/liner_api_request.py +263 -0
  96. webscout/Provider/UNFINISHED/oivscode.py +351 -0
  97. webscout/Provider/UNFINISHED/test_lmarena.py +119 -0
  98. webscout/Provider/Writecream.py +11 -2
  99. webscout/Provider/__init__.py +8 -14
  100. webscout/Provider/ai4chat.py +4 -58
  101. webscout/Provider/asksteve.py +17 -9
  102. webscout/Provider/cerebras.py +3 -1
  103. webscout/Provider/koala.py +170 -268
  104. webscout/Provider/llmchat.py +3 -0
  105. webscout/Provider/lmarena.py +198 -0
  106. webscout/Provider/meta.py +7 -4
  107. webscout/Provider/samurai.py +223 -0
  108. webscout/Provider/scira_chat.py +4 -2
  109. webscout/Provider/typefully.py +23 -151
  110. webscout/__init__.py +4 -2
  111. webscout/cli.py +3 -28
  112. webscout/conversation.py +35 -35
  113. webscout/litagent/Readme.md +276 -0
  114. webscout/scout/README.md +402 -0
  115. webscout/swiftcli/Readme.md +323 -0
  116. webscout/version.py +1 -1
  117. webscout/webscout_search.py +2 -182
  118. webscout/webscout_search_async.py +1 -179
  119. webscout/zeroart/README.md +89 -0
  120. webscout/zeroart/__init__.py +134 -54
  121. webscout/zeroart/base.py +19 -13
  122. webscout/zeroart/effects.py +101 -99
  123. webscout/zeroart/fonts.py +1239 -816
  124. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/METADATA +116 -74
  125. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/RECORD +130 -103
  126. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/WHEEL +1 -1
  127. webscout-8.2.8.dist-info/entry_points.txt +3 -0
  128. webscout-8.2.8.dist-info/top_level.txt +1 -0
  129. webscout/Provider/AISEARCH/ISou.py +0 -256
  130. webscout/Provider/ElectronHub.py +0 -773
  131. webscout/Provider/Free2GPT.py +0 -241
  132. webscout/Provider/GPTWeb.py +0 -249
  133. webscout/Provider/bagoodex.py +0 -145
  134. webscout/Provider/geminiprorealtime.py +0 -160
  135. webscout/scout/core.py +0 -881
  136. webscout-8.2.6.dist-info/entry_points.txt +0 -3
  137. webscout-8.2.6.dist-info/top_level.txt +0 -2
  138. webstoken/__init__.py +0 -30
  139. webstoken/classifier.py +0 -189
  140. webstoken/keywords.py +0 -216
  141. webstoken/language.py +0 -128
  142. webstoken/ner.py +0 -164
  143. webstoken/normalizer.py +0 -35
  144. webstoken/processor.py +0 -77
  145. webstoken/sentiment.py +0 -206
  146. webstoken/stemmer.py +0 -73
  147. webstoken/tagger.py +0 -60
  148. webstoken/tokenizer.py +0 -158
  149. /webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +0 -0
  150. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/licenses/LICENSE.md +0 -0
@@ -103,11 +103,6 @@ class AsyncWEBS:
103
103
  self.sleep_timestamp = 0.0
104
104
 
105
105
  self._exception_event = asyncio.Event()
106
- self._chat_messages: List[Dict[str, str]] = []
107
- self._chat_tokens_count = 0
108
- self._chat_vqd: str = ""
109
- self._chat_vqd_hash: str = ""
110
- self._chat_xfe: str = ""
111
106
 
112
107
  async def __aenter__(self) -> AsyncWEBS:
113
108
  return self
@@ -189,179 +184,6 @@ class AsyncWEBS:
189
184
  resp_content = (await self._get_url("GET", "https://duckduckgo.com", params={"q": keywords})).content
190
185
  return _extract_vqd(resp_content, keywords)
191
186
 
192
- async def achat_yield(self, keywords: str, model: str = "gpt-4o-mini", timeout: int = 30, max_retries: int = 3) -> AsyncIterator[str]:
193
- """Initiates an async chat session with webscout AI.
194
-
195
- Args:
196
- keywords (str): The initial message or question to send to the AI.
197
- model (str): The model to use: "gpt-4o-mini", "llama-3.3-70b", "claude-3-haiku",
198
- "o3-mini", "mistral-small-3". Defaults to "gpt-4o-mini".
199
- timeout (int): Timeout value for the HTTP client. Defaults to 30.
200
- max_retries (int): Maximum number of retry attempts for rate limited requests. Defaults to 3.
201
-
202
- Yields:
203
- str: Chunks of the response from the AI.
204
- """
205
- # Get Cloudflare Turnstile token
206
- async def get_turnstile_token():
207
- try:
208
- # Visit the DuckDuckGo chat page to get the Turnstile token
209
- resp_content = (await self._get_url(
210
- method="GET",
211
- url="https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=1",
212
- )).content
213
-
214
- # Extract the Turnstile token if available
215
- if b'cf-turnstile-response' in resp_content:
216
- token = resp_content.split(b'cf-turnstile-response="', maxsplit=1)[1].split(b'"', maxsplit=1)[0].decode()
217
- return token
218
- return ""
219
- except Exception:
220
- return ""
221
-
222
- # x-fe-version
223
- if not self._chat_xfe:
224
- resp_content = (await self._get_url(
225
- method="GET",
226
- url="https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=1",
227
- )).content
228
- try:
229
- xfe1 = resp_content.split(b'__DDG_BE_VERSION__="', maxsplit=1)[1].split(b'"', maxsplit=1)[0].decode()
230
- xfe2 = resp_content.split(b'__DDG_FE_CHAT_HASH__="', maxsplit=1)[1].split(b'"', maxsplit=1)[0].decode()
231
- self._chat_xfe = f"{xfe1}-{xfe2}"
232
- except Exception as ex:
233
- raise WebscoutE(
234
- f"achat_yield() Error to get _chat_xfe: {type(ex).__name__}: {ex}"
235
- ) from ex
236
- # vqd
237
- if not self._chat_vqd:
238
- resp = await self._get_url(
239
- method="GET", url="https://duckduckgo.com/duckchat/v1/status", headers={"x-vqd-accept": "1"}
240
- )
241
- self._chat_vqd = resp.headers.get("x-vqd-4", "")
242
- self._chat_vqd_hash = resp.headers.get("x-vqd-hash-1", "")
243
-
244
- self._chat_messages.append({"role": "user", "content": keywords})
245
- self._chat_tokens_count += max(len(keywords) // 4, 1) # approximate number of tokens
246
- if model not in self._chat_models:
247
- warnings.warn(f"{model=} is unavailable. Using 'gpt-4o-mini'", stacklevel=1)
248
- model = "gpt-4o-mini"
249
-
250
- # Get Cloudflare Turnstile token
251
- turnstile_token = await get_turnstile_token()
252
-
253
- json_data = {
254
- "model": self._chat_models[model],
255
- "messages": self._chat_messages,
256
- }
257
-
258
- # Add Turnstile token if available
259
- if turnstile_token:
260
- json_data["cf-turnstile-response"] = turnstile_token
261
-
262
- # Enhanced headers to better mimic a real browser
263
- chat_headers = {
264
- "x-fe-version": self._chat_xfe,
265
- "x-vqd-4": self._chat_vqd,
266
- "x-vqd-hash-1": "",
267
- "Accept": "text/event-stream",
268
- "Accept-Language": "en-US,en;q=0.9",
269
- "Cache-Control": "no-cache",
270
- "Content-Type": "application/json",
271
- "DNT": "1",
272
- "Origin": "https://duckduckgo.com",
273
- "Referer": "https://duckduckgo.com/",
274
- "Sec-Fetch-Dest": "empty",
275
- "Sec-Fetch-Mode": "cors",
276
- "Sec-Fetch-Site": "same-origin",
277
- "User-Agent": self.client.headers.get("User-Agent", "")
278
- }
279
-
280
- # Retry logic for rate limited requests
281
- retry_count = 0
282
- while retry_count <= max_retries:
283
- try:
284
- resp = await self._get_url(
285
- method="POST",
286
- url="https://duckduckgo.com/duckchat/v1/chat",
287
- headers=chat_headers,
288
- json=json_data,
289
- timeout=timeout,
290
- )
291
-
292
- self._chat_vqd = resp.headers.get("x-vqd-4", "")
293
- self._chat_vqd_hash = resp.headers.get("x-vqd-hash-1", "")
294
- chunks = []
295
-
296
- # curl_cffi uses aiter_content instead of aiter_bytes
297
- async for chunk in resp.aiter_content(chunk_size=1024):
298
- lines = chunk.split(b"data:")
299
- for line in lines:
300
- if line := line.strip():
301
- if line == b"[DONE]":
302
- break
303
- if line == b"[DONE][LIMIT_CONVERSATION]":
304
- raise ConversationLimitException("ERR_CONVERSATION_LIMIT")
305
- try:
306
- x = json_loads(line)
307
- if isinstance(x, dict):
308
- if x.get("action") == "error":
309
- err_message = x.get("type", "")
310
- if x.get("status") == 429:
311
- raise (
312
- ConversationLimitException(err_message)
313
- if err_message == "ERR_CONVERSATION_LIMIT"
314
- else RatelimitE(err_message)
315
- )
316
- raise WebscoutE(err_message)
317
- elif message := x.get("message"):
318
- chunks.append(message)
319
- yield message
320
- except Exception:
321
- # Skip invalid JSON data
322
- continue
323
-
324
- # If we get here, the request was successful
325
- result = "".join(chunks)
326
- self._chat_messages.append({"role": "assistant", "content": result})
327
- self._chat_tokens_count += len(result)
328
- return
329
-
330
- except RatelimitE as ex:
331
- retry_count += 1
332
- if retry_count > max_retries:
333
- raise WebscoutE(f"achat_yield() Rate limit exceeded after {max_retries} retries: {ex}") from ex
334
-
335
- # Get a fresh Turnstile token for the retry
336
- turnstile_token = await get_turnstile_token()
337
- if turnstile_token:
338
- json_data["cf-turnstile-response"] = turnstile_token
339
-
340
- # Exponential backoff
341
- sleep_time = 2 ** retry_count
342
- await asyncio.sleep(sleep_time)
343
-
344
- except Exception as ex:
345
- raise WebscoutE(f"achat_yield() {type(ex).__name__}: {ex}") from ex
346
-
347
- async def achat(self, keywords: str, model: str = "gpt-4o-mini", timeout: int = 30, max_retries: int = 3) -> str:
348
- """Initiates an async chat session with webscout AI.
349
-
350
- Args:
351
- keywords (str): The initial message or question to send to the AI.
352
- model (str): The model to use: "gpt-4o-mini", "llama-3.3-70b", "claude-3-haiku",
353
- "o3-mini", "mistral-small-3". Defaults to "gpt-4o-mini".
354
- timeout (int): Timeout value for the HTTP client. Defaults to 30.
355
- max_retries (int): Maximum number of retry attempts for rate limited requests. Defaults to 3.
356
-
357
- Returns:
358
- str: The response from the AI.
359
- """
360
- chunks = []
361
- async for chunk in self.achat_yield(keywords, model, timeout, max_retries):
362
- chunks.append(chunk)
363
- return "".join(chunks)
364
-
365
187
  async def atext(
366
188
  self,
367
189
  keywords: str,
@@ -829,4 +651,4 @@ class AsyncWEBS:
829
651
  TimeoutE: Inherits from WebscoutE, raised for API request timeouts.
830
652
  """
831
653
  # These methods are not implemented in the async version yet
832
- raise NotImplementedError("aweather method is not implemented yet")
654
+ raise NotImplementedError("aweather method is not implemented yet")
@@ -0,0 +1,89 @@
1
+ # 🎨 ZeroArt: Zero-Dependency ASCII Art Generator
2
+
3
+ ## 🚀 Overview
4
+
5
+ ZeroArt is a powerful, lightweight Python library for generating stunning ASCII art text with zero external dependencies. Transform your plain text into eye-catching, stylized art with just a few lines of code!
6
+
7
+ ## ✨ Features
8
+
9
+ - **Multiple Font Styles**
10
+ - Block Font
11
+ - Slant Font
12
+ - Neon Font
13
+ - Cyber Font
14
+
15
+ - **Zero Dependencies**
16
+ - Completely standalone library
17
+ - No external package requirements
18
+
19
+ - **Easy to Use**
20
+ - Simple, intuitive API
21
+ - Minimal setup needed
22
+
23
+ - **Text Effects**
24
+ - Rainbow coloring
25
+ - Glitch effect
26
+ - Text wrapping
27
+ - Outline generation
28
+
29
+ ## 🛠 Installation
30
+
31
+ No installation required! Just copy the `zeroart` directory into your project.
32
+
33
+ ## 💻 Usage Examples
34
+
35
+ ### Basic ASCII Art
36
+
37
+ ```python
38
+ from webscout import zeroart
39
+
40
+ # Generate ASCII art
41
+ art = zeroart.figlet_format("PYTHON", font='block')
42
+ print(art)
43
+
44
+ # Directly print ASCII art
45
+ zeroart.print_figlet("CODING", font='slant')
46
+ ```
47
+
48
+ ### Font Styles
49
+
50
+ ```python
51
+ from webscout import zeroart
52
+
53
+ # Different font styles
54
+ print(zeroart.figlet_format("AWESOME", font='block')) # Block style
55
+ print(zeroart.figlet_format("CODING", font='slant')) # Slant style
56
+ print(zeroart.figlet_format("NEON", font='neon')) # Neon style
57
+ print(zeroart.figlet_format("CYBER", font='cyber')) # Cyber style
58
+ ```
59
+
60
+ ### Text Effects
61
+
62
+ ```python
63
+ from webscout import zeroart
64
+
65
+ # Rainbow effect
66
+ print(zeroart.rainbow("COLORFUL", font='neon'))
67
+
68
+ # Glitch effect
69
+ print(zeroart.glitch("GLITCH", font='cyber'))
70
+
71
+ # Outline effect
72
+ print(zeroart.outline("BORDER", font='block'))
73
+ ```
74
+
75
+ ## 🎨 Available Fonts
76
+
77
+ 1. **Block Font**: Classic, bold block-style letters
78
+ 2. **Slant Font**: Elegant, slanted text
79
+ 3. **Neon Font**: Glowing, pixel-style art
80
+ 4. **Cyber Font**: Cyberpunk-inspired rendering
81
+
82
+ ## 🤝 Contributing
83
+
84
+ Contributions are welcome!
85
+
86
+ - Fork the repository
87
+ - Create a new font
88
+ - Add text effects
89
+ - Improve existing code
@@ -1,55 +1,135 @@
1
- """
2
- ZeroArt: A zero-dependency ASCII art text generator
3
-
4
- Create awesome ASCII art text without external dependencies!
5
- """
6
-
7
- from .base import ZeroArtFont
8
- from .fonts import BlockFont, SlantFont, NeonFont, CyberFont
9
- from .effects import AsciiArtEffects
10
-
11
- def figlet_format(text, font='block'):
12
- """
13
- Generate ASCII art text
14
-
15
- :param text: Text to convert
16
- :param font: Font style (default: 'block')
17
- :return: ASCII art representation of text
18
- """
19
- font_map = {
20
- 'block': BlockFont(),
21
- 'slant': SlantFont(),
22
- 'neon': NeonFont(),
23
- 'cyber': CyberFont()
24
- }
25
-
26
- selected_font = font_map.get(font.lower(), BlockFont())
27
- return selected_font.render(text)
28
-
29
- def print_figlet(text, font='block'):
30
- """
31
- Print ASCII art text directly
32
-
33
- :param text: Text to convert and print
34
- :param font: Font style (default: 'block')
35
- """
36
- print(figlet_format(text, font))
37
-
38
- # Expose additional effects
39
- rainbow = AsciiArtEffects.rainbow_effect
40
- glitch = AsciiArtEffects.glitch_effect
41
- wrap_text = AsciiArtEffects.wrap_text
42
- outline = AsciiArtEffects.outline_effect
43
-
44
- __all__ = [
45
- 'figlet_format',
46
- 'print_figlet',
47
- 'rainbow',
48
- 'glitch',
49
- 'wrap_text',
50
- 'outline',
51
- 'BlockFont',
52
- 'SlantFont',
53
- 'NeonFont',
54
- 'CyberFont'
1
+ """
2
+ ZeroArt: A zero-dependency ASCII art text generator
3
+
4
+ Create awesome ASCII art text without external dependencies!
5
+ """
6
+
7
+ from typing import Dict, List, Literal, Optional, Union
8
+ from .base import ZeroArtFont
9
+ from .fonts import BlockFont, SlantFont, NeonFont, CyberFont, DottedFont, ShadowFont
10
+ from .effects import AsciiArtEffects
11
+
12
+ FontType = Literal['block', 'slant', 'neon', 'cyber', 'dotted', 'shadow']
13
+
14
+ def figlet_format(text: str, font: Union[str, ZeroArtFont] = 'block') -> str:
15
+ """
16
+ Generate ASCII art text
17
+
18
+ :param text: Text to convert
19
+ :param font: Font style (default: 'block')
20
+ :return: ASCII art representation of text
21
+ """
22
+ font_map: Dict[str, ZeroArtFont] = {
23
+ 'block': BlockFont(),
24
+ 'slant': SlantFont(),
25
+ 'neon': NeonFont(),
26
+ 'cyber': CyberFont(),
27
+ 'dotted': DottedFont(),
28
+ 'shadow': ShadowFont()
29
+ }
30
+
31
+ if isinstance(font, str):
32
+ selected_font: ZeroArtFont = font_map.get(font.lower(), BlockFont())
33
+ else:
34
+ selected_font = font
35
+ return selected_font.render(text)
36
+
37
+ def print_figlet(text: str, font: Union[str, ZeroArtFont] = 'block') -> None:
38
+ """
39
+ Print ASCII art text directly
40
+
41
+ :param text: Text to convert and print
42
+ :param font: Font style (default: 'block')
43
+ """
44
+ print(figlet_format(text, font))
45
+
46
+ # Expose additional effects with font handling
47
+ def rainbow(text: str, font: Union[str, ZeroArtFont] = 'block') -> str:
48
+ """
49
+ Apply a rainbow-like color effect to ASCII art
50
+
51
+ :param text: Text to render
52
+ :param font: Font style (default: 'block')
53
+ :return: Rainbow-styled ASCII art
54
+ """
55
+ font_map: Dict[str, ZeroArtFont] = {
56
+ 'block': BlockFont(),
57
+ 'slant': SlantFont(),
58
+ 'neon': NeonFont(),
59
+ 'cyber': CyberFont(),
60
+ 'dotted': DottedFont(),
61
+ 'shadow': ShadowFont()
62
+ }
63
+
64
+ if isinstance(font, str):
65
+ selected_font: ZeroArtFont = font_map.get(font.lower(), BlockFont())
66
+ else:
67
+ selected_font = font
68
+ return AsciiArtEffects.rainbow_effect(text, selected_font)
69
+
70
+ def glitch(text: str, font: Union[str, ZeroArtFont] = 'block', glitch_intensity: float = 0.1) -> str:
71
+ """
72
+ Apply a glitch-like distortion to ASCII art
73
+
74
+ :param text: Text to render
75
+ :param font: Font style (default: 'block')
76
+ :param glitch_intensity: Probability of character distortion
77
+ :return: Glitched ASCII art
78
+ """
79
+ font_map: Dict[str, ZeroArtFont] = {
80
+ 'block': BlockFont(),
81
+ 'slant': SlantFont(),
82
+ 'neon': NeonFont(),
83
+ 'cyber': CyberFont(),
84
+ 'dotted': DottedFont(),
85
+ 'shadow': ShadowFont()
86
+ }
87
+
88
+ if isinstance(font, str):
89
+ selected_font: ZeroArtFont = font_map.get(font.lower(), BlockFont())
90
+ else:
91
+ selected_font = font
92
+ return AsciiArtEffects.glitch_effect(text, selected_font, glitch_intensity)
93
+
94
+ wrap_text = AsciiArtEffects.wrap_text
95
+
96
+ def outline(text: str, font: Union[str, ZeroArtFont] = 'block', outline_char: str = '*') -> str:
97
+ """
98
+ Add an outline effect to ASCII art
99
+
100
+ :param text: Text to render
101
+ :param font: Font style (default: 'block')
102
+ :param outline_char: Character to use for outline
103
+ :return: ASCII art with outline
104
+ """
105
+ font_map: Dict[str, ZeroArtFont] = {
106
+ 'block': BlockFont(),
107
+ 'slant': SlantFont(),
108
+ 'neon': NeonFont(),
109
+ 'cyber': CyberFont(),
110
+ 'dotted': DottedFont(),
111
+ 'shadow': ShadowFont()
112
+ }
113
+
114
+ if isinstance(font, str):
115
+ selected_font: ZeroArtFont = font_map.get(font.lower(), BlockFont())
116
+ else:
117
+ selected_font = font
118
+ return AsciiArtEffects.outline_effect(text, selected_font, outline_char)
119
+
120
+ __all__ = [
121
+ 'figlet_format',
122
+ 'print_figlet',
123
+ 'rainbow',
124
+ 'glitch',
125
+ 'wrap_text',
126
+ 'outline',
127
+ 'BlockFont',
128
+ 'SlantFont',
129
+ 'NeonFont',
130
+ 'CyberFont',
131
+ 'DottedFont',
132
+ 'ShadowFont',
133
+ 'ZeroArtFont',
134
+ 'FontType'
55
135
  ]
webscout/zeroart/base.py CHANGED
@@ -1,15 +1,16 @@
1
1
  """
2
2
  ZeroArt Base: Core classes and utilities for ASCII art generation
3
3
  """
4
+ from typing import Dict, List, Optional, Union
4
5
 
5
6
  class ZeroArtFont:
6
7
  """Base class for ASCII art fonts"""
7
- def __init__(self, name):
8
- self.name = name
9
- self.letters = {}
10
- self.special_chars = {}
8
+ def __init__(self, name: str) -> None:
9
+ self.name: str = name
10
+ self.letters: Dict[str, List[str]] = {}
11
+ self.special_chars: Dict[str, List[str]] = {}
11
12
 
12
- def add_letter(self, char, art_lines):
13
+ def add_letter(self, char: str, art_lines: List[str]) -> None:
13
14
  """
14
15
  Add a custom letter to the font
15
16
 
@@ -18,7 +19,7 @@ class ZeroArtFont:
18
19
  """
19
20
  self.letters[char.upper()] = art_lines
20
21
 
21
- def add_special_char(self, name, art_lines):
22
+ def add_special_char(self, name: str, art_lines: List[str]) -> None:
22
23
  """
23
24
  Add a special ASCII art character or design
24
25
 
@@ -27,7 +28,7 @@ class ZeroArtFont:
27
28
  """
28
29
  self.special_chars[name] = art_lines
29
30
 
30
- def get_letter(self, char):
31
+ def get_letter(self, char: str) -> List[str]:
31
32
  """
32
33
  Get ASCII art for a specific character
33
34
 
@@ -36,19 +37,24 @@ class ZeroArtFont:
36
37
  """
37
38
  return self.letters.get(char.upper(), self.letters.get(' ', [' ']))
38
39
 
39
- def render(self, text):
40
+ def render(self, text: str) -> str:
41
+ """
42
+ Render text as ASCII art
43
+
44
+ :param text: Text to render as ASCII art
45
+ :return: ASCII art representation of the text
46
+ """
40
47
  if not text:
41
48
  return ""
42
-
43
- # Get the maximum height of any character in the font
44
- max_height = max(len(self.get_letter(c)) for c in text)
49
+ # Get the maximum height of any character in the font
50
+ max_height: int = max(len(self.get_letter(c)) for c in text)
45
51
 
46
52
  # Initialize art_lines with empty strings
47
- art_lines = ["" for _ in range(max_height)]
53
+ art_lines: List[str] = ["" for _ in range(max_height)]
48
54
 
49
55
  # Process each character
50
56
  for char in text:
51
- char_art = self.get_letter(char)
57
+ char_art: List[str] = self.get_letter(char)
52
58
  # Pad shorter characters with empty lines to match max_height
53
59
  while len(char_art) < max_height:
54
60
  char_art.append(" " * len(char_art[0]))