This commit is contained in:
IGNY8 VPS (Salman)
2025-12-04 17:58:41 +00:00
parent 40dfe20ead
commit 1521f3ff8c
13 changed files with 506 additions and 120 deletions

View File

@@ -117,7 +117,7 @@ class AutomationLogger:
Returns:
List of log lines (newest first)
"""
log_file = os.path.join(self._get_run_dir(account_id, site_id, run_id), 'automation_run.log')
log_file = os.path.join(self._get_run_dir(account_id, site_id, str(run_id)), 'automation_run.log')
if not os.path.exists(log_file):
return []

View File

@@ -218,6 +218,29 @@ class AutomationService:
keyword_ids = list(pending_keywords.values_list('id', flat=True))
for i in range(0, len(keyword_ids), actual_batch_size):
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({keywords_processed} keywords processed)"
)
# Save current progress
credits_used = self._get_credits_used() - credits_before
time_elapsed = self._format_time_elapsed(start_time)
self.run.stage_1_result = {
'keywords_processed': keywords_processed,
'clusters_created': clusters_created,
'batches_run': batches_run,
'credits_used': credits_used,
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.total_credits_used += credits_used
self.run.save()
return
try:
batch = keyword_ids[i:i + actual_batch_size]
batch_num = (i // actual_batch_size) + 1
@@ -354,13 +377,11 @@ class AutomationService:
stage_number, "Pre-stage validation passed: 0 keywords pending from Stage 1"
)
# Query clusters without ideas
# Query clusters with status='new'
pending_clusters = Clusters.objects.filter(
site=self.site,
status='new',
disabled=False
).exclude(
ideas__isnull=False
)
total_count = pending_clusters.count()
@@ -386,6 +407,33 @@ class AutomationService:
credits_before = self._get_credits_used()
for cluster in pending_clusters:
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({clusters_processed} clusters processed)"
)
# Save current progress
ideas_created = ContentIdeas.objects.filter(
site=self.site,
created_at__gte=self.run.started_at
).count()
credits_used = self._get_credits_used() - credits_before
time_elapsed = self._format_time_elapsed(start_time)
from django.utils import timezone
self.run.stage_2_result = {
'clusters_processed': clusters_processed,
'ideas_created': ideas_created,
'credits_used': credits_used,
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.total_credits_used += credits_used
self.run.save()
return
try:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
@@ -523,6 +571,29 @@ class AutomationService:
idea_list = list(pending_ideas)
for i in range(0, len(idea_list), batch_size):
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({ideas_processed} ideas processed, {tasks_created} tasks created)"
)
# Save current progress
time_elapsed = self._format_time_elapsed(start_time)
from django.utils import timezone
self.run.stage_3_result = {
'ideas_processed': ideas_processed,
'tasks_created': tasks_created,
'batches_run': batches_run,
'started_at': self.run.started_at.isoformat(),
'completed_at': timezone.now().isoformat(),
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.save()
return
batch = idea_list[i:i + batch_size]
batch_num = (i // batch_size) + 1
total_batches = (len(idea_list) + batch_size - 1) // batch_size
@@ -658,6 +729,33 @@ class AutomationService:
total_tasks = len(task_list)
for idx, task in enumerate(task_list, 1):
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({tasks_processed} tasks processed)"
)
# Save current progress
content_created = Content.objects.filter(
site=self.site,
created_at__gte=self.run.started_at
).count()
credits_used = self._get_credits_used() - credits_before
time_elapsed = self._format_time_elapsed(start_time)
from django.utils import timezone
self.run.stage_4_result = {
'tasks_processed': tasks_processed,
'content_created': content_created,
'credits_used': credits_used,
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.total_credits_used += credits_used
self.run.save()
return
try:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
@@ -834,6 +932,33 @@ class AutomationService:
total_content = len(content_list)
for idx, content in enumerate(content_list, 1):
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({content_processed} content processed)"
)
# Save current progress
prompts_created = Images.objects.filter(
site=self.site,
created_at__gte=self.run.started_at
).count()
credits_used = self._get_credits_used() - credits_before
time_elapsed = self._format_time_elapsed(start_time)
from django.utils import timezone
self.run.stage_5_result = {
'content_processed': content_processed,
'prompts_created': prompts_created,
'credits_used': credits_used,
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.total_credits_used += credits_used
self.run.save()
return
try:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
@@ -981,6 +1106,40 @@ class AutomationService:
total_images = len(image_list)
for idx, image in enumerate(image_list, 1):
# Check if automation should stop (paused or cancelled)
should_stop, reason = self._check_should_stop()
if should_stop:
self.logger.log_stage_progress(
self.run.run_id, self.account.id, self.site.id,
stage_number, f"Stage {reason} - saving progress ({images_processed} images processed)"
)
# Save current progress
images_generated = Images.objects.filter(
site=self.site,
status='completed',
created_at__gte=self.run.started_at
).count()
content_moved = Content.objects.filter(
site=self.site,
status='review',
updated_at__gte=self.run.started_at
).count()
credits_used = self._get_credits_used() - credits_before
time_elapsed = self._format_time_elapsed(start_time)
from django.utils import timezone
self.run.stage_6_result = {
'images_processed': images_processed,
'images_generated': images_generated,
'content_moved_to_review': content_moved,
'credits_used': credits_used,
'time_elapsed': time_elapsed,
'partial': True,
'stopped_reason': reason
}
self.run.total_credits_used += credits_used
self.run.save()
return
try:
content_title = image.content.title if image.content else 'Unknown'
self.logger.log_stage_progress(

View File

@@ -151,12 +151,6 @@ def resume_automation_task(self, run_id: str):
# Alias for continue_automation_task (same as resume)
continue_automation_task = resume_automation_task
# Release lock
from django.core.cache import cache
cache.delete(f'automation_lock_{run.site.id}')
raise
def _calculate_next_run(config: AutomationConfig, now: datetime) -> datetime:

View File

@@ -280,7 +280,7 @@ class AutomationViewSet(viewsets.ViewSet):
lines = int(request.query_params.get('lines', 100))
log_text = service.logger.get_activity_log(
run_id, run.account.id, run.site.id, lines
run.account.id, run.site.id, run_id, lines
)
return Response({

View File

@@ -0,0 +1,54 @@
"""
Billing API Views
Stub endpoints for billing pages
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class BillingViewSet(viewsets.ViewSet):
"""Billing endpoints"""
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['get'], url_path='account_balance')
def account_balance(self, request):
"""Get user's credit balance"""
return Response({
'credits': 0,
'subscription_plan': 'Free',
'monthly_credits_included': 0,
'bonus_credits': 0
})
@action(detail=False, methods=['get'])
def transactions(self, request):
"""List credit transactions"""
return Response({
'results': [],
'count': 0
})
@action(detail=False, methods=['get'])
def usage(self, request):
"""List credit usage"""
return Response({
'results': [],
'count': 0
})
class AdminBillingViewSet(viewsets.ViewSet):
"""Admin billing endpoints"""
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['get'])
def stats(self, request):
"""System billing stats"""
return Response({
'total_users': 0,
'active_users': 0,
'total_credits_issued': 0,
'total_credits_used': 0
})