webscout 8.3.5__py3-none-any.whl → 8.3.7__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 (159) hide show
  1. webscout/AIutel.py +2 -0
  2. webscout/Bard.py +12 -6
  3. webscout/DWEBS.py +66 -57
  4. webscout/Provider/{UNFINISHED → AISEARCH}/PERPLEXED_search.py +34 -74
  5. webscout/Provider/AISEARCH/__init__.py +18 -11
  6. webscout/Provider/AISEARCH/scira_search.py +3 -1
  7. webscout/Provider/Aitopia.py +2 -3
  8. webscout/Provider/Andi.py +3 -3
  9. webscout/Provider/ChatGPTClone.py +1 -1
  10. webscout/Provider/ChatSandbox.py +1 -0
  11. webscout/Provider/Cloudflare.py +1 -1
  12. webscout/Provider/Cohere.py +1 -0
  13. webscout/Provider/Deepinfra.py +13 -10
  14. webscout/Provider/ExaAI.py +1 -1
  15. webscout/Provider/ExaChat.py +1 -80
  16. webscout/Provider/Flowith.py +6 -1
  17. webscout/Provider/Gemini.py +7 -5
  18. webscout/Provider/GeminiProxy.py +1 -0
  19. webscout/Provider/GithubChat.py +4 -1
  20. webscout/Provider/Groq.py +1 -1
  21. webscout/Provider/HeckAI.py +8 -4
  22. webscout/Provider/Jadve.py +23 -38
  23. webscout/Provider/K2Think.py +308 -0
  24. webscout/Provider/Koboldai.py +8 -186
  25. webscout/Provider/LambdaChat.py +2 -4
  26. webscout/Provider/Nemotron.py +3 -4
  27. webscout/Provider/Netwrck.py +6 -8
  28. webscout/Provider/OLLAMA.py +1 -0
  29. webscout/Provider/OPENAI/Cloudflare.py +6 -7
  30. webscout/Provider/OPENAI/FalconH1.py +2 -7
  31. webscout/Provider/OPENAI/FreeGemini.py +6 -8
  32. webscout/Provider/OPENAI/{monochat.py → K2Think.py} +180 -77
  33. webscout/Provider/OPENAI/NEMOTRON.py +3 -6
  34. webscout/Provider/OPENAI/PI.py +5 -4
  35. webscout/Provider/OPENAI/Qwen3.py +2 -3
  36. webscout/Provider/OPENAI/README.md +2 -1
  37. webscout/Provider/OPENAI/TogetherAI.py +52 -57
  38. webscout/Provider/OPENAI/TwoAI.py +3 -4
  39. webscout/Provider/OPENAI/__init__.py +17 -56
  40. webscout/Provider/OPENAI/ai4chat.py +313 -303
  41. webscout/Provider/OPENAI/base.py +9 -29
  42. webscout/Provider/OPENAI/chatgpt.py +7 -2
  43. webscout/Provider/OPENAI/chatgptclone.py +4 -7
  44. webscout/Provider/OPENAI/chatsandbox.py +84 -59
  45. webscout/Provider/OPENAI/deepinfra.py +12 -6
  46. webscout/Provider/OPENAI/e2b.py +60 -8
  47. webscout/Provider/OPENAI/flowith.py +4 -3
  48. webscout/Provider/OPENAI/generate_api_key.py +48 -0
  49. webscout/Provider/OPENAI/heckai.py +4 -1
  50. webscout/Provider/OPENAI/netwrck.py +9 -12
  51. webscout/Provider/OPENAI/refact.py +274 -0
  52. webscout/Provider/OPENAI/scirachat.py +6 -0
  53. webscout/Provider/OPENAI/textpollinations.py +3 -14
  54. webscout/Provider/OPENAI/toolbaz.py +14 -10
  55. webscout/Provider/OpenGPT.py +1 -1
  56. webscout/Provider/Openai.py +150 -402
  57. webscout/Provider/PI.py +1 -0
  58. webscout/Provider/Perplexitylabs.py +1 -2
  59. webscout/Provider/QwenLM.py +107 -89
  60. webscout/Provider/STT/__init__.py +17 -2
  61. webscout/Provider/{Llama3.py → Sambanova.py} +9 -10
  62. webscout/Provider/StandardInput.py +1 -1
  63. webscout/Provider/TTI/__init__.py +18 -12
  64. webscout/Provider/TTI/bing.py +14 -2
  65. webscout/Provider/TTI/together.py +10 -9
  66. webscout/Provider/TTS/README.md +0 -1
  67. webscout/Provider/TTS/__init__.py +18 -11
  68. webscout/Provider/TTS/base.py +479 -159
  69. webscout/Provider/TTS/deepgram.py +409 -156
  70. webscout/Provider/TTS/elevenlabs.py +425 -111
  71. webscout/Provider/TTS/freetts.py +317 -140
  72. webscout/Provider/TTS/gesserit.py +192 -128
  73. webscout/Provider/TTS/murfai.py +248 -113
  74. webscout/Provider/TTS/openai_fm.py +347 -129
  75. webscout/Provider/TTS/speechma.py +620 -586
  76. webscout/Provider/TeachAnything.py +1 -0
  77. webscout/Provider/TextPollinationsAI.py +5 -15
  78. webscout/Provider/TogetherAI.py +136 -142
  79. webscout/Provider/TwoAI.py +53 -309
  80. webscout/Provider/TypliAI.py +2 -1
  81. webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +1 -1
  82. webscout/Provider/UNFINISHED/VercelAIGateway.py +339 -0
  83. webscout/Provider/Venice.py +2 -1
  84. webscout/Provider/VercelAI.py +1 -0
  85. webscout/Provider/WiseCat.py +2 -1
  86. webscout/Provider/WrDoChat.py +2 -1
  87. webscout/Provider/__init__.py +18 -174
  88. webscout/Provider/ai4chat.py +1 -1
  89. webscout/Provider/akashgpt.py +7 -10
  90. webscout/Provider/cerebras.py +194 -38
  91. webscout/Provider/chatglm.py +170 -83
  92. webscout/Provider/cleeai.py +1 -2
  93. webscout/Provider/deepseek_assistant.py +1 -1
  94. webscout/Provider/elmo.py +1 -1
  95. webscout/Provider/geminiapi.py +1 -1
  96. webscout/Provider/granite.py +1 -1
  97. webscout/Provider/hermes.py +1 -3
  98. webscout/Provider/julius.py +1 -0
  99. webscout/Provider/learnfastai.py +1 -1
  100. webscout/Provider/llama3mitril.py +1 -1
  101. webscout/Provider/llmchat.py +1 -1
  102. webscout/Provider/llmchatco.py +1 -1
  103. webscout/Provider/meta.py +3 -3
  104. webscout/Provider/oivscode.py +2 -2
  105. webscout/Provider/scira_chat.py +51 -124
  106. webscout/Provider/searchchat.py +1 -0
  107. webscout/Provider/sonus.py +1 -1
  108. webscout/Provider/toolbaz.py +15 -11
  109. webscout/Provider/turboseek.py +31 -22
  110. webscout/Provider/typefully.py +2 -1
  111. webscout/Provider/x0gpt.py +1 -0
  112. webscout/Provider/yep.py +2 -1
  113. webscout/conversation.py +22 -20
  114. webscout/sanitize.py +14 -10
  115. webscout/scout/README.md +20 -23
  116. webscout/scout/core/crawler.py +125 -38
  117. webscout/scout/core/scout.py +26 -5
  118. webscout/tempid.py +6 -0
  119. webscout/version.py +1 -1
  120. webscout/webscout_search.py +13 -6
  121. webscout/webscout_search_async.py +10 -8
  122. webscout/yep_search.py +13 -5
  123. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/METADATA +3 -1
  124. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/RECORD +132 -155
  125. webscout/Provider/AllenAI.py +0 -440
  126. webscout/Provider/Blackboxai.py +0 -793
  127. webscout/Provider/FreeGemini.py +0 -250
  128. webscout/Provider/Glider.py +0 -225
  129. webscout/Provider/Hunyuan.py +0 -283
  130. webscout/Provider/MCPCore.py +0 -322
  131. webscout/Provider/MiniMax.py +0 -207
  132. webscout/Provider/OPENAI/BLACKBOXAI.py +0 -1045
  133. webscout/Provider/OPENAI/MiniMax.py +0 -298
  134. webscout/Provider/OPENAI/autoproxy.py +0 -1067
  135. webscout/Provider/OPENAI/c4ai.py +0 -394
  136. webscout/Provider/OPENAI/copilot.py +0 -305
  137. webscout/Provider/OPENAI/glider.py +0 -330
  138. webscout/Provider/OPENAI/mcpcore.py +0 -431
  139. webscout/Provider/OPENAI/multichat.py +0 -378
  140. webscout/Provider/Reka.py +0 -214
  141. webscout/Provider/TTS/sthir.py +0 -94
  142. webscout/Provider/UNFINISHED/fetch_together_models.py +0 -90
  143. webscout/Provider/asksteve.py +0 -220
  144. webscout/Provider/copilot.py +0 -422
  145. webscout/Provider/freeaichat.py +0 -294
  146. webscout/Provider/koala.py +0 -182
  147. webscout/Provider/lmarena.py +0 -198
  148. webscout/Provider/monochat.py +0 -275
  149. webscout/Provider/multichat.py +0 -375
  150. webscout/Provider/scnet.py +0 -244
  151. webscout/Provider/talkai.py +0 -194
  152. /webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +0 -0
  153. /webscout/Provider/{Qodo.py → UNFINISHED/Qodo.py} +0 -0
  154. /webscout/Provider/{XenAI.py → UNFINISHED/XenAI.py} +0 -0
  155. /webscout/Provider/{samurai.py → UNFINISHED/samurai.py} +0 -0
  156. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/WHEEL +0 -0
  157. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/entry_points.txt +0 -0
  158. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/licenses/LICENSE.md +0 -0
  159. {webscout-8.3.5.dist-info → webscout-8.3.7.dist-info}/top_level.txt +0 -0
