karaoke-gen 0.101.0__py3-none-any.whl → 0.103.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@ import asyncio
15
15
  import logging
16
16
  import os
17
17
  import tempfile
18
- from typing import Optional, List, Dict, Any, Tuple
18
+ from typing import Optional, List, Dict, Any
19
19
 
20
20
  from fastapi import APIRouter, HTTPException, BackgroundTasks, Request, Depends
21
21
  from pydantic import BaseModel, Field, validator
@@ -34,6 +34,7 @@ from backend.services.audio_search_service import (
34
34
  DownloadError,
35
35
  )
36
36
  from backend.services.theme_service import get_theme_service
37
+ from backend.services.job_defaults_service import resolve_cdg_txt_defaults
37
38
  from backend.config import get_settings
38
39
  from backend.version import VERSION
39
40
  from backend.api.dependencies import require_auth
@@ -201,35 +202,6 @@ class AudioSelectResponse(BaseModel):
201
202
  selected_provider: str
202
203
 
203
204
 
204
- def _resolve_cdg_txt_defaults(
205
- theme_id: Optional[str],
206
- enable_cdg: Optional[bool],
207
- enable_txt: Optional[bool]
208
- ) -> Tuple[bool, bool]:
209
- """
210
- Resolve CDG/TXT settings based on theme and explicit settings.
211
-
212
- When a theme is selected, CDG and TXT are enabled by default.
213
- Explicit True/False values always override the default.
214
-
215
- Args:
216
- theme_id: Theme identifier (if any)
217
- enable_cdg: Explicit CDG setting (None means use default)
218
- enable_txt: Explicit TXT setting (None means use default)
219
-
220
- Returns:
221
- Tuple of (resolved_enable_cdg, resolved_enable_txt)
222
- """
223
- # Default based on whether theme is set
224
- default_enabled = theme_id is not None
225
-
226
- # Explicit values override defaults, None uses default
227
- resolved_cdg = enable_cdg if enable_cdg is not None else default_enabled
228
- resolved_txt = enable_txt if enable_txt is not None else default_enabled
229
-
230
- return resolved_cdg, resolved_txt
231
-
232
-
233
205
  def extract_request_metadata(request: Request, created_from: str = "audio_search") -> Dict[str, Any]:
234
206
  """Extract metadata from request for job tracking."""
235
207
  headers = dict(request.headers)
