Spaces:
Sleeping
Sleeping
File size: 5,520 Bytes
d343201 06d3276 86368f8 6b7bfdd 06d3276 83c8c73 d343201 83c8c73 d343201 83c8c73 d343201 83c8c73 06d3276 f9e7cf4 06d3276 d465b34 06d3276 d465b34 06d3276 d465b34 06d3276 d465b34 06d3276 d465b34 d24e71f 06d3276 d24e71f 06d3276 d24e71f 2f38435 d343201 d24e71f 6b7bfdd d24e71f 06d3276 d465b34 06d3276 d465b34 06d3276 83c8c73 d343201 fa7a61e 86368f8 1606dca f9e7cf4 86368f8 f9e7cf4 1606dca 86368f8 61c4d2f 83c8c73 d343201 83c8c73 d343201 06d3276 d343201 83c8c73 d343201 83c8c73 d343201 |
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 |
from shiny import reactive, render, ui
import os
import requests
from dotenv import load_dotenv
from bs4 import BeautifulSoup
import subprocess
import time
from llm_connect import get_response
load_dotenv()
PAGE_ID = os.getenv("FB_PAGE_ID")
ACCESS_TOKEN = os.getenv("FB_PAGE_ACCESS_TOKEN")
generated_fb_post = reactive.Value("")
def scrape_shopify_blog(url: str) -> str:
try:
resp = requests.get(url, timeout=10)
soup = BeautifulSoup(resp.content, 'html.parser')
section = soup.find(
'div',
class_='w940 align-center size-content'
)
return section.get_text(strip=True, separator=' ') if section else ""
except Exception as e:
return f"❌ Error scraping blog: {e}"
def generate_facebook_post(topic: str = "", url: str = "", min_len: int = 500, max_len: int = 1000) -> str:
# Handle blog scraping
if url:
scraped = scrape_shopify_blog(url)
if scraped.startswith("❌") or not scraped.strip():
return f"⚠️ Failed to extract blog content from URL: {url}"
prompt = (
f"You are a social media manager for a hobby e-commerce company called 'Ultima Supply'.\n"
f"Write a detailed, engaging Facebook post (min {min_len} characters, max {max_len} characters) summarizing the following Shopify blog:\n\n"
f"{scraped}\n\n"
f"The post MUST include this exact URL: {url}\n"
f"Use a casual, friendly tone with emojis.\n"
f"VERY IMPORTANT: The post MUST include exactly 5 to 10 SEO-relevant hashtags at the end.\n"
f"Do not include hashtags inline — list them as a group at the end of the post.\n"
f"Keep everything under {max_len} characters total."
)
elif topic:
prompt = (
f"You are a social media manager for a hobby e-commerce company called 'Ultima Supply'.\n"
f"Write a short, engaging Facebook post (min {min_len} characters, max {max_len} characters) about: '{topic}'.\n"
f"Use a casual, friendly tone with fun emojis.\n"
f"VERY IMPORTANT: Include exactly 5 to 10 SEO-relevant hashtags grouped at the end of the post.\n"
f"Do NOT place hashtags inline — they must be in a clean list at the end.\n"
f"The entire post must be under {max_len} characters total."
)
else:
return "⚠️ Provide either a topic or a Shopify blog URL."
# Step 1: Generate initial post
post = get_response(
input=prompt,
template=lambda x: x.strip(),
llm="gemini",
md=False,
temperature=0.9,
max_tokens=250
).strip()
if len(post) <= max_len:
return post
time.sleep(5)
# Step 2: Shorten if needed
shorten_prompt = (
f"Shorten this Facebook post to {max_len} characters or fewer.\n"
f"You MUST keep the Shopify blog link ({url}) and all original hashtags:\n\n{post}"
if url else
f"Shorten this Facebook post to {max_len} characters or fewer, keeping the tone, emojis, and all original hashtags:\n\n{post}"
)
shortened = get_response(
input=shorten_prompt,
template=lambda x: x.strip(),
llm="gemini",
md=False,
temperature=0.7,
max_tokens=200
).strip()
return shortened[:max_len]
def post_to_facebook(message: str) -> str:
proxy_url = "https://facebook-proxy.onrender.com/post-to-facebook" # your actual deployed Render URL
try:
res = requests.post(proxy_url, json={"message": message}, timeout=10)
res.raise_for_status()
data = res.json()
# Safely handle both proxy success and raw Facebook responses
if isinstance(data, dict):
if "status" in data and data["status"] == "success":
return f"✅ Post successful! Facebook Post ID: {data.get('post_id', 'unknown')}"
elif "id" in data or "post_id" in data:
post_id = data.get("post_id") or data.get("id")
return f"✅ Post successful! Facebook Post ID: {post_id}"
elif "error" in data:
return f"❌ Facebook error: {data['error']}"
return f"⚠️ Unexpected response: {data}"
except requests.RequestException as e:
return f"❌ Network or proxy error: {e}"
except Exception as e:
return f"❌ Unexpected error: {e}"
def server(input, output, session):
post_status = reactive.Value("")
@output
@render.ui
@reactive.event(input.gen_btn_fb)
def fb_post_draft():
topic = input.fb_topic().strip()
url = input.fb_url().strip()
if not topic and not url:
return ui.HTML("<p><strong>⚠️ Enter a topic or a blog URL.</strong></p>")
post = generate_facebook_post(topic=topic, url=url)
if post.startswith("⚠️") or post.startswith("❌"):
return ui.HTML(f"<p><strong>{post}</strong></p>")
generated_fb_post.set(post)
return ui.HTML(f"<p><strong>Generated Facebook Post:</strong><br>{post}</p>")
@output
@render.text
def fb_post_status():
return post_status()
@reactive.effect
@reactive.event(input.post_btn_fb)
def _():
post = generated_fb_post()
if not post:
post_status.set("⚠️ No post generated yet.")
else:
result = post_to_facebook(post)
post_status.set(result)
|