new site
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
"""
|
||||
Odoo Directory CLI - Main entry point.
|
||||
|
||||
A Python CLI tool that generates static XML/HTML pages for Odoo partners,
|
||||
integrating with the existing odoo-expertos.com static website.
|
||||
|
||||
Usage:
|
||||
python -m directory.cli setup
|
||||
python -m directory.cli plan --country DE --cities berlin muenchen
|
||||
python -m directory.cli execute --plan <plan-id>
|
||||
python -m directory.cli export --country DE
|
||||
python -m directory.cli deploy
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
|
||||
import typer
|
||||
from rich.console import Console
|
||||
|
||||
from .config import get_settings
|
||||
from .utils.logger import setup_logging
|
||||
from .commands.setup import setup_command, print_schema
|
||||
from .commands.plan import plan_command, list_plans, show_plan
|
||||
from .commands.execute import execute_command
|
||||
from .commands.export import export_command
|
||||
from .commands.deploy import deploy_command, status_command
|
||||
|
||||
# Create CLI app
|
||||
app = typer.Typer(
|
||||
name="odoo-directory",
|
||||
help="Generate static pages for Odoo partner directory.",
|
||||
add_completion=False,
|
||||
)
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
# ==================== Setup Commands ====================
|
||||
|
||||
@app.command()
|
||||
def setup(
|
||||
seed_tags: bool = typer.Option(True, help="Seed default tags"),
|
||||
seed_germany: bool = typer.Option(True, help="Seed Germany cities"),
|
||||
schema: bool = typer.Option(False, "--schema", help="Print SQL schema only"),
|
||||
):
|
||||
"""
|
||||
Initialize database with schema and seed data.
|
||||
|
||||
Run this once when setting up a new installation.
|
||||
"""
|
||||
setup_logging()
|
||||
|
||||
if schema:
|
||||
print_schema()
|
||||
return
|
||||
|
||||
setup_command(seed_tags=seed_tags, seed_germany=seed_germany)
|
||||
|
||||
|
||||
# ==================== Plan Commands ====================
|
||||
|
||||
@app.command()
|
||||
def plan(
|
||||
country: str = typer.Option(..., "--country", "-c", help="Country code (e.g., DE)"),
|
||||
cities: Optional[List[str]] = typer.Option(None, "--cities", help="City slugs to include"),
|
||||
name: Optional[str] = typer.Option(None, "--name", "-n", help="Plan name"),
|
||||
):
|
||||
"""
|
||||
Create an execution plan for a country.
|
||||
|
||||
Specify which cities to process with --cities or process all cities
|
||||
in the country by default.
|
||||
"""
|
||||
setup_logging()
|
||||
plan_command(country=country, cities=cities, name=name)
|
||||
|
||||
|
||||
@app.command("plans")
|
||||
def plans_list():
|
||||
"""List all execution plans."""
|
||||
setup_logging()
|
||||
list_plans()
|
||||
|
||||
|
||||
@app.command("plan-show")
|
||||
def plan_show(
|
||||
plan_id: str = typer.Argument(..., help="Plan UUID"),
|
||||
):
|
||||
"""Show details of a specific plan."""
|
||||
setup_logging()
|
||||
show_plan(plan_id)
|
||||
|
||||
|
||||
# ==================== Execute Commands ====================
|
||||
|
||||
@app.command()
|
||||
def execute(
|
||||
plan_id: str = typer.Option(..., "--plan", "-p", help="Plan UUID"),
|
||||
step: Optional[str] = typer.Option(None, "--step", "-s", help="Specific step: scrape, enrich, content"),
|
||||
city: Optional[str] = typer.Option(None, "--city", help="Specific city slug"),
|
||||
dry_run: bool = typer.Option(False, "--dry-run", help="Don't make actual API calls"),
|
||||
):
|
||||
"""
|
||||
Execute a plan or specific step.
|
||||
|
||||
Runs the pipeline: scrape -> enrich -> content generation.
|
||||
"""
|
||||
setup_logging()
|
||||
execute_command(plan_id=plan_id, step=step, city=city, dry_run=dry_run)
|
||||
|
||||
|
||||
# ==================== Export Commands ====================
|
||||
|
||||
@app.command()
|
||||
def export(
|
||||
country: str = typer.Option(..., "--country", "-c", help="Country code"),
|
||||
city: Optional[str] = typer.Option(None, "--city", help="Specific city slug"),
|
||||
output: Optional[str] = typer.Option(None, "--output", "-o", help="Output directory"),
|
||||
):
|
||||
"""
|
||||
Export static files for a country.
|
||||
|
||||
Generates HTML pages, sitemaps, and tag JSON files.
|
||||
"""
|
||||
setup_logging()
|
||||
export_command(country=country, city=city, output_dir=output)
|
||||
|
||||
|
||||
# ==================== Deploy Commands ====================
|
||||
|
||||
@app.command()
|
||||
def deploy(
|
||||
message: Optional[str] = typer.Option(None, "--message", "-m", help="Commit message"),
|
||||
no_push: bool = typer.Option(False, "--no-push", help="Don't push to remote"),
|
||||
):
|
||||
"""
|
||||
Deploy changes via Git.
|
||||
|
||||
Commits exported files and pushes to trigger Vercel deployment.
|
||||
"""
|
||||
setup_logging()
|
||||
deploy_command(message=message, push=not no_push)
|
||||
|
||||
|
||||
@app.command()
|
||||
def status():
|
||||
"""Show git status of the project."""
|
||||
setup_logging()
|
||||
status_command()
|
||||
|
||||
|
||||
# ==================== Utility Commands ====================
|
||||
|
||||
@app.command()
|
||||
def info():
|
||||
"""Show configuration and environment info."""
|
||||
setup_logging()
|
||||
|
||||
console.print("\n[bold blue]Odoo Directory CLI[/bold blue]\n")
|
||||
|
||||
try:
|
||||
settings = get_settings()
|
||||
|
||||
console.print("[bold]Configuration:[/bold]")
|
||||
console.print(f" Export directory: {settings.export_dir}")
|
||||
console.print(f" Images directory: {settings.images_dir}")
|
||||
console.print(f" Templates directory: {settings.templates_dir}")
|
||||
console.print(f" Log level: {settings.log_level}")
|
||||
console.print(f" Batch size: {settings.batch_size}")
|
||||
|
||||
console.print("\n[bold]API Status:[/bold]")
|
||||
console.print(f" Supabase URL: {settings.supabase_url[:30]}...")
|
||||
console.print(f" Supabase Key: {'*' * 10}... (configured)")
|
||||
console.print(f" Apify Token: {'*' * 10}... (configured)")
|
||||
console.print(f" Firecrawl Key: {'*' * 10}... (configured)")
|
||||
console.print(f" Anthropic Key: {'*' * 10}... (configured)")
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"\n[red]Configuration error: {e}[/red]")
|
||||
console.print("\nMake sure you have a .env file with all required variables.")
|
||||
console.print("Copy .env.example to .env and fill in your API keys.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def test_connection():
|
||||
"""Test connections to all external services."""
|
||||
setup_logging()
|
||||
|
||||
console.print("\n[bold blue]Testing Connections[/bold blue]\n")
|
||||
|
||||
# Test Supabase
|
||||
console.print("Testing Supabase...")
|
||||
try:
|
||||
from .services.supabase import SupabaseService
|
||||
db = SupabaseService()
|
||||
regions = db.list_regions()
|
||||
console.print(f" [green]Connected! Found {len(regions)} regions.[/green]")
|
||||
except Exception as e:
|
||||
console.print(f" [red]Failed: {e}[/red]")
|
||||
|
||||
# Test Anthropic
|
||||
console.print("Testing Anthropic...")
|
||||
try:
|
||||
from anthropic import Anthropic
|
||||
settings = get_settings()
|
||||
client = Anthropic(api_key=settings.anthropic_api_key)
|
||||
# Just verify the key format
|
||||
console.print(" [green]API key configured.[/green]")
|
||||
except Exception as e:
|
||||
console.print(f" [red]Failed: {e}[/red]")
|
||||
|
||||
# Note about other services
|
||||
console.print("\nNote: Apify and Firecrawl are tested during actual execution.")
|
||||
|
||||
|
||||
# ==================== Main Entry ====================
|
||||
|
||||
def main():
|
||||
"""Main entry point for the CLI."""
|
||||
app()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user