@@ -1,128 +1,192 @@
1
- import time
2
- import requests
3
- import pathlib
4
- import base64
5
- from io import BytesIO
6
- from webscout import exceptions
7
- from webscout.litagent import LitAgent
8
- from concurrent.futures import ThreadPoolExecutor, as_completed
9
- from . import utils
10
- from .base import BaseTTSProvider
11
-
12
- class GesseritTTS(BaseTTSProvider):
13
- """Text-to-speech provider using the GesseritTTS API."""
14
- # Request headers
15
- headers: dict[str, str] = {
16
- "User-Agent": LitAgent().random()
17
- }
18
- cache_dir = pathlib.Path("./audio_cache")
19
- all_voices: dict[str, str] = {
20
- "Emma": "en_us_001", # Female Voice
21
- "Liam": "en_us_006", # Male Voice
22
- "Noah": "en_us_007", # Male Voice
23
- "Oliver": "en_us_009", # Male Voice
24
- "Elijah": "en_us_010", # Male Voice
25
- "James": "en_male_narration", # Male Voice
26
- "Charlie": "en_male_funny", # Male Voice
27
- "Sophia": "en_female_emotional", # Female Voice
28
- "Cody": "en_male_cody", # Male Voice
29
- }
30
-
31
- def __init__(self, timeout: int = 20, proxies: dict = None):
32
- """Initializes the GesseritTTS TTS client."""
33
- super().__init__()
34
- self.session = requests.Session()
35
- self.session.headers.update(self.headers)
36
- if proxies:
37
- self.session.proxies.update(proxies)
38
- self.timeout = timeout
39
-
40
- def tts(self, text: str, voice: str = "Oliver", verbose:bool = True) -> str:
41
- """Converts text to speech using the GesseritTTS API and saves it to a file."""
42
- assert (
43
- voice in self.all_voices
44
- ), f"Voice '{voice}' not one of [{', '.join(self.all_voices.keys())}]"
45
-
46
- filename = self.cache_dir / f"{int(time.time())}.mp3"
47
-
48
- voice_id = self.all_voices[voice]
49
-
50
- # Split text into sentences
51
- sentences = utils.split_sentences(text)
52
-
53
- # Function to request audio for each chunk
54
- def generate_audio_for_chunk(part_text: str, part_number: int):
55
- while True:
56
- try:
57
- payload = {
58
- "text": part_text,
59
- "voice": voice_id
60
- }
61
- response = self.session.post('https://gesserit.co/api/tiktok-tts', headers=self.headers, json=payload, timeout=self.timeout)
62
- response.raise_for_status()
63
-
64
- # Create the audio_cache directory if it doesn't exist
65
- self.cache_dir.mkdir(parents=True, exist_ok=True)
66
-
67
- # Check if the request was successful
68
- if response.ok and response.status_code == 200:
69
- data = response.json()
70
- audio_base64 = data["audioUrl"].split(",")[1]
71
- audio_data = base64.b64decode(audio_base64)
72
- if verbose:
73
- print(f"[debug] Chunk {part_number} processed successfully")
74
- return part_number, audio_data
75
- else:
76
- if verbose:
77
- print(f"[debug] No data received for chunk {part_number}. Retrying...")
78
- except requests.RequestException as e:
79
- if verbose:
80
- print(f"[debug] Error for chunk {part_number}: {e}. Retrying...")
81
- time.sleep(1)
82
- try:
83
- # Using ThreadPoolExecutor to handle requests concurrently
84
- with ThreadPoolExecutor() as executor:
85
- futures = {executor.submit(generate_audio_for_chunk, sentence.strip(), chunk_num): chunk_num
86
- for chunk_num, sentence in enumerate(sentences, start=1)}
87
-
88
- # Dictionary to store results with order preserved
89
- audio_chunks = {}
90
-
91
- for future in as_completed(futures):
92
- chunk_num = futures[future]
93
- try:
94
- part_number, audio_data = future.result()
95
- audio_chunks[part_number] = audio_data # Store the audio data in correct sequence
96
- except Exception as e:
97
- if verbose:
98
- print(f"[debug] Failed to generate audio for chunk {chunk_num}: {e}")
99
-
100
- # Combine audio chunks in the correct sequence
101
- combined_audio = BytesIO()
102
- for part_number in sorted(audio_chunks.keys()):
103
- combined_audio.write(audio_chunks[part_number])
104
- if verbose:
105
- print(f"[debug] Added chunk {part_number} to the combined file.")
106
-
107
- # Save the combined audio data to a single file
108
- with open(filename, 'wb') as f:
109
- f.write(combined_audio.getvalue())
110
- if verbose:
111
- print(f"[debug] Final Audio Saved as {filename}")
112
- return filename.as_posix()
113
-
114
- except requests.exceptions.RequestException as e:
115
- if verbose:
116
- print(f"[debug] Failed to perform the operation: {e}")
117
- raise exceptions.FailedToGenerateResponseError(
118
- f"Failed to perform the operation: {e}"
119
- )
120
-
121
- # Example usage
122
- if __name__ == "__main__":
123
- gesserit = GesseritTTS()
124
- text = "This is a test of the GesseritTTS text-to-speech API. It supports multiple sentences and advanced logging."
125
-
126
- print("[debug] Generating audio...")
127
- audio_file = gesserit.tts(text, voice="Oliver")
128
- print(f"Audio saved to: {audio_file}")
1
+ import time
2
+ import requests
3
+ import pathlib
4
+ import base64
5
+ from io import BytesIO
6
+ from webscout import exceptions
7
+ from webscout.litagent import LitAgent
8
+ from concurrent.futures import ThreadPoolExecutor, as_completed
9
+ from . import utils
10
+ from .base import BaseTTSProvider
11
+
12
+
13
+ class GesseritTTS(BaseTTSProvider):
14
+ """
15
+ Text-to-speech provider using the GesseritTTS API with OpenAI-compatible interface.
16
+
17
+ This provider follows the OpenAI TTS API structure with support for:
18
+ - Multiple TTS models (gpt-4o-mini-tts, tts-1, tts-1-hd)
19
+ - Multiple voices with OpenAI-style naming
20
+ - Voice instructions for controlling speech aspects
21
+ - Multiple output formats (mp3, wav, aac, flac, opus, pcm)
22
+ - Streaming support
23
+ """
24
+
25
+ # Override supported models for GesseritTTS
26
+ SUPPORTED_MODELS = [
27
+ "gpt-4o-mini-tts", # Latest intelligent realtime model
28
+ "tts-1", # Lower latency model
29
+ "tts-1-hd" # Higher quality model
30
+ ]
31
+
32
+ # Override supported voices with real Gesserit voice names
33
+ SUPPORTED_VOICES = [
34
+ "Emma", # Female Voice
35
+ "Liam", # Male Voice
36
+ "Noah", # Male Voice
37
+ "Oliver", # Male Voice
38
+ "Elijah", # Male Voice
39
+ "James", # Male Voice
40
+ "Charlie", # Male Voice
41
+ "Sophia", # Female Voice
42
+ "Cody", # Male Voice
43
+ "Emma" # Female Voice (duplicate for variety)
44
+ ]
45
+
46
+ # Request headers
47
+ headers: dict[str, str] = {
48
+ "User-Agent": LitAgent().random()
49
+ }
50
+ cache_dir = pathlib.Path("./audio_cache")
51
+
52
+ # Voice mapping from real names to Gesserit voice IDs
53
+ voice_mapping: dict[str, str] = {
54
+ "Emma": "en_us_001", # Female Voice
55
+ "Liam": "en_us_006", # Male Voice
56
+ "Noah": "en_us_007", # Male Voice
57
+ "Oliver": "en_us_009", # Male Voice
58
+ "Elijah": "en_us_010", # Male Voice
59
+ "James": "en_male_narration", # Male Voice
60
+ "Charlie": "en_male_funny", # Male Voice
61
+ "Sophia": "en_female_emotional", # Female Voice
62
+ "Cody": "en_male_cody" # Male Voice
63
+ }
64
+
65
+ def __init__(self, timeout: int = 20, proxies: dict = None):
66
+ """Initializes the GesseritTTS TTS client."""
67
+ super().__init__()
68
+ self.session = requests.Session()
69
+ self.session.headers.update(self.headers)
70
+ if proxies:
71
+ self.session.proxies.update(proxies)
72
+ self.timeout = timeout
73
+
74
+ def tts(self, text: str, voice: str = "Oliver", verbose: bool = False, **kwargs) -> str:
75
+ """
76
+ Converts text to speech using the GesseritTTS API and saves it to a file.
77
+
78
+ Args:
79
+ text (str): The text to convert to speech
80
+ voice (str): The voice to use (default: "Oliver")
81
+ verbose (bool): Whether to print debug information
82
+ **kwargs: Additional parameters (model, response_format, instructions)
83
+
84
+ Returns:
85
+ str: Path to the generated audio file
86
+ """
87
+ # Validate input parameters
88
+ if not text or not isinstance(text, str):
89
+ raise ValueError("Input text must be a non-empty string")
90
+ if len(text) > 10000:
91
+ raise ValueError("Input text exceeds maximum allowed length of 10,000 characters")
92
+
93
+ # Use default voice if not provided
94
+ if voice is None:
95
+ voice = "Oliver"
96
+
97
+ # Validate voice using base class method
98
+ self.validate_voice(voice)
99
+
100
+ # Map real voice name to Gesserit voice ID
101
+ voice_id = self.voice_mapping.get(voice, "en_us_009") # Default to Oliver
102
+
103
+ filename = self.cache_dir / f"{int(time.time())}.mp3"
104
+
105
+ # Split text into sentences
106
+ sentences = utils.split_sentences(text)
107
+
108
+ # Function to request audio for each chunk
109
+ def generate_audio_for_chunk(part_text: str, part_number: int):
110
+ while True:
111
+ try:
112
+ payload = {
113
+ "text": part_text,
114
+ "voice": voice_id
115
+ }
116
+ response = self.session.post('https://gesserit.co/api/tiktok-tts', headers=self.headers, json=payload, timeout=self.timeout)
117
+ response.raise_for_status()
118
+
119
+ # Create the audio_cache directory if it doesn't exist
120
+ self.cache_dir.mkdir(parents=True, exist_ok=True)
121
+
122
+ # Check if the request was successful
123
+ if response.ok and response.status_code == 200:
124
+ data = response.json()
125
+ audio_base64 = data["audioUrl"].split(",")[1]
126
+ audio_data = base64.b64decode(audio_base64)
127
+ if verbose:
128
+ print(f"[debug] Chunk {part_number} processed successfully")
129
+ return part_number, audio_data
130
+ else:
131
+ if verbose:
132
+ print(f"[debug] No data received for chunk {part_number}. Retrying...")
133
+ except requests.RequestException as e:
134
+ if verbose:
135
+ print(f"[debug] Error for chunk {part_number}: {e}. Retrying...")
136
+ time.sleep(1)
137
+ try:
138
+ # Using ThreadPoolExecutor to handle requests concurrently
139
+ with ThreadPoolExecutor() as executor:
140
+ futures = {executor.submit(generate_audio_for_chunk, sentence.strip(), chunk_num): chunk_num
141
+ for chunk_num, sentence in enumerate(sentences, start=1)}
142
+
143
+ # Dictionary to store results with order preserved
144
+ audio_chunks = {}
145
+
146
+ for future in as_completed(futures):
147
+ chunk_num = futures[future]
148
+ try:
149
+ part_number, audio_data = future.result()
150
+ audio_chunks[part_number] = audio_data # Store the audio data in correct sequence
151
+ except Exception as e:
152
+ if verbose:
153
+ print(f"[debug] Failed to generate audio for chunk {chunk_num}: {e}")
154
+
155
+ # Combine audio chunks in the correct sequence
156
+ combined_audio = BytesIO()
157
+ for part_number in sorted(audio_chunks.keys()):
158
+ combined_audio.write(audio_chunks[part_number])
159
+ if verbose:
160
+ print(f"[debug] Added chunk {part_number} to the combined file.")
161
+
162
+ # Save the combined audio data to a single file
163
+ with open(filename, 'wb') as f:
164
+ f.write(combined_audio.getvalue())
165
+ if verbose:
166
+ print(f"[debug] Final Audio Saved as {filename}")
167
+ return filename.as_posix()
168
+
169
+ except requests.exceptions.RequestException as e:
170
+ if verbose:
171
+ print(f"[debug] Failed to perform the operation: {e}")
172
+ raise exceptions.FailedToGenerateResponseError(
173
+ f"Failed to perform the operation: {e}"
174
+ )
175
+
176
+ # Example usage
177
+ if __name__ == "__main__":
178
+ gesserit = GesseritTTS()
179
+ text = "This is a test of the GesseritTTS text-to-speech API. It supports multiple sentences and advanced logging."
180
+
181
+ print("[debug] Generating audio...")
182
+ try:
183
+ audio_file = gesserit.create_speech(
184
+ input=text,
185
+ model="gpt-4o-mini-tts",
186
+ voice="Oliver",
187
+ response_format="mp3",
188
+ verbose=True
189
+ )
190
+ print(f"Audio saved to: {audio_file}")
191
+ except Exception as e:
192
+ print(f"Error: {e}")