Spaces:
Sleeping
Sleeping
File size: 12,250 Bytes
3c7d0f6 df0eb35 5b4a293 94a7d52 457afbf ae4bc61 3cdec01 94a7d52 3c7d0f6 e4f36f5 df0eb35 ddc7a67 df0eb35 ddc7a67 df0eb35 ddc7a67 df0eb35 3c7d0f6 94a7d52 ae4bc61 94a7d52 e4f36f5 94a7d52 ae4bc61 94a7d52 3c7d0f6 e4f36f5 94a7d52 3c7d0f6 94a7d52 3c7d0f6 94a7d52 3c7d0f6 ae4bc61 3c7d0f6 94a7d52 3c7d0f6 9944cf3 94a7d52 3c7d0f6 94a7d52 df0eb35 94a7d52 ae4bc61 3c7d0f6 5b4a293 df0eb35 02d4d4d c5d76a1 30d4e20 c5d76a1 02d4d4d df0eb35 6bc7ff7 ddc7a67 df0eb35 3c7d0f6 170eb66 e4f36f5 9362af6 170eb66 e4f36f5 170eb66 94a7d52 5b4a293 df0eb35 5b4a293 df0eb35 5b4a293 df0eb35 ddc7a67 df0eb35 02d4d4d df0eb35 ddc7a67 df0eb35 02d4d4d df0eb35 ddc7a67 5b4a293 ae4bc61 ddc7a67 02d4d4d ddc7a67 ae4bc61 5b4a293 96e9004 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
import gradio as gr
import os
import base64
from dotenv import load_dotenv
from image_generator_tool import GenerateImageTool
from social_media_crew import SocialMediaCrew
from utils_tools import GetImageUrlTool
load_dotenv()
def clean_env_vars():
os.environ.pop("OPENAI_API_KEY", None)
os.environ.pop("NATURA_API_TOKEN", None)
os.environ.pop("OPENAI_BASE_URL", None)
os.environ.pop("OPENAI_MODEL_NAME", None)
js_share_logic = """
async (image_url) => {
if (!image_url) {
console.error("Share button clicked, but no image URL found.");
alert("No image to share. Please generate an image first.");
return;
}
try {
const response = await fetch(image_url);
const blob = await response.blob();
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = async function() {
const base64data = reader.result;
const parts = base64data.split(';base64,');
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
const newBlob = new Blob([uInt8Array], { type: contentType });
const fileName = `shared_image_${new Date().getTime()}.png`;
const file = new File([newBlob], fileName, { type: contentType });
if (navigator.share && navigator.canShare({ files: [file] })) {
await navigator.share({
files: [file],
title: "Image",
text: "Shared from app.",
});
} else {
alert("Sharing not supported on this browser.");
}
};
reader.onerror = function(error) {
console.error("Error converting blob to data URL:", error);
alert("An error occurred while preparing image for sharing.");
};
} catch (error) {
if (error.name === 'AbortError') {
console.log("Share dialog cancelled by user.");
} else {
console.error("Error sharing:", error);
alert("An error occurred while trying to share.");
}
}
}
"""
# --- Gradio Interface ---
def generate_ad(product_url: str, store_name: str, main_cupom: str, main_cupom_discount_percentage: float, cupom_1: str, original_price: float, discounted_price: float, openai_api_key: str, natura_api_token: str, openai_base_url: str, openai_model_name: str):
yield gr.update(interactive=False, value="Generating..."), gr.Markdown(value="⏳ Generating ad... Please wait."), gr.Image(label="Product Image", show_label=True, visible=False, width=200, height=200)
if not openai_api_key or not natura_api_token or not openai_model_name or not openai_base_url:
yield gr.update(interactive=True, value="Generate Ad"), gr.Markdown(value="Please configure your API keys in the settings section below.")
return
image_url = None
if "natura" in product_url:
image_url = GetImageUrlTool()._run(product_url)
print(f"Extracted image URL: {image_url}")
original_price = original_price if original_price is not None else 0
discounted_price = discounted_price if discounted_price is not None else 0
social_media_crew = SocialMediaCrew(openai_api_key, natura_api_token, openai_base_url, openai_model_name)
result = social_media_crew.run_crew(product_url, store_name, main_cupom, main_cupom_discount_percentage, cupom_1, original_price, discounted_price)
if result == "INVALID_URL":
yield gr.update(interactive=True, value="Generate Ad"), gr.Markdown(value="❌ The provided URL is invalid or the product page could not be found.")
elif result == "MISSING_PRODUCT_INFO":
yield gr.update(interactive=True, value="Generate Ad"), gr.Markdown(value="⚠️ Could not extract all required product information from the URL. Please check the URL or try a different one.")
else:
yield gr.update(interactive=True, value="Generate Ad"), gr.Markdown(value=result.raw), gr.Image(value=image_url, visible=image_url is not None)
with gr.Blocks() as demo:
gr.Markdown("# 🚀 Social Media Ad Generator")
gr.Markdown("Enter a product URL to generate a social media ad.")
with gr.Tab("Generate Ad"):
url_input = gr.Textbox(label="Product URL", placeholder="Enter product URL here...")
store_name_input = gr.Textbox(label="Store Name (e.g., O Boticário)", placeholder="Enter store name...")
main_cupom_input = gr.Textbox(label="Main Cupom (e.g., PRIMEIRACOMPRA)", value="MINHALOJATAON")
main_cupom_discount_percentage_input = gr.Number(label="Main Cupom Discount Percentage (e.g., 20 for 20%)", value=15, minimum=0, maximum=100)
cupom_1_input = gr.Textbox(label="Cupom 1 (e.g., AMIGO15)", placeholder="Enter first coupon code...")
original_price_input = gr.Number(label="Original Price (Optional)", value=0, minimum=0)
discounted_price_input = gr.Number(label="Discounted Price (Optional)", value=0, minimum=0)
with gr.Row():
generate_ad_button = gr.Button("Generate Ad")
clear_button = gr.Button("Clear")
with gr.Row():
ad_output = gr.Markdown(label="Your Generated Ad", show_copy_button=True)
ad_image_output = gr.Image(label="Product Image", show_label=False, visible=True, width=200, height=200)
with gr.Tab("Fragrantica"):
gr.Markdown("### 👃 Fragrantica Website Analyzer")
fragrantica_url_input = gr.Textbox(label="Fragrantica Product URL", placeholder="Enter Fragrantica product URL here...")
analyze_fragrantica_button = gr.Button("Analyze Fragrantica Product")
fragrantica_output = gr.Markdown(label="Fragrantica Analysis Report")
with gr.Tab("Images"):
gr.Markdown("### 🖼️ Generate Promotional Image")
with gr.Row():
with gr.Column():
image_product_url_input = gr.Textbox(label="Product Image URL", placeholder="Enter product image URL...")
image_product_name_input = gr.Textbox(label="Product Name", placeholder="Enter product name...")
image_original_price_input = gr.Number(label="Original Price", placeholder="Enter original price...")
image_final_price_input = gr.Number(label="Final Price", placeholder="Enter final price...")
image_coupon_code_input = gr.Textbox(label="Coupon Code", placeholder="Enter coupon code...")
template_selection = gr.Radio(
choices=[
"outros",
"outros_sem_cupom",
"natura",
"avon",
"lidi_promo",
],
value="outros",
label="Template Selection"
)
gen_image_btn = gr.Button("Generate Image")
with gr.Column():
image_output = gr.Image(label="Generated Image", height=500, type="filepath", interactive=False, show_share_button=True)
base64_debug_output = gr.Textbox(label="Base64 Debug Output", visible=True, interactive=False)
share_button = gr.Button("🚀 Share Image", interactive=False)
with gr.Tab("Settings"):
gr.Markdown("### ⚙️ API Key Settings")
gr.Markdown("Enter your API keys below. These will be used for the current session.")
openai_key_input = gr.Textbox(label="OPENAI_API_KEY", type="password", value=os.getenv("OPENAI_API_KEY", ""))
natura_token_input = gr.Textbox(label="NATURA_API_TOKEN", type="password", value=os.getenv("NATURA_API_TOKEN", ""))
openai_base_url_input = gr.Textbox(label="OPENAI_BASE_URL", value=os.getenv("OPENAI_BASE_URL", "https://llm-openai-ibombonato.openai.azure.com/openai/deployments/gpt-4.1-mini/chat/completions?api-version=2025-01-01-preview"))
openai_model_name_input = gr.Textbox(label="OPENAI_MODEL_NAME", value=os.getenv("OPENAI_MODEL_NAME", "azure/gpt-4.1-mini"))
clean_env_vars()
# No save button needed as keys are passed directly
gr.Markdown("API keys are used directly from these fields when you click 'Generate Ad'. They are not saved persistently.")
def clear_fields():
return "", 0, 0
def analyze_fragrantica_url(url, openai_api_key, natura_api_token, openai_base_url, openai_model_name):
yield "⏳ Analyzing Fragrantica product... Please wait." # Loading message
if not openai_api_key or not openai_model_name or not openai_base_url:
yield "Please configure your API keys in the settings section below."
return
from fragrantica_crew import FragranticaCrew
fragrantica_crew = FragranticaCrew(openai_api_key, openai_base_url, openai_model_name)
report = fragrantica_crew.kickoff(url=url)
if report == "SCRAPING_FAILED":
yield "❌ Scraping failed. The website could not be accessed or parsed. Please check the URL or try again later."
return
yield report.raw
def generate_image(product_image_url, product_name, original_price, final_price, coupon_code, template_name):
tool = GenerateImageTool()
original_price_str = f"{original_price:.2f}".replace('.', ',')
final_price_str = f"{final_price:.2f}".replace('.', ',')
yield gr.update(interactive=False, value="Generating..."), None, gr.update(interactive=False)
image_path = tool._run(
product_image_url=product_image_url,
product_name=product_name,
original_price=original_price_str,
final_price=final_price_str,
coupon_code=coupon_code,
template_name=template_name
)
yield gr.update(interactive=True, value="Generate Image"), image_path, gr.update(interactive=True)
def process_image_for_sharing(image_path):
if image_path is None:
return ""
try:
with open(image_path, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode("utf-8")
data_url = f"data:image/png;base64,{encoded_string}"
return data_url
except Exception as e:
print(f"Error processing image for sharing: {e}")
return ""
generate_ad_button.click(generate_ad,
inputs=[url_input, store_name_input, main_cupom_input, main_cupom_discount_percentage_input, cupom_1_input, original_price_input, discounted_price_input, openai_key_input, natura_token_input, openai_base_url_input, openai_model_name_input],
outputs=[generate_ad_button, ad_output, ad_image_output])
clear_button.click(clear_fields,
inputs=[],
outputs=[url_input, original_price_input, discounted_price_input])
analyze_fragrantica_button.click(analyze_fragrantica_url,
inputs=[fragrantica_url_input, openai_key_input, natura_token_input, openai_base_url_input, openai_model_name_input],
outputs=fragrantica_output)
gen_image_btn.click(generate_image,
inputs=[image_product_url_input, image_product_name_input, image_original_price_input, image_final_price_input, image_coupon_code_input, template_selection],
outputs=[gen_image_btn, image_output, share_button])
share_button.click(fn=process_image_for_sharing,
inputs=[image_output],
outputs=[base64_debug_output])
base64_debug_output.change(fn=None,
inputs=[base64_debug_output],
js=js_share_logic)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
|