Blogger-Toolkit / app.py
lexicalspace's picture
Update app.py
80ffb94 verified
raw
history blame
6.68 kB
import streamlit as st
import streamlit.components.v1 as components
import re
from bs4 import BeautifulSoup
import markdown
from PIL import Image
import io
# --- PAGE CONFIG ---
st.set_page_config(
page_title="Lexical Tools",
page_icon="⚡",
layout="centered",
initial_sidebar_state="expanded"
)
# --- SIDEBAR ---
st.sidebar.title("Navigation")
query_params = st.query_params
default_index = 1 if query_params.get("mode") == "downloader" else 0
app_mode = st.sidebar.radio(
"Choose Tool:",
["Webmaster Toolkit", "YouTube Downloader"],
index=default_index
)
# ==========================================
# VIEW 1: YOUTUBE DOWNLOADER (Client-Side JS)
# ==========================================
if app_mode == "YouTube Downloader":
st.title("🎥 YouTube Media Extractor")
st.caption("🚀 Client-Side Mode: Runs on your browser (No Server Blocks)")
# Input Fields
url = st.text_input("Paste YouTube URL", placeholder="https://youtube.com/watch?v=...")
col1, col2 = st.columns(2)
with col1:
is_audio = st.toggle("Audio Only (MP3)", value=False)
# We pass these variables into the HTML/JS block below
mode_str = "audio" if is_audio else "auto"
if url:
st.info("👇 Click the button below to process.")
# --- THE MAGIC JAVASCRIPT BLOCK ---
# This HTML runs in the user's browser, bypassing the server completely.
html_code = f"""
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: sans-serif; color: white; background: transparent; }}
.btn {{
background: #FF4B4B; color: white; border: none; padding: 12px 24px;
border-radius: 8px; font-size: 16px; cursor: pointer; width: 100%;
transition: 0.3s; font-weight: bold;
}}
.btn:hover {{ background: #FF2B2B; }}
.btn:disabled {{ background: #555; cursor: not-allowed; }}
.result {{ margin-top: 15px; padding: 10px; border-radius: 5px; display: none; }}
.success {{ background: #1E3A2F; border: 1px solid #2ecc71; color: #2ecc71; }}
.error {{ background: #3A1E1E; border: 1px solid #e74c3c; color: #e74c3c; }}
a {{ color: white; text-decoration: none; display: block; padding: 10px; background: #2ecc71; border-radius: 5px; text-align: center; }}
</style>
</head>
<body>
<button id="procBtn" class="btn" onclick="fetchMedia()">🚀 Process Media</button>
<div id="status" class="result"></div>
<script>
async function fetchMedia() {{
const btn = document.getElementById('procBtn');
const status = document.getElementById('status');
btn.disabled = true;
btn.innerText = "⏳ Processing...";
status.style.display = "none";
// The Payload
const data = {{
url: "{url}",
downloadMode: "{mode_str}",
videoQuality: "1080"
}};
try {{
// We use a public instance that allows CORS (Browser access)
const response = await fetch("https://co.wuk.sh/api/json", {{
method: "POST",
headers: {{
"Accept": "application/json",
"Content-Type": "application/json"
}},
body: JSON.stringify(data)
}});
const result = await response.json();
if (result.url) {{
status.className = "result success";
status.innerHTML = `
<strong>✅ Success!</strong><br><br>
<a href="${{result.url}}" target="_blank">⬇️ Click to Download</a>
`;
status.style.display = "block";
btn.innerText = "🚀 Process Another";
}} else {{
throw new Error(result.text || "Unknown error");
}}
}} catch (err) {{
status.className = "result error";
status.innerText = "Error: " + err.message;
status.style.display = "block";
btn.innerText = "❌ Retry";
}}
btn.disabled = false;
}}
</script>
</body>
</html>
"""
# Inject the HTML/JS into the Streamlit app
components.html(html_code, height=250)
# ==========================================
# VIEW 2: WEBMASTER TOOLKIT (Server Side)
# ==========================================
elif app_mode == "Webmaster Toolkit":
st.title("⚡ Webmaster's Toolkit")
tab1, tab2 = st.tabs(["📝 Text Cleaner & SEO", "🖼️ Media Optimizer"])
with tab1:
st.write("Paste your raw text or messy HTML below.")
raw_text = st.text_area("Input Text", height=200)
c1, c2, c3 = st.columns(3)
processed_text = ""
if c1.button("Strip HTML"):
soup = BeautifulSoup(raw_text, "html.parser")
processed_text = soup.get_text(separator=" ")
if c2.button("Fix Spacing"):
processed_text = re.sub(r'\s+', ' ', raw_text).strip()
if c3.button("MD to HTML"):
processed_text = markdown.markdown(raw_text)
if processed_text:
st.success("Done!")
st.text_area("Result", value=processed_text, height=200)
with tab2:
st.write("Convert heavy images to WebP.")
uploaded_file = st.file_uploader("Upload Image", type=['png', 'jpg', 'jpeg'])
if uploaded_file:
original_image = Image.open(uploaded_file)
st.image(original_image, caption="Original", use_container_width=True)
if st.button("Convert to WebP"):
buffer = io.BytesIO()
original_image.save(buffer, format="WEBP", quality=80, optimize=True)
buffer.seek(0)
st.success("Converted!")
st.download_button("Download WebP", data=buffer, file_name="image.webp")