File size: 7,062 Bytes
3d2214e
 
 
 
 
 
 
 
 
d17746a
 
 
 
 
 
 
 
 
 
 
 
 
3d2214e
 
 
 
 
 
 
 
 
 
 
 
 
d17746a
 
 
 
 
 
3d2214e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba3f155
 
 
 
 
 
3d2214e
 
 
 
 
 
 
 
 
 
 
 
ba3f155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d2214e
 
d17746a
 
 
 
3d2214e
 
 
 
 
d17746a
3d2214e
 
 
 
d17746a
3d2214e
 
 
d17746a
3d2214e
 
 
 
 
d17746a
3d2214e
 
 
 
 
 
 
 
 
 
 
 
ba3f155
3d2214e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba3f155
3d2214e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import openai
import gradio as gr
from bs4 import BeautifulSoup
import requests

openai.api_key = os.getenv("OPENAI_API_KEY")

def extract_text_from_url(url):
    try:
        resp = requests.get(url, timeout=30, headers={
            "User-Agent": "Mozilla/5.0 (compatible; Bot/1.0)"
        })
        soup = BeautifulSoup(resp.content, "html.parser")
        candidates = soup.find_all(['h1','h2','h3','h4','p','span','li'])
        text = ' '.join([c.get_text(strip=True) for c in candidates])
        text = text[:4000]
        if len(text) < 100:
            raise ValueError("Could not extract enough content (site may require JavaScript). Please enter keywords manually.")
        return text
    except Exception as e:
        raise ValueError(f"URL extraction error: {e}")

def extract_keywords(text):
    prompt = f"""
    Extract up to 10 concise, relevant SEO keywords suitable for an automotive advertisement from the following content:
    {text}
    Keywords:
    """
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.6,
        max_tokens=100
    )
    output = response.choices[0].message.content.strip()
    if ',' in output:
        keywords = output.split(',')
    else:
        keywords = output.split('\n')
    return [kw.strip() for kw in keywords if kw.strip()]

def generate_ad_copy(platform, keywords):
    prompt = f"""
    Create a compelling, SEO-optimized {platform} ad using these keywords: {', '.join(keywords)}. 
    Include a clear and enticing call-to-action.
    """
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.7,
        max_tokens=300
    )
    return response.choices[0].message.content.strip()

def generate_ad_image(keywords):
    kw_str = ", ".join(keywords)
    # Enhanced prompt for better visuals
    image_prompt = (
        f"High-quality, photorealistic automotive ad photo of a luxury car. "
        f"Clean background, professional lighting, stylish dealership setting. "
        f"Keywords: {kw_str}. Room for text overlay, wide format, visually appealing."
    )
    response = openai.Image.create(
        prompt=image_prompt,
        n=1,
        size="512x512"
    )
    image_url = response["data"][0]["url"]
    img_data = requests.get(image_url).content
    img_file = "generated_ad_image.png"
    with open(img_file, "wb") as f:
        f.write(img_data)
    return img_file

def platform_html(platform, ad_text):
    # Platform-specific color and icons
    if platform == "Facebook":
        color = "#1877F2"
        icon = "🌐"
    elif platform == "Instagram":
        # Instagram gradient
        color = "linear-gradient(90deg, #f58529 0%, #dd2a7b 50%, #8134af 100%)"
        icon = "πŸ“Έ"
    elif platform == "X (Twitter)":
        color = "#14171A"
        icon = "🐦"
    else: # Google Search
        color = "#4285F4"
        icon = "πŸ”"

    if platform == "Instagram":
        # Gradient needs to be on a child div (not background-color)
        content = f"""
        <div style="background: {color}; padding: 2px; border-radius: 12px; margin-bottom:16px;">
            <div style="background: white; color: #333; padding: 18px 20px; border-radius: 10px;">
                <span style="font-size: 1.5em;">{icon} <b>{platform}</b></span>
                <div style="margin-top: 12px; font-size: 1.1em; line-height:1.6;">{ad_text}</div>
            </div>
        </div>
        """
    else:
        content = f"""
        <div style="background: {color}; color: white; padding: 18px 20px; border-radius: 12px; margin-bottom:16px; min-height: 120px;">
            <span style="font-size: 1.5em;">{icon} <b>{platform}</b></span>
            <div style="margin-top: 12px; font-size: 1.1em; line-height:1.6;">{ad_text}</div>
        </div>
        """
    return content

def main_workflow(input_mode, url_or_keywords):
    error = None
    keywords = []
    ad_copies = {}
    image_path = None

    if input_mode == "URL":
        try:
            text = extract_text_from_url(url_or_keywords)
            keywords = extract_keywords(text)
        except Exception as e:
            return None, None, None, f"{e}"
    else:
        keywords = [kw.strip() for kw in url_or_keywords.split(",") if kw.strip()]
        if not keywords:
            return None, None, None, "Please provide at least one keyword."
    # Generate ad copies
    platforms = ["Facebook", "Instagram", "X (Twitter)", "Google Search"]
    for platform in platforms:
        ad_copies[platform] = generate_ad_copy(platform, keywords)
    # Generate image
    try:
        image_path = generate_ad_image(keywords)
    except Exception as e:
        error = f"Image generation error: {e}"

    # Save ads to txt
    output_txt = "generated_ads.txt"
    with open(output_txt, "w", encoding="utf-8") as f:
        for platform, content in ad_copies.items():
            f.write(f"--- {platform} Ad Copy ---\n{content}\n\n")
    return keywords, ad_copies, image_path, error

def run_space(input_mode, url, keywords):
    url_or_keywords = url if input_mode == "URL" else keywords
    keywords, ad_copies, image_path, error = main_workflow(input_mode, url_or_keywords)
    ad_previews = ""
    if ad_copies:
        for platform, ad in ad_copies.items():
            ad_previews += platform_html(platform, ad)
    return (
        keywords,
        ad_previews,
        image_path,
        "generated_ads.txt" if ad_copies else None,
        error
    )

with gr.Blocks() as demo:
    gr.Markdown("# πŸš— Auto Ad Generator\nPaste a car listing URL **or** enter your own keywords, then preview AI-generated ads for each social media platform, plus an auto-generated image!")
    input_mode = gr.Radio(["URL", "Keywords"], value="URL", label="Input Type")
    url_input = gr.Textbox(label="Listing URL", placeholder="https://www.cars.com/listing/...", visible=True)
    kw_input = gr.Textbox(label="Manual Keywords (comma separated)", placeholder="e.g. BMW, used car, sunroof", visible=False)
    submit_btn = gr.Button("Generate Ads")

    gr.Markdown("## Keywords")
    kw_out = gr.JSON(label="Extracted/Provided Keywords")

    gr.Markdown("## Ad Copy Previews")
    ad_out = gr.HTML(label="Ad Copy Preview")   # Now HTML, not Markdown

    gr.Markdown("## Generated Ad Image")
    img_out = gr.Image(label="Generated Ad Image", type="filepath")

    gr.Markdown("## Download Ad Copies")
    file_out = gr.File(label="Download TXT")

    err_out = gr.Textbox(label="Errors", interactive=False)

    def show_hide_fields(choice):
        return (
            gr.update(visible=choice == "URL"),
            gr.update(visible=choice == "Keywords"),
        )

    input_mode.change(show_hide_fields, input_mode, [url_input, kw_input])

    submit_btn.click(
        run_space,
        inputs=[input_mode, url_input, kw_input],
        outputs=[kw_out, ad_out, img_out, file_out, err_out]
    )

demo.launch()