webscout 8.2.7__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.
- webscout/AIauto.py +1 -1
- webscout/AIutel.py +298 -249
- webscout/Extra/Act.md +309 -0
- webscout/Extra/GitToolkit/__init__.py +10 -0
- webscout/Extra/GitToolkit/gitapi/README.md +110 -0
- webscout/Extra/GitToolkit/gitapi/__init__.py +12 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -0
- webscout/Extra/GitToolkit/gitapi/user.py +96 -0
- webscout/Extra/GitToolkit/gitapi/utils.py +62 -0
- webscout/Extra/YTToolkit/README.md +375 -0
- webscout/Extra/YTToolkit/YTdownloader.py +957 -0
- webscout/Extra/YTToolkit/__init__.py +3 -0
- webscout/Extra/YTToolkit/transcriber.py +476 -0
- webscout/Extra/YTToolkit/ytapi/README.md +44 -0
- 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 +118 -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 +40 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +63 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
- webscout/Extra/YTToolkit/ytapi/video.py +232 -0
- webscout/Extra/__init__.py +7 -0
- webscout/Extra/autocoder/__init__.py +9 -0
- webscout/Extra/autocoder/autocoder.py +1105 -0
- webscout/Extra/autocoder/autocoder_utiles.py +332 -0
- webscout/Extra/gguf.md +430 -0
- webscout/Extra/gguf.py +684 -0
- webscout/Extra/tempmail/README.md +488 -0
- webscout/Extra/tempmail/__init__.py +28 -0
- webscout/Extra/tempmail/async_utils.py +141 -0
- webscout/Extra/tempmail/base.py +161 -0
- webscout/Extra/tempmail/cli.py +187 -0
- webscout/Extra/tempmail/emailnator.py +84 -0
- webscout/Extra/tempmail/mail_tm.py +361 -0
- webscout/Extra/tempmail/temp_mail_io.py +292 -0
- webscout/Extra/weather.md +281 -0
- webscout/Extra/weather.py +194 -0
- webscout/Extra/weather_ascii.py +76 -0
- webscout/Litlogger/Readme.md +175 -0
- webscout/Litlogger/__init__.py +67 -0
- webscout/Litlogger/core/__init__.py +6 -0
- webscout/Litlogger/core/level.py +23 -0
- webscout/Litlogger/core/logger.py +165 -0
- webscout/Litlogger/handlers/__init__.py +12 -0
- webscout/Litlogger/handlers/console.py +33 -0
- webscout/Litlogger/handlers/file.py +143 -0
- webscout/Litlogger/handlers/network.py +173 -0
- webscout/Litlogger/styles/__init__.py +7 -0
- webscout/Litlogger/styles/colors.py +249 -0
- webscout/Litlogger/styles/formats.py +458 -0
- webscout/Litlogger/styles/text.py +87 -0
- webscout/Litlogger/utils/__init__.py +6 -0
- webscout/Litlogger/utils/detectors.py +153 -0
- webscout/Litlogger/utils/formatters.py +200 -0
- webscout/Provider/AI21.py +177 -0
- webscout/Provider/AISEARCH/DeepFind.py +254 -0
- webscout/Provider/AISEARCH/Perplexity.py +359 -0
- webscout/Provider/AISEARCH/README.md +279 -0
- webscout/Provider/AISEARCH/__init__.py +9 -0
- webscout/Provider/AISEARCH/felo_search.py +228 -0
- webscout/Provider/AISEARCH/genspark_search.py +350 -0
- webscout/Provider/AISEARCH/hika_search.py +198 -0
- webscout/Provider/AISEARCH/iask_search.py +436 -0
- webscout/Provider/AISEARCH/monica_search.py +246 -0
- webscout/Provider/AISEARCH/scira_search.py +324 -0
- webscout/Provider/AISEARCH/webpilotai_search.py +281 -0
- webscout/Provider/Aitopia.py +316 -0
- webscout/Provider/AllenAI.py +440 -0
- webscout/Provider/Andi.py +228 -0
- webscout/Provider/Blackboxai.py +673 -0
- webscout/Provider/ChatGPTClone.py +237 -0
- webscout/Provider/ChatGPTGratis.py +194 -0
- webscout/Provider/ChatSandbox.py +342 -0
- webscout/Provider/Cloudflare.py +324 -0
- webscout/Provider/Cohere.py +208 -0
- webscout/Provider/Deepinfra.py +340 -0
- webscout/Provider/ExaAI.py +261 -0
- webscout/Provider/ExaChat.py +358 -0
- webscout/Provider/Flowith.py +217 -0
- webscout/Provider/FreeGemini.py +250 -0
- webscout/Provider/Gemini.py +169 -0
- webscout/Provider/GithubChat.py +370 -0
- webscout/Provider/GizAI.py +295 -0
- webscout/Provider/Glider.py +225 -0
- webscout/Provider/Groq.py +801 -0
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +206 -0
- webscout/Provider/HeckAI.py +285 -0
- webscout/Provider/HuggingFaceChat.py +469 -0
- webscout/Provider/Hunyuan.py +283 -0
- webscout/Provider/Jadve.py +291 -0
- webscout/Provider/Koboldai.py +384 -0
- webscout/Provider/LambdaChat.py +411 -0
- webscout/Provider/Llama3.py +259 -0
- webscout/Provider/MCPCore.py +315 -0
- webscout/Provider/Marcus.py +198 -0
- webscout/Provider/Nemotron.py +218 -0
- webscout/Provider/Netwrck.py +270 -0
- webscout/Provider/OLLAMA.py +396 -0
- webscout/Provider/OPENAI/BLACKBOXAI.py +735 -0
- webscout/Provider/OPENAI/Cloudflare.py +378 -0
- webscout/Provider/OPENAI/FreeGemini.py +282 -0
- webscout/Provider/OPENAI/NEMOTRON.py +244 -0
- webscout/Provider/OPENAI/README.md +1253 -0
- webscout/Provider/OPENAI/__init__.py +36 -0
- webscout/Provider/OPENAI/ai4chat.py +293 -0
- webscout/Provider/OPENAI/api.py +810 -0
- webscout/Provider/OPENAI/base.py +249 -0
- webscout/Provider/OPENAI/c4ai.py +373 -0
- webscout/Provider/OPENAI/chatgpt.py +556 -0
- webscout/Provider/OPENAI/chatgptclone.py +488 -0
- webscout/Provider/OPENAI/chatsandbox.py +172 -0
- webscout/Provider/OPENAI/deepinfra.py +319 -0
- webscout/Provider/OPENAI/e2b.py +1356 -0
- webscout/Provider/OPENAI/exaai.py +411 -0
- webscout/Provider/OPENAI/exachat.py +443 -0
- webscout/Provider/OPENAI/flowith.py +162 -0
- webscout/Provider/OPENAI/freeaichat.py +359 -0
- webscout/Provider/OPENAI/glider.py +323 -0
- webscout/Provider/OPENAI/groq.py +361 -0
- webscout/Provider/OPENAI/heckai.py +307 -0
- webscout/Provider/OPENAI/llmchatco.py +335 -0
- webscout/Provider/OPENAI/mcpcore.py +383 -0
- webscout/Provider/OPENAI/multichat.py +376 -0
- webscout/Provider/OPENAI/netwrck.py +356 -0
- webscout/Provider/OPENAI/opkfc.py +496 -0
- webscout/Provider/OPENAI/scirachat.py +471 -0
- webscout/Provider/OPENAI/sonus.py +303 -0
- webscout/Provider/OPENAI/standardinput.py +433 -0
- webscout/Provider/OPENAI/textpollinations.py +339 -0
- webscout/Provider/OPENAI/toolbaz.py +413 -0
- webscout/Provider/OPENAI/typefully.py +355 -0
- webscout/Provider/OPENAI/typegpt.py +358 -0
- webscout/Provider/OPENAI/uncovrAI.py +462 -0
- webscout/Provider/OPENAI/utils.py +307 -0
- webscout/Provider/OPENAI/venice.py +425 -0
- webscout/Provider/OPENAI/wisecat.py +381 -0
- webscout/Provider/OPENAI/writecream.py +163 -0
- webscout/Provider/OPENAI/x0gpt.py +378 -0
- webscout/Provider/OPENAI/yep.py +356 -0
- webscout/Provider/OpenGPT.py +209 -0
- webscout/Provider/Openai.py +496 -0
- webscout/Provider/PI.py +429 -0
- webscout/Provider/Perplexitylabs.py +415 -0
- webscout/Provider/QwenLM.py +254 -0
- webscout/Provider/Reka.py +214 -0
- webscout/Provider/StandardInput.py +290 -0
- webscout/Provider/TTI/AiForce/README.md +159 -0
- webscout/Provider/TTI/AiForce/__init__.py +22 -0
- webscout/Provider/TTI/AiForce/async_aiforce.py +224 -0
- webscout/Provider/TTI/AiForce/sync_aiforce.py +245 -0
- webscout/Provider/TTI/FreeAIPlayground/README.md +99 -0
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +9 -0
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +181 -0
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +180 -0
- webscout/Provider/TTI/ImgSys/README.md +174 -0
- webscout/Provider/TTI/ImgSys/__init__.py +23 -0
- webscout/Provider/TTI/ImgSys/async_imgsys.py +202 -0
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +195 -0
- webscout/Provider/TTI/MagicStudio/README.md +101 -0
- webscout/Provider/TTI/MagicStudio/__init__.py +2 -0
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +111 -0
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +109 -0
- webscout/Provider/TTI/Nexra/README.md +155 -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/README.md +146 -0
- webscout/Provider/TTI/PollinationsAI/__init__.py +23 -0
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +311 -0
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +265 -0
- webscout/Provider/TTI/README.md +128 -0
- webscout/Provider/TTI/__init__.py +12 -0
- webscout/Provider/TTI/aiarta/README.md +134 -0
- webscout/Provider/TTI/aiarta/__init__.py +2 -0
- webscout/Provider/TTI/aiarta/async_aiarta.py +482 -0
- webscout/Provider/TTI/aiarta/sync_aiarta.py +440 -0
- webscout/Provider/TTI/artbit/README.md +100 -0
- webscout/Provider/TTI/artbit/__init__.py +22 -0
- webscout/Provider/TTI/artbit/async_artbit.py +155 -0
- webscout/Provider/TTI/artbit/sync_artbit.py +148 -0
- webscout/Provider/TTI/fastflux/README.md +129 -0
- webscout/Provider/TTI/fastflux/__init__.py +22 -0
- webscout/Provider/TTI/fastflux/async_fastflux.py +261 -0
- webscout/Provider/TTI/fastflux/sync_fastflux.py +252 -0
- webscout/Provider/TTI/huggingface/README.md +114 -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/piclumen/README.md +161 -0
- webscout/Provider/TTI/piclumen/__init__.py +23 -0
- webscout/Provider/TTI/piclumen/async_piclumen.py +268 -0
- webscout/Provider/TTI/piclumen/sync_piclumen.py +233 -0
- webscout/Provider/TTI/pixelmuse/README.md +79 -0
- webscout/Provider/TTI/pixelmuse/__init__.py +4 -0
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +249 -0
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +182 -0
- webscout/Provider/TTI/talkai/README.md +139 -0
- 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/README.md +192 -0
- webscout/Provider/TTS/__init__.py +9 -0
- webscout/Provider/TTS/base.py +159 -0
- webscout/Provider/TTS/deepgram.py +156 -0
- webscout/Provider/TTS/elevenlabs.py +111 -0
- webscout/Provider/TTS/gesserit.py +128 -0
- webscout/Provider/TTS/murfai.py +113 -0
- webscout/Provider/TTS/parler.py +111 -0
- webscout/Provider/TTS/speechma.py +580 -0
- webscout/Provider/TTS/sthir.py +94 -0
- webscout/Provider/TTS/streamElements.py +333 -0
- webscout/Provider/TTS/utils.py +280 -0
- webscout/Provider/TeachAnything.py +229 -0
- webscout/Provider/TextPollinationsAI.py +308 -0
- webscout/Provider/TwoAI.py +280 -0
- webscout/Provider/TypliAI.py +305 -0
- webscout/Provider/UNFINISHED/ChatHub.py +209 -0
- webscout/Provider/UNFINISHED/Youchat.py +330 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +263 -0
- webscout/Provider/UNFINISHED/oivscode.py +351 -0
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -0
- webscout/Provider/Venice.py +258 -0
- webscout/Provider/VercelAI.py +253 -0
- webscout/Provider/WiseCat.py +233 -0
- webscout/Provider/WrDoChat.py +370 -0
- webscout/Provider/Writecream.py +246 -0
- webscout/Provider/WritingMate.py +269 -0
- webscout/Provider/__init__.py +172 -0
- webscout/Provider/ai4chat.py +149 -0
- webscout/Provider/akashgpt.py +335 -0
- webscout/Provider/asksteve.py +220 -0
- webscout/Provider/cerebras.py +290 -0
- webscout/Provider/chatglm.py +215 -0
- webscout/Provider/cleeai.py +213 -0
- webscout/Provider/copilot.py +425 -0
- webscout/Provider/elmo.py +283 -0
- webscout/Provider/freeaichat.py +285 -0
- webscout/Provider/geminiapi.py +208 -0
- webscout/Provider/granite.py +235 -0
- webscout/Provider/hermes.py +266 -0
- webscout/Provider/julius.py +223 -0
- webscout/Provider/koala.py +170 -0
- webscout/Provider/learnfastai.py +325 -0
- webscout/Provider/llama3mitril.py +215 -0
- webscout/Provider/llmchat.py +258 -0
- webscout/Provider/llmchatco.py +306 -0
- webscout/Provider/lmarena.py +198 -0
- webscout/Provider/meta.py +801 -0
- webscout/Provider/multichat.py +364 -0
- webscout/Provider/samurai.py +223 -0
- webscout/Provider/scira_chat.py +299 -0
- webscout/Provider/scnet.py +243 -0
- webscout/Provider/searchchat.py +292 -0
- webscout/Provider/sonus.py +258 -0
- webscout/Provider/talkai.py +194 -0
- webscout/Provider/toolbaz.py +353 -0
- webscout/Provider/turboseek.py +266 -0
- webscout/Provider/typefully.py +202 -0
- webscout/Provider/typegpt.py +289 -0
- webscout/Provider/uncovr.py +368 -0
- webscout/Provider/x0gpt.py +299 -0
- webscout/Provider/yep.py +389 -0
- webscout/__init__.py +4 -2
- webscout/cli.py +3 -28
- webscout/conversation.py +35 -35
- webscout/litagent/Readme.md +276 -0
- webscout/litagent/__init__.py +29 -0
- webscout/litagent/agent.py +455 -0
- webscout/litagent/constants.py +60 -0
- webscout/litprinter/__init__.py +59 -0
- webscout/scout/README.md +402 -0
- webscout/scout/__init__.py +8 -0
- webscout/scout/core/__init__.py +7 -0
- webscout/scout/core/crawler.py +140 -0
- webscout/scout/core/scout.py +568 -0
- webscout/scout/core/search_result.py +96 -0
- webscout/scout/core/text_analyzer.py +63 -0
- webscout/scout/core/text_utils.py +277 -0
- webscout/scout/core/web_analyzer.py +52 -0
- webscout/scout/element.py +460 -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 +37 -0
- webscout/swiftcli/Readme.md +323 -0
- webscout/swiftcli/__init__.py +95 -0
- webscout/swiftcli/core/__init__.py +7 -0
- webscout/swiftcli/core/cli.py +297 -0
- webscout/swiftcli/core/context.py +104 -0
- webscout/swiftcli/core/group.py +241 -0
- webscout/swiftcli/decorators/__init__.py +28 -0
- webscout/swiftcli/decorators/command.py +221 -0
- webscout/swiftcli/decorators/options.py +220 -0
- webscout/swiftcli/decorators/output.py +252 -0
- webscout/swiftcli/exceptions.py +21 -0
- webscout/swiftcli/plugins/__init__.py +9 -0
- webscout/swiftcli/plugins/base.py +135 -0
- webscout/swiftcli/plugins/manager.py +262 -0
- webscout/swiftcli/utils/__init__.py +59 -0
- webscout/swiftcli/utils/formatting.py +252 -0
- webscout/swiftcli/utils/parsing.py +267 -0
- webscout/version.py +1 -1
- webscout/webscout_search.py +2 -182
- webscout/webscout_search_async.py +1 -179
- webscout/zeroart/README.md +89 -0
- webscout/zeroart/__init__.py +135 -0
- webscout/zeroart/base.py +66 -0
- webscout/zeroart/effects.py +101 -0
- webscout/zeroart/fonts.py +1239 -0
- {webscout-8.2.7.dist-info → webscout-8.2.8.dist-info}/METADATA +115 -60
- webscout-8.2.8.dist-info/RECORD +334 -0
- {webscout-8.2.7.dist-info → webscout-8.2.8.dist-info}/WHEEL +1 -1
- webscout-8.2.7.dist-info/RECORD +0 -26
- {webscout-8.2.7.dist-info → webscout-8.2.8.dist-info}/entry_points.txt +0 -0
- {webscout-8.2.7.dist-info → webscout-8.2.8.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.2.7.dist-info → webscout-8.2.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>☀️ Webscout Weather Toolkit</h1>
|
|
3
|
+
<p><strong>Comprehensive weather data retrieval and visualization tools</strong></p>
|
|
4
|
+
|
|
5
|
+
<!-- Badges -->
|
|
6
|
+
<p>
|
|
7
|
+
<a href="#-installation"><img src="https://img.shields.io/badge/Easy-Installation-success?style=flat-square" alt="Easy Installation"></a>
|
|
8
|
+
<a href="#-current-weather-data"><img src="https://img.shields.io/badge/Real--time-Data-blue?style=flat-square" alt="Real-time Data"></a>
|
|
9
|
+
<a href="#-ascii-art-weather"><img src="https://img.shields.io/badge/ASCII-Visualization-orange?style=flat-square" alt="ASCII Visualization"></a>
|
|
10
|
+
</p>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
> Webscout's Weather Toolkit provides powerful tools to retrieve and display weather information in various formats, including structured data and ASCII art visualization.
|
|
15
|
+
|
|
16
|
+
## 📋 Table of Contents
|
|
17
|
+
|
|
18
|
+
- [🚀 Installation](#-installation)
|
|
19
|
+
- [🌡️ Current Weather Data](#-current-weather-data)
|
|
20
|
+
- [🔮 Weather Forecast](#-weather-forecast)
|
|
21
|
+
- [🎨 ASCII Art Weather](#-ascii-art-weather)
|
|
22
|
+
- [📊 Data Structure](#-data-structure)
|
|
23
|
+
- [⚙️ Advanced Usage](#-advanced-usage)
|
|
24
|
+
|
|
25
|
+
## 🚀 Installation
|
|
26
|
+
|
|
27
|
+
The Weather Toolkit is included in the Webscout package. Install or update Webscout to get access:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install -U webscout
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 🌡️ Current Weather Data
|
|
34
|
+
|
|
35
|
+
Retrieve structured current weather information for any location worldwide.
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from webscout.Extra import weather
|
|
39
|
+
|
|
40
|
+
# Get weather for a specific location
|
|
41
|
+
forecast = weather.get("London")
|
|
42
|
+
|
|
43
|
+
# Access current conditions
|
|
44
|
+
print(f"Current weather: {forecast.summary}")
|
|
45
|
+
|
|
46
|
+
# Access temperature details
|
|
47
|
+
if forecast.current_condition:
|
|
48
|
+
print(f"Temperature: {forecast.current_condition.temp_c}°C / {forecast.current_condition.temp_f}°F")
|
|
49
|
+
print(f"Feels like: {forecast.current_condition.feels_like_c}°C")
|
|
50
|
+
print(f"Conditions: {forecast.current_condition.weather_desc}")
|
|
51
|
+
print(f"Wind: {forecast.current_condition.wind_speed_kmph} km/h from {forecast.current_condition.wind_direction}")
|
|
52
|
+
print(f"Humidity: {forecast.current_condition.humidity}%")
|
|
53
|
+
print(f"Visibility: {forecast.current_condition.visibility} km")
|
|
54
|
+
print(f"Pressure: {forecast.current_condition.pressure} mb")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 🔮 Weather Forecast
|
|
58
|
+
|
|
59
|
+
Access detailed forecast information for today and upcoming days.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from webscout.Extra import weather
|
|
63
|
+
|
|
64
|
+
forecast = weather.get("Tokyo")
|
|
65
|
+
|
|
66
|
+
# Today's forecast
|
|
67
|
+
if forecast.today:
|
|
68
|
+
print(f"Today ({forecast.today.date_formatted}):")
|
|
69
|
+
print(f" Temperature range: {forecast.today.min_temp_c}°C - {forecast.today.max_temp_c}°C")
|
|
70
|
+
print(f" Sunrise: {forecast.today.sunrise}, Sunset: {forecast.today.sunset}")
|
|
71
|
+
|
|
72
|
+
# Access hourly forecasts
|
|
73
|
+
if forecast.today.hourly and len(forecast.today.hourly) > 4:
|
|
74
|
+
noon = forecast.today.hourly[4] # Noon (12:00) is usually index 4
|
|
75
|
+
print(f" Noon conditions: {noon.weather_desc}")
|
|
76
|
+
print(f" Chance of rain: {noon.chance_of_rain}%")
|
|
77
|
+
print(f" Humidity: {noon.humidity}%")
|
|
78
|
+
print(f" UV Index: {noon.uv_index}")
|
|
79
|
+
|
|
80
|
+
# Tomorrow's forecast
|
|
81
|
+
if forecast.tomorrow:
|
|
82
|
+
print(f"\nTomorrow ({forecast.tomorrow.date_formatted}):")
|
|
83
|
+
print(f" Temperature range: {forecast.tomorrow.min_temp_c}°C - {forecast.tomorrow.max_temp_c}°C")
|
|
84
|
+
print(f" Weather: {forecast.tomorrow.weather_desc}")
|
|
85
|
+
print(f" Sunrise: {forecast.tomorrow.sunrise}, Sunset: {forecast.tomorrow.sunset}")
|
|
86
|
+
|
|
87
|
+
# Extended forecast (next 3 days)
|
|
88
|
+
if forecast.days and len(forecast.days) > 2:
|
|
89
|
+
print("\nExtended Forecast:")
|
|
90
|
+
for day in forecast.days[2:5]: # Days 3-5
|
|
91
|
+
print(f" {day.date_formatted}: {day.min_temp_c}°C - {day.max_temp_c}°C, {day.weather_desc}")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 🎨 ASCII Art Weather
|
|
95
|
+
|
|
96
|
+
Retrieve weather information as visually appealing ASCII art.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from webscout.Extra import weather_ascii
|
|
100
|
+
|
|
101
|
+
# Get ASCII art weather
|
|
102
|
+
result = weather_ascii.get("Paris")
|
|
103
|
+
|
|
104
|
+
# Display the ASCII art weather
|
|
105
|
+
print(result.content)
|
|
106
|
+
|
|
107
|
+
# Get ASCII art with temperature in Fahrenheit
|
|
108
|
+
result_f = weather_ascii.get("New York", units="imperial")
|
|
109
|
+
print(result_f.content)
|
|
110
|
+
|
|
111
|
+
# Get ASCII art with a specific number of forecast days
|
|
112
|
+
result_days = weather_ascii.get("Berlin", days=3)
|
|
113
|
+
print(result_days.content)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Example output:
|
|
117
|
+
```
|
|
118
|
+
Weather for Paris, France
|
|
119
|
+
|
|
120
|
+
\ / Clear
|
|
121
|
+
.-. +20°C
|
|
122
|
+
― ( ) ― ↗ 11 km/h
|
|
123
|
+
`-' 10 km
|
|
124
|
+
/ \ 0.0 mm
|
|
125
|
+
┌─────────────┐
|
|
126
|
+
┌───────────────────────┤ Wed 14 Apr ├───────────────────────┐
|
|
127
|
+
│ Morning └──────┬──────┘ Evening Night │
|
|
128
|
+
├──────────────────────────────┼──────────────────────────────┤
|
|
129
|
+
│ Cloudy │ Clear │
|
|
130
|
+
│ .--. +20..+22 °C │ \ / +15 °C │
|
|
131
|
+
│ .-( ). ↗ 11-13 km/h │ .-. ↗ 7-9 km/h │
|
|
132
|
+
│ (___.__)__) 10 km │ ― ( ) ― 10 km │
|
|
133
|
+
│ 0.0 mm | 0% │ `-' 0.0 mm | 0% │
|
|
134
|
+
└──────────────────────────────┴──────────────────────────────┘
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 📊 Data Structure
|
|
138
|
+
|
|
139
|
+
The Weather Toolkit returns structured data objects with the following key components:
|
|
140
|
+
|
|
141
|
+
<details>
|
|
142
|
+
<summary><strong>Forecast Object Structure</strong></summary>
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
forecast = weather.get("London")
|
|
146
|
+
|
|
147
|
+
# Main forecast object attributes
|
|
148
|
+
forecast.location # Location information (city, country, etc.)
|
|
149
|
+
forecast.summary # Brief summary of current weather
|
|
150
|
+
forecast.current_condition # Current weather conditions
|
|
151
|
+
forecast.today # Today's forecast
|
|
152
|
+
forecast.tomorrow # Tomorrow's forecast
|
|
153
|
+
forecast.days # List of daily forecasts (including today and tomorrow)
|
|
154
|
+
|
|
155
|
+
# Current condition attributes
|
|
156
|
+
current = forecast.current_condition
|
|
157
|
+
current.temp_c # Temperature in Celsius
|
|
158
|
+
current.temp_f # Temperature in Fahrenheit
|
|
159
|
+
current.feels_like_c # "Feels like" temperature in Celsius
|
|
160
|
+
current.feels_like_f # "Feels like" temperature in Fahrenheit
|
|
161
|
+
current.wind_speed_kmph # Wind speed in km/h
|
|
162
|
+
current.wind_speed_mph # Wind speed in mph
|
|
163
|
+
current.wind_direction # Wind direction (e.g., "NW")
|
|
164
|
+
current.humidity # Humidity percentage
|
|
165
|
+
current.pressure # Atmospheric pressure in millibars
|
|
166
|
+
current.visibility # Visibility in kilometers
|
|
167
|
+
current.weather_desc # Weather description (e.g., "Partly cloudy")
|
|
168
|
+
current.weather_code # Weather code for icon mapping
|
|
169
|
+
|
|
170
|
+
# Daily forecast attributes
|
|
171
|
+
day = forecast.today # or any day from forecast.days
|
|
172
|
+
day.date # Date (YYYY-MM-DD)
|
|
173
|
+
day.date_formatted # Formatted date (e.g., "Wed 14 Apr")
|
|
174
|
+
day.max_temp_c # Maximum temperature in Celsius
|
|
175
|
+
day.min_temp_c # Minimum temperature in Celsius
|
|
176
|
+
day.max_temp_f # Maximum temperature in Fahrenheit
|
|
177
|
+
day.min_temp_f # Minimum temperature in Fahrenheit
|
|
178
|
+
day.sunrise # Sunrise time
|
|
179
|
+
day.sunset # Sunset time
|
|
180
|
+
day.weather_desc # Weather description
|
|
181
|
+
day.weather_code # Weather code
|
|
182
|
+
day.hourly # List of hourly forecasts for this day
|
|
183
|
+
```
|
|
184
|
+
</details>
|
|
185
|
+
|
|
186
|
+
<details>
|
|
187
|
+
<summary><strong>ASCII Weather Object Structure</strong></summary>
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
result = weather_ascii.get("Paris")
|
|
191
|
+
|
|
192
|
+
# ASCII result attributes
|
|
193
|
+
result.content # The full ASCII art weather display
|
|
194
|
+
result.location # Location information
|
|
195
|
+
result.temperature # Current temperature
|
|
196
|
+
result.conditions # Current weather conditions
|
|
197
|
+
result.forecast_days # Number of forecast days included
|
|
198
|
+
```
|
|
199
|
+
</details>
|
|
200
|
+
|
|
201
|
+
## ⚙️ Advanced Usage
|
|
202
|
+
|
|
203
|
+
<details>
|
|
204
|
+
<summary><strong>Custom Location Formats</strong></summary>
|
|
205
|
+
|
|
206
|
+
The Weather Toolkit supports various location formats:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# City name
|
|
210
|
+
weather.get("London")
|
|
211
|
+
|
|
212
|
+
# City and country
|
|
213
|
+
weather.get("Paris, France")
|
|
214
|
+
|
|
215
|
+
# ZIP/Postal code (US)
|
|
216
|
+
weather.get("10001") # New York, NY
|
|
217
|
+
|
|
218
|
+
# Latitude and Longitude
|
|
219
|
+
weather.get("40.7128,-74.0060") # New York coordinates
|
|
220
|
+
```
|
|
221
|
+
</details>
|
|
222
|
+
|
|
223
|
+
<details>
|
|
224
|
+
<summary><strong>Temperature Units</strong></summary>
|
|
225
|
+
|
|
226
|
+
Control temperature units in ASCII weather display:
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
# Default (metric - Celsius)
|
|
230
|
+
weather_ascii.get("Tokyo")
|
|
231
|
+
|
|
232
|
+
# Imperial (Fahrenheit)
|
|
233
|
+
weather_ascii.get("New York", units="imperial")
|
|
234
|
+
|
|
235
|
+
# Metric (Celsius)
|
|
236
|
+
weather_ascii.get("Berlin", units="metric")
|
|
237
|
+
```
|
|
238
|
+
</details>
|
|
239
|
+
|
|
240
|
+
<details>
|
|
241
|
+
<summary><strong>Forecast Days</strong></summary>
|
|
242
|
+
|
|
243
|
+
Control the number of forecast days in ASCII weather display:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
# Default (1 day)
|
|
247
|
+
weather_ascii.get("Sydney")
|
|
248
|
+
|
|
249
|
+
# 3-day forecast
|
|
250
|
+
weather_ascii.get("Rio de Janeiro", days=3)
|
|
251
|
+
|
|
252
|
+
# 5-day forecast (maximum)
|
|
253
|
+
weather_ascii.get("Moscow", days=5)
|
|
254
|
+
```
|
|
255
|
+
</details>
|
|
256
|
+
|
|
257
|
+
<details>
|
|
258
|
+
<summary><strong>Error Handling</strong></summary>
|
|
259
|
+
|
|
260
|
+
Implement proper error handling for robust applications:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from webscout.Extra import weather
|
|
264
|
+
from webscout.exceptions import APIError
|
|
265
|
+
|
|
266
|
+
try:
|
|
267
|
+
forecast = weather.get("London")
|
|
268
|
+
print(f"Current temperature: {forecast.current_condition.temp_c}°C")
|
|
269
|
+
except APIError as e:
|
|
270
|
+
print(f"API Error: {e}")
|
|
271
|
+
except Exception as e:
|
|
272
|
+
print(f"An error occurred: {e}")
|
|
273
|
+
```
|
|
274
|
+
</details>
|
|
275
|
+
|
|
276
|
+
<div align="center">
|
|
277
|
+
<p>
|
|
278
|
+
<a href="https://github.com/OEvortex/Webscout"><img alt="GitHub Repository" src="https://img.shields.io/badge/GitHub-Repository-181717?style=for-the-badge&logo=github&logoColor=white"></a>
|
|
279
|
+
<a href="https://t.me/PyscoutAI"><img alt="Telegram Group" src="https://img.shields.io/badge/Telegram%20Group-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white"></a>
|
|
280
|
+
</p>
|
|
281
|
+
</div>
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Weather information module with a clean, strongly-typed API structure.
|
|
3
|
+
|
|
4
|
+
This module provides a simple client for fetching weather data
|
|
5
|
+
from the wttr.in service with proper typing and a consistent interface.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import List, Dict, Any, Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CurrentCondition:
|
|
14
|
+
"""Current weather conditions with strongly typed properties."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
17
|
+
"""Initialize with current condition data.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
data: Current condition data dictionary from wttr.in
|
|
21
|
+
"""
|
|
22
|
+
self.temp_c: Optional[str] = data.get('temp_C')
|
|
23
|
+
self.temp_f: Optional[str] = data.get('temp_F')
|
|
24
|
+
self.feels_like_c: Optional[str] = data.get('FeelsLikeC')
|
|
25
|
+
self.feels_like_f: Optional[str] = data.get('FeelsLikeF')
|
|
26
|
+
self.weather_desc: str = data.get('weatherDesc', [{}])[0].get('value', '')
|
|
27
|
+
self.weather_code: Optional[str] = data.get('weatherCode')
|
|
28
|
+
self.humidity: Optional[str] = data.get('humidity')
|
|
29
|
+
self.visibility: Optional[str] = data.get('visibility')
|
|
30
|
+
self.pressure: Optional[str] = data.get('pressure')
|
|
31
|
+
self.wind_speed_kmph: Optional[str] = data.get('windspeedKmph')
|
|
32
|
+
self.wind_direction: Optional[str] = data.get('winddir16Point')
|
|
33
|
+
self.wind_degree: Optional[str] = data.get('winddirDegree')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Location:
|
|
37
|
+
"""Location information with strongly typed properties."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
40
|
+
"""Initialize with location data.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
data: Location data dictionary from wttr.in
|
|
44
|
+
"""
|
|
45
|
+
self.name: str = data.get('areaName', [{}])[0].get('value', '')
|
|
46
|
+
self.country: str = data.get('country', [{}])[0].get('value', '')
|
|
47
|
+
self.region: str = data.get('region', [{}])[0].get('value', '')
|
|
48
|
+
self.latitude: Optional[str] = data.get('latitude')
|
|
49
|
+
self.longitude: Optional[str] = data.get('longitude')
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class HourlyForecast:
|
|
53
|
+
"""Hourly forecast information with strongly typed properties."""
|
|
54
|
+
|
|
55
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
56
|
+
"""Initialize with hourly forecast data.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
data: Hourly forecast data dictionary from wttr.in
|
|
60
|
+
"""
|
|
61
|
+
self.time: Optional[str] = data.get('time')
|
|
62
|
+
self.temp_c: Optional[str] = data.get('tempC')
|
|
63
|
+
self.temp_f: Optional[str] = data.get('tempF')
|
|
64
|
+
self.weather_desc: str = data.get('weatherDesc', [{}])[0].get('value', '')
|
|
65
|
+
self.weather_code: Optional[str] = data.get('weatherCode')
|
|
66
|
+
self.wind_speed_kmph: Optional[str] = data.get('windspeedKmph')
|
|
67
|
+
self.wind_direction: Optional[str] = data.get('winddir16Point')
|
|
68
|
+
self.feels_like_c: Optional[str] = data.get('FeelsLikeC')
|
|
69
|
+
self.feels_like_f: Optional[str] = data.get('FeelsLikeF')
|
|
70
|
+
self.chance_of_rain: Optional[str] = data.get('chanceofrain')
|
|
71
|
+
self.chance_of_snow: Optional[str] = data.get('chanceofsnow')
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class DayForecast:
|
|
75
|
+
"""Daily forecast information with strongly typed properties."""
|
|
76
|
+
|
|
77
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
78
|
+
"""Initialize with daily forecast data.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
data: Daily forecast data dictionary from wttr.in
|
|
82
|
+
"""
|
|
83
|
+
self.date: Optional[str] = data.get('date')
|
|
84
|
+
self.date_formatted: Optional[str] = None
|
|
85
|
+
if self.date:
|
|
86
|
+
try:
|
|
87
|
+
self.date_formatted = datetime.strptime(self.date, '%Y-%m-%d').strftime('%a, %b %d')
|
|
88
|
+
except ValueError:
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
self.max_temp_c: Optional[str] = data.get('maxtempC')
|
|
92
|
+
self.max_temp_f: Optional[str] = data.get('maxtempF')
|
|
93
|
+
self.min_temp_c: Optional[str] = data.get('mintempC')
|
|
94
|
+
self.min_temp_f: Optional[str] = data.get('mintempF')
|
|
95
|
+
self.avg_temp_c: Optional[str] = data.get('avgtempC')
|
|
96
|
+
self.avg_temp_f: Optional[str] = data.get('avgtempF')
|
|
97
|
+
self.sun_hour: Optional[str] = data.get('sunHour')
|
|
98
|
+
|
|
99
|
+
# Parse astronomy data (simplified)
|
|
100
|
+
if data.get('astronomy') and len(data.get('astronomy', [])) > 0:
|
|
101
|
+
astro = data.get('astronomy', [{}])[0]
|
|
102
|
+
self.sunrise: Optional[str] = astro.get('sunrise')
|
|
103
|
+
self.sunset: Optional[str] = astro.get('sunset')
|
|
104
|
+
self.moon_phase: Optional[str] = astro.get('moon_phase')
|
|
105
|
+
else:
|
|
106
|
+
self.sunrise = self.sunset = self.moon_phase = None
|
|
107
|
+
|
|
108
|
+
# Parse hourly forecasts
|
|
109
|
+
self.hourly: List[HourlyForecast] = []
|
|
110
|
+
for hour_data in data.get('hourly', []):
|
|
111
|
+
self.hourly.append(HourlyForecast(hour_data))
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class Weather:
|
|
115
|
+
"""Weather response object with strongly typed properties."""
|
|
116
|
+
|
|
117
|
+
def __init__(self, data: Optional[Dict[str, Any]] = None) -> None:
|
|
118
|
+
"""Initialize with weather data.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
data: Weather data dictionary from wttr.in
|
|
122
|
+
"""
|
|
123
|
+
if not data:
|
|
124
|
+
self.current_condition = None
|
|
125
|
+
self.location = None
|
|
126
|
+
self.forecast_days = []
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
# Parse current condition
|
|
130
|
+
self.current_condition: Optional[CurrentCondition] = None
|
|
131
|
+
if data.get('current_condition') and len(data.get('current_condition', [])) > 0:
|
|
132
|
+
self.current_condition = CurrentCondition(data.get('current_condition', [{}])[0])
|
|
133
|
+
|
|
134
|
+
# Parse location
|
|
135
|
+
self.location: Optional[Location] = None
|
|
136
|
+
if data.get('nearest_area') and len(data.get('nearest_area', [])) > 0:
|
|
137
|
+
self.location = Location(data.get('nearest_area', [{}])[0])
|
|
138
|
+
|
|
139
|
+
# Parse forecast days
|
|
140
|
+
self.forecast_days: List[DayForecast] = []
|
|
141
|
+
for day_data in data.get('weather', []):
|
|
142
|
+
self.forecast_days.append(DayForecast(day_data))
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def today(self) -> Optional[DayForecast]:
|
|
146
|
+
"""Get today's forecast."""
|
|
147
|
+
return self.forecast_days[0] if self.forecast_days else None
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def tomorrow(self) -> Optional[DayForecast]:
|
|
151
|
+
"""Get tomorrow's forecast."""
|
|
152
|
+
return self.forecast_days[1] if len(self.forecast_days) > 1 else None
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def summary(self) -> str:
|
|
156
|
+
"""Get a simple text summary of current weather."""
|
|
157
|
+
if not self.current_condition or not self.location:
|
|
158
|
+
return "Weather data not available"
|
|
159
|
+
|
|
160
|
+
return f"{self.location.name}, {self.location.country}: {self.current_condition.weather_desc}, {self.current_condition.temp_c}°C ({self.current_condition.temp_f}°F)"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class WeatherClient:
|
|
164
|
+
"""Client for fetching weather information."""
|
|
165
|
+
|
|
166
|
+
def get_weather(self, location: str) -> Weather:
|
|
167
|
+
"""Get weather for the specified location.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
location: Location to get weather for (city name, zip code, etc.)
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Weather object containing all weather data
|
|
174
|
+
"""
|
|
175
|
+
try:
|
|
176
|
+
response = requests.get(f"https://wttr.in/{location}?format=j1", timeout=10)
|
|
177
|
+
response.raise_for_status()
|
|
178
|
+
return Weather(response.json())
|
|
179
|
+
except Exception as e:
|
|
180
|
+
print(f"Error fetching weather data: {str(e)}")
|
|
181
|
+
return Weather()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def get(location: str) -> Weather:
|
|
185
|
+
"""Convenience function to get weather for a location.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
location: Location to get weather for
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Weather object containing all weather data
|
|
192
|
+
"""
|
|
193
|
+
client = WeatherClient()
|
|
194
|
+
return client.get_weather(location)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Weather ASCII art visualization module with a simple, strongly-typed API.
|
|
3
|
+
|
|
4
|
+
This module provides a clean interface for fetching weather information
|
|
5
|
+
in ASCII art format using the wttr.in service.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
from typing import Dict, Optional, Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WeatherAscii:
|
|
13
|
+
"""Container for ASCII weather data with a simple API."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, content: str) -> None:
|
|
16
|
+
"""Initialize with ASCII weather content.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
content: ASCII weather data or error message
|
|
20
|
+
"""
|
|
21
|
+
self._content = content
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def content(self) -> str:
|
|
25
|
+
"""Get the ASCII content, similar to choices.message.content in OpenAI API."""
|
|
26
|
+
return self._content
|
|
27
|
+
|
|
28
|
+
def __str__(self) -> str:
|
|
29
|
+
"""String representation of ASCII weather."""
|
|
30
|
+
return self.content
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class WeatherAsciiClient:
|
|
34
|
+
"""Client for fetching weather information in ASCII art."""
|
|
35
|
+
|
|
36
|
+
def get_weather(self, location: str, params: Optional[Dict[str, Any]] = None) -> WeatherAscii:
|
|
37
|
+
"""Get ASCII weather for a location.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
location: The location for which to fetch weather data
|
|
41
|
+
params: Additional parameters for the request
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
WeatherAscii object containing ASCII art weather data
|
|
45
|
+
"""
|
|
46
|
+
url = f"https://wttr.in/{location}"
|
|
47
|
+
headers = {'User-Agent': 'curl'}
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
response = requests.get(url, headers=headers, params=params, timeout=10)
|
|
51
|
+
response.raise_for_status()
|
|
52
|
+
|
|
53
|
+
if response.status_code == 200:
|
|
54
|
+
# Remove the footer line from wttr.in
|
|
55
|
+
ascii_weather = "\n".join(response.text.splitlines()[:-1])
|
|
56
|
+
return WeatherAscii(ascii_weather)
|
|
57
|
+
else:
|
|
58
|
+
error_msg = f"Error: Unable to fetch weather data. Status code: {response.status_code}"
|
|
59
|
+
return WeatherAscii(error_msg)
|
|
60
|
+
except requests.exceptions.RequestException as e:
|
|
61
|
+
return WeatherAscii(f"Error: {str(e)}")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get(location: str, params: Optional[Dict[str, Any]] = None) -> WeatherAscii:
|
|
65
|
+
"""Convenience function to get ASCII weather for a location.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
location: Location to get weather for
|
|
69
|
+
params: Additional parameters for the request
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
WeatherAscii object containing ASCII art weather data
|
|
73
|
+
"""
|
|
74
|
+
client = WeatherAsciiClient()
|
|
75
|
+
return client.get_weather(location, params)
|
|
76
|
+
|