nat-ad / utils_tools.py
ibombonato's picture
fix: handle 404 images
e752a05 verified
import requests
from crewai.tools import BaseTool
import re
from typing import Any
from merchs.merch import Merchant, NaturaMerchant, MercadoLivreMerchant
def get_valid_image_url(url):
"""
Checks if an image URL is accessible.
Returns the URL if it's valid, otherwise returns None.
"""
if not url:
return None
try:
# Use a HEAD request to check headers without downloading the full image
# A timeout is added as a good practice
response = requests.head(url, allow_redirects=True, timeout=5)
# Check if the status code is 200 (OK)
if response.status_code == 200:
print(f"URL is valid: {url}")
return url
else:
print(f"URL is invalid, status code: {response.status_code}")
return None
except requests.RequestException as e:
# Handle connection errors, timeouts, etc.
print(f"An error occurred while checking the URL: {e}")
return None
class CalculateDiscountedPriceTool(BaseTool):
"""
A tool to calculate the final price of an item after a discount is applied.
"""
name: str = "Calculate Discounted Price Tool"
description: str = "Calculates the price after applying a given discount percentage."
def _run(self, original_price: float, discount_percentage: float) -> float:
"""Calculates the discounted price and the total discount amount.
This method takes an original price and a discount percentage, validates
the inputs, and then computes the final price after the discount is
applied, as well as the amount saved.
Args:
original_price: The initial price of the item as a float or integer.
Returns:
float:
- The final discounted price, rounded to 2 decimal places.
"""
if not isinstance(original_price, (int, float)) or not isinstance(discount_percentage, (int, float)):
raise ValueError("Both original_price and discount_percentage must be numbers.")
if discount_percentage < 0 or discount_percentage > 100:
raise ValueError("Discount percentage must be between 0 and 100.")
discount_amount = original_price * (discount_percentage / 100)
discounted_price = original_price - discount_amount
return round(discounted_price, 2)
class CalculateDiscountValueTool(BaseTool):
"""
A tool to calculate the final discount value of an item after comparing the original value and the final value.
"""
name: str = "Calculate Discount Value Tool"
description: str = "Calculates the discount value after comparing two values."
def _run(self, original_price: float, final_price: float) -> int:
"""Calculates the total discounted amount give the original and final price.
This method takes an original price and a final price, validates
the inputs, and then computes the final discounted value.
Args:
original_price: The initial price of the item as a float or integer.
final_price: The final price after discount as a float or integer.
Returns:
float:
- The final discount value, rounded to 0 decimal places.
"""
if not isinstance(original_price, (int, float)) or not isinstance(final_price, (int, float)):
raise ValueError("Both original_price and final_price must be numbers.")
discount_value = original_price - final_price
discount_percentage = (discount_value / original_price) * 100
return int(discount_percentage)
class GetImageUrlTool(BaseTool):
"""
A tool to retrieve the image URL for a given product URL.
"""
name: str = "Get Image URL Tool"
description: str = "Retrieves the image URL for a given product URL."
def _run(self, product_url: str) -> str:
"""
Retrieves the image URL for a given product URL.
Example:
product_url = (
"https://minhaloja.natura.com/p/refil-shampoo-mamae-e-bebe/"
"NATBRA-92791?product=refil-shampoo-mamae-e-bebe&productId=NATBRA-92791"
"&consultoria=lidimelocosmeticos&marca=natura"
)
image_url = GetImageUrlTool()._run(product_url)
# Returns:
# "https://production.na01.natura.com/on/demandware.static/-/Sites-natura-br-storefront-catalog/default/dw68595724/NATBRA-92791_1.jpg"
"""
if not isinstance(product_url, str):
raise ValueError("product_url must be a string.")
# Extract the numeric part after "NATBRA-" or "AVNBRA-" using a regular expression.
match = re.search(r"(NATBRA|AVNBRA)-(\d+)", product_url)
if not match:
raise ValueError(
"Could not extract product_id from the provided URL. "
"Expected a pattern like 'NATBRA-<digits>' or 'AVNBRA-<digits>'."
)
product_type = match.group(1)
product_id = match.group(2)
# Build the final image URL based on product type.
if product_type == "NATBRA":
image_url = (
f"https://production.na01.natura.com/on/demandware.static/-/Sites-natura-br-storefront-catalog/"
f"default/dw68595724/NATBRA-{product_id}_1.jpg"
)
elif product_type == "AVNBRA":
image_url = (
f"https://production.na01.natura.com/on/demandware.static/-/Sites-avon-br-storefront-catalog/"
f"default/dw4b952185/produtos/AVNBRA-{product_id}_1.jpg"
)
else:
raise ValueError(f"Unsupported product type: {product_type}")
image_url = get_valid_image_url(image_url)
return image_url
class MerchantSelectorTool(BaseTool):
name: str = "Merchant Selector Tool"
description: str = "Selects the merchant based on url."
natura_api_token: str
def _run(self, original_url: str) -> Merchant:
if "mercadolivre" in original_url or "ml.com.br" in original_url:
return MercadoLivreMerchant()
elif "natura.com" in original_url:
return NaturaMerchant(natura_api_token=self.natura_api_token)
else:
raise ValueError("Unsupported merchant in URL.")