Merge remote-tracking branch 'origin/codex/update-backlink-outreach-for-campaign-validation'

This commit is contained in:
ajaysi
2026-06-03 18:22:35 +05:30
2 changed files with 31 additions and 3 deletions

View File

@@ -22,7 +22,10 @@ from services.backlink_outreach_models import (
SuppressionAddRequest, SuppressionAddRequest,
) )
from services.backlink_outreach_service import backlink_outreach_service from services.backlink_outreach_service import backlink_outreach_service
from services.backlink_outreach_storage import BacklinkOutreachStorageService from services.backlink_outreach_storage import (
BacklinkCampaignNotFoundError,
BacklinkOutreachStorageService,
)
from services.backlink_outreach_sender import backlink_outreach_sender from services.backlink_outreach_sender import backlink_outreach_sender
from services.backlink_outreach_reply_monitor import backlink_outreach_reply_monitor from services.backlink_outreach_reply_monitor import backlink_outreach_reply_monitor
from services.backlink_outreach_template_generator import ( from services.backlink_outreach_template_generator import (
@@ -87,9 +90,14 @@ async def discover_deep_backlink_opportunities(
): ):
"""Enhanced discovery using Exa neural search + DuckDuckGo with full-page scraping.""" """Enhanced discovery using Exa neural search + DuckDuckGo with full-page scraping."""
user_id = _resolve_user_id(current_user) user_id = _resolve_user_id(current_user)
result = await backlink_outreach_service.deep_discover(payload.keyword, payload.max_results) storage = None
if payload.campaign_id: if payload.campaign_id:
storage = BacklinkOutreachStorageService() storage = BacklinkOutreachStorageService()
if not storage.get_campaign(payload.campaign_id, user_id):
raise HTTPException(status_code=404, detail="Campaign not found")
result = await backlink_outreach_service.deep_discover(payload.keyword, payload.max_results)
if payload.campaign_id:
saved = 0 saved = 0
save_failed = 0 save_failed = 0
for opp in result.get("opportunities", []): for opp in result.get("opportunities", []):
@@ -183,7 +191,9 @@ async def add_campaign_lead(
notes=payload.notes, notes=payload.notes,
) )
return lead return lead
except Exception as e: except BacklinkCampaignNotFoundError:
raise HTTPException(status_code=404, detail="Campaign not found")
except Exception:
raise HTTPException(status_code=500, detail="Failed to add lead") raise HTTPException(status_code=500, detail="Failed to add lead")

View File

@@ -16,6 +16,10 @@ from models.backlink_outreach_models import (
) )
class BacklinkCampaignNotFoundError(RuntimeError):
"""Raised when a backlink campaign is missing or not owned by the user."""
class BacklinkOutreachStorageService: class BacklinkOutreachStorageService:
_NEW_LEAD_COLUMNS = [ _NEW_LEAD_COLUMNS = [
"url", "page_title", "snippet", "confidence_score", "discovery_source", "notes" "url", "page_title", "snippet", "confidence_score", "discovery_source", "notes"
@@ -120,6 +124,14 @@ class BacklinkOutreachStorageService:
# -- Lead CRUD -- # -- Lead CRUD --
def _campaign_belongs_to_user(self, db, campaign_id: str, user_id: str) -> bool:
return (
db.query(BacklinkCampaign)
.filter(BacklinkCampaign.id == campaign_id, BacklinkCampaign.user_id == user_id)
.first()
is not None
)
def add_lead( def add_lead(
self, self,
campaign_id: str, campaign_id: str,
@@ -138,6 +150,9 @@ class BacklinkOutreachStorageService:
if not db: if not db:
raise RuntimeError("Database session unavailable") raise RuntimeError("Database session unavailable")
try: try:
if not self._campaign_belongs_to_user(db, campaign_id, user_id):
raise BacklinkCampaignNotFoundError("Campaign not found")
lead = BacklinkLead( lead = BacklinkLead(
id=f"bl_{uuid4().hex[:16]}", id=f"bl_{uuid4().hex[:16]}",
campaign_id=campaign_id, campaign_id=campaign_id,
@@ -164,6 +179,9 @@ class BacklinkOutreachStorageService:
if not db: if not db:
raise RuntimeError("Database session unavailable") raise RuntimeError("Database session unavailable")
try: try:
if not self._campaign_belongs_to_user(db, campaign_id, user_id):
raise BacklinkCampaignNotFoundError("Campaign not found")
added = [] added = []
for data in leads_data: for data in leads_data:
lead = BacklinkLead( lead = BacklinkLead(