@@ -554,7 +526,7 @@ async def search_audio(
554
526
  logger.info(f"Applying default theme: {effective_theme_id}")
555
527
 
556
528
  # Resolve CDG/TXT defaults based on theme
557
- resolved_cdg, resolved_txt = _resolve_cdg_txt_defaults(
529
+ resolved_cdg, resolved_txt = resolve_cdg_txt_defaults(
558
530
  effective_theme_id, body.enable_cdg, body.enable_txt
559
531
  )
560
532
 
@@ -597,7 +569,7 @@ async def search_audio(
597
569
  # Tenant scoping
598
570
  tenant_id=tenant_config.id if tenant_config else None,
599
571
  )
600
- job = job_manager.create_job(job_create)
572
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
601
573
  job_id = job.job_id
602
574
 
603
575
  logger.info(f"Created job {job_id} for audio search: {body.artist} - {body.title}")
@@ -15,7 +15,6 @@ import json
15
15
  import logging
16
16
  import tempfile
17
17
  import os
18
- from dataclasses import dataclass
19
18
  from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks, Request, Body, Depends
20
19
  from pathlib import Path
21
20
  from typing import Optional, List, Dict, Any, Tuple
@@ -29,6 +28,11 @@ from backend.services.storage_service import StorageService
29
28
  from backend.services.worker_service import get_worker_service
30
29
  from backend.services.credential_manager import get_credential_manager, CredentialStatus
31
30
  from backend.services.theme_service import get_theme_service
31
+ from backend.services.job_defaults_service import (
32
+ get_effective_distribution_settings,
33
+ resolve_cdg_txt_defaults,
34
+ EffectiveDistributionSettings,
35
+ )
32
36
  from backend.config import get_settings
33
37
  from backend.version import VERSION
34
38
  from backend.services.metrics import metrics
@@ -264,75 +268,6 @@ async def _trigger_audio_worker_only(job_id: str) -> None:
264
268
  await worker_service.trigger_audio_worker(job_id)
265
269
 
266
270
 
267
- def _resolve_cdg_txt_defaults(
268
- theme_id: Optional[str],
269
- enable_cdg: Optional[bool],
270
- enable_txt: Optional[bool]
271
- ) -> Tuple[bool, bool]:
272
- """
273
- Resolve CDG/TXT settings based on theme and explicit settings.
274
-
275
- When a theme is selected, CDG and TXT are enabled by default.
276
- Explicit True/False values always override the default.
277
-
278
- Args:
279
- theme_id: Theme identifier (if any)
280
- enable_cdg: Explicit CDG setting (None means use default)
281
- enable_txt: Explicit TXT setting (None means use default)
282
-
283
- Returns:
284
- Tuple of (resolved_enable_cdg, resolved_enable_txt)
285
- """
286
- # Default based on whether theme is set
287
- default_enabled = theme_id is not None
288
-
289
- # Resolve with explicit override taking precedence
290
- resolved_cdg = enable_cdg if enable_cdg is not None else default_enabled
291
- resolved_txt = enable_txt if enable_txt is not None else default_enabled
292
-
293
- return resolved_cdg, resolved_txt
294
-
295
-
296
- @dataclass
297
- class EffectiveDistributionSettings:
298
- """Settings with defaults applied from environment variables."""
299
- dropbox_path: Optional[str]
300
- gdrive_folder_id: Optional[str]
301
- discord_webhook_url: Optional[str]
302
- brand_prefix: Optional[str]
303
-
304
-
305
- def _get_effective_distribution_settings(
306
- dropbox_path: Optional[str] = None,
307
- gdrive_folder_id: Optional[str] = None,
308
- discord_webhook_url: Optional[str] = None,
309
- brand_prefix: Optional[str] = None,
310
- ) -> EffectiveDistributionSettings:
311
- """
312
- Get distribution settings with defaults applied from environment variables.
313
-
314
- This ensures consistent handling of defaults across all job creation endpoints.
315
- Each parameter, if not provided (None), falls back to the corresponding
316
- environment variable configured in settings.
317
-
318
- Args:
319
- dropbox_path: Explicit Dropbox path or None for default
320
- gdrive_folder_id: Explicit Google Drive folder ID or None for default
321
- discord_webhook_url: Explicit Discord webhook URL or None for default
322
- brand_prefix: Explicit brand prefix or None for default
323
-
324
- Returns:
325
- EffectiveDistributionSettings with defaults applied
326
- """
327
- settings = get_settings()
328
- return EffectiveDistributionSettings(
329
- dropbox_path=dropbox_path or settings.default_dropbox_path,
330
- gdrive_folder_id=gdrive_folder_id or settings.default_gdrive_folder_id,
331
- discord_webhook_url=discord_webhook_url or settings.default_discord_webhook_url,
332
- brand_prefix=brand_prefix or settings.default_brand_prefix,
333
- )
334
-
335
-
336
271
  def _prepare_theme_for_job(
337
272
  job_id: str,
338
273
  theme_id: str,
@@ -503,7 +438,7 @@ async def upload_and_create_job(
503
438
  )
504
439
 
505
440
  # Apply default distribution settings from environment if not provided
506
- dist = _get_effective_distribution_settings(
441
+ dist = get_effective_distribution_settings(
507
442
  dropbox_path=dropbox_path,
508
443
  gdrive_folder_id=gdrive_folder_id,
509
444
  discord_webhook_url=discord_webhook_url,
@@ -581,7 +516,7 @@ async def upload_and_create_job(
581
516
  logger.info(f"Applying default theme: {effective_theme_id}")
582
517
 
583
518
  # Resolve CDG/TXT defaults based on theme
584
- resolved_cdg, resolved_txt = _resolve_cdg_txt_defaults(
519
+ resolved_cdg, resolved_txt = resolve_cdg_txt_defaults(
585
520
  effective_theme_id, enable_cdg, enable_txt
586
521
  )
587
522
 
@@ -644,7 +579,7 @@ async def upload_and_create_job(
644
579
  # Tenant scoping
645
580
  tenant_id=tenant_config.id if tenant_config else None,
646
581
  )
647
- job = job_manager.create_job(job_create)
582
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
648
583
  job_id = job.job_id
649
584
 
650
585
  # Record job creation metric
@@ -1077,7 +1012,7 @@ async def create_job_with_upload_urls(
1077
1012
  )
1078
1013
 
1079
1014
  # Apply default distribution settings from environment if not provided
1080
- dist = _get_effective_distribution_settings(
1015
+ dist = get_effective_distribution_settings(
1081
1016
  dropbox_path=body.dropbox_path,
1082
1017
  gdrive_folder_id=body.gdrive_folder_id,
1083
1018
  discord_webhook_url=body.discord_webhook_url,
@@ -1135,7 +1070,7 @@ async def create_job_with_upload_urls(
1135
1070
  logger.info(f"Applying default theme: {effective_theme_id}")
1136
1071
 
1137
1072
  # Resolve CDG/TXT defaults based on theme
1138
- resolved_cdg, resolved_txt = _resolve_cdg_txt_defaults(
1073
+ resolved_cdg, resolved_txt = resolve_cdg_txt_defaults(
1139
1074
  effective_theme_id, body.enable_cdg, body.enable_txt
1140
1075
  )
1141
1076
 
@@ -1175,7 +1110,7 @@ async def create_job_with_upload_urls(
1175
1110
  # Tenant scoping
1176
1111
  tenant_id=tenant_config.id if tenant_config else None,
1177
1112
  )
1178
- job = job_manager.create_job(job_create)
1113
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
1179
1114
  job_id = job.job_id
1180
1115
 
1181
1116
  # Record job creation metric
@@ -1519,7 +1454,7 @@ async def create_job_from_url(
1519
1454
  )
1520
1455
 
1521
1456
  # Apply default distribution settings from environment if not provided
1522
- dist = _get_effective_distribution_settings(
1457
+ dist = get_effective_distribution_settings(
1523
1458
  dropbox_path=body.dropbox_path,
1524
1459
  gdrive_folder_id=body.gdrive_folder_id,
1525
1460
  discord_webhook_url=body.discord_webhook_url,
@@ -1578,7 +1513,7 @@ async def create_job_from_url(
1578
1513
  logger.info(f"Applying default theme: {effective_theme_id}")
1579
1514
 
1580
1515
  # Resolve CDG/TXT defaults based on theme
1581
- resolved_cdg, resolved_txt = _resolve_cdg_txt_defaults(
1516
+ resolved_cdg, resolved_txt = resolve_cdg_txt_defaults(
1582
1517
  effective_theme_id, body.enable_cdg, body.enable_txt
1583
1518
  )
1584
1519
 
@@ -1615,7 +1550,7 @@ async def create_job_from_url(
1615
1550
  # Tenant scoping
1616
1551
  tenant_id=tenant_config.id if tenant_config else None,
1617
1552
  )
1618
- job = job_manager.create_job(job_create)
1553
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
1619
1554
  job_id = job.job_id
1620
1555
 
1621
1556
  # Record job creation metric
@@ -1635,7 +1570,7 @@ async def create_job_from_url(
1635
1570
  update_data['youtube_description_template'] = youtube_desc
1636
1571
  job_manager.update_job(job_id, update_data)
1637
1572
  logger.info(f"Applied theme '{effective_theme_id}' to job {job_id}")
1638
-
1573
+
1639
1574
  logger.info(f"Created URL-based job {job_id} for URL: {body.url}")
1640
1575
  if artist:
1641
1576
  logger.info(f" Artist: {artist}")
@@ -1789,7 +1724,7 @@ async def create_finalise_only_job(
1789
1724
  )
1790
1725
 
1791
1726
  # Apply default distribution settings
1792
- dist = _get_effective_distribution_settings(
1727
+ dist = get_effective_distribution_settings(
1793
1728
  dropbox_path=body.dropbox_path,
1794
1729
  gdrive_folder_id=body.gdrive_folder_id,
1795
1730
  discord_webhook_url=body.discord_webhook_url,
@@ -1844,7 +1779,7 @@ async def create_finalise_only_job(
1844
1779
  logger.info(f"Applying default theme: {effective_theme_id}")
1845
1780
 
1846
1781
  # Resolve CDG/TXT defaults based on theme
1847
- resolved_cdg, resolved_txt = _resolve_cdg_txt_defaults(
1782
+ resolved_cdg, resolved_txt = resolve_cdg_txt_defaults(
1848
1783
  effective_theme_id, body.enable_cdg, body.enable_txt
1849
1784
  )
1850
1785
 
@@ -1876,7 +1811,7 @@ async def create_finalise_only_job(
1876
1811
  # Tenant scoping
1877
1812
  tenant_id=tenant_config.id if tenant_config else None,
1878
1813
  )
1879
- job = job_manager.create_job(job_create)
1814
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
1880
1815
  job_id = job.job_id
1881
1816
 
1882
1817
  # Record job creation metric
@@ -118,8 +118,8 @@ async def create_job(
118
118
  webhook_url=request.webhook_url,
119
119
  user_email=user_email
120
120
  )
121
- job = job_manager.create_job(job_create)
122
-
121
+ job = job_manager.create_job(job_create, is_admin=auth_result.is_admin)
122
+
123
123
  # Record job creation metric
124
124
  metrics.record_job_created(job.job_id, source="url")
125
125