From 3a871d4de0f7ccd4ba61c5609179cf9a2b9677a2 Mon Sep 17 00:00:00 2001 From: ajaysi Date: Wed, 16 Apr 2025 19:31:51 +0530 Subject: [PATCH] Getting the twitter dashboard working. --- .../twitter_writers/twitter_dashboard.py | 513 +++++++----------- .../components/ai_research_setup.py | 8 - .../components/website_setup.py | 2 +- 3 files changed, 192 insertions(+), 331 deletions(-) diff --git a/lib/ai_writers/twitter_writers/twitter_dashboard.py b/lib/ai_writers/twitter_writers/twitter_dashboard.py index d69032ee..64bd3f4c 100644 --- a/lib/ai_writers/twitter_writers/twitter_dashboard.py +++ b/lib/ai_writers/twitter_writers/twitter_dashboard.py @@ -1,342 +1,211 @@ import streamlit as st -import re +import streamlit.components.v1 as components +from typing import Dict, List import json -import time -from typing import Dict, List, Tuple, Optional -import random -import emoji -from datetime import datetime -from ....gpt_providers.text_generation.main_text_generation import llm_text_gen +from .tweet_generator import smart_tweet_generator -# Constants -MAX_TWEET_LENGTH = 280 -EMOJI_CATEGORIES = { - "Humorous": ["😄", "😂", "ðŸĪĢ", "😊", "😉", "😎", "ðŸĪŠ", "😜", "ðŸĪ“", "😇"], - "Informative": ["📚", "📊", "📈", "🔍", "ðŸ’Ą", "📝", "📋", "🔎", "📖", "📑"], - "Inspirational": ["âœĻ", "🌟", "ðŸ’Ŧ", "⭐", "ðŸ”Ĩ", "💊", "🙌", "👏", "ðŸ’Ŋ", "ðŸŽŊ"], - "Serious": ["ðŸĪ”", "💭", "🧐", "ðŸ“Ē", "🔔", "⚖ïļ", "🎓", "📊", "🔎", "📰"], - "Casual": ["👋", "👍", "🙋", "💁", "ðŸĪ—", "👌", "✌ïļ", "ðŸĪ", "👊", "🙏"] -} - -def count_characters(text: str) -> int: - """Count characters in tweet, accounting for emojis.""" - return len(text) - -def extract_hashtags(text: str) -> List[str]: - """Extract hashtags from tweet text.""" - return re.findall(r'#\w+', text) - -def suggest_hashtags(topic: str, tone: str) -> List[str]: - """Suggest relevant hashtags based on topic and tone.""" - # Enhanced hashtag suggestions based on topic and tone - base_hashtags = { - "professional": ["#Business", "#Leadership", "#Innovation"], - "casual": ["#Life", "#Fun", "#Trending"], - "informative": ["#Learn", "#Tips", "#HowTo"], - "humorous": ["#Funny", "#LOL", "#Humor"], - "inspirational": ["#Motivation", "#Success", "#Growth"] - } - - topic_hashtags = { - "tech": ["#Technology", "#TechNews", "#Innovation"], - "business": ["#Business", "#Entrepreneurship", "#Startup"], - "marketing": ["#Marketing", "#DigitalMarketing", "#SocialMedia"], - "education": ["#Education", "#Learning", "#Knowledge"], - "health": ["#Health", "#Wellness", "#Fitness"] - } - - # Combine base and topic hashtags - suggested = base_hashtags.get(tone.lower(), []) + topic_hashtags.get(topic.lower(), []) - return list(set(suggested))[:5] # Return unique hashtags, max 5 - -def suggest_emojis(tone: str, count: int = 3) -> List[str]: - """Suggest emojis based on tone.""" - emoji_map = { - "professional": ["💞", "📊", "ðŸŽŊ", "ðŸ’Ą", "📈"], - "casual": ["😊", "👍", "🙌", "âœĻ", "🌟"], - "informative": ["📚", "🔍", "ðŸ’Ą", "📝", "🎓"], - "humorous": ["😄", "😂", "ðŸĪĢ", "😉", "😎"], - "inspirational": ["âœĻ", "🌟", "ðŸ’Ŧ", "ðŸ”Ĩ", "💊"] - } - return emoji_map.get(tone.lower(), ["âœĻ"])[:count] - -def predict_tweet_performance(tweet: str, target_audience: str, tone: str) -> Dict: - """Predict tweet performance with enhanced metrics.""" - char_count = count_characters(tweet) - hashtags = extract_hashtags(tweet) - - # Enhanced performance metrics - metrics = { - "character_count": { - "score": min(100, (char_count / 280) * 100), - "status": "optimal" if 100 <= char_count <= 200 else "suboptimal", - "suggestion": "Consider adjusting length for optimal engagement" if char_count < 100 or char_count > 200 else "Length is optimal" - }, - "hashtag_usage": { - "score": min(100, (len(hashtags) / 3) * 100), - "status": "optimal" if 1 <= len(hashtags) <= 3 else "suboptimal", - "suggestion": "Add more hashtags" if len(hashtags) < 1 else "Reduce hashtag count" if len(hashtags) > 3 else "Hashtag count is optimal" - }, - "engagement_potential": { - "score": 0, - "status": "needs_improvement", - "suggestion": "" - }, - "audience_alignment": { - "score": 0, - "status": "needs_improvement", - "suggestion": "" - } - } - - # Calculate engagement potential - engagement_triggers = ["?", "!", "RT", "like", "follow", "check", "learn", "discover"] - trigger_count = sum(1 for trigger in engagement_triggers if trigger.lower() in tweet.lower()) - metrics["engagement_potential"]["score"] = min(100, (trigger_count / 3) * 100) - metrics["engagement_potential"]["status"] = "optimal" if trigger_count >= 1 else "needs_improvement" - metrics["engagement_potential"]["suggestion"] = "Add engagement triggers" if trigger_count < 1 else "Good engagement potential" - - # Calculate audience alignment - audience_keywords = { - "professionals": ["business", "industry", "professional", "career"], - "students": ["learn", "study", "education", "student"], - "general": ["everyone", "people", "community", "world"] - } - keyword_count = sum(1 for keyword in audience_keywords.get(target_audience.lower(), []) - if keyword.lower() in tweet.lower()) - metrics["audience_alignment"]["score"] = min(100, (keyword_count / 2) * 100) - metrics["audience_alignment"]["status"] = "optimal" if keyword_count >= 1 else "needs_improvement" - metrics["audience_alignment"]["suggestion"] = "Add audience-specific keywords" if keyword_count < 1 else "Good audience alignment" - - # Calculate overall score - overall_score = sum(metric["score"] for metric in metrics.values()) / len(metrics) - +def load_feature_data() -> Dict: + """Load feature data from a structured format.""" return { - "metrics": metrics, - "overall_score": overall_score, - "status": "excellent" if overall_score >= 80 else "good" if overall_score >= 60 else "fair" if overall_score >= 40 else "needs_improvement" + "tweet_generation": { + "title": "Tweet Generation & Optimization", + "icon": "ðŸĶ", + "description": "Create and optimize engaging tweets with AI assistance", + "features": [ + { + "name": "Smart Tweet Generator", + "description": "Generate multiple tweet variations with optimal character count, hashtags, and emojis", + "status": "active", + "icon": "âœĻ", + "function": smart_tweet_generator + }, + { + "name": "Tweet Performance Predictor", + "description": "Predict engagement rates and best posting times for maximum impact", + "status": "coming_soon", + "icon": "📊" + } + ] + }, + "content_strategy": { + "title": "Content Strategy Tools", + "icon": "📅", + "description": "Plan and manage your Twitter content strategy effectively", + "features": [ + { + "name": "Content Calendar Generator", + "description": "Create weekly/monthly content plans with theme-based scheduling", + "status": "coming_soon", + "icon": "🗓ïļ" + }, + { + "name": "Hashtag Strategy Manager", + "description": "Research and manage trending hashtags for better reach", + "status": "coming_soon", + "icon": "#ïļâƒĢ" + } + ] + }, + "visual_content": { + "title": "Visual Content Creation", + "icon": "ðŸŽĻ", + "description": "Create engaging visual content for your tweets", + "features": [ + { + "name": "Image Generator", + "description": "Create tweet cards, infographics, and quote designs", + "status": "coming_soon", + "icon": "🖞ïļ" + }, + { + "name": "Video Content Assistant", + "description": "Generate video scripts and optimize captions", + "status": "coming_soon", + "icon": "ðŸŽĨ" + } + ] + }, + "engagement": { + "title": "Engagement & Community", + "icon": "ðŸĪ", + "description": "Manage and enhance community engagement", + "features": [ + { + "name": "Reply Generator", + "description": "Generate context-aware responses with appropriate tone", + "status": "coming_soon", + "icon": "💎" + }, + { + "name": "Community Tools", + "description": "Create polls and plan Q&A sessions", + "status": "coming_soon", + "icon": "ðŸ‘Ĩ" + } + ] + }, + "analytics": { + "title": "Analytics & Optimization", + "icon": "📈", + "description": "Track performance and optimize your Twitter strategy", + "features": [ + { + "name": "Performance Analytics", + "description": "Track tweet performance and engagement metrics", + "status": "coming_soon", + "icon": "📊" + }, + { + "name": "A/B Testing Assistant", + "description": "Test and optimize tweet variations for better results", + "status": "coming_soon", + "icon": "🔍" + } + ] + }, + "research": { + "title": "Research & Intelligence", + "icon": "🔎", + "description": "Gain insights and stay ahead of trends", + "features": [ + { + "name": "Market Research", + "description": "Analyze competitors and track industry trends", + "status": "coming_soon", + "icon": "📊" + }, + { + "name": "Content Inspiration", + "description": "Get trending topic suggestions and content ideas", + "status": "coming_soon", + "icon": "ðŸ’Ą" + } + ] + } } -def generate_tweet_variations( - hook: str, - target_audience: str, - tone: str, - call_to_action: str = "", - keywords: str = "", - length: str = "medium", - num_variations: int = 3 -) -> List[Dict]: - """Generate multiple tweet variations with enhanced AI suggestions.""" - # Enhanced prompt template for better AI suggestions - prompt_template = f""" - Create {num_variations} engaging tweet variations with the following parameters: - - Hook/Topic: {hook} - - Target Audience: {target_audience} - - Tone: {tone} - - Call to Action: {call_to_action} - - Keywords: {keywords} - - Length: {length} - - Each tweet should: - 1. Start with an attention-grabbing hook - 2. Include relevant hashtags - 3. Use appropriate emojis - 4. End with a clear call-to-action - 5. Stay within Twitter's character limit - 6. Match the specified tone and audience - - Format each tweet as a JSON object with: - - text: The tweet content - - hashtags: List of suggested hashtags - - emojis: List of suggested emojis - - engagement_score: Predicted engagement score (0-100) - """ - - # Simulate AI-generated tweets (replace with actual AI call) - sample_tweets = [ - { - "text": f"🚀 {hook} #Innovation #Tech", - "hashtags": ["#Innovation", "#Tech"], - "emojis": ["🚀"], - "engagement_score": 85 - }, - { - "text": f"ðŸ’Ą {hook} #Business #Growth", - "hashtags": ["#Business", "#Growth"], - "emojis": ["ðŸ’Ą"], - "engagement_score": 75 - }, - { - "text": f"âœĻ {hook} #Success #Leadership", - "hashtags": ["#Success", "#Leadership"], - "emojis": ["âœĻ"], - "engagement_score": 80 - } - ] - - return sample_tweets[:num_variations] - -def suggest_improvements(tweet: str, performance: Dict) -> List[str]: - """Generate actionable improvement suggestions.""" - suggestions = [] - metrics = performance["metrics"] - - # Character count suggestions - if metrics["character_count"]["status"] == "suboptimal": - suggestions.append(f"📝 {metrics['character_count']['suggestion']}") - - # Hashtag suggestions - if metrics["hashtag_usage"]["status"] == "suboptimal": - suggestions.append(f"#ïļâƒĢ {metrics['hashtag_usage']['suggestion']}") - - # Engagement suggestions - if metrics["engagement_potential"]["status"] == "needs_improvement": - suggestions.append(f"ðŸŽŊ {metrics['engagement_potential']['suggestion']}") - - # Audience alignment suggestions - if metrics["audience_alignment"]["status"] == "needs_improvement": - suggestions.append(f"ðŸ‘Ĩ {metrics['audience_alignment']['suggestion']}") - - return suggestions - -def render_tweet_card(tweet: Dict, index: int) -> None: - """Render an enhanced tweet card with interactive elements.""" +def render_feature_card(feature: Dict) -> None: + """Render a single feature card with its details.""" with st.container(): st.markdown(f"""
-

Tweet Variation {index + 1}

-

{tweet['text']}

-
- - Score: {tweet['engagement_score']}% - -
+

{feature['icon']} {feature['name']}

+

{feature['description']}

+ + {feature['status'].title()} +
""", unsafe_allow_html=True) - - # Interactive elements - col1, col2 = st.columns(2) - with col1: - if st.button(f"Copy Tweet {index + 1}", key=f"copy_{index}"): - st.write("Tweet copied to clipboard!") - with col2: - if st.button(f"Save Tweet {index + 1}", key=f"save_{index}"): - st.write("Tweet saved!") -def smart_tweet_generator(): - """Enhanced Smart Tweet Generator with improved UI and AI integration.""" - st.title("âœĻ Smart Tweet Generator") - st.markdown("Create engaging tweets with AI-powered optimization") +def render_category_section(category: Dict) -> None: + """Render a category section with all its features.""" + st.markdown(f"### {category['icon']} {category['title']}") + st.markdown(f"*{category['description']}*") - # Input section with improved UI - with st.expander("Tweet Parameters", expanded=True): - col1, col2 = st.columns(2) + col1, col2 = st.columns(2) + with col1: + render_feature_card(category['features'][0]) + with col2: + render_feature_card(category['features'][1]) + +def run_dashboard(): + """Main function to run the Twitter dashboard.""" + # Header + st.title("ðŸĶ Twitter AI Writer Dashboard") + st.markdown(""" + Welcome to your all-in-one Twitter content creation and management platform. + Explore our AI-powered tools to enhance your Twitter marketing strategy. + """) + + # Load feature data + features = load_feature_data() + + # Create tabs for different sections + tab1, tab2, tab3 = st.tabs(["ðŸŽŊ Quick Actions", "📊 Analytics", "⚙ïļ Settings"]) + + with tab1: + st.markdown("### 🚀 Quick Actions") + col1, col2, col3 = st.columns(3) with col1: - hook = st.text_area("Tweet Hook/Topic", - placeholder="Enter your main message or topic...", - help="The main message or topic of your tweet") - - target_audience = st.selectbox( - "Target Audience", - ["Professionals", "Students", "General"], - help="Select your target audience" - ) - - tone = st.radio( - "Tweet Tone", - ["Professional", "Casual", "Informative", "Humorous", "Inspirational"], - horizontal=True, - help="Choose the tone for your tweet" - ) - + if st.button("📝 Create New Tweet", use_container_width=True): + # Call the Smart Tweet Generator + smart_tweet_generator() with col2: - call_to_action = st.text_input( - "Call to Action", - placeholder="e.g., Learn more, Follow us...", - help="What action do you want your audience to take?" - ) - - keywords = st.text_input( - "Keywords/Hashtags", - placeholder="Enter keywords separated by commas", - help="Keywords to include in your tweet" - ) - - length = st.select_slider( - "Tweet Length", - options=["short", "medium", "long"], - value="medium", - help="Choose your desired tweet length" - ) - - num_variations = st.slider( - "Number of Variations", - min_value=1, - max_value=5, - value=3, - help="How many tweet variations would you like to generate?" - ) + st.button("📅 Schedule Content", use_container_width=True) + with col3: + st.button("📊 View Analytics", use_container_width=True) + + with tab2: + st.markdown("### 📈 Analytics Dashboard") + st.info("Analytics features coming soon! Stay tuned for detailed insights and performance metrics.") + + with tab3: + st.markdown("### ⚙ïļ Settings") + st.info("Settings and configuration options coming soon!") + + # Main content area + st.markdown("## 🛠ïļ Available Tools") - # Generate button with loading state - if st.button("Generate Tweets", use_container_width=True): - with st.spinner("Generating tweet variations..."): - tweets = generate_tweet_variations( - hook, target_audience, tone, - call_to_action, keywords, length, - num_variations - ) - - # Display performance metrics - st.markdown("### 📊 Performance Metrics") - for tweet in tweets: - performance = predict_tweet_performance(tweet["text"], target_audience, tone) - - # Overall score with progress bar - st.progress(performance["overall_score"] / 100) - st.metric("Overall Score", f"{performance['overall_score']:.1f}%") - - # Detailed metrics in columns - cols = st.columns(4) - metrics = performance["metrics"] - - with cols[0]: - st.metric("Character Count", f"{metrics['character_count']['score']:.1f}%") - with cols[1]: - st.metric("Hashtag Usage", f"{metrics['hashtag_usage']['score']:.1f}%") - with cols[2]: - st.metric("Engagement", f"{metrics['engagement_potential']['score']:.1f}%") - with cols[3]: - st.metric("Audience Fit", f"{metrics['audience_alignment']['score']:.1f}%") - - # Improvement suggestions - suggestions = suggest_improvements(tweet["text"], performance) - if suggestions: - st.markdown("### ðŸ’Ą Improvement Suggestions") - for suggestion in suggestions: - st.info(suggestion) - - # Tweet card - render_tweet_card(tweet, tweets.index(tweet)) - - st.markdown("---") - - # Export options - st.markdown("### ðŸ“Ĩ Export Options") - col1, col2 = st.columns(2) - with col1: - if st.button("Export as JSON"): - st.download_button( - "Download JSON", - data=json.dumps(tweets, indent=2), - file_name=f"tweets_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json", - mime="application/json" - ) - with col2: - if st.button("Copy All Tweets"): - tweet_texts = "\n\n".join(tweet["text"] for tweet in tweets) - st.code(tweet_texts) + # Render each category + for category in features.values(): + render_category_section(category) + + # If this is the tweet generation category and the Smart Tweet Generator is active, + # add a button to launch it + if category["title"] == "Tweet Generation & Optimization" and category["features"][0]["status"] == "active": + if st.button(f"🚀 Launch {category['features'][0]['name']}", use_container_width=True): + category["features"][0]["function"]() + + # Footer + st.markdown("---") + st.markdown(""" +
+

Need help? Check out our documentation or contact support

+
+ """, unsafe_allow_html=True) if __name__ == "__main__": - smart_tweet_generator() + run_dashboard() \ No newline at end of file diff --git a/lib/utils/api_key_manager/components/ai_research_setup.py b/lib/utils/api_key_manager/components/ai_research_setup.py index 3df488b7..c2ccb2be 100644 --- a/lib/utils/api_key_manager/components/ai_research_setup.py +++ b/lib/utils/api_key_manager/components/ai_research_setup.py @@ -7,14 +7,6 @@ from ..manager import APIKeyManager import os from dotenv import load_dotenv # Keep if api_key_manager uses it import sys -# Corrected import: Assuming validation functions are in validation.py in the parent directory -from ..validation import ( - test_serpapi_key, - test_tavily_key, - test_metaphor_key, - test_firecrawl_key - # Add others if needed later, e.g., test_bing_key, test_google_search_key -) # Configure logger (assuming configured elsewhere or keep minimal here) logger.add(sys.stderr, level="INFO") # Keep simple example if needed diff --git a/lib/utils/api_key_manager/components/website_setup.py b/lib/utils/api_key_manager/components/website_setup.py index 66f47ddb..51bad20f 100644 --- a/lib/utils/api_key_manager/components/website_setup.py +++ b/lib/utils/api_key_manager/components/website_setup.py @@ -199,7 +199,7 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]: # --- Removed Analysis Section --- # The detailed website analysis should be a separate feature, not part of the initial setup validation. - st.markdown("--- ---“) + st.markdown("---") st.markdown("â„đïļ *The detailed Website Analyzer tool is available separately in the main application.*") st.info("Entering your website URL is optional. Click Continue to proceed.")