Fixed: auto asks for money_site_url on script run if not provided
parent
26b6e75448
commit
b168d33e2d
|
|
@ -13,6 +13,12 @@ Usage:
|
||||||
uv run python scripts/post_process_batch.py --project-id 1 --all-tiers
|
uv run python scripts/post_process_batch.py --project-id 1 --all-tiers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
project_root = Path(__file__).parent.parent
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import os
|
import os
|
||||||
from src.database.session import db_manager
|
from src.database.session import db_manager
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,12 @@ Usage:
|
||||||
uv run python scripts/set_money_site_url.py --project-id 1 --url "https://www.mysite.com"
|
uv run python scripts/set_money_site_url.py --project-id 1 --url "https://www.mysite.com"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
project_root = Path(__file__).parent.parent
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from src.database.session import db_manager
|
from src.database.session import db_manager
|
||||||
from src.database.repositories import ProjectRepository
|
from src.database.repositories import ProjectRepository
|
||||||
|
|
|
||||||
|
|
@ -774,10 +774,11 @@ def sync_sites(admin_user: Optional[str], admin_password: Optional[str], dry_run
|
||||||
@app.command()
|
@app.command()
|
||||||
@click.option('--file', '-f', 'file_path', required=True, type=click.Path(exists=True), help='Path to CORA .xlsx file')
|
@click.option('--file', '-f', 'file_path', required=True, type=click.Path(exists=True), help='Path to CORA .xlsx file')
|
||||||
@click.option('--name', '-n', required=True, help='Project name')
|
@click.option('--name', '-n', required=True, help='Project name')
|
||||||
|
@click.option('--money-site-url', '-m', help='Money site URL (e.g., https://example.com)')
|
||||||
@click.option('--custom-anchors', '-a', help='Comma-separated list of custom anchor text (optional)')
|
@click.option('--custom-anchors', '-a', help='Comma-separated list of custom anchor text (optional)')
|
||||||
@click.option('--username', '-u', help='Username for authentication')
|
@click.option('--username', '-u', help='Username for authentication')
|
||||||
@click.option('--password', '-p', help='Password for authentication')
|
@click.option('--password', '-p', help='Password for authentication')
|
||||||
def ingest_cora(file_path: str, name: str, custom_anchors: Optional[str], username: Optional[str], password: Optional[str]):
|
def ingest_cora(file_path: str, name: str, money_site_url: Optional[str], custom_anchors: Optional[str], username: Optional[str], password: Optional[str]):
|
||||||
"""Ingest a CORA .xlsx report and create a new project"""
|
"""Ingest a CORA .xlsx report and create a new project"""
|
||||||
try:
|
try:
|
||||||
if not username or not password:
|
if not username or not password:
|
||||||
|
|
@ -809,7 +810,26 @@ def ingest_cora(file_path: str, name: str, custom_anchors: Optional[str], userna
|
||||||
click.echo(f"Entities Found: {len(cora_data['entities'])}")
|
click.echo(f"Entities Found: {len(cora_data['entities'])}")
|
||||||
click.echo(f"Related Searches: {len(cora_data['related_searches'])}")
|
click.echo(f"Related Searches: {len(cora_data['related_searches'])}")
|
||||||
|
|
||||||
|
# Prompt for money_site_url if not provided
|
||||||
|
if not money_site_url:
|
||||||
|
money_site_url = click.prompt(
|
||||||
|
"\nEnter money site URL (required for tiered linking)",
|
||||||
|
type=str
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate money_site_url
|
||||||
|
if not money_site_url.startswith('http://') and not money_site_url.startswith('https://'):
|
||||||
|
click.echo("Error: Money site URL must start with http:// or https://", err=True)
|
||||||
|
raise click.Abort()
|
||||||
|
|
||||||
|
# Clean up URL (remove trailing slash)
|
||||||
|
money_site_url = money_site_url.rstrip('/')
|
||||||
|
|
||||||
click.echo(f"\nCreating project: {name}")
|
click.echo(f"\nCreating project: {name}")
|
||||||
|
click.echo(f"Money Site URL: {money_site_url}")
|
||||||
|
|
||||||
|
# Add money_site_url to cora_data
|
||||||
|
cora_data['money_site_url'] = money_site_url
|
||||||
|
|
||||||
project_repo = ProjectRepository(session)
|
project_repo = ProjectRepository(session)
|
||||||
project = project_repo.create(
|
project = project_repo.create(
|
||||||
|
|
@ -820,6 +840,7 @@ def ingest_cora(file_path: str, name: str, custom_anchors: Optional[str], userna
|
||||||
|
|
||||||
click.echo(f"\nSuccess: Project '{project.name}' created (ID: {project.id})")
|
click.echo(f"\nSuccess: Project '{project.name}' created (ID: {project.id})")
|
||||||
click.echo(f"Main Keyword: {project.main_keyword}")
|
click.echo(f"Main Keyword: {project.main_keyword}")
|
||||||
|
click.echo(f"Money Site URL: {project.money_site_url}")
|
||||||
click.echo(f"Entities: {len(project.entities or [])}")
|
click.echo(f"Entities: {len(project.entities or [])}")
|
||||||
click.echo(f"Related Searches: {len(project.related_searches or [])}")
|
click.echo(f"Related Searches: {len(project.related_searches or [])}")
|
||||||
|
|
||||||
|
|
@ -983,24 +1004,24 @@ def generate_batch(
|
||||||
|
|
||||||
@app.command("deploy-batch")
|
@app.command("deploy-batch")
|
||||||
@click.option('--batch-id', '-b', required=True, type=int, help='Project/batch ID to deploy')
|
@click.option('--batch-id', '-b', required=True, type=int, help='Project/batch ID to deploy')
|
||||||
@click.option('--admin-user', help='Admin username for authentication')
|
@click.option('--username', '-u', help='Username for authentication')
|
||||||
@click.option('--admin-password', help='Admin password for authentication')
|
@click.option('--password', '-p', help='Password for authentication')
|
||||||
@click.option('--continue-on-error', is_flag=True, default=True,
|
@click.option('--continue-on-error', is_flag=True, default=True,
|
||||||
help='Continue if file fails (default: True)')
|
help='Continue if file fails (default: True)')
|
||||||
@click.option('--dry-run', is_flag=True, help='Preview what would be deployed')
|
@click.option('--dry-run', is_flag=True, help='Preview what would be deployed')
|
||||||
def deploy_batch(
|
def deploy_batch(
|
||||||
batch_id: int,
|
batch_id: int,
|
||||||
admin_user: Optional[str],
|
username: Optional[str],
|
||||||
admin_password: Optional[str],
|
password: Optional[str],
|
||||||
continue_on_error: bool,
|
continue_on_error: bool,
|
||||||
dry_run: bool
|
dry_run: bool
|
||||||
):
|
):
|
||||||
"""Deploy all content in a batch to cloud storage"""
|
"""Deploy all content in a batch to cloud storage"""
|
||||||
try:
|
try:
|
||||||
if not admin_user or not admin_password:
|
if not username or not password:
|
||||||
admin_user, admin_password = prompt_admin_credentials()
|
username, password = prompt_admin_credentials()
|
||||||
|
|
||||||
admin = authenticate_admin(admin_user, admin_password)
|
admin = authenticate_admin(username, password)
|
||||||
if not admin:
|
if not admin:
|
||||||
click.echo("Error: Authentication failed or insufficient permissions", err=True)
|
click.echo("Error: Authentication failed or insufficient permissions", err=True)
|
||||||
raise click.Abort()
|
raise click.Abort()
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,7 @@ class ContentGenerator:
|
||||||
)
|
)
|
||||||
|
|
||||||
content = content.strip()
|
content = content.strip()
|
||||||
|
content = self._clean_markdown_fences(content)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
self._save_debug_output(
|
self._save_debug_output(
|
||||||
|
|
@ -294,6 +295,7 @@ class ContentGenerator:
|
||||||
)
|
)
|
||||||
|
|
||||||
augmented = augmented.strip()
|
augmented = augmented.strip()
|
||||||
|
augmented = self._clean_markdown_fences(augmented)
|
||||||
|
|
||||||
if debug and project_id:
|
if debug and project_id:
|
||||||
self._save_debug_output(
|
self._save_debug_output(
|
||||||
|
|
@ -352,6 +354,24 @@ class ContentGenerator:
|
||||||
print(f"Error applying template to content {content_id}: {e}")
|
print(f"Error applying template to content {content_id}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _clean_markdown_fences(self, content: str) -> str:
|
||||||
|
"""
|
||||||
|
Remove markdown code fences from AI-generated content
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content: Raw content that may contain ```html or ``` markers
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Cleaned content without markdown code fences
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
content = re.sub(r'^```html\s*\n?', '', content, flags=re.MULTILINE)
|
||||||
|
content = re.sub(r'^```\s*$', '', content, flags=re.MULTILINE)
|
||||||
|
content = re.sub(r'\n```\s*$', '', content)
|
||||||
|
|
||||||
|
return content.strip()
|
||||||
|
|
||||||
def _save_debug_output(
|
def _save_debug_output(
|
||||||
self,
|
self,
|
||||||
project_id: int,
|
project_id: int,
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,7 @@
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
nav {
|
||||||
nav {
|
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue