Content Calendar, Content Gap Analysis, and Content Optimization

This commit is contained in:
ajaysi
2025-05-27 09:15:08 +05:30
parent 4049d19787
commit 889021c078
100 changed files with 18504 additions and 1251 deletions

View File

@@ -194,7 +194,7 @@ def facebook_main_menu():
if st.session_state.selected_tool is not None:
with tool_container:
# Add a back button at the top
if st.button("← Back to Dashboard", key="back_to_dashboard"):
if st.button("← Back to Dashboard", key="back_to_facebook_dashboard"):
st.session_state.selected_tool = None
st.rerun()

View File

@@ -0,0 +1,190 @@
# AI Finance Report Generator
An advanced AI-powered financial analysis and report generation system that combines data collection, technical analysis, visualization, and automated report generation.
## Project Structure
```
ai_finance_report_generator/
├── ai_financial_dashboard.py # Main dashboard interface
├── utils/ # Utility functions
│ ├── __init__.py
│ └── storage.py # Data persistence
├── reports/ # Report generation modules
│ ├── technical_analysis/ # Technical analysis reports
│ ├── fundamental_analysis/ # Fundamental analysis reports
│ ├── options_analysis/ # Options analysis reports
│ ├── portfolio_analysis/ # Portfolio analysis reports
│ ├── market_research/ # Market research reports
│ └── news_analysis/ # News analysis reports
└── README.md # This file
```
## Features
### Current Features
- Unified dashboard interface for all financial analysis tools
- Technical Analysis report generation
- Options analysis report generation
- User preferences management
- Recent reports tracking
- Data persistence with JSON storage
- Financial data collection from various sources
- Integration with LLM for report generation
### Planned Features
#### 1. Data Collection Module
- Web scraping for financial news and data
- API integrations (Yahoo Finance, Alpha Vantage, Financial Modeling Prep)
- Real-time market data collection
- Historical data retrieval
- Company financial statements
- Market sentiment data
- Economic indicators
- Sector analysis data
#### 2. Technical Analysis Module
- Moving averages (SMA, EMA, WMA)
- RSI, MACD, Bollinger Bands
- Volume analysis
- Support/Resistance levels
- Trend analysis
- Pattern recognition
- Fibonacci retracements
- Momentum indicators
#### 3. Fundamental Analysis Module
- Financial ratios calculation
- Company valuation metrics
- Growth analysis
- Profitability analysis
- Debt analysis
- Cash flow analysis
- Industry comparison
- Peer analysis
#### 4. Data Visualization Module
- Candlestick charts
- Technical indicator overlays
- Volume charts
- Price action patterns
- Correlation matrices
- Heat maps
- Interactive charts
- Custom chart templates
#### 5. Report Generation Module
- Technical analysis reports
- Fundamental analysis reports
- Market research reports
- Investment recommendations
- Risk assessment reports
- Sector analysis reports
- News impact analysis
- Custom report templates
#### 6. News and Sentiment Analysis Module
- News aggregation
- Sentiment scoring
- Social media analysis
- Market sentiment indicators
- News impact analysis
- Event correlation
- Trend detection
- Sentiment visualization
#### 7. Portfolio Analysis Module
- Portfolio performance analysis
- Risk assessment
- Asset allocation
- Correlation analysis
- Diversification metrics
- Performance attribution
- Portfolio optimization
- Rebalancing suggestions
## Usage
### Basic Usage
```python
from lib.ai_writers.ai_finance_report_generator.ai_financial_dashboard import get_dashboard
# Get dashboard instance
dashboard = get_dashboard()
# Generate technical analysis report
ta_report = dashboard.generate_technical_analysis("AAPL")
# Generate options analysis report
options_report = dashboard.generate_options_analysis("AAPL")
# Get recent reports
recent_reports = dashboard.get_recent_reports()
```
### User Preferences
```python
# Update user preferences
dashboard.update_preferences({
"report_format": "markdown",
"include_charts": True,
"chart_style": "dark",
"language": "en"
})
# Get current preferences
preferences = dashboard.get_preferences()
```
### Portfolio Analysis
```python
# Create portfolio
portfolio = [
{"symbol": "AAPL", "shares": 100},
{"symbol": "GOOGL", "shares": 50}
]
# Generate portfolio report
portfolio_report = dashboard.generate_portfolio_analysis(portfolio)
```
## Installation
```bash
pip install -r requirements.txt
```
## Dependencies
1. **Data Collection**
- `finance_data_researcher`
- `web_scraping_tools`
2. **Analysis Tools**
- `pandas_ta`
- `numpy`
- `scipy`
3. **Visualization**
- `matplotlib`
- `plotly`
4. **Text Generation**
- `llm_text_gen`
- `gpt_providers`
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the LICENSE file for details.

View File

@@ -0,0 +1,358 @@
"""
AI Financial Dashboard Module
This module combines the financial dashboard interface with financial report generation capabilities.
It provides a unified interface for managing financial analysis tools and generating reports.
"""
import sys
import os
from textwrap import dedent
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional, Union
from loguru import logger
logger.remove()
logger.add(sys.stdout,
colorize=True,
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
)
from ...ai_web_researcher.finance_data_researcher import get_finance_data, get_fin_options_data
from ...gpt_providers.text_generation.main_text_generation import llm_text_gen
from .utils import get_feature_status
from .utils.storage import get_storage_manager
class UserPreferences:
"""Class to manage user preferences and settings."""
def __init__(self):
self.default_settings = {
"theme": "light",
"currency": "USD",
"timezone": "UTC",
"date_format": "%Y-%m-%d",
"default_symbols": [],
"notifications": True,
"auto_refresh": False,
"refresh_interval": 300, # 5 minutes
"report_format": "markdown",
"include_charts": True,
"chart_style": "default",
"language": "en"
}
self.settings = self.default_settings.copy()
self.storage = get_storage_manager()
self.load_settings()
def update_setting(self, key: str, value: Any) -> None:
"""Update a specific setting."""
if key in self.default_settings:
self.settings[key] = value
self.save_settings()
def get_setting(self, key: str) -> Any:
"""Get a specific setting value."""
return self.settings.get(key, self.default_settings.get(key))
def reset_settings(self) -> None:
"""Reset all settings to default values."""
self.settings = self.default_settings.copy()
self.save_settings()
def save_settings(self) -> None:
"""Save current settings to storage."""
self.storage.save_user_preferences(self.settings)
def load_settings(self) -> None:
"""Load settings from storage."""
stored_settings = self.storage.load_user_preferences()
if stored_settings:
self.settings.update(stored_settings)
class RecentReport:
"""Class to represent a recently generated report."""
def __init__(self, report_type: str, symbol: Optional[str], timestamp: datetime, content: Optional[str] = None):
self.report_type = report_type
self.symbol = symbol
self.timestamp = timestamp
self.content = content
self.id = f"{report_type}_{symbol}_{timestamp.strftime('%Y%m%d%H%M%S')}"
def to_dict(self) -> Dict[str, Any]:
"""Convert report to dictionary format."""
return {
"id": self.id,
"type": self.report_type,
"symbol": self.symbol,
"timestamp": self.timestamp.isoformat(),
"content": self.content
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'RecentReport':
"""Create report from dictionary format."""
return cls(
report_type=data["type"],
symbol=data["symbol"],
timestamp=datetime.fromisoformat(data["timestamp"]),
content=data.get("content")
)
class FinancialDashboard:
"""Main dashboard class for managing financial analysis tools and generating reports."""
def __init__(self):
self.features = {
"technical_analysis": {
"name": "Technical Analysis",
"description": "Generate technical analysis reports with indicators and patterns",
"icon": "📊",
"route": "/technical-analysis",
"category": "analysis",
"dependencies": ["data_collection"],
"version": "1.0.0"
},
"fundamental_analysis": {
"name": "Fundamental Analysis",
"description": "Analyze company financials and valuation metrics",
"icon": "📈",
"route": "/fundamental-analysis",
"category": "analysis",
"dependencies": ["data_collection"],
"version": "0.1.0"
},
"options_analysis": {
"name": "Options Analysis",
"description": "Analyze options chains and generate trading strategies",
"icon": "",
"route": "/options-analysis",
"category": "analysis",
"dependencies": ["data_collection", "options_data"],
"version": "1.0.0"
},
"portfolio_analysis": {
"name": "Portfolio Analysis",
"description": "Analyze portfolio performance and risk metrics",
"icon": "📑",
"route": "/portfolio-analysis",
"category": "portfolio",
"dependencies": ["data_collection", "portfolio_data"],
"version": "0.1.0"
},
"market_research": {
"name": "Market Research",
"description": "Generate market research reports and sector analysis",
"icon": "🔍",
"route": "/market-research",
"category": "research",
"dependencies": ["data_collection", "news_data"],
"version": "0.1.0"
},
"news_analysis": {
"name": "News Analysis",
"description": "Analyze news impact and market sentiment",
"icon": "📰",
"route": "/news-analysis",
"category": "research",
"dependencies": ["data_collection", "news_data"],
"version": "0.1.0"
}
}
self.user_preferences = UserPreferences()
self.storage = get_storage_manager()
self.recent_reports: List[RecentReport] = []
self.max_recent_reports = 10
self.load_recent_reports()
def get_all_features(self) -> List[Dict[str, Any]]:
"""Get all available features with their status."""
features_list = []
for feature_id, feature_info in self.features.items():
status = get_feature_status(feature_id)
feature_info.update(status)
features_list.append(feature_info)
return features_list
def get_feature(self, feature_id: str) -> Dict[str, Any]:
"""Get information about a specific feature."""
if feature_id not in self.features:
raise ValueError(f"Feature {feature_id} not found")
feature_info = self.features[feature_id].copy()
status = get_feature_status(feature_id)
feature_info.update(status)
return feature_info
def get_implemented_features(self) -> List[Dict[str, Any]]:
"""Get only the implemented features."""
return [f for f in self.get_all_features() if f["implemented"]]
def get_coming_soon_features(self) -> List[Dict[str, Any]]:
"""Get features that are coming soon."""
return [f for f in self.get_all_features() if f["coming_soon"]]
def get_features_by_category(self, category: str) -> List[Dict[str, Any]]:
"""Get features filtered by category."""
return [f for f in self.get_all_features() if f["category"] == category]
def add_recent_report(self, report_type: str, symbol: Optional[str] = None, content: Optional[str] = None) -> None:
"""Add a report to the recent reports list."""
report = RecentReport(report_type, symbol, datetime.now(), content)
self.recent_reports.insert(0, report)
if len(self.recent_reports) > self.max_recent_reports:
self.recent_reports.pop()
self.save_recent_reports()
def get_recent_reports(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
"""Get recent reports."""
reports = self.recent_reports[:limit] if limit else self.recent_reports
return [{
**r.to_dict(),
"feature_info": self.get_feature(r.report_type)
} for r in reports]
def save_recent_reports(self) -> None:
"""Save recent reports to storage."""
reports_data = [r.to_dict() for r in self.recent_reports]
self.storage.save_recent_reports(reports_data)
def load_recent_reports(self) -> None:
"""Load recent reports from storage."""
reports_data = self.storage.load_recent_reports()
self.recent_reports = [RecentReport.from_dict(r) for r in reports_data]
def get_dashboard_summary(self) -> Dict[str, Any]:
"""Get a summary of the dashboard state."""
return {
"total_features": len(self.features),
"implemented_features": len(self.get_implemented_features()),
"coming_soon_features": len(self.get_coming_soon_features()),
"recent_reports": len(self.recent_reports),
"categories": list(set(f["category"] for f in self.features.values())),
"user_preferences": self.user_preferences.settings
}
def check_feature_dependencies(self, feature_id: str) -> Dict[str, bool]:
"""Check if all dependencies for a feature are met."""
if feature_id not in self.features:
raise ValueError(f"Feature {feature_id} not found")
feature = self.features[feature_id]
dependencies = feature.get("dependencies", [])
return {
dep: get_feature_status(dep)["implemented"]
for dep in dependencies
}
def backup_data(self, backup_dir: Optional[str] = None) -> None:
"""Create a backup of all dashboard data."""
self.storage.backup_storage(backup_dir)
def restore_from_backup(self, backup_file: str) -> None:
"""Restore dashboard data from a backup file."""
self.storage.restore_from_backup(backup_file)
self.user_preferences.load_settings()
self.load_recent_reports()
def generate_technical_analysis(self, symbol: str) -> str:
"""Generate a technical analysis report for the given symbol."""
try:
# Get financial data
symbol_fin_data = get_finance_data(symbol)
# Generate report
report_content = self._generate_ta_report(symbol_fin_data, symbol)
# Add to recent reports
self.add_recent_report("technical_analysis", symbol, report_content)
logger.info(f"Done: Final Technical Analysis for {symbol}")
return report_content
except Exception as err:
logger.error(f"Error: Failed to generate Technical Analysis report: {err}")
raise
def generate_options_analysis(self, symbol: str) -> str:
"""Generate an options analysis report for the given symbol."""
try:
# Get options data
options_data = get_fin_options_data(symbol)
# Generate report
report_content = self._generate_options_report(options_data, symbol)
# Add to recent reports
self.add_recent_report("options_analysis", symbol, report_content)
logger.info(f"Done: Options Analysis for {symbol}")
return report_content
except Exception as err:
logger.error(f"Error: Failed to generate Options Analysis report: {err}")
raise
def _generate_ta_report(self, last_day_summary: str, symbol: str) -> str:
"""Generate technical analysis report using LLM."""
prompt = f"""
You are a seasoned Technical Analysis (TA) expert, rivaling legends like Charles Dow, John Bollinger, and Alan Andrews.
Your deep understanding of market dynamics, coupled with mastery of technical indicators,
allows you to decipher complex patterns and offer precise predictions.
Your expertise extends to practical tools like the pandas_ta module, enabling you to extract valuable insights from raw data.
**Objective:**
Analyze the provided technical indicators for {symbol} on its last trading day and predict its price movement over the next few trading sessions.
**Instructions:**
1. **Identify Potential Trading Signals:** Highlight specific indicators suggesting bullish, bearish, or neutral signals. Explain the rationale behind each signal, referencing historical patterns or comparable market scenarios.
2. **Detect Patterns and Divergences:** Analyze the interplay between different indicators. Detect patterns like moving average crossovers, candlestick formations, or divergences between price action and indicators. Explain the significance of each pattern.
3. **Price Movement Prediction:** Based on your analysis, provide a clear prediction for {symbol}'s price movement in the next few days. State the expected direction (up, down, sideways) and potential price targets if identifiable.
4. **Risk Assessment:** Briefly discuss any potential risks or factors that could invalidate your predictions, promoting a balanced and informed perspective.
**Technical Indicators for {symbol} on the Last Trading Day:**
{last_day_summary}
Remember, your analysis should be detailed, insightful, and actionable for traders seeking to capitalize on market movements.
"""
try:
return llm_text_gen(prompt)
except Exception as err:
logger.error(f"Failed to generate TA report: {err}")
raise
def _generate_options_report(self, results_sentences: List[str], ticker: str) -> str:
"""Generate options analysis report using LLM."""
prompt = f"""
You are a financial expert specializing in options trading and market sentiment analysis.
You have been provided with the following technical analysis of options data for the ticker symbol {ticker} with the nearest expiry date:
{chr(10).join(results_sentences)}
Based on this data, provide a comprehensive analysis of the options market for {ticker}.
Your analysis should include:
1. **Implied Volatility Interpretation:** Discuss the significance of the average implied volatility for both call and put options. What does it suggest about market expectations of future price movements?
2. **Volume and Open Interest Insights:** Analyze the volume and open interest for call and put options. What does this data reveal about current market positioning and potential future trading activity?
3. **Sentiment Analysis:** Evaluate the put-call ratio, implied volatility skew, and overall market sentiment. What do these indicators suggest about trader sentiment and potential future price direction?
4. **Potential Trading Strategies:** Based on your analysis, suggest potential options trading strategies that could be employed for {ticker}, considering the current market conditions and sentiment.
Please provide your analysis in a clear and concise manner, suitable for someone with a good understanding of options trading.
"""
try:
return llm_text_gen(prompt)
except Exception as err:
logger.error(f"Failed to generate options report: {err}")
raise
def get_dashboard() -> FinancialDashboard:
"""Get the financial dashboard instance."""
return FinancialDashboard()

View File

@@ -0,0 +1,265 @@
# Financial Reports Module
This directory contains the core report generation modules for different types of financial analysis. Each module is designed to handle a specific type of financial report and can be accessed through the main dashboard interface.
## Directory Structure
```
reports/
├── technical_analysis/ # Technical analysis reports
├── fundamental_analysis/ # Fundamental analysis reports
├── options_analysis/ # Options analysis reports
├── portfolio_analysis/ # Portfolio analysis reports
├── market_research/ # Market research reports
└── news_analysis/ # News analysis reports
```
## Report Types
### 1. Technical Analysis Reports
Location: `technical_analysis/`
Generates technical analysis reports including:
- Moving averages (SMA, EMA, WMA)
- RSI, MACD, Bollinger Bands
- Volume analysis
- Support/Resistance levels
- Trend analysis
- Pattern recognition
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.technical_analysis import generate_ta_report
report = generate_ta_report("AAPL")
```
### 2. Fundamental Analysis Reports
Location: `fundamental_analysis/`
Generates fundamental analysis reports including:
- Financial ratios
- Company valuation metrics
- Growth analysis
- Profitability analysis
- Debt analysis
- Cash flow analysis
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.fundamental_analysis import generate_fa_report
report = generate_fa_report("AAPL")
```
### 3. Options Analysis Reports
Location: `options_analysis/`
Generates options analysis reports including:
- Options chain analysis
- Implied volatility analysis
- Options strategies
- Risk metrics
- Greeks analysis
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.options_analysis import generate_options_report
report = generate_options_report("AAPL")
```
### 4. Portfolio Analysis Reports
Location: `portfolio_analysis/`
Generates portfolio analysis reports including:
- Portfolio performance analysis
- Risk assessment
- Asset allocation
- Correlation analysis
- Diversification metrics
- Performance attribution
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.portfolio_analysis import generate_portfolio_report
portfolio = [
{"symbol": "AAPL", "shares": 100},
{"symbol": "GOOGL", "shares": 50}
]
report = generate_portfolio_report(portfolio)
```
### 5. Market Research Reports
Location: `market_research/`
Generates market research reports including:
- Sector analysis
- Industry trends
- Market overview
- Competitive analysis
- Market opportunities
- Risk factors
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.market_research import generate_market_research_report
report = generate_market_research_report(sectors=["Technology", "Healthcare"])
```
### 6. News Analysis Reports
Location: `news_analysis/`
Generates news analysis reports including:
- News sentiment analysis
- Market impact analysis
- Event correlation
- Trend detection
- Social media analysis
- News aggregation
Usage:
```python
from lib.ai_writers.ai_finance_report_generator.reports.news_analysis import generate_news_analysis_report
report = generate_news_analysis_report("AAPL")
```
## Common Features
All report modules share the following features:
1. **Data Validation**
- Input validation for symbols and parameters
- Error handling for invalid inputs
- Data type checking
2. **Report Formatting**
- Markdown formatting
- Chart generation (when applicable)
- Customizable templates
3. **Storage Integration**
- Automatic report storage
- Recent reports tracking
- Report versioning
4. **User Preferences**
- Customizable report formats
- Language selection
- Chart style preferences
## Integration with Dashboard
All report modules are integrated with the main dashboard and can be accessed through the `FinancialDashboard` class:
```python
from lib.ai_writers.ai_finance_report_generator.ai_financial_dashboard import get_dashboard
dashboard = get_dashboard()
# Generate reports through dashboard
ta_report = dashboard.generate_technical_analysis("AAPL")
options_report = dashboard.generate_options_analysis("AAPL")
# Get recent reports
recent_reports = dashboard.get_recent_reports()
```
## Adding New Report Types
To add a new report type:
1. Create a new directory in the `reports/` folder
2. Create an `__init__.py` file with the report generation function
3. Add the report type to the dashboard features
4. Implement the report generation logic
5. Add appropriate error handling and validation
Example:
```python
# reports/new_analysis/__init__.py
from typing import Dict, Any
from ...utils import validate_symbol
def generate_new_analysis_report(symbol: str) -> Dict[str, Any]:
"""
Generate a new type of analysis report.
Args:
symbol (str): Stock symbol to analyze
Returns:
Dict[str, Any]: Analysis report
"""
if not validate_symbol(symbol):
raise ValueError("Invalid symbol provided")
# Implement report generation logic
return {
"symbol": symbol,
"analysis": "Report content"
}
```
## Error Handling
All report modules implement consistent error handling:
1. **Input Validation**
- Symbol validation
- Parameter validation
- Data type checking
2. **Data Collection Errors**
- API errors
- Network errors
- Data format errors
3. **Report Generation Errors**
- LLM errors
- Template errors
- Formatting errors
4. **Storage Errors**
- File system errors
- Database errors
- Backup errors
## Contributing
When contributing to the reports module:
1. Follow the existing code structure
2. Add appropriate type hints
3. Include comprehensive docstrings
4. Add error handling
5. Update the dashboard integration
6. Add tests for new functionality
## Dependencies
The reports module depends on:
1. **Data Collection**
- `finance_data_researcher`
- `web_scraping_tools`
2. **Analysis Tools**
- `pandas_ta`
- `numpy`
- `scipy`
3. **Visualization**
- `matplotlib`
- `plotly`
4. **Text Generation**
- `llm_text_gen`
- `gpt_providers`
## License
This module is part of the AI Finance Report Generator project and is licensed under the MIT License.

View File

@@ -0,0 +1,34 @@
"""
Fundamental Analysis Reports Module
This module handles the generation of fundamental analysis reports including:
- Financial ratios
- Company valuation metrics
- Growth analysis
- Profitability analysis
- Debt analysis
- Cash flow analysis
"""
from typing import Dict, Any
from ...utils import validate_symbol
def generate_fa_report(symbol: str) -> Dict[str, Any]:
"""
Generate a fundamental analysis report for the given symbol.
Args:
symbol (str): Stock symbol to analyze
Returns:
Dict[str, Any]: Fundamental analysis report
"""
if not validate_symbol(symbol):
raise ValueError("Invalid symbol provided")
# TODO: Implement fundamental analysis report generation
return {
"symbol": symbol,
"status": "coming_soon",
"message": "Fundamental analysis report generation is coming soon"
}

View File

@@ -0,0 +1,29 @@
"""
Market Research Reports Module
This module handles the generation of market research reports including:
- Sector analysis
- Industry trends
- Market overview
- Competitive analysis
- Market opportunities
- Risk factors
"""
from typing import Dict, Any, List
def generate_market_research_report(sectors: List[str] = None) -> Dict[str, Any]:
"""
Generate a market research report.
Args:
sectors (List[str], optional): List of sectors to analyze
Returns:
Dict[str, Any]: Market research report
"""
# TODO: Implement market research report generation
return {
"status": "coming_soon",
"message": "Market research report generation is coming soon"
}

View File

@@ -0,0 +1,33 @@
"""
News Analysis Reports Module
This module handles the generation of news analysis reports including:
- News sentiment analysis
- Market impact analysis
- Event correlation
- Trend detection
- Social media analysis
- News aggregation
"""
from typing import Dict, Any, List
from ...utils import validate_symbol
def generate_news_analysis_report(symbol: str = None) -> Dict[str, Any]:
"""
Generate a news analysis report.
Args:
symbol (str, optional): Stock symbol to analyze news for
Returns:
Dict[str, Any]: News analysis report
"""
if symbol and not validate_symbol(symbol):
raise ValueError("Invalid symbol provided")
# TODO: Implement news analysis report generation
return {
"status": "coming_soon",
"message": "News analysis report generation is coming soon"
}

View File

@@ -0,0 +1,33 @@
"""
Options Analysis Reports Module
This module handles the generation of options analysis reports including:
- Options chain analysis
- Implied volatility analysis
- Options strategies
- Risk metrics
- Greeks analysis
"""
from typing import Dict, Any
from ...utils import validate_symbol
def generate_options_report(symbol: str) -> Dict[str, Any]:
"""
Generate an options analysis report for the given symbol.
Args:
symbol (str): Stock symbol to analyze
Returns:
Dict[str, Any]: Options analysis report
"""
if not validate_symbol(symbol):
raise ValueError("Invalid symbol provided")
# TODO: Implement options analysis report generation
return {
"symbol": symbol,
"status": "coming_soon",
"message": "Options analysis report generation is coming soon"
}

View File

@@ -0,0 +1,32 @@
"""
Portfolio Analysis Reports Module
This module handles the generation of portfolio analysis reports including:
- Portfolio performance analysis
- Risk assessment
- Asset allocation
- Correlation analysis
- Diversification metrics
- Performance attribution
"""
from typing import Dict, Any, List
def generate_portfolio_report(portfolio: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
Generate a portfolio analysis report.
Args:
portfolio (List[Dict[str, Any]]): List of portfolio positions
Returns:
Dict[str, Any]: Portfolio analysis report
"""
if not portfolio:
raise ValueError("Portfolio cannot be empty")
# TODO: Implement portfolio analysis report generation
return {
"status": "coming_soon",
"message": "Portfolio analysis report generation is coming soon"
}

View File

@@ -0,0 +1,314 @@
"""
Technical Analysis Reports Module
This module handles the generation of technical analysis reports using yfinance data and pandas_ta for indicators.
"""
from typing import Dict, Any, List, Optional
import yfinance as yf
import pandas as pd
import pandas_ta as ta
import plotly.graph_objects as go
from datetime import datetime, timedelta
from loguru import logger
from ...utils import validate_symbol
from ...ai_financial_dashboard import get_dashboard
class TechnicalAnalysis:
def __init__(self, symbol: str, timeframe: str = "1d", period: str = "1y"):
"""
Initialize Technical Analysis.
Args:
symbol (str): Stock symbol to analyze
timeframe (str): Data timeframe (1m, 5m, 15m, 30m, 1h, 1d, 1wk, 1mo)
period (str): Data period (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)
"""
logger.info(f"Initializing Technical Analysis for {symbol} with timeframe {timeframe} and period {period}")
self.symbol = symbol
self.timeframe = timeframe
self.period = period
self.data = None
self.indicators = {}
self.stock = yf.Ticker(symbol)
def fetch_data(self) -> None:
"""Fetch historical price data using yfinance"""
try:
logger.info(f"Fetching historical data for {self.symbol}")
# Get historical data
self.data = self.stock.history(period=self.period, interval=self.timeframe)
logger.debug(f"Retrieved {len(self.data)} data points")
# Get additional info
logger.info("Fetching company information")
self.info = self.stock.info
# Calculate basic metrics
logger.debug("Calculating basic metrics")
self.data['Returns'] = self.data['Close'].pct_change()
self.data['Volatility'] = self.data['Returns'].rolling(window=20).std()
logger.success(f"Successfully fetched data for {self.symbol}")
except Exception as e:
logger.error(f"Error fetching data for {self.symbol}: {str(e)}")
raise ValueError(f"Error fetching data for {self.symbol}: {str(e)}")
def calculate_indicators(self) -> None:
"""Calculate technical indicators using pandas_ta"""
if self.data is None:
logger.error("Data not fetched. Call fetch_data() first.")
raise ValueError("Data not fetched. Call fetch_data() first.")
logger.info("Calculating technical indicators")
# Moving Averages
logger.debug("Calculating Moving Averages")
self.indicators['sma_20'] = self.data.ta.sma(length=20)
self.indicators['sma_50'] = self.data.ta.sma(length=50)
self.indicators['sma_200'] = self.data.ta.sma(length=200)
self.indicators['ema_20'] = self.data.ta.ema(length=20)
# RSI
logger.debug("Calculating RSI")
self.indicators['rsi'] = self.data.ta.rsi()
# MACD
logger.debug("Calculating MACD")
macd = self.data.ta.macd()
self.indicators['macd'] = macd['MACD_12_26_9']
self.indicators['macd_signal'] = macd['MACDs_12_26_9']
self.indicators['macd_hist'] = macd['MACDh_12_26_9']
# Bollinger Bands
logger.debug("Calculating Bollinger Bands")
bbands = self.data.ta.bbands()
self.indicators['bb_upper'] = bbands['BBU_20_2.0']
self.indicators['bb_middle'] = bbands['BBM_20_2.0']
self.indicators['bb_lower'] = bbands['BBL_20_2.0']
# Volume Analysis
logger.debug("Calculating Volume indicators")
self.indicators['volume_sma'] = self.data['Volume'].rolling(window=20).mean()
self.indicators['obv'] = self.data.ta.obv()
# Additional Indicators
logger.debug("Calculating additional indicators")
self.indicators['stoch'] = self.data.ta.stoch()
self.indicators['adx'] = self.data.ta.adx()
self.indicators['atr'] = self.data.ta.atr()
logger.success("Successfully calculated all technical indicators")
def identify_patterns(self) -> List[Dict[str, Any]]:
"""Identify chart patterns"""
logger.info("Identifying chart patterns")
patterns = []
# Candlestick Patterns
if len(self.data) >= 3:
logger.debug("Analyzing candlestick patterns")
# Doji
doji = self.data.ta.cdl_doji()
if doji['CDL_DOJI'].iloc[-1] != 0:
logger.debug("Doji pattern detected")
patterns.append({
'type': 'doji',
'date': self.data.index[-1],
'significance': 'neutral'
})
# Engulfing
engulfing = self.data.ta.cdl_engulfing()
if engulfing['CDL_ENGULFING'].iloc[-1] != 0:
logger.debug("Engulfing pattern detected")
patterns.append({
'type': 'engulfing',
'date': self.data.index[-1],
'significance': 'bullish' if engulfing['CDL_ENGULFING'].iloc[-1] > 0 else 'bearish'
})
logger.info(f"Identified {len(patterns)} patterns")
return patterns
def find_support_resistance(self) -> Dict[str, List[float]]:
"""Find support and resistance levels using price action"""
logger.info("Finding support and resistance levels")
levels = {
'support': [],
'resistance': []
}
# Use recent price action to identify levels
recent_data = self.data.tail(100)
logger.debug(f"Analyzing {len(recent_data)} recent data points for S/R levels")
# Find local minima and maxima
for i in range(2, len(recent_data) - 2):
# Support level
if (recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i-1] and
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i-2] and
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i+1] and
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i+2]):
levels['support'].append(recent_data['Low'].iloc[i])
# Resistance level
if (recent_data['High'].iloc[i] > recent_data['High'].iloc[i-1] and
recent_data['High'].iloc[i] > recent_data['High'].iloc[i-2] and
recent_data['High'].iloc[i] > recent_data['High'].iloc[i+1] and
recent_data['High'].iloc[i] > recent_data['High'].iloc[i+2]):
levels['resistance'].append(recent_data['High'].iloc[i])
# Remove duplicates and sort
levels['support'] = sorted(list(set(levels['support'])))
levels['resistance'] = sorted(list(set(levels['resistance'])))
logger.info(f"Found {len(levels['support'])} support and {len(levels['resistance'])} resistance levels")
return levels
def generate_chart(self) -> go.Figure:
"""Generate interactive chart using plotly"""
logger.info("Generating interactive chart")
fig = go.Figure()
# Candlestick chart
logger.debug("Adding candlestick chart")
fig.add_trace(go.Candlestick(
x=self.data.index,
open=self.data['Open'],
high=self.data['High'],
low=self.data['Low'],
close=self.data['Close'],
name='Price'
))
# Moving Averages
logger.debug("Adding moving averages")
fig.add_trace(go.Scatter(
x=self.data.index,
y=self.indicators['sma_20'],
name='SMA 20',
line=dict(color='blue')
))
fig.add_trace(go.Scatter(
x=self.data.index,
y=self.indicators['sma_50'],
name='SMA 50',
line=dict(color='orange')
))
# Bollinger Bands
logger.debug("Adding Bollinger Bands")
fig.add_trace(go.Scatter(
x=self.data.index,
y=self.indicators['bb_upper'],
name='BB Upper',
line=dict(color='gray', dash='dash')
))
fig.add_trace(go.Scatter(
x=self.data.index,
y=self.indicators['bb_lower'],
name='BB Lower',
line=dict(color='gray', dash='dash'),
fill='tonexty'
))
# Volume
logger.debug("Adding volume bars")
fig.add_trace(go.Bar(
x=self.data.index,
y=self.data['Volume'],
name='Volume',
marker_color='rgba(0,0,255,0.3)'
))
# Layout
logger.debug("Setting chart layout")
fig.update_layout(
title=f'{self.symbol} Technical Analysis',
yaxis_title='Price',
xaxis_title='Date',
template='plotly_dark'
)
logger.success("Successfully generated chart")
return fig
def _generate_summary(self) -> Dict[str, Any]:
"""Generate summary of technical analysis"""
logger.info("Generating analysis summary")
current_price = self.data['Close'].iloc[-1]
sma_20 = self.indicators['sma_20'].iloc[-1]
sma_50 = self.indicators['sma_50'].iloc[-1]
rsi = self.indicators['rsi'].iloc[-1]
summary = {
'current_price': current_price,
'price_change': self.data['Returns'].iloc[-1] * 100,
'trend': 'bullish' if current_price > sma_20 > sma_50 else 'bearish',
'rsi_signal': 'overbought' if rsi > 70 else 'oversold' if rsi < 30 else 'neutral',
'volatility': self.data['Volatility'].iloc[-1],
'volume_trend': 'increasing' if self.data['Volume'].iloc[-1] > self.indicators['volume_sma'].iloc[-1] else 'decreasing'
}
logger.debug(f"Analysis summary: {summary}")
return summary
def generate_report(self) -> Dict[str, Any]:
"""Generate comprehensive technical analysis report"""
logger.info(f"Generating comprehensive report for {self.symbol}")
self.fetch_data()
self.calculate_indicators()
patterns = self.identify_patterns()
levels = self.find_support_resistance()
chart = self.generate_chart()
summary = self._generate_summary()
report = {
'symbol': self.symbol,
'timestamp': datetime.now(),
'company_info': self.info,
'indicators': self.indicators,
'patterns': patterns,
'levels': levels,
'chart': chart,
'summary': summary
}
logger.success(f"Successfully generated report for {self.symbol}")
return report
def generate_ta_report(symbol: str) -> Dict[str, Any]:
"""
Generate a technical analysis report for the given symbol.
Args:
symbol (str): Stock symbol to analyze
Returns:
Dict[str, Any]: Technical analysis report
"""
logger.info(f"Generating technical analysis report for {symbol}")
if not validate_symbol(symbol):
logger.error(f"Invalid symbol provided: {symbol}")
raise ValueError("Invalid symbol provided")
try:
analysis = TechnicalAnalysis(symbol)
report = analysis.generate_report()
# Add to dashboard's recent reports
dashboard = get_dashboard()
dashboard.add_recent_report("technical_analysis", symbol, report)
logger.success(f"Successfully completed technical analysis for {symbol}")
return report
except Exception as e:
logger.error(f"Error generating technical analysis report for {symbol}: {str(e)}")
raise

View File

@@ -0,0 +1,62 @@
"""
Utility functions and helpers for the AI Finance Report Generator.
"""
from typing import Dict, List, Any
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def validate_symbol(symbol: str) -> bool:
"""
Validate if the given symbol is in correct format.
Args:
symbol (str): Stock symbol to validate
Returns:
bool: True if valid, False otherwise
"""
if not isinstance(symbol, str):
return False
return len(symbol.strip()) > 0
def format_currency(value: float) -> str:
"""
Format number as currency.
Args:
value (float): Number to format
Returns:
str: Formatted currency string
"""
return f"${value:,.2f}"
def get_feature_status(feature_name: str) -> Dict[str, Any]:
"""
Get the status of a feature.
Args:
feature_name (str): Name of the feature
Returns:
Dict[str, Any]: Feature status information
"""
# This will be expanded as we implement more features
implemented_features = {
"technical_analysis": True,
"options_analysis": True,
}
return {
"name": feature_name,
"implemented": implemented_features.get(feature_name, False),
"coming_soon": not implemented_features.get(feature_name, False)
}

View File

@@ -0,0 +1,208 @@
"""
Storage Module for AI Finance Report Generator
This module handles the persistence of user preferences and recent reports using JSON files.
"""
import json
import os
from typing import Dict, List, Any, Optional
from datetime import datetime
from pathlib import Path
class StorageManager:
"""Manages storage operations for user preferences and recent reports."""
def __init__(self, base_dir: Optional[str] = None):
"""
Initialize the storage manager.
Args:
base_dir (Optional[str]): Base directory for storage files
"""
if base_dir is None:
# Use user's home directory by default
self.base_dir = Path.home() / ".ai_finance"
else:
self.base_dir = Path(base_dir)
# Create storage directory if it doesn't exist
self.base_dir.mkdir(parents=True, exist_ok=True)
# Define file paths
self.prefs_file = self.base_dir / "preferences.json"
self.reports_file = self.base_dir / "recent_reports.json"
# Initialize files if they don't exist
self._initialize_storage()
def _initialize_storage(self) -> None:
"""Initialize storage files if they don't exist."""
if not self.prefs_file.exists():
self._save_preferences({})
if not self.reports_file.exists():
self._save_reports([])
def _save_preferences(self, preferences: Dict[str, Any]) -> None:
"""
Save user preferences to file.
Args:
preferences (Dict[str, Any]): User preferences to save
"""
with open(self.prefs_file, 'w') as f:
json.dump(preferences, f, indent=4)
def _load_preferences(self) -> Dict[str, Any]:
"""
Load user preferences from file.
Returns:
Dict[str, Any]: User preferences
"""
try:
with open(self.prefs_file, 'r') as f:
return json.load(f)
except (json.JSONDecodeError, FileNotFoundError):
return {}
def _save_reports(self, reports: List[Dict[str, Any]]) -> None:
"""
Save recent reports to file.
Args:
reports (List[Dict[str, Any]]): Recent reports to save
"""
with open(self.reports_file, 'w') as f:
json.dump(reports, f, indent=4)
def _load_reports(self) -> List[Dict[str, Any]]:
"""
Load recent reports from file.
Returns:
List[Dict[str, Any]]: Recent reports
"""
try:
with open(self.reports_file, 'r') as f:
return json.load(f)
except (json.JSONDecodeError, FileNotFoundError):
return []
def save_user_preferences(self, preferences: Dict[str, Any]) -> None:
"""
Save user preferences.
Args:
preferences (Dict[str, Any]): User preferences to save
"""
self._save_preferences(preferences)
def load_user_preferences(self) -> Dict[str, Any]:
"""
Load user preferences.
Returns:
Dict[str, Any]: User preferences
"""
return self._load_preferences()
def save_recent_reports(self, reports: List[Dict[str, Any]]) -> None:
"""
Save recent reports.
Args:
reports (List[Dict[str, Any]]): Recent reports to save
"""
# Convert datetime objects to ISO format strings
serialized_reports = []
for report in reports:
serialized_report = report.copy()
if isinstance(report.get('timestamp'), datetime):
serialized_report['timestamp'] = report['timestamp'].isoformat()
serialized_reports.append(serialized_report)
self._save_reports(serialized_reports)
def load_recent_reports(self) -> List[Dict[str, Any]]:
"""
Load recent reports.
Returns:
List[Dict[str, Any]]: Recent reports with datetime objects
"""
reports = self._load_reports()
# Convert ISO format strings back to datetime objects
for report in reports:
if isinstance(report.get('timestamp'), str):
report['timestamp'] = datetime.fromisoformat(report['timestamp'])
return reports
def clear_storage(self) -> None:
"""Clear all stored data."""
self._save_preferences({})
self._save_reports([])
def backup_storage(self, backup_dir: Optional[str] = None) -> None:
"""
Create a backup of the storage files.
Args:
backup_dir (Optional[str]): Directory to store backup files
"""
if backup_dir is None:
backup_dir = self.base_dir / "backups"
else:
backup_dir = Path(backup_dir)
backup_dir.mkdir(parents=True, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# Backup preferences
if self.prefs_file.exists():
backup_prefs = backup_dir / f"preferences_{timestamp}.json"
with open(self.prefs_file, 'r') as src, open(backup_prefs, 'w') as dst:
dst.write(src.read())
# Backup reports
if self.reports_file.exists():
backup_reports = backup_dir / f"recent_reports_{timestamp}.json"
with open(self.reports_file, 'r') as src, open(backup_reports, 'w') as dst:
dst.write(src.read())
def restore_from_backup(self, backup_file: str) -> None:
"""
Restore storage from a backup file.
Args:
backup_file (str): Path to the backup file
"""
backup_path = Path(backup_file)
if not backup_path.exists():
raise FileNotFoundError(f"Backup file not found: {backup_file}")
# Determine which type of backup file it is
if "preferences" in backup_path.name:
with open(backup_path, 'r') as src, open(self.prefs_file, 'w') as dst:
dst.write(src.read())
elif "recent_reports" in backup_path.name:
with open(backup_path, 'r') as src, open(self.reports_file, 'w') as dst:
dst.write(src.read())
else:
raise ValueError(f"Unknown backup file type: {backup_file}")
def get_storage_manager(base_dir: Optional[str] = None) -> StorageManager:
"""
Get a storage manager instance.
Args:
base_dir (Optional[str]): Base directory for storage files
Returns:
StorageManager: Storage manager instance
"""
return StorageManager(base_dir)

View File

@@ -1,91 +0,0 @@
import sys
import os
from textwrap import dedent
from pathlib import Path
from datetime import datetime
from loguru import logger
logger.remove()
logger.add(sys.stdout,
colorize=True,
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
)
from ..ai_web_researcher.finance_data_researcher import get_finance_data, get_fin_options_data
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
def write_basic_ta_report(symbol):
""" Write financial TA for given ticker symbol """
try:
symbol_fin_data = get_finance_data(symbol)
#get_visual_reports
fin_report = gen_finta_report(symbol_fin_data, symbol)
logger.info(f"Done: Final Technical Analysis for {symbol}:\n\n")
except Exception as err:
logger.error(f"Error: Failed to generate Financial report: {err}")
#fin_options_data = get_fin_options_data(symbol)
#options_report = gen_options_report(fin_options_data, symbol)
def gen_options_report(results_sentences, ticker):
""" Call LLM to generate options report """
prompt = f"""
You are a financial expert specializing in options trading and market sentiment analysis.
You have been provided with the following technical analysis of options data for the ticker symbol {ticker} with the nearest expiry date:
{chr(10).join(results_sentences)}
Based on this data, provide a comprehensive analysis of the options market for {ticker}.
Your analysis should include:
1. **Implied Volatility Interpretation:** Discuss the significance of the average implied volatility for both call and put options. What does it suggest about market expectations of future price movements?
2. **Volume and Open Interest Insights:** Analyze the volume and open interest for call and put options. What does this data reveal about current market positioning and potential future trading activity?
3. **Sentiment Analysis:** Evaluate the put-call ratio, implied volatility skew, and overall market sentiment. What do these indicators suggest about trader sentiment and potential future price direction?
4. **Potential Trading Strategies:** Based on your analysis, suggest potential options trading strategies that could be employed for {ticker}, considering the current market conditions and sentiment.
Please provide your analysis in a clear and concise manner, suitable for someone with a good understanding of options trading.
"""
logger.info("Generating Financial Technical report..")
try:
response = llm_text_gen(prompt)
return response
except Exception as err:
logger.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)
def gen_finta_report(last_day_summary, symbol):
""" Get AI to write TA report from given data """
prompt = f"""
You are a seasoned Technical Analysis (TA) expert, rivaling legends like Charles Dow, John Bollinger, and Alan Andrews.
Your deep understanding of market dynamics, coupled with mastery of technical indicators,
allows you to decipher complex patterns and offer precise predictions.
Your expertise extends to practical tools like the pandas_ta module, enabling you to extract valuable insights from raw data.
**Objective:**
Analyze the provided technical indicators for {symbol} on its last trading day and predict its price movement over the next few trading sessions.
**Instructions:**
1. **Identify Potential Trading Signals:** Highlight specific indicators suggesting bullish, bearish, or neutral signals. Explain the rationale behind each signal, referencing historical patterns or comparable market scenarios.
2. **Detect Patterns and Divergences:** Analyze the interplay between different indicators. Detect patterns like moving average crossovers, candlestick formations, or divergences between price action and indicators. Explain the significance of each pattern.
3. **Price Movement Prediction:** Based on your analysis, provide a clear prediction for {symbol}'s price movement in the next few days. State the expected direction (up, down, sideways) and potential price targets if identifiable.
4. **Risk Assessment:** Briefly discuss any potential risks or factors that could invalidate your predictions, promoting a balanced and informed perspective.
**Technical Indicators for {symbol} on the Last Trading Day:**
{last_day_summary}
Remember, your analysis should be detailed, insightful, and actionable for traders seeking to capitalize on market movements.
"""
logger.info("Generating Financial Technical report..")
try:
response = llm_text_gen(prompt)
return response
except Exception as err:
logger.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)

View File

@@ -1,13 +1,33 @@
"""
Smart Tweet Generator with modern UI components.
"""
import streamlit as st
import re
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 ..twitter_streamlit_ui import (
TweetForm,
TweetCard,
Theme,
save_to_session,
get_from_session,
show_success_message,
show_error_message,
show_info_message,
validate_tweet_content,
validate_hashtags,
validate_emojis,
calculate_engagement_score,
generate_tweet_metrics,
copy_to_clipboard,
create_download_button
)
# Constants
MAX_TWEET_LENGTH = 280
@@ -19,14 +39,6 @@ EMOJI_CATEGORIES = {
"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
@@ -61,63 +73,6 @@ def suggest_emojis(tone: str, count: int = 3) -> List[str]:
}
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)
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"
}
def generate_tweet_variations(
hook: str,
target_audience: str,
@@ -177,58 +132,14 @@ def generate_tweet_variations(
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."""
with st.container():
st.markdown(f"""
<div style='padding: 20px; border-radius: 10px; background-color: #f0f2f6; margin-bottom: 20px;'>
<h3 style='margin: 0;'>Tweet Variation {index + 1}</h3>
<p style='margin: 10px 0;'>{tweet['text']}</p>
<div style='display: flex; gap: 10px;'>
<span style='background-color: #e1e4e8; padding: 5px 10px; border-radius: 15px; font-size: 0.8em;'>
Score: {tweet['engagement_score']}%
</span>
</div>
</div>
""", 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")
# Apply theme
Theme().apply()
# Input section with improved UI
with st.expander("Tweet Parameters", expanded=True):
col1, col2 = st.columns(2)
@@ -291,34 +202,27 @@ def smart_tweet_generator():
# Display performance metrics
st.markdown("### 📊 Performance Metrics")
for tweet in tweets:
performance = predict_tweet_performance(tweet["text"], target_audience, tone)
# Calculate engagement score
engagement_score = calculate_engagement_score(
tweet["text"],
tweet["hashtags"],
tweet["emojis"],
tone
)
# Overall score with progress bar
st.progress(performance["overall_score"] / 100)
st.metric("Overall Score", f"{performance['overall_score']:.1f}%")
# Generate metrics
metrics = generate_tweet_metrics(engagement_score)
# 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))
# Display tweet card
TweetCard(
content=tweet["text"],
engagement_score=engagement_score,
hashtags=tweet["hashtags"],
emojis=tweet["emojis"],
metrics=metrics,
on_copy=lambda: copy_to_clipboard(tweet["text"]),
on_save=lambda: save_tweet(tweet)
).render()
st.markdown("---")
@@ -326,17 +230,23 @@ def smart_tweet_generator():
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"
)
create_download_button(
data=tweets,
filename=f"tweets_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
button_text="Export as JSON"
)
with col2:
if st.button("Copy All Tweets"):
tweet_texts = "\n\n".join(tweet["text"] for tweet in tweets)
st.code(tweet_texts)
copy_to_clipboard(tweet_texts)
show_success_message("All tweets copied to clipboard!")
def save_tweet(tweet: Dict):
"""Save tweet for later."""
tweets = get_from_session("tweets", [])
tweets.append(tweet)
save_to_session("tweets", tweets)
show_success_message("Tweet saved successfully!")
if __name__ == "__main__":
smart_tweet_generator()

View File

@@ -1,116 +1,29 @@
"""
Twitter Dashboard with modern UI components.
"""
import streamlit as st
import streamlit.components.v1 as components
from typing import Dict, List
import json
import base64
from datetime import datetime
from .tweet_generator import smart_tweet_generator
def add_bg_from_base64(base64_string):
"""Add background image using base64 string."""
return f'''
<style>
.stApp {{
background-image: url("data:image/png;base64,{base64_string}");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
}}
/* Enhanced styling for containers */
.element-container, .stMarkdown, .stButton {{
background-color: rgba(0, 0, 0, 0.7);
border-radius: 10px;
padding: 20px;
margin: 10px 0;
backdrop-filter: blur(10px);
}}
/* Typography enhancements */
h1, h2, h3 {{
color: #ffffff !important;
font-family: 'Helvetica Neue', sans-serif;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}}
p, li {{
color: #e0e0e0 !important;
font-family: 'Helvetica Neue', sans-serif;
}}
/* Button styling */
.stButton > button {{
background: linear-gradient(45deg, #1DA1F2, #0C85D0);
color: white;
border: none;
padding: 10px 20px;
border-radius: 25px;
font-weight: bold;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}}
.stButton > button:hover {{
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}}
/* Tab styling */
.stTabs [data-baseweb="tab-list"] {{
gap: 8px;
background-color: rgba(0, 0, 0, 0.6);
padding: 10px;
border-radius: 10px;
}}
.stTabs [data-baseweb="tab"] {{
background-color: transparent;
color: #ffffff;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 5px;
}}
.stTabs [data-baseweb="tab"]:hover {{
background-color: rgba(29, 161, 242, 0.2);
}}
/* Feature card styling */
.feature-card {{
background: linear-gradient(135deg, rgba(29, 161, 242, 0.1), rgba(0, 0, 0, 0.3));
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 20px;
border-radius: 15px;
margin-bottom: 20px;
transition: transform 0.3s ease;
}}
.feature-card:hover {{
transform: translateY(-5px);
}}
/* Status badge styling */
.status-badge {{
display: inline-block;
padding: 5px 15px;
border-radius: 20px;
font-size: 0.8em;
font-weight: bold;
text-transform: uppercase;
}}
.status-active {{
background: linear-gradient(45deg, #00C853, #69F0AE);
color: #000000;
}}
.status-coming-soon {{
background: linear-gradient(45deg, #FFD700, #FFA000);
color: #000000;
}}
</style>
'''
from .twitter_streamlit_ui import (
TwitterDashboard,
FeatureCard,
TweetForm,
SettingsForm,
Sidebar,
Header,
Tabs,
Breadcrumbs,
Theme,
save_to_session,
get_from_session,
clear_session,
show_success_message,
show_error_message
)
def load_feature_data() -> Dict:
"""Load feature data from a structured format."""
@@ -232,125 +145,167 @@ def load_feature_data() -> Dict:
}
}
def render_feature_card(feature: Dict) -> None:
"""Render a single feature card with its details."""
status_class = "status-active" if feature['status'] == 'active' else "status-coming-soon"
with st.container():
st.markdown(f"""
<div class='feature-card'>
<h3 style='color: #ffffff; margin: 0;'>{feature['icon']} {feature['name']}</h3>
<p style='color: #e0e0e0; margin: 10px 0;'>{feature['description']}</p>
<span class='status-badge {status_class}'>
{feature['status'].title()}
</span>
</div>
""", unsafe_allow_html=True)
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']}*")
col1, col2 = st.columns(2)
with col1:
render_feature_card(category['features'][0])
with col2:
render_feature_card(category['features'][1])
def get_space_background() -> str:
"""Return base64 encoded space-themed background."""
return """iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN8/+F9PQAJYgN4hWvGzQAAAABJRU5ErkJggg==""" # This is a placeholder. You'll need to replace with actual base64 image
def run_dashboard():
"""Main function to run the Twitter dashboard."""
# Add space-themed background
st.markdown(add_bg_from_base64(get_space_background()), unsafe_allow_html=True)
# Initialize dashboard
dashboard = TwitterDashboard()
# Enhanced Header with gradient text
st.markdown("""
<div style='text-align: center; padding: 40px 0;'>
<h1 style='
font-size: 3em;
background: linear-gradient(45deg, #1DA1F2, #ffffff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 10px;
'>🐦 Twitter AI Writer</h1>
<p style='
font-size: 1.2em;
color: #e0e0e0;
max-width: 600px;
margin: 0 auto;
'>Your all-in-one Twitter content creation and management platform.
Harness the power of AI to enhance your Twitter marketing strategy.</p>
</div>
""", unsafe_allow_html=True)
# Load feature data
features = load_feature_data()
# Create tabs with enhanced styling
tab1, tab2, tab3 = st.tabs(["🎯 Quick Actions", "📊 Analytics", "⚙️ Settings"])
with tab1:
st.markdown("<h2 style='color: #ffffff;'>🚀 Quick Actions</h2>", unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
if st.button("📝 Create New Tweet", use_container_width=True):
# Call the Smart Tweet Generator
smart_tweet_generator()
with col2:
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")
# 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"]()
# Setup navigation
sidebar = Sidebar(title="Twitter Tools")
sidebar.add_menu_item("Dashboard", "📊", "dashboard")
sidebar.add_menu_item("Tweet Generator", "✍️", "tweet_generator")
sidebar.add_menu_item("Analytics", "📈", "analytics")
sidebar.add_menu_item("Settings", "⚙️", "settings")
# Setup header
header = Header(
title="Twitter AI Writer",
subtitle="Your all-in-one Twitter content creation and management platform"
)
header.add_action("New Tweet", "✏️", lambda: save_to_session("current_page", "tweet_generator"))
header.add_action("Refresh", "🔄", lambda: st.experimental_rerun())
# Setup tabs
tabs = Tabs()
tabs.add_tab("Overview", "📊", lambda: render_overview(features))
tabs.add_tab("Recent Tweets", "🐦", lambda: render_recent_tweets())
tabs.add_tab("Analytics", "📈", lambda: render_analytics())
# Setup breadcrumbs
breadcrumbs = Breadcrumbs()
breadcrumbs.add_item("Home", "dashboard", "🏠")
breadcrumbs.add_item(get_from_session("current_page", "Dashboard").title())
# Render dashboard
dashboard.render()
# Enhanced Footer
st.markdown("---")
st.markdown("""
<div style='text-align: center; padding: 20px; background: rgba(0, 0, 0, 0.5); border-radius: 10px;'>
<p style='color: #ffffff; margin-bottom: 10px;'>Need assistance? We're here to help!</p>
<div style='display: flex; justify-content: center; gap: 20px;'>
<a href='#' style='
text-decoration: none;
color: #1DA1F2;
background: rgba(255, 255, 255, 0.1);
padding: 8px 20px;
border-radius: 20px;
transition: all 0.3s ease;
'>📚 Documentation</a>
<a href='#' style='
text-decoration: none;
color: #1DA1F2;
background: rgba(255, 255, 255, 0.1);
padding: 8px 20px;
border-radius: 20px;
transition: all 0.3s ease;
'>💬 Contact Support</a>
</div>
</div>
""", unsafe_allow_html=True)
def render_overview(features: Dict):
"""Render the overview tab content."""
# Feature cards
col1, col2, col3 = st.columns(3)
with col1:
FeatureCard(
title="Tweet Generator",
description="Create engaging tweets with AI assistance",
icon="✍️",
features=[
{
"name": "AI-Powered",
"description": "Generate tweets using advanced AI"
},
{
"name": "Customizable",
"description": "Adjust tone, length, and style"
}
],
on_click=lambda: save_to_session("current_page", "tweet_generator")
).render()
with col2:
FeatureCard(
title="Analytics",
description="Track your tweet performance",
icon="📈",
features=[
{
"name": "Engagement",
"description": "Monitor likes, retweets, and replies"
},
{
"name": "Growth",
"description": "Track follower growth over time"
}
]
).render()
with col3:
FeatureCard(
title="Settings",
description="Customize your experience",
icon="⚙️",
features=[
{
"name": "Preferences",
"description": "Set your default options"
},
{
"name": "API",
"description": "Configure Twitter API settings"
}
]
).render()
def render_recent_tweets():
"""Render the recent tweets tab content."""
# Tweet form
tweet_form = TweetForm(
on_submit=lambda: handle_tweet_submit()
)
tweet_form.render()
# Recent tweets
st.markdown("### Recent Tweets")
tweets = get_from_session("tweets", [])
for tweet in tweets:
TweetCard(
content=tweet["content"],
engagement_score=tweet["engagement_score"],
hashtags=tweet["hashtags"],
emojis=tweet["emojis"],
metrics=tweet["metrics"],
on_copy=lambda: copy_tweet(tweet),
on_save=lambda: save_tweet(tweet)
).render()
def render_analytics():
"""Render the analytics tab content."""
st.markdown("### Tweet Analytics")
st.info("Analytics features coming soon!")
def handle_tweet_submit():
"""Handle tweet form submission."""
# Get form data
content = get_from_session("tweet_content")
tone = get_from_session("tone")
length = get_from_session("length")
hashtags = get_from_session("hashtags")
emojis = get_from_session("emojis")
engagement_boost = get_from_session("engagement_boost")
# Create tweet object
tweet = {
"content": content,
"tone": tone,
"length": length,
"hashtags": hashtags,
"emojis": emojis,
"engagement_score": engagement_boost,
"metrics": {
"Engagement": engagement_boost,
"Reach": engagement_boost * 0.8,
"Growth": engagement_boost * 0.6
}
}
# Add to tweets list
tweets = get_from_session("tweets", [])
tweets.append(tweet)
save_to_session("tweets", tweets)
# Show success message
show_success_message("Tweet created successfully!")
def copy_tweet(tweet: Dict):
"""Copy tweet to clipboard."""
show_success_message("Tweet copied to clipboard!")
def save_tweet(tweet: Dict):
"""Save tweet for later."""
show_success_message("Tweet saved!")
if __name__ == "__main__":
run_dashboard()

View File

@@ -0,0 +1,203 @@
# Twitter Streamlit UI Components
This module provides a unified, reusable UI component library for all Twitter-related features in the AI Writer suite. It implements best practices for Streamlit UI development and ensures consistency across all Twitter tools.
## Structure
```
twitter_streamlit_ui/
├── components/ # Reusable UI components
│ ├── __init__.py
│ ├── cards.py # Card components (feature cards, tweet cards)
│ ├── forms.py # Form components (input forms, settings forms)
│ ├── navigation.py # Navigation components (tabs, sidebar)
│ ├── feedback.py # Feedback components (loading, errors, success)
│ └── layout.py # Layout components (containers, columns)
├── styles/ # CSS and styling
│ ├── __init__.py
│ ├── theme.py # Theme configuration
│ ├── components.py # Component-specific styles
│ └── animations.py # Animation styles
├── utils/ # UI utilities
│ ├── __init__.py
│ ├── state.py # State management
│ ├── validation.py # Input validation
│ └── performance.py # Performance optimizations
└── README.md # This file
```
## Key Improvements
### 1. Consistent UI Components
- **Card Components**
- Feature cards with consistent styling
- Tweet cards with standardized layout
- Status badges with unified design
- **Form Components**
- Standardized input forms
- Consistent validation feedback
- Unified error handling
- **Navigation Components**
- Consistent tab styling
- Standardized sidebar navigation
- Breadcrumb navigation
### 2. Enhanced User Experience
- **Loading States**
- Progress indicators for long operations
- Skeleton loading for content
- Smooth transitions between states
- **Feedback Mechanisms**
- Toast notifications for actions
- Error messages with recovery options
- Success confirmations
- **Responsive Design**
- Mobile-friendly layouts
- Adaptive column systems
- Flexible containers
### 3. Performance Optimizations
- **State Management**
- Centralized state handling
- Efficient data persistence
- Optimized re-rendering
- **Resource Loading**
- Lazy loading of components
- Optimized image loading
- Cached computations
### 4. Accessibility Features
- **Keyboard Navigation**
- Focus management
- Keyboard shortcuts
- ARIA labels
- **Visual Accessibility**
- High contrast themes
- Screen reader support
- Color blind friendly
### 5. Error Handling
- **Graceful Degradation**
- Fallback UI components
- Error boundaries
- Recovery options
- **User Feedback**
- Clear error messages
- Actionable suggestions
- Help documentation
## Usage
### Basic Component Usage
```python
from twitter_streamlit_ui.components.cards import FeatureCard
from twitter_streamlit_ui.components.forms import TweetForm
from twitter_streamlit_ui.styles.theme import apply_theme
# Apply theme
apply_theme()
# Use components
feature_card = FeatureCard(
title="Tweet Generator",
description="Create engaging tweets with AI",
icon="🐦"
)
feature_card.render()
tweet_form = TweetForm()
tweet_form.render()
```
### State Management
```python
from twitter_streamlit_ui.utils.state import StateManager
# Initialize state
state = StateManager()
state.initialize()
# Update state
state.update("current_tweet", tweet_data)
```
### Error Handling
```python
from twitter_streamlit_ui.components.feedback import ErrorBoundary
with ErrorBoundary():
# Your code here
pass
```
## Best Practices
1. **Component Reusability**
- Use existing components when possible
- Create new components only when necessary
- Follow the established patterns
2. **State Management**
- Use the StateManager for all state
- Avoid direct session state manipulation
- Keep state updates atomic
3. **Performance**
- Use lazy loading for heavy components
- Implement caching where appropriate
- Monitor render performance
4. **Accessibility**
- Include ARIA labels
- Ensure keyboard navigation
- Test with screen readers
5. **Error Handling**
- Use ErrorBoundary components
- Provide clear error messages
- Include recovery options
## Future Improvements
1. **Component Library**
- Add more specialized components
- Enhance existing components
- Create component documentation
2. **Theme System**
- Add more theme options
- Implement theme switching
- Create custom theme builder
3. **Performance**
- Implement virtual scrolling
- Add performance monitoring
- Optimize resource loading
4. **Testing**
- Add component tests
- Implement E2E tests
- Create test documentation
## Contributing
1. Follow the established patterns
2. Add tests for new components
3. Update documentation
4. Ensure accessibility
5. Optimize performance

View File

@@ -0,0 +1,66 @@
"""
Twitter Streamlit UI package.
Provides a modern and user-friendly interface for Twitter tools.
"""
from .dashboard import TwitterDashboard
from .components.cards import FeatureCard, TweetCard
from .components.forms import TweetForm, SettingsForm
from .components.navigation import Sidebar, Header, Tabs, Breadcrumbs
from .styles.theme import Theme
from .utils.helpers import (
save_to_session,
get_from_session,
clear_session,
save_to_file,
load_from_file,
format_datetime,
parse_datetime,
validate_tweet_content,
validate_hashtags,
validate_emojis,
calculate_engagement_score,
generate_tweet_metrics,
copy_to_clipboard,
show_success_message,
show_error_message,
show_info_message,
show_warning_message,
create_download_button,
create_upload_button
)
__version__ = "1.0.0"
__author__ = "AI Writer Team"
__all__ = [
"TwitterDashboard",
"FeatureCard",
"TweetCard",
"TweetForm",
"SettingsForm",
"Sidebar",
"Header",
"Tabs",
"Breadcrumbs",
"Theme",
"save_to_session",
"get_from_session",
"clear_session",
"save_to_file",
"load_from_file",
"format_datetime",
"parse_datetime",
"validate_tweet_content",
"validate_hashtags",
"validate_emojis",
"calculate_engagement_score",
"generate_tweet_metrics",
"copy_to_clipboard",
"show_success_message",
"show_error_message",
"show_info_message",
"show_warning_message",
"create_download_button",
"create_upload_button"
]

View File

@@ -0,0 +1,174 @@
"""
Card components for Twitter UI.
Provides consistent card layouts for features and tweets.
"""
import streamlit as st
from typing import Dict, Any, Optional, List
from ..styles.theme import Theme
class BaseCard:
"""Base class for all card components."""
def __init__(
self,
title: str,
description: str,
icon: Optional[str] = None,
status: Optional[str] = None,
actions: Optional[List[Dict[str, Any]]] = None
):
self.title = title
self.description = description
self.icon = icon
self.status = status
self.actions = actions or []
def render(self) -> None:
"""Render the card with consistent styling."""
with st.container():
st.markdown(f"""
<div class="card">
<div style="display: flex; align-items: center; margin-bottom: {Theme.SPACING["sm"]};">
{f'<span style="font-size: 1.5em; margin-right: {Theme.SPACING["sm"]};">{self.icon}</span>' if self.icon else ''}
<h3 style="margin: 0;">{self.title}</h3>
</div>
<p style="color: {Theme.COLORS["text_secondary"]}; margin: {Theme.SPACING["sm"]} 0;">
{self.description}
</p>
{f'<span class="status-badge status-{self.status}">{self.status.title()}</span>' if self.status else ''}
</div>
""", unsafe_allow_html=True)
if self.actions:
cols = st.columns(len(self.actions))
for i, action in enumerate(self.actions):
with cols[i]:
if st.button(
action["label"],
key=f"action_{i}",
help=action.get("help"),
use_container_width=True
):
action["callback"]()
class FeatureCard(BaseCard):
"""Card component for displaying features."""
def __init__(
self,
title: str,
description: str,
icon: str,
status: str = "active",
features: Optional[List[Dict[str, Any]]] = None,
on_click: Optional[callable] = None
):
super().__init__(title, description, icon, status)
self.features = features or []
self.on_click = on_click
def render(self) -> None:
"""Render the feature card with enhanced styling."""
with st.container():
st.markdown(f"""
<div class="card feature-card">
<div style="display: flex; align-items: center; margin-bottom: {Theme.SPACING["sm"]};">
<span style="font-size: 1.5em; margin-right: {Theme.SPACING["sm"]};">{self.icon}</span>
<h3 style="margin: 0;">{self.title}</h3>
</div>
<p style="color: {Theme.COLORS["text_secondary"]}; margin: {Theme.SPACING["sm"]} 0;">
{self.description}
</p>
<span class="status-badge status-{self.status}">{self.status.title()}</span>
</div>
""", unsafe_allow_html=True)
if self.features:
for feature in self.features:
st.markdown(f"""
<div style="margin-left: {Theme.SPACING["lg"]}; margin-top: {Theme.SPACING["sm"]};">
<p style="margin: 0;">
<strong>{feature["name"]}</strong>: {feature["description"]}
</p>
</div>
""", unsafe_allow_html=True)
if self.on_click:
if st.button(
f"Launch {self.title}",
key=f"launch_{self.title.lower().replace(' ', '_')}",
use_container_width=True
):
self.on_click()
class TweetCard(BaseCard):
"""Card component for displaying tweets."""
def __init__(
self,
content: str,
engagement_score: float,
hashtags: List[str],
emojis: List[str],
metrics: Optional[Dict[str, Any]] = None,
on_copy: Optional[callable] = None,
on_save: Optional[callable] = None
):
super().__init__(
title="Tweet",
description=content,
icon="🐦",
actions=[
{
"label": "Copy",
"callback": on_copy or (lambda: None),
"help": "Copy tweet to clipboard"
},
{
"label": "Save",
"callback": on_save or (lambda: None),
"help": "Save tweet for later"
}
]
)
self.engagement_score = engagement_score
self.hashtags = hashtags
self.emojis = emojis
self.metrics = metrics or {}
def render(self) -> None:
"""Render the tweet card with metrics and actions."""
with st.container():
st.markdown(f"""
<div class="card tweet-card">
<div style="display: flex; align-items: center; margin-bottom: {Theme.SPACING["sm"]};">
<span style="font-size: 1.5em; margin-right: {Theme.SPACING["sm"]};">{self.icon}</span>
<h3 style="margin: 0;">Tweet</h3>
</div>
<p style="color: {Theme.COLORS["text"]}; margin: {Theme.SPACING["sm"]} 0;">
{self.description}
</p>
<div style="display: flex; gap: {Theme.SPACING["sm"]}; margin: {Theme.SPACING["sm"]} 0;">
{''.join(f'<span style="color: {Theme.COLORS["primary"]};">{tag}</span>' for tag in self.hashtags)}
</div>
<div style="display: flex; gap: {Theme.SPACING["sm"]}; margin: {Theme.SPACING["sm"]} 0;">
{''.join(f'<span>{emoji}</span>' for emoji in self.emojis)}
</div>
<div style="margin-top: {Theme.SPACING["md"]};">
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>Engagement Score: {self.engagement_score}%</span>
<div style="display: flex; gap: {Theme.SPACING["sm"]};">
<button class="stButton" onclick="copyTweet()">Copy</button>
<button class="stButton" onclick="saveTweet()">Save</button>
</div>
</div>
</div>
</div>
""", unsafe_allow_html=True)
if self.metrics:
cols = st.columns(len(self.metrics))
for i, (metric, value) in enumerate(self.metrics.items()):
with cols[i]:
st.metric(metric, f"{value}%")

View File

@@ -0,0 +1,255 @@
"""
Form components for Twitter UI.
Provides consistent form layouts and input validation.
"""
import streamlit as st
from typing import Dict, Any, Optional, List, Callable
from ..styles.theme import Theme
class BaseForm:
"""Base class for all form components."""
def __init__(
self,
title: str,
description: Optional[str] = None,
on_submit: Optional[Callable] = None
):
self.title = title
self.description = description
self.on_submit = on_submit
self.fields: Dict[str, Any] = {}
def add_field(
self,
key: str,
label: str,
field_type: str = "text",
required: bool = False,
help_text: Optional[str] = None,
options: Optional[List[str]] = None,
default: Any = None,
validation: Optional[Callable] = None
) -> None:
"""Add a field to the form."""
self.fields[key] = {
"label": label,
"type": field_type,
"required": required,
"help_text": help_text,
"options": options,
"default": default,
"validation": validation
}
def validate(self) -> bool:
"""Validate all form fields."""
for key, field in self.fields.items():
if field["required"] and not st.session_state.get(key):
st.error(f"{field['label']} is required")
return False
if field["validation"] and not field["validation"](st.session_state.get(key)):
return False
return True
def render(self) -> None:
"""Render the form with consistent styling."""
with st.container():
st.markdown(f"""
<div class="form-container">
<h3 style="margin-bottom: {Theme.SPACING['sm']};">{self.title}</h3>
{f'<p style="color: {Theme.COLORS["text_secondary"]}; margin-bottom: {Theme.SPACING["md"]};">{self.description}</p>' if self.description else ''}
</div>
""", unsafe_allow_html=True)
for key, field in self.fields.items():
if field["type"] == "text":
st.text_input(
field["label"],
key=key,
help=field["help_text"],
value=field["default"]
)
elif field["type"] == "textarea":
st.text_area(
field["label"],
key=key,
help=field["help_text"],
value=field["default"]
)
elif field["type"] == "select":
st.selectbox(
field["label"],
options=field["options"],
key=key,
help=field["help_text"],
index=field["options"].index(field["default"]) if field["default"] in field["options"] else 0
)
elif field["type"] == "multiselect":
st.multiselect(
field["label"],
options=field["options"],
key=key,
help=field["help_text"],
default=field["default"]
)
elif field["type"] == "number":
st.number_input(
field["label"],
key=key,
help=field["help_text"],
value=field["default"]
)
elif field["type"] == "slider":
st.slider(
field["label"],
key=key,
help=field["help_text"],
value=field["default"]
)
elif field["type"] == "checkbox":
st.checkbox(
field["label"],
key=key,
help=field["help_text"],
value=field["default"]
)
if st.button("Submit", use_container_width=True):
if self.validate() and self.on_submit:
self.on_submit()
class TweetForm(BaseForm):
"""Form component for tweet generation."""
def __init__(
self,
on_submit: Optional[Callable] = None,
default_tone: str = "professional",
default_length: str = "medium"
):
super().__init__(
title="Generate Tweet",
description="Create engaging tweets with AI assistance",
on_submit=on_submit
)
# Add tweet content field
self.add_field(
"tweet_content",
"Tweet Content",
field_type="textarea",
required=True,
help_text="Enter your tweet content or topic"
)
# Add tone selection
self.add_field(
"tone",
"Tweet Tone",
field_type="select",
options=["professional", "casual", "humorous", "informative", "inspirational"],
default=default_tone,
help_text="Select the tone for your tweet"
)
# Add length selection
self.add_field(
"length",
"Tweet Length",
field_type="select",
options=["short", "medium", "long"],
default=default_length,
help_text="Select the desired length of your tweet"
)
# Add hashtag options
self.add_field(
"hashtags",
"Hashtags",
field_type="multiselect",
options=["#AI", "#Tech", "#Innovation", "#Business", "#Marketing"],
help_text="Select relevant hashtags"
)
# Add emoji options
self.add_field(
"emojis",
"Emojis",
field_type="multiselect",
options=["🚀", "💡", "🎯", "🔥", ""],
help_text="Select emojis to include"
)
# Add engagement settings
self.add_field(
"engagement_boost",
"Engagement Boost",
field_type="slider",
default=50,
help_text="Adjust the engagement optimization level"
)
class SettingsForm(BaseForm):
"""Form component for user settings."""
def __init__(
self,
on_submit: Optional[Callable] = None,
default_settings: Optional[Dict[str, Any]] = None
):
super().__init__(
title="User Settings",
description="Customize your Twitter experience",
on_submit=on_submit
)
settings = default_settings or {}
# Add API settings
self.add_field(
"api_key",
"Twitter API Key",
field_type="text",
help_text="Enter your Twitter API key",
default=settings.get("api_key", "")
)
# Add theme settings
self.add_field(
"theme",
"Theme",
field_type="select",
options=["light", "dark", "system"],
default=settings.get("theme", "system"),
help_text="Select your preferred theme"
)
# Add notification settings
self.add_field(
"notifications",
"Enable Notifications",
field_type="checkbox",
default=settings.get("notifications", True),
help_text="Receive notifications for important updates"
)
# Add auto-save settings
self.add_field(
"auto_save",
"Auto-save Drafts",
field_type="checkbox",
default=settings.get("auto_save", True),
help_text="Automatically save tweet drafts"
)
# Add language settings
self.add_field(
"language",
"Language",
field_type="select",
options=["English", "Spanish", "French", "German", "Japanese"],
default=settings.get("language", "English"),
help_text="Select your preferred language"
)

View File

@@ -0,0 +1,222 @@
"""
Navigation components for Twitter UI.
Provides consistent navigation and layout structure.
"""
import streamlit as st
from typing import Dict, Any, Optional, List
from ..styles.theme import Theme
class Sidebar:
"""Sidebar navigation component."""
def __init__(
self,
title: str = "Twitter Tools",
logo: Optional[str] = None,
menu_items: Optional[List[Dict[str, Any]]] = None
):
self.title = title
self.logo = logo
self.menu_items = menu_items or []
def add_menu_item(
self,
label: str,
icon: str,
page: str,
badge: Optional[str] = None
) -> None:
"""Add a menu item to the sidebar."""
self.menu_items.append({
"label": label,
"icon": icon,
"page": page,
"badge": badge
})
def render(self) -> None:
"""Render the sidebar with consistent styling."""
with st.sidebar:
# Logo and title
if self.logo:
st.image(self.logo, width=50)
st.markdown(f"""
<h2 style="margin: {Theme.SPACING["sm"]} 0;">{self.title}</h2>
""", unsafe_allow_html=True)
# Menu items
for item in self.menu_items:
st.markdown(f"""
<div class="menu-item">
<span style="font-size: 1.2em; margin-right: {Theme.SPACING["sm"]};">{item["icon"]}</span>
<span>{item["label"]}</span>
{f'<span class="badge">{item["badge"]}</span>' if item.get("badge") else ""}
</div>
""", unsafe_allow_html=True)
if st.button(
item["label"],
key=f"nav_{item['page']}",
use_container_width=True
):
st.session_state["current_page"] = item["page"]
class Header:
"""Header navigation component."""
def __init__(
self,
title: str,
subtitle: Optional[str] = None,
actions: Optional[List[Dict[str, Any]]] = None
):
self.title = title
self.subtitle = subtitle
self.actions = actions or []
def add_action(
self,
label: str,
icon: str,
callback: callable,
help_text: Optional[str] = None
) -> None:
"""Add an action button to the header."""
self.actions.append({
"label": label,
"icon": icon,
"callback": callback,
"help_text": help_text
})
def render(self) -> None:
"""Render the header with consistent styling."""
# Build action buttons HTML
action_buttons = []
for action in self.actions:
help_text = action.get("help_text", "")
action_buttons.append(f"""
<button class="header-action" title="{help_text}">
<span style="font-size: 1.2em; margin-right: {Theme.SPACING["xs"]};">{action["icon"]}</span>
{action["label"]}
</button>
""")
st.markdown(f"""
<div class="header">
<div>
<h1 style="margin: 0;">{self.title}</h1>
{f'<p style="color: {Theme.COLORS["text_secondary"]}; margin: {Theme.SPACING["xs"]} 0;">{self.subtitle}</p>' if self.subtitle else ""}
</div>
<div style="display: flex; gap: {Theme.SPACING["sm"]};">
{''.join(action_buttons)}
</div>
</div>
""", unsafe_allow_html=True)
# Add action button callbacks
for i, action in enumerate(self.actions):
if st.button(
action["label"],
key=f"header_action_{i}",
help=action.get("help_text")
):
action["callback"]()
class Tabs:
"""Tab navigation component."""
def __init__(
self,
tabs: Optional[List[Dict[str, Any]]] = None,
default_tab: Optional[str] = None
):
self.tabs = tabs or []
self.default_tab = default_tab
def add_tab(
self,
label: str,
icon: Optional[str] = None,
content: Optional[callable] = None
) -> None:
"""Add a tab to the navigation."""
self.tabs.append({
"label": label,
"icon": icon,
"content": content
})
def render(self) -> None:
"""Render the tabs with consistent styling."""
if not self.tabs:
return
# Create tab labels with icons
tab_labels = [
f"{tab['icon']} {tab['label']}" if tab.get('icon') else tab['label']
for tab in self.tabs
]
# Get current tab from session state or use default
current_tab = st.session_state.get("current_tab", self.default_tab or self.tabs[0]["label"])
# Render tabs
selected_tab = st.tabs(tab_labels)[tab_labels.index(current_tab)]
# Update session state
st.session_state["current_tab"] = current_tab
# Render tab content
with selected_tab:
for tab in self.tabs:
if tab["label"] == current_tab and tab.get("content"):
tab["content"]()
class Breadcrumbs:
"""Breadcrumb navigation component."""
def __init__(
self,
items: Optional[List[Dict[str, Any]]] = None
):
self.items = items or []
def add_item(
self,
label: str,
page: Optional[str] = None,
icon: Optional[str] = None
) -> None:
"""Add a breadcrumb item."""
self.items.append({
"label": label,
"page": page,
"icon": icon
})
def render(self) -> None:
"""Render the breadcrumbs with consistent styling."""
if not self.items:
return
breadcrumb_items = []
for i, item in enumerate(self.items):
icon_html = f'<span style="font-size: 1.2em; margin-right: {Theme.SPACING["xs"]};">{item["icon"]}</span>' if item.get("icon") else ""
link_html = f'<a href="#" onclick="setPage(\'{item["page"]}\')">{item["label"]}</a>' if item.get("page") else f'<span>{item["label"]}</span>'
separator = f'<span style="margin: 0 {Theme.SPACING["xs"]};">/</span>' if i < len(self.items) - 1 else ""
breadcrumb_items.append(f"""
<span class="breadcrumb-item">
{icon_html}
{link_html}
</span>
{separator}
""")
st.markdown(f"""
<div class="breadcrumbs">
{''.join(breadcrumb_items)}
</div>
""", unsafe_allow_html=True)

View File

@@ -0,0 +1,270 @@
"""
Main dashboard for Twitter UI.
Combines all UI components into a cohesive interface.
"""
import streamlit as st
from typing import Dict, Any, Optional
from .components.cards import FeatureCard, TweetCard
from .components.forms import TweetForm, SettingsForm
from .components.navigation import Sidebar, Header, Tabs, Breadcrumbs
from .styles.theme import Theme
class TwitterDashboard:
"""Main dashboard class for Twitter UI."""
def __init__(self):
self.setup_page()
self.setup_theme()
self.setup_navigation()
self.setup_state()
def setup_page(self) -> None:
"""Configure the Streamlit page settings."""
st.set_page_config(
page_title="Twitter Tools",
page_icon="🐦",
layout="wide",
initial_sidebar_state="expanded"
)
def setup_theme(self) -> None:
"""Apply the theme to the dashboard."""
Theme().apply()
def setup_navigation(self) -> None:
"""Setup navigation components."""
# Sidebar
self.sidebar = Sidebar(
title="Twitter Tools",
logo="assets/logo.png"
)
# Add menu items
self.sidebar.add_menu_item("Dashboard", "📊", "dashboard")
self.sidebar.add_menu_item("Tweet Generator", "✍️", "tweet_generator")
self.sidebar.add_menu_item("Analytics", "📈", "analytics")
self.sidebar.add_menu_item("Settings", "⚙️", "settings")
# Header
self.header = Header(
title="Twitter Dashboard",
subtitle="Create and manage your Twitter content"
)
# Add header actions
self.header.add_action(
"New Tweet",
"✏️",
self.create_new_tweet,
"Create a new tweet"
)
self.header.add_action(
"Refresh",
"🔄",
self.refresh_dashboard,
"Refresh dashboard data"
)
# Tabs
self.tabs = Tabs()
# Add tabs
self.tabs.add_tab("Overview", "📊", self.render_overview)
self.tabs.add_tab("Recent Tweets", "🐦", self.render_recent_tweets)
self.tabs.add_tab("Analytics", "📈", self.render_analytics)
# Breadcrumbs
self.breadcrumbs = Breadcrumbs()
def setup_state(self) -> None:
"""Initialize session state variables."""
if "current_page" not in st.session_state:
st.session_state["current_page"] = "dashboard"
if "current_tab" not in st.session_state:
st.session_state["current_tab"] = "Overview"
if "tweets" not in st.session_state:
st.session_state["tweets"] = []
def create_new_tweet(self) -> None:
"""Handle new tweet creation."""
st.session_state["current_page"] = "tweet_generator"
def refresh_dashboard(self) -> None:
"""Refresh dashboard data."""
st.experimental_rerun()
def render_overview(self) -> None:
"""Render the overview tab content."""
# Feature cards
col1, col2, col3 = st.columns(3)
with col1:
FeatureCard(
title="Tweet Generator",
description="Create engaging tweets with AI assistance",
icon="✍️",
features=[
{
"name": "AI-Powered",
"description": "Generate tweets using advanced AI"
},
{
"name": "Customizable",
"description": "Adjust tone, length, and style"
}
],
on_click=self.create_new_tweet
).render()
with col2:
FeatureCard(
title="Analytics",
description="Track your tweet performance",
icon="📈",
features=[
{
"name": "Engagement",
"description": "Monitor likes, retweets, and replies"
},
{
"name": "Growth",
"description": "Track follower growth over time"
}
]
).render()
with col3:
FeatureCard(
title="Settings",
description="Customize your experience",
icon="⚙️",
features=[
{
"name": "Preferences",
"description": "Set your default options"
},
{
"name": "API",
"description": "Configure Twitter API settings"
}
]
).render()
def render_recent_tweets(self) -> None:
"""Render the recent tweets tab content."""
# Tweet form
tweet_form = TweetForm(
on_submit=self.handle_tweet_submit
)
tweet_form.render()
# Recent tweets
st.markdown("### Recent Tweets")
for tweet in st.session_state["tweets"]:
TweetCard(
content=tweet["content"],
engagement_score=tweet["engagement_score"],
hashtags=tweet["hashtags"],
emojis=tweet["emojis"],
metrics=tweet["metrics"],
on_copy=lambda: self.copy_tweet(tweet),
on_save=lambda: self.save_tweet(tweet)
).render()
def render_analytics(self) -> None:
"""Render the analytics tab content."""
# Analytics content
st.markdown("### Tweet Analytics")
# Placeholder for analytics charts
st.info("Analytics features coming soon!")
def handle_tweet_submit(self) -> None:
"""Handle tweet form submission."""
# Get form data
content = st.session_state["tweet_content"]
tone = st.session_state["tone"]
length = st.session_state["length"]
hashtags = st.session_state["hashtags"]
emojis = st.session_state["emojis"]
engagement_boost = st.session_state["engagement_boost"]
# Create tweet object
tweet = {
"content": content,
"tone": tone,
"length": length,
"hashtags": hashtags,
"emojis": emojis,
"engagement_score": engagement_boost,
"metrics": {
"Engagement": engagement_boost,
"Reach": engagement_boost * 0.8,
"Growth": engagement_boost * 0.6
}
}
# Add to tweets list
st.session_state["tweets"].append(tweet)
# Show success message
st.success("Tweet created successfully!")
def copy_tweet(self, tweet: Dict[str, Any]) -> None:
"""Copy tweet to clipboard."""
st.write("Tweet copied to clipboard!")
def save_tweet(self, tweet: Dict[str, Any]) -> None:
"""Save tweet for later."""
st.write("Tweet saved!")
def render(self) -> None:
"""Render the complete dashboard."""
# Render navigation
self.sidebar.render()
self.header.render()
self.breadcrumbs.render()
# Render content based on current page
if st.session_state["current_page"] == "dashboard":
self.tabs.render()
elif st.session_state["current_page"] == "tweet_generator":
self.render_recent_tweets()
elif st.session_state["current_page"] == "analytics":
self.render_analytics()
elif st.session_state["current_page"] == "settings":
settings_form = SettingsForm(
on_submit=self.handle_settings_submit
)
settings_form.render()
def handle_settings_submit(self) -> None:
"""Handle settings form submission."""
# Get form data
api_key = st.session_state["api_key"]
theme = st.session_state["theme"]
notifications = st.session_state["notifications"]
auto_save = st.session_state["auto_save"]
language = st.session_state["language"]
# Save settings
st.session_state["settings"] = {
"api_key": api_key,
"theme": theme,
"notifications": notifications,
"auto_save": auto_save,
"language": language
}
# Show success message
st.success("Settings saved successfully!")
def main():
"""Main entry point for the dashboard."""
dashboard = TwitterDashboard()
dashboard.render()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,173 @@
"""
Theme configuration for Twitter UI components.
Provides consistent styling across all Twitter-related features.
"""
import streamlit as st
from typing import Dict, Any
class Theme:
"""Theme configuration for Twitter UI components."""
# Color palette
COLORS = {
"primary": "#1DA1F2", # Twitter blue
"secondary": "#14171A", # Dark blue
"background": "#15202B", # Dark background
"text": "#FFFFFF", # White text
"text_secondary": "#8899A6", # Gray text
"success": "#17BF63", # Green
"warning": "#FFAD1F", # Yellow
"error": "#E0245E", # Red
"border": "rgba(255, 255, 255, 0.1)", # Subtle border
}
# Typography
TYPOGRAPHY = {
"font_family": "'Helvetica Neue', sans-serif",
"font_sizes": {
"h1": "2.5rem",
"h2": "2rem",
"h3": "1.5rem",
"body": "1rem",
"small": "0.875rem",
},
"font_weights": {
"regular": 400,
"medium": 500,
"bold": 700,
},
}
# Spacing
SPACING = {
"xs": "0.25rem",
"sm": "0.5rem",
"md": "1rem",
"lg": "1.5rem",
"xl": "2rem",
}
# Border radius
BORDER_RADIUS = {
"sm": "4px",
"md": "8px",
"lg": "12px",
"xl": "16px",
"full": "9999px",
}
# Shadows
SHADOWS = {
"sm": "0 1px 2px rgba(0, 0, 0, 0.05)",
"md": "0 4px 6px rgba(0, 0, 0, 0.1)",
"lg": "0 10px 15px rgba(0, 0, 0, 0.1)",
"xl": "0 20px 25px rgba(0, 0, 0, 0.15)",
}
# Transitions
TRANSITIONS = {
"fast": "0.15s ease",
"normal": "0.3s ease",
"slow": "0.5s ease",
}
@classmethod
def get_css(cls) -> str:
"""Get the complete CSS for the theme."""
return f"""
/* Base styles */
.stApp {{
background-color: {cls.COLORS['background']};
color: {cls.COLORS['text']};
font-family: {cls.TYPOGRAPHY['font_family']};
}}
/* Typography */
h1, h2, h3, h4, h5, h6 {{
color: {cls.COLORS['text']};
font-family: {cls.TYPOGRAPHY['font_family']};
font-weight: {cls.TYPOGRAPHY['font_weights']['bold']};
}}
/* Buttons */
.stButton > button {{
background: linear-gradient(45deg, {cls.COLORS['primary']}, #0C85D0);
color: {cls.COLORS['text']};
border: none;
padding: {cls.SPACING['md']} {cls.SPACING['lg']};
border-radius: {cls.BORDER_RADIUS['full']};
font-weight: {cls.TYPOGRAPHY['font_weights']['medium']};
transition: all {cls.TRANSITIONS['normal']};
box-shadow: {cls.SHADOWS['md']};
}}
.stButton > button:hover {{
transform: translateY(-2px);
box-shadow: {cls.SHADOWS['lg']};
}}
/* Cards */
.card {{
background: rgba(255, 255, 255, 0.05);
border: 1px solid {cls.COLORS['border']};
border-radius: {cls.BORDER_RADIUS['lg']};
padding: {cls.SPACING['lg']};
margin-bottom: {cls.SPACING['md']};
backdrop-filter: blur(10px);
transition: transform {cls.TRANSITIONS['normal']};
}}
.card:hover {{
transform: translateY(-4px);
}}
/* Forms */
.stTextInput > div > div > input {{
background-color: rgba(255, 255, 255, 0.05);
border: 1px solid {cls.COLORS['border']};
border-radius: {cls.BORDER_RADIUS['md']};
color: {cls.COLORS['text']};
padding: {cls.SPACING['md']};
}}
/* Tabs */
.stTabs [data-baseweb="tab-list"] {{
gap: {cls.SPACING['sm']};
background-color: rgba(0, 0, 0, 0.2);
padding: {cls.SPACING['md']};
border-radius: {cls.BORDER_RADIUS['lg']};
}}
.stTabs [data-baseweb="tab"] {{
background-color: transparent;
color: {cls.COLORS['text']};
border: 1px solid {cls.COLORS['border']};
border-radius: {cls.BORDER_RADIUS['md']};
padding: {cls.SPACING['sm']} {cls.SPACING['md']};
}}
/* Status badges */
.status-badge {{
display: inline-block;
padding: {cls.SPACING['xs']} {cls.SPACING['md']};
border-radius: {cls.BORDER_RADIUS['full']};
font-size: {cls.TYPOGRAPHY['font_sizes']['small']};
font-weight: {cls.TYPOGRAPHY['font_weights']['medium']};
}}
.status-active {{
background: linear-gradient(45deg, {cls.COLORS['success']}, #69F0AE);
color: {cls.COLORS['secondary']};
}}
.status-coming-soon {{
background: linear-gradient(45deg, {cls.COLORS['warning']}, #FFA000);
color: {cls.COLORS['secondary']};
}}
"""
@classmethod
def apply(cls) -> None:
"""Apply the theme to the Streamlit app."""
st.markdown(f"<style>{cls.get_css()}</style>", unsafe_allow_html=True)

View File

@@ -0,0 +1,194 @@
"""
Utility functions for Twitter UI.
Provides helper functions for common operations.
"""
import streamlit as st
from typing import Dict, Any, List, Optional
import json
import os
from datetime import datetime
def save_to_session(key: str, value: Any) -> None:
"""Save a value to the session state."""
st.session_state[key] = value
def get_from_session(key: str, default: Any = None) -> Any:
"""Get a value from the session state."""
return st.session_state.get(key, default)
def clear_session() -> None:
"""Clear all session state variables."""
for key in list(st.session_state.keys()):
del st.session_state[key]
def save_to_file(data: Dict[str, Any], filename: str) -> None:
"""Save data to a JSON file."""
try:
with open(filename, 'w') as f:
json.dump(data, f, indent=4)
except Exception as e:
st.error(f"Error saving data: {str(e)}")
def load_from_file(filename: str) -> Optional[Dict[str, Any]]:
"""Load data from a JSON file."""
try:
if os.path.exists(filename):
with open(filename, 'r') as f:
return json.load(f)
except Exception as e:
st.error(f"Error loading data: {str(e)}")
return None
def format_datetime(dt: datetime) -> str:
"""Format a datetime object for display."""
return dt.strftime("%Y-%m-%d %H:%M:%S")
def parse_datetime(dt_str: str) -> Optional[datetime]:
"""Parse a datetime string."""
try:
return datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
except ValueError:
return None
def validate_tweet_content(content: str) -> bool:
"""Validate tweet content."""
if not content:
st.error("Tweet content cannot be empty")
return False
if len(content) > 280:
st.error("Tweet content cannot exceed 280 characters")
return False
return True
def validate_hashtags(hashtags: List[str]) -> bool:
"""Validate hashtags."""
for tag in hashtags:
if not tag.startswith('#'):
st.error(f"Hashtag {tag} must start with #")
return False
if len(tag) > 30:
st.error(f"Hashtag {tag} cannot exceed 30 characters")
return False
return True
def validate_emojis(emojis: List[str]) -> bool:
"""Validate emojis."""
for emoji in emojis:
if len(emoji) != 1:
st.error(f"Invalid emoji: {emoji}")
return False
return True
def calculate_engagement_score(
content: str,
hashtags: List[str],
emojis: List[str],
tone: str
) -> float:
"""Calculate engagement score for a tweet."""
score = 0.0
# Content length score (optimal length is 100-150 characters)
content_length = len(content)
if 100 <= content_length <= 150:
score += 30
elif 50 <= content_length <= 200:
score += 20
else:
score += 10
# Hashtag score (optimal number is 2-3 hashtags)
hashtag_count = len(hashtags)
if 2 <= hashtag_count <= 3:
score += 20
elif 1 <= hashtag_count <= 4:
score += 15
else:
score += 5
# Emoji score (optimal number is 1-2 emojis)
emoji_count = len(emojis)
if 1 <= emoji_count <= 2:
score += 20
elif 0 <= emoji_count <= 3:
score += 15
else:
score += 5
# Tone score
tone_scores = {
"professional": 15,
"casual": 20,
"humorous": 25,
"informative": 15,
"inspirational": 20
}
score += tone_scores.get(tone, 10)
return min(score, 100)
def generate_tweet_metrics(engagement_score: float) -> Dict[str, float]:
"""Generate metrics for a tweet based on engagement score."""
return {
"Engagement": engagement_score,
"Reach": engagement_score * 0.8,
"Growth": engagement_score * 0.6
}
def copy_to_clipboard(text: str) -> None:
"""Copy text to clipboard."""
try:
st.write(f'<script>navigator.clipboard.writeText("{text}")</script>', unsafe_allow_html=True)
except Exception as e:
st.error(f"Error copying to clipboard: {str(e)}")
def show_success_message(message: str) -> None:
"""Show a success message."""
st.success(message)
def show_error_message(message: str) -> None:
"""Show an error message."""
st.error(message)
def show_info_message(message: str) -> None:
"""Show an info message."""
st.info(message)
def show_warning_message(message: str) -> None:
"""Show a warning message."""
st.warning(message)
def create_download_button(
data: Dict[str, Any],
filename: str,
button_text: str = "Download"
) -> None:
"""Create a download button for data."""
try:
json_str = json.dumps(data, indent=4)
st.download_button(
label=button_text,
data=json_str,
file_name=filename,
mime="application/json"
)
except Exception as e:
st.error(f"Error creating download button: {str(e)}")
def create_upload_button(
on_upload: callable,
button_text: str = "Upload",
file_types: List[str] = ["json"]
) -> None:
"""Create an upload button for data."""
try:
uploaded_file = st.file_uploader(
button_text,
type=file_types
)
if uploaded_file is not None:
data = json.load(uploaded_file)
on_upload(data)
except Exception as e:
st.error(f"Error handling upload: {str(e)}")

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@ from .modules.tags_generator import write_yt_tags
from .modules.shorts_script_generator import write_yt_shorts
from .modules.community_post_generator import write_yt_community_post
from .modules.shorts_video_generator import write_yt_shorts_video
from .modules.channel_trailer_generator import write_yt_channel_trailer
def youtube_main_menu():
@@ -75,6 +76,15 @@ def youtube_main_menu():
"function": write_yt_shorts_video,
"status": "active"
},
{
"name": "Channel Trailer Generator",
"icon": "🎥",
"description": "Create compelling channel trailers that convert visitors into subscribers.",
"color": "#FF0000", # YouTube red
"category": "Content Creation",
"function": write_yt_channel_trailer,
"status": "active"
},
# Optimization Tools
{
@@ -135,15 +145,6 @@ def youtube_main_menu():
"function": None,
"status": "future"
},
{
"name": "Channel Trailer Generator",
"icon": "🎥",
"description": "Create compelling channel trailers that convert visitors into subscribers.",
"color": "#990000", # Even darker red for future
"category": "Future Tools",
"function": None,
"status": "future"
},
{
"name": "Video Series Planner",
"icon": "📅",