webscout 6.3__py3-none-any.whl → 6.5__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.
- webscout/AIauto.py +191 -176
- webscout/AIbase.py +0 -197
- webscout/AIutel.py +441 -1130
- webscout/DWEBS.py +189 -35
- webscout/{YTdownloader.py → Extra/YTToolkit/YTdownloader.py} +990 -1103
- webscout/Extra/YTToolkit/__init__.py +3 -0
- webscout/{transcriber.py → Extra/YTToolkit/transcriber.py} +479 -551
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
- webscout/Extra/YTToolkit/ytapi/extras.py +45 -0
- webscout/Extra/YTToolkit/ytapi/https.py +88 -0
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
- webscout/Extra/YTToolkit/ytapi/query.py +37 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +60 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
- webscout/Extra/YTToolkit/ytapi/video.py +102 -0
- webscout/Extra/__init__.py +3 -1
- webscout/Extra/autocoder/__init__.py +9 -0
- webscout/Extra/autocoder/autocoder_utiles.py +121 -0
- webscout/Extra/autocoder/rawdog.py +680 -0
- webscout/Extra/autollama.py +246 -195
- webscout/Extra/gguf.py +81 -56
- webscout/Extra/markdownlite/__init__.py +862 -0
- webscout/Extra/weather_ascii.py +2 -2
- webscout/LLM.py +206 -43
- webscout/Litlogger/__init__.py +681 -0
- webscout/Provider/DARKAI.py +1 -1
- webscout/Provider/EDITEE.py +1 -1
- webscout/Provider/NinjaChat.py +1 -1
- webscout/Provider/PI.py +120 -35
- webscout/Provider/Perplexity.py +590 -598
- webscout/Provider/Reka.py +0 -1
- webscout/Provider/RoboCoders.py +206 -0
- webscout/Provider/TTI/AiForce/__init__.py +22 -0
- webscout/Provider/TTI/AiForce/async_aiforce.py +257 -0
- webscout/Provider/TTI/AiForce/sync_aiforce.py +242 -0
- webscout/Provider/TTI/Nexra/__init__.py +22 -0
- webscout/Provider/TTI/Nexra/async_nexra.py +286 -0
- webscout/Provider/TTI/Nexra/sync_nexra.py +258 -0
- webscout/Provider/TTI/PollinationsAI/__init__.py +23 -0
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +330 -0
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +285 -0
- webscout/Provider/TTI/__init__.py +2 -4
- webscout/Provider/TTI/artbit/__init__.py +22 -0
- webscout/Provider/TTI/artbit/async_artbit.py +184 -0
- webscout/Provider/TTI/artbit/sync_artbit.py +176 -0
- webscout/Provider/TTI/blackbox/__init__.py +4 -0
- webscout/Provider/TTI/blackbox/async_blackbox.py +212 -0
- webscout/Provider/TTI/{blackboximage.py → blackbox/sync_blackbox.py} +199 -153
- webscout/Provider/TTI/deepinfra/__init__.py +4 -0
- webscout/Provider/TTI/deepinfra/async_deepinfra.py +227 -0
- webscout/Provider/TTI/deepinfra/sync_deepinfra.py +199 -0
- webscout/Provider/TTI/huggingface/__init__.py +22 -0
- webscout/Provider/TTI/huggingface/async_huggingface.py +199 -0
- webscout/Provider/TTI/huggingface/sync_huggingface.py +195 -0
- webscout/Provider/TTI/imgninza/__init__.py +4 -0
- webscout/Provider/TTI/imgninza/async_ninza.py +214 -0
- webscout/Provider/TTI/{imgninza.py → imgninza/sync_ninza.py} +209 -136
- webscout/Provider/TTI/talkai/__init__.py +4 -0
- webscout/Provider/TTI/talkai/async_talkai.py +229 -0
- webscout/Provider/TTI/talkai/sync_talkai.py +207 -0
- webscout/Provider/TTS/__init__.py +5 -1
- webscout/Provider/TTS/deepgram.py +183 -0
- webscout/Provider/TTS/elevenlabs.py +137 -0
- webscout/Provider/TTS/gesserit.py +151 -0
- webscout/Provider/TTS/murfai.py +139 -0
- webscout/Provider/TTS/parler.py +134 -107
- webscout/Provider/TTS/streamElements.py +360 -275
- webscout/Provider/TTS/utils.py +280 -0
- webscout/Provider/TTS/voicepod.py +116 -116
- webscout/Provider/__init__.py +8 -1
- webscout/Provider/askmyai.py +2 -2
- webscout/Provider/cerebras.py +227 -219
- webscout/Provider/llama3mitril.py +0 -1
- webscout/Provider/meta.py +794 -779
- webscout/Provider/mhystical.py +176 -0
- webscout/Provider/perplexitylabs.py +265 -0
- webscout/Provider/twitterclone.py +251 -245
- webscout/Provider/typegpt.py +358 -0
- webscout/__init__.py +9 -8
- webscout/__main__.py +5 -5
- webscout/cli.py +252 -280
- webscout/conversation.py +227 -0
- webscout/exceptions.py +161 -29
- webscout/litagent/__init__.py +172 -0
- webscout/litprinter/__init__.py +832 -0
- webscout/optimizers.py +270 -0
- webscout/prompt_manager.py +279 -0
- webscout/scout/__init__.py +11 -0
- webscout/scout/core.py +884 -0
- webscout/scout/element.py +459 -0
- webscout/scout/parsers/__init__.py +69 -0
- webscout/scout/parsers/html5lib_parser.py +172 -0
- webscout/scout/parsers/html_parser.py +236 -0
- webscout/scout/parsers/lxml_parser.py +178 -0
- webscout/scout/utils.py +38 -0
- webscout/swiftcli/__init__.py +810 -0
- webscout/update_checker.py +125 -0
- webscout/version.py +1 -1
- webscout/zeroart/__init__.py +55 -0
- webscout/zeroart/base.py +61 -0
- webscout/zeroart/effects.py +99 -0
- webscout/zeroart/fonts.py +816 -0
- webscout/zerodir/__init__.py +225 -0
- {webscout-6.3.dist-info → webscout-6.5.dist-info}/METADATA +37 -112
- webscout-6.5.dist-info/RECORD +179 -0
- webscout/Agents/Onlinesearcher.py +0 -182
- webscout/Agents/__init__.py +0 -2
- webscout/Agents/functioncall.py +0 -248
- webscout/Bing_search.py +0 -154
- webscout/Provider/TTI/AIuncensoredimage.py +0 -103
- webscout/Provider/TTI/Nexra.py +0 -120
- webscout/Provider/TTI/PollinationsAI.py +0 -138
- webscout/Provider/TTI/WebSimAI.py +0 -142
- webscout/Provider/TTI/aiforce.py +0 -160
- webscout/Provider/TTI/artbit.py +0 -141
- webscout/Provider/TTI/deepinfra.py +0 -148
- webscout/Provider/TTI/huggingface.py +0 -155
- webscout/Provider/TTI/talkai.py +0 -116
- webscout/g4f.py +0 -666
- webscout/models.py +0 -23
- webscout/requestsHTMLfix.py +0 -775
- webscout/webai.py +0 -2590
- webscout-6.3.dist-info/RECORD +0 -124
- {webscout-6.3.dist-info → webscout-6.5.dist-info}/LICENSE.md +0 -0
- {webscout-6.3.dist-info → webscout-6.5.dist-info}/WHEEL +0 -0
- {webscout-6.3.dist-info → webscout-6.5.dist-info}/entry_points.txt +0 -0
- {webscout-6.3.dist-info → webscout-6.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from urllib.request import Request, urlopen
|
|
2
|
+
from collections import OrderedDict
|
|
3
|
+
from urllib.error import HTTPError
|
|
4
|
+
from .errors import TooManyRequests, InvalidURL, RequestError
|
|
5
|
+
from webscout.litagent import LitAgent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = ['dup_filter', 'request']
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
_USER_AGENT_GENERATOR = LitAgent()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def request(url: str, retry_attempts: int = 3) -> str:
|
|
15
|
+
"""
|
|
16
|
+
Send a request with a random user agent and built-in retry mechanism.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
url (str): The URL to request
|
|
20
|
+
retry_attempts (int, optional): Number of retry attempts. Defaults to 3.
|
|
21
|
+
|
|
22
|
+
Raises:
|
|
23
|
+
InvalidURL: If the URL cannot be found
|
|
24
|
+
TooManyRequests: If rate-limited
|
|
25
|
+
RequestError: For other request-related errors
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
str: Decoded response content
|
|
29
|
+
"""
|
|
30
|
+
for attempt in range(retry_attempts):
|
|
31
|
+
try:
|
|
32
|
+
headers = {
|
|
33
|
+
"User-Agent": _USER_AGENT_GENERATOR.random()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
req = Request(url, headers=headers)
|
|
37
|
+
response = urlopen(req)
|
|
38
|
+
return response.read().decode('utf-8')
|
|
39
|
+
|
|
40
|
+
except HTTPError as e:
|
|
41
|
+
if e.code == 404:
|
|
42
|
+
raise InvalidURL(f'Cannot find anything with the requested URL: {url}')
|
|
43
|
+
if e.code == 429:
|
|
44
|
+
raise TooManyRequests(f'Rate-limited on attempt {attempt + 1}')
|
|
45
|
+
|
|
46
|
+
if attempt == retry_attempts - 1:
|
|
47
|
+
raise RequestError(f'HTTP Error {e.code}: {e.reason}') from e
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
if attempt == retry_attempts - 1:
|
|
51
|
+
raise RequestError(f'Request failed: {e!r}') from None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def dup_filter(iterable: list, limit: int = None) -> list:
|
|
55
|
+
if not iterable:
|
|
56
|
+
return []
|
|
57
|
+
lim = limit if limit else len(iterable)
|
|
58
|
+
converted = list(OrderedDict.fromkeys(iterable))
|
|
59
|
+
if len(converted) - lim > 0:
|
|
60
|
+
return converted[:-len(converted) + lim]
|
|
61
|
+
else:
|
|
62
|
+
return converted
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
from .https import video_data
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Video:
|
|
8
|
+
|
|
9
|
+
_HEAD = 'https://www.youtube.com/watch?v='
|
|
10
|
+
|
|
11
|
+
def __init__(self, video_id: str):
|
|
12
|
+
"""
|
|
13
|
+
Represents a YouTube video
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
video_id : str
|
|
18
|
+
The id or url of the video
|
|
19
|
+
"""
|
|
20
|
+
pattern = re.compile('.be/(.*?)$|=(.*?)$|^(\w{11})$') # noqa
|
|
21
|
+
self._matched_id = (
|
|
22
|
+
pattern.search(video_id).group(1)
|
|
23
|
+
or pattern.search(video_id).group(2)
|
|
24
|
+
or pattern.search(video_id).group(3)
|
|
25
|
+
)
|
|
26
|
+
if self._matched_id:
|
|
27
|
+
self._url = self._HEAD + self._matched_id
|
|
28
|
+
self._video_data = video_data(self._matched_id)
|
|
29
|
+
else:
|
|
30
|
+
raise ValueError('invalid video id or url')
|
|
31
|
+
|
|
32
|
+
def __repr__(self):
|
|
33
|
+
return f'<Video {self._url}>'
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def metadata(self):
|
|
37
|
+
"""
|
|
38
|
+
Fetches video metadata in a dict format
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
Dict
|
|
43
|
+
Video metadata in a dict format containing keys: title, id, views, duration, author_id,
|
|
44
|
+
upload_date, url, thumbnails, tags, description
|
|
45
|
+
"""
|
|
46
|
+
details_pattern = re.compile('videoDetails\":(.*?)\"isLiveContent\":.*?}')
|
|
47
|
+
upload_date_pattern = re.compile("<meta itemprop=\"uploadDate\" content=\"(.*?)\">")
|
|
48
|
+
genre_pattern = re.compile("<meta itemprop=\"genre\" content=\"(.*?)\">")
|
|
49
|
+
like_count_pattern = re.compile("iconType\":\"LIKE\"},\"defaultText\":(.*?)}}")
|
|
50
|
+
|
|
51
|
+
# Add robust error handling
|
|
52
|
+
raw_details_match = details_pattern.search(self._video_data)
|
|
53
|
+
if not raw_details_match:
|
|
54
|
+
# Fallback metadata for search results or incomplete video data
|
|
55
|
+
return {
|
|
56
|
+
'title': getattr(self, 'title', None),
|
|
57
|
+
'id': getattr(self, 'id', None),
|
|
58
|
+
'views': getattr(self, 'views', None),
|
|
59
|
+
'streamed': False,
|
|
60
|
+
'duration': None,
|
|
61
|
+
'author_id': None,
|
|
62
|
+
'upload_date': None,
|
|
63
|
+
'url': f"https://www.youtube.com/watch?v={getattr(self, 'id', '')}" if hasattr(self, 'id') else None,
|
|
64
|
+
'thumbnails': None,
|
|
65
|
+
'tags': None,
|
|
66
|
+
'description': None,
|
|
67
|
+
'likes': None,
|
|
68
|
+
'genre': None
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
raw_details = raw_details_match.group(0)
|
|
72
|
+
|
|
73
|
+
# Add None checking for upload_date
|
|
74
|
+
upload_date_match = upload_date_pattern.search(self._video_data)
|
|
75
|
+
upload_date = upload_date_match.group(1) if upload_date_match else None
|
|
76
|
+
|
|
77
|
+
metadata = json.loads(raw_details.replace('videoDetails\":', ''))
|
|
78
|
+
data = {
|
|
79
|
+
'title': metadata['title'],
|
|
80
|
+
'id': metadata['videoId'],
|
|
81
|
+
'views': metadata.get('viewCount'),
|
|
82
|
+
'streamed': metadata['isLiveContent'],
|
|
83
|
+
'duration': metadata['lengthSeconds'],
|
|
84
|
+
'author_id': metadata['channelId'],
|
|
85
|
+
'upload_date': upload_date,
|
|
86
|
+
'url': f"https://www.youtube.com/watch?v={metadata['videoId']}",
|
|
87
|
+
'thumbnails': metadata.get('thumbnail', {}).get('thumbnails'),
|
|
88
|
+
'tags': metadata.get('keywords'),
|
|
89
|
+
'description': metadata.get('shortDescription'),
|
|
90
|
+
}
|
|
91
|
+
try:
|
|
92
|
+
likes_count = like_count_pattern.search(self._video_data).group(1)
|
|
93
|
+
data['likes'] = json.loads(likes_count + '}}}')[
|
|
94
|
+
'accessibility'
|
|
95
|
+
]['accessibilityData']['label'].split(' ')[0].replace(',', '')
|
|
96
|
+
except (AttributeError, KeyError, json.decoder.JSONDecodeError):
|
|
97
|
+
data['likes'] = None
|
|
98
|
+
try:
|
|
99
|
+
data['genre'] = genre_pattern.search(self._video_data).group(1)
|
|
100
|
+
except AttributeError:
|
|
101
|
+
data['genre'] = None
|
|
102
|
+
return data
|
webscout/Extra/__init__.py
CHANGED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""AutoCoder utilities module."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import datetime
|
|
6
|
+
import pygetwindow as gw
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from webscout.optimizers import Optimizers
|
|
10
|
+
|
|
11
|
+
def get_current_app():
|
|
12
|
+
"""Get the current active application name."""
|
|
13
|
+
try:
|
|
14
|
+
active_window = gw.getActiveWindow()
|
|
15
|
+
return f"{active_window.title if active_window else 'Unknown'}"
|
|
16
|
+
except Exception as e:
|
|
17
|
+
return "Unknown"
|
|
18
|
+
|
|
19
|
+
def get_intro_prompt():
|
|
20
|
+
"""Get the introduction prompt for the AutoCoder."""
|
|
21
|
+
current_app = get_current_app()
|
|
22
|
+
python_version = sys.version.split()[0]
|
|
23
|
+
|
|
24
|
+
return f"""
|
|
25
|
+
You are a command-line coding assistant called Rawdog that generates and auto-executes Python scripts.
|
|
26
|
+
|
|
27
|
+
A typical interaction goes like this:
|
|
28
|
+
1. The user gives you a natural language PROMPT.
|
|
29
|
+
2. You:
|
|
30
|
+
i. Determine what needs to be done
|
|
31
|
+
ii. Write a short Python SCRIPT to do it
|
|
32
|
+
iii. Communicate back to the user by printing to the console in that SCRIPT
|
|
33
|
+
3. The compiler extracts the script and then runs it using exec(). If there will be an exception raised,
|
|
34
|
+
it will be send back to you starting with "PREVIOUS SCRIPT EXCEPTION:".
|
|
35
|
+
4. In case of exception, regenerate error free script.
|
|
36
|
+
|
|
37
|
+
If you need to review script outputs before completing the task, you can print the word "CONTINUE" at the end of your SCRIPT.
|
|
38
|
+
This can be useful for summarizing documents or technical readouts, reading instructions before
|
|
39
|
+
deciding what to do, or other tasks that require multi-step reasoning.
|
|
40
|
+
A typical 'CONTINUE' interaction looks like this:
|
|
41
|
+
1. The user gives you a natural language PROMPT.
|
|
42
|
+
2. You:
|
|
43
|
+
i. Determine what needs to be done
|
|
44
|
+
ii. Determine that you need to see the output of some subprocess call to complete the task
|
|
45
|
+
iii. Write a short Python SCRIPT to print that and then print the word "CONTINUE"
|
|
46
|
+
3. The compiler
|
|
47
|
+
i. Checks and runs your SCRIPT
|
|
48
|
+
ii. Captures the output and appends it to the conversation as "LAST SCRIPT OUTPUT:"
|
|
49
|
+
iii. Finds the word "CONTINUE" and sends control back to you
|
|
50
|
+
4. You again:
|
|
51
|
+
i. Look at the original PROMPT + the "LAST SCRIPT OUTPUT:" to determine what needs to be done
|
|
52
|
+
ii. Write a short Python SCRIPT to do it
|
|
53
|
+
iii. Communicate back to the user by printing to the console in that SCRIPT
|
|
54
|
+
5. The compiler...
|
|
55
|
+
|
|
56
|
+
Please follow these conventions carefully:
|
|
57
|
+
- Decline any tasks that seem dangerous, irreversible, or that you don't understand.
|
|
58
|
+
- Always review the full conversation prior to answering and maintain continuity.
|
|
59
|
+
- If asked for information, just print the information clearly and concisely.
|
|
60
|
+
- If asked to do something, print a concise summary of what you've done as confirmation.
|
|
61
|
+
- If asked a question, respond in a friendly, conversational way. Use programmatically-generated and natural language responses as appropriate.
|
|
62
|
+
- If you need clarification, return a SCRIPT that prints your question. In the next interaction, continue based on the user's response.
|
|
63
|
+
- Assume the user would like something concise. For example rather than printing a massive table, filter or summarize it to what's likely of interest.
|
|
64
|
+
- Actively clean up any temporary processes or files you use.
|
|
65
|
+
- When looking through files, use git as available to skip files, and skip hidden files (.env, .git, etc) by default.
|
|
66
|
+
- You can plot anything with matplotlib.
|
|
67
|
+
- ALWAYS Return your SCRIPT inside of a single pair of ``` delimiters. Only the console output of the first such SCRIPT is visible to the user, so make sure that it's complete and don't bother returning anything else.
|
|
68
|
+
|
|
69
|
+
Environment Information:
|
|
70
|
+
- System: {platform.system()}
|
|
71
|
+
- Python: {python_version}
|
|
72
|
+
- Directory: {os.getcwd()}
|
|
73
|
+
- Datetime: {datetime.datetime.now()}
|
|
74
|
+
- Active App: {current_app}
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
EXAMPLES = """
|
|
78
|
+
EXAMPLES:
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
1. User: Kill the process running on port 3000
|
|
82
|
+
|
|
83
|
+
LLM:
|
|
84
|
+
```python
|
|
85
|
+
import os
|
|
86
|
+
os.system("kill $(lsof -t -i:3000)")
|
|
87
|
+
print("Process killed")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
2. User: Summarize my essay
|
|
91
|
+
|
|
92
|
+
LLM:
|
|
93
|
+
```python
|
|
94
|
+
import glob
|
|
95
|
+
files = glob.glob("*essay*.*")
|
|
96
|
+
with open(files[0], "r") as f:
|
|
97
|
+
print(f.read())
|
|
98
|
+
```
|
|
99
|
+
CONTINUE
|
|
100
|
+
|
|
101
|
+
User:
|
|
102
|
+
LAST SCRIPT OUTPUT:
|
|
103
|
+
John Smith
|
|
104
|
+
Essay 2021-09-01
|
|
105
|
+
...
|
|
106
|
+
|
|
107
|
+
LLM:
|
|
108
|
+
```python
|
|
109
|
+
print("The essay is about...")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
3. User: Weather in qazigund
|
|
113
|
+
|
|
114
|
+
LLM:
|
|
115
|
+
```python
|
|
116
|
+
from webscout import weather as w
|
|
117
|
+
weather = w.get("Qazigund")
|
|
118
|
+
w.print_weather(weather)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
"""
|