import os import warnings import logging # Suppress technical initialization warnings from Torch/Transformers/HF os.environ["TORCH_LOGS"] = "-all" os.environ["TORCH_CPP_LOG_LEVEL"] = "3" os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" os.environ["HUGGINGFACE_HUB_VERBOSITY"] = "error" warnings.filterwarnings("ignore", message=".*torch.classes.*") logging.getLogger("torch").setLevel(logging.ERROR) import streamlit as st # Page Config must be first Streamlit command st.set_page_config( page_title="AutoContentForge AI", page_icon="⚒️", layout="wide", initial_sidebar_state="expanded", ) from streamlit_calendar import calendar from forge_utils import ContentExtractor, ForgeAI # Initialize ForgeAI with caching @st.cache_resource def get_forge(): return ForgeAI() forge = get_forge() # Session State for Content if 'forge_results' not in st.session_state: st.session_state.forge_results = None if 'extracted_content' not in st.session_state: st.session_state.extracted_content = None # Custom CSS for Premium Look st.markdown(""" """, unsafe_allow_html=True) # Sidebar Branding & Pro CTA with st.sidebar: st.title("⚒️ AutoContentForge AI") st.caption("Automate Your Content. Forge Every Platform.") st.markdown("---") st.markdown(""" """, unsafe_allow_html=True) if st.button("Contact for Pro Version", use_container_width=True): st.info("Email: rajue@smackcoders.com with subject 'AutoContentForge AI Pro Inquiry'") st.markdown("---") st.markdown("### Resources") st.markdown("[Documentation](#)") st.markdown("[Pricing](#)") st.markdown("[YouTube Channel](#)") # Main Navigation Tabs tab1, tab2, tab3 = st.tabs([ "📝 Single Post", "📦 Bulk Posting", "⚙️ Admin Settings" ]) # Initialize session states for the new workflow if 'master_variations' not in st.session_state: st.session_state.master_variations = None if 'selected_variation' not in st.session_state: st.session_state.selected_variation = None if 'current_hashtags' not in st.session_state: st.session_state.current_hashtags = "" # Module 1: Single Post with tab1: st.header("📝 Create Single Social Post") st.write("Fetch from a URL or use the manual editor to forge your master variations.") col_in, col_out = st.columns([1, 1.2]) with col_in: st.subheader("1. Source Content") input_mode = st.radio( "Input Mode", ["URL Fetch", "Manual Editor"], horizontal=True, help="Choose 'URL Fetch' to extract content from a website, or 'Manual Editor' to paste your own text directly." ) if input_mode == "URL Fetch": source_url = st.text_input( "Enter Content URL", placeholder="https://example.com/blog-post", help="Paste the full link (including https://) of the article or blog post you want to repurpose." ) if st.button("🚀 Fetch & Analyze"): if not source_url or "://" not in source_url: st.error("Please enter a valid URL (including https://)") else: with st.spinner("Forging 3 master variations..."): extracted = ContentExtractor.from_url(source_url) if "error" in extracted: st.error(extracted["error"]) else: st.session_state.extracted_content = extracted st.session_state.master_variations = forge.generate_master_variations(extracted['text']) st.session_state.current_hashtags = forge.extract_hashtags(extracted['text']) st.session_state.selected_variation = None # Reset selection st.success("Successfully generated 3 variations!") else: pasted_title = st.text_input("Post Title (Optional)", help="Give your post a title for easier tracking.") pasted_text = st.text_area( "Master Content / Article Text", height=200, help="Paste the core content you want to turn into social posts. Aim for at least 50 words for the best AI results." ) if st.button("✨ Generate Variations"): if len(pasted_text) < 50: st.warning("Please provide more content for better AI results.") else: with st.spinner("Processing..."): st.session_state.extracted_content = {"title": pasted_title or "Manual Input", "text": pasted_text} st.session_state.master_variations = forge.generate_master_variations(pasted_text) st.session_state.current_hashtags = forge.extract_hashtags(pasted_text) st.session_state.selected_variation = None st.success("Variations generated!") if st.session_state.master_variations: st.markdown("---") st.subheader("2. Choose Master Variation") st.info("💡 **Tip:** Each variation has a different tone. Expand them to see which one fits your brand voice best.") for var in st.session_state.master_variations: with st.expander(f"🔹 {var['type']}", expanded=(st.session_state.selected_variation == var['id'])): st.write(var['text']) if st.button(f"Select {var['type']}", key=f"sel_{var['id']}", help=f"Choose the {var['type']} to be adapted for your social networks."): st.session_state.selected_variation = var['id'] st.rerun() with col_out: st.subheader("3. Preview & Adapt") if not st.session_state.selected_variation: st.info("Select a master variation on the left to see platform-specific previews.") else: selected_var_obj = next(v for v in st.session_state.master_variations if v['id'] == st.session_state.selected_variation) platforms = st.multiselect( "Select Social Networks", ["LinkedIn", "Twitter/X", "Instagram", "Facebook", "YouTube", "Bluesky"], default=["LinkedIn", "Twitter/X"], help="Choose which platforms you want to generate previews for. The AI will format your selected variation for each." ) if st.session_state.extracted_content.get("images"): st.image(st.session_state.extracted_content['images'][0], caption="Extracted Media", width=300) else: st.write("📸 *No media found. You can add media in the Pro version or manual editor.*") st.markdown("---") for platform in platforms: adapted_text = forge.adapt_for_platform(selected_var_obj['text'], platform, st.session_state.current_hashtags) with st.container(): st.markdown(f"""
{platform} Preview

{adapted_text if isinstance(adapted_text, str) else adapted_text.get('title')}

""", unsafe_allow_html=True) if isinstance(adapted_text, dict) and platform == "YouTube": st.caption(f"Description: {adapted_text.get('description')}") if st.button("📅 Post / Schedule Now", type="primary"): st.success("✅ Successfully queued! (Flow simulation)") st.balloons() st.info("🔒 In Pro: This would instantly publish or sync to your drag-and-drop calendar.") # Module 2: Bulk Posting with tab2: st.header("📦 Bulk URL Posting") st.write("Forge content from multiple URLs at once. Perfect for content migration or high-volume publishing.") bulk_urls = st.text_area( "List of URLs (one per line)", height=250, placeholder="https://site.com/post-1\nhttps://site.com/post-2", help="Enter a list of blog post links. In the Pro version, the AI will process all of them in one batch." ) st.markdown("""
Pro Feature Highlights:
• Automatic batch processing of sitemaps
• Intelligent image matching for bulk lists
• Scheduled intervals (e.g., 1 post every 2 hours)
• CSV / JSON Export for external schedulers
""", unsafe_allow_html=True) st.button("🚀 Process Bulk List", disabled=True, help="This feature is exclusive to the Pro version.") st.markdown("---") if st.button("Unlock Bulk & Automation", key="bulk_pro", help="Contact us to upgrade to the full self-hosted version."): st.info("Email: rajue@smackcoders.com with subject 'AutoContentForge AI Pro Inquiry'") # Module 3: Admin Settings with tab3: st.header("⚙️ Admin Settings") st.write("Authorize and manage your social network connections.") networks = [ {"name": "LinkedIn", "icon": "👔"}, {"name": "Twitter/X", "icon": "🐦"}, {"name": "Instagram", "icon": "📸"}, {"name": "Facebook", "icon": "👥"}, {"name": "YouTube", "icon": "🎥"}, {"name": "Bluesky", "icon": "🦋"} ] cols = st.columns(3) for i, net in enumerate(networks): with cols[i % 3]: st.markdown(f"### {net['icon']} {net['name']}") st.button(f"Authorize {net['name']}", key=f"auth_btn_{net['name']}", help=f"Connect your {net['name']} account via OAuth for direct posting.") st.caption(f"Status: Not Connected") st.markdown("---") st.subheader("Global Settings") st.checkbox("Auto-add smart hashtags to all posts", value=True, help="Automatically suggest and append hashtags based on content analysis.") st.checkbox("Notify me on successful publishing", value=True, help="Send a notification once a post is live on the selected platform.") st.selectbox("Default AI Tone", ["Professional", "Conversational", "Exciting", "Detailed"], help="Select the default voice for your AI-generated master variations.") if st.button("Save Settings", help="Save your preferences for future sessions."): st.success("Settings saved locally! (Simulation)")