Kgshop commited on
Commit
a45e8a6
·
verified ·
1 Parent(s): def234f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -152
app.py CHANGED
@@ -1271,7 +1271,6 @@ textarea {
1271
  <div class="form-group">
1272
  <label for="age" data-lang-key="age">Возраст</label>
1273
  <select id="age">
1274
- <option value="teenager" data-lang-key="age_teen">14-18 лет</option>
1275
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1276
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1277
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
@@ -1522,6 +1521,7 @@ textarea {
1522
  <option value="toddler (2-4 years old)" data-lang-key="child_age_toddler">2-4 года</option>
1523
  <option value="child (5-8 years old)" data-lang-key="child_age_child">5-8 лет</option>
1524
  <option value="pre-teen (9-12 years old)" data-lang-key="child_age_preteen">9-12 лет</option>
 
1525
  </select>
1526
  </div>
1527
  <div class="form-group">
@@ -1727,7 +1727,6 @@ textarea {
1727
  <div class="form-group">
1728
  <label for="object_age" data-lang-key="age">Возраст</label>
1729
  <select id="object_age">
1730
- <option value="teenager" data-lang-key="age_teen">14-18 лет</option>
1731
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1732
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1733
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
@@ -1946,7 +1945,6 @@ textarea {
1946
  <div class="form-group">
1947
  <label for="cosmetics_age" data-lang-key="age">Возраст</label>
1948
  <select id="cosmetics_age">
1949
- <option value="teenager" data-lang-key="age_teen">14-18 лет</option>
1950
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1951
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1952
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
@@ -2285,7 +2283,7 @@ const translations = {
2285
  female_body_types: {'standard': 'Стандарттуу', 'very_slim': 'Абдан сымбаттуу (модель)', 'slim': 'Сымбаттуу (табигый)', 'slim_busty': 'Сымбаттуу, чоң төштүү', 'athletic': 'Атлетикалык', 'petite': 'Кичинекей', 'hourglass': 'Кум саат', 'fit_curvy': 'Спорттук (curvy)', 'plus_size': 'Толук', 'curvy': 'Жумшак (curvy)', 'full_figured': 'Плюс-сайз', 'pregnant': 'Кош бойлуу (кош бойлуулар үчүн кийим)'},
2286
  male_body_types: {'athletic': 'Атлетикалык', 'lean and toned': 'Чымыр', 'muscular build': 'Булчуңдуу', 'broad build': 'Чоң', 'slim build': 'Арык'},
2287
  female_hairstyles: {'long wavy hair': 'Узун толкундуу', 'short bob cut': 'Кыска боб', 'elegant updo': 'Элеганттуу түймөк', 'straight shoulder-length hair': 'Ийинге чейин түз', 'pixie cut': 'Пикси', 'messy bun': 'Шалакы түймөк', 'high ponytail': 'Бийик куйрук', 'braids': 'Өрүмдөр', 'curly afro': 'Афро тармал', 'bangs': 'Кекил менен', 'layered haircut': 'Каскад', 'wearing a hijab': 'Жоолукта'},
2288
- male_hairstyles: {'short classic cut': 'Кыска классикалық', 'fade haircut': 'Фейд', 'slicked back hair': 'Артка тараган', 'textured crop': 'Текстуралуу кроп', 'quiff': 'Квифф', 'man bun': 'Эркектердин түймөгү', 'buzz cut': 'Таз', 'medium-length wavy hair': 'Орто узундуктагы толкундуу', 'side part': 'Жанынан бөлүнгөн', 'undercut': 'Андеркат'},
2289
  child_hairstyles_infant: {'wispy fine hair': 'Сейрек ичке чач', 'soft baby curls': 'Жумшак балдар тармалдары', 'almost bald': 'Ча��ы жокко эсе'},
2290
  child_hairstyles_girl: {'long wavy hair': 'Узун толкундуу', 'two pigtails': 'Эки куйрукча', 'braids': 'Өрүмдөр', 'bob cut': 'Карэ', 'high ponytail': 'Бийик куйрук'},
2291
  child_hairstyles_boy: {'short neat cut': 'Кыска тыкан', 'slightly messy hair': 'Жеңил иретсиз', 'капталдан бөлүнгөн': 'Капталдан бөлүнгөн', 'textured crop': 'Текстуралуу кроп'},
@@ -2522,7 +2520,7 @@ function updateChildModelOptions() {
2522
  options = langData.child_hairstyles_boy;
2523
  } else {
2524
  options = langData.child_hairstyles_girl;
2525
- if (age.includes('child') || age.includes('pre-teen')) {
2526
  defaultValue = 'long wavy hair';
2527
  }
2528
  }
@@ -2644,12 +2642,12 @@ function getPrompt() {
2644
  } else {
2645
  shortPrompt += "model ";
2646
  }
2647
- shortPrompt += `shot as ${shotType}, posing: ${pose}, on a ${styleKey.replace(/_/g, ' ')} background, in strict vertical portrait orientation (9:16 aspect ratio)`;
2648
 
2649
  let addOns = [];
2650
  if (document.getElementById('detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of clothing details");
2651
  if (document.getElementById('anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2652
- if (document.getElementById('variantsCollage').checked) addOns.push("formatted as a collage showing exactly 3 or 4 distinct, realistic color variants, ensuring no duplicated colors and no unnatural hallucinated colors");
2653
 
2654
  const wantsTextOverlay = document.getElementById('textOverlayCheck').checked;
2655
  const textToOverlay = document.getElementById('textOverlayInput').value.trim();
@@ -2722,7 +2720,7 @@ function getPrompt() {
2722
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (4-VIEW COLLAGE):** Create a professional 4-view collage in a single image. The collage must clearly show the model wearing the garment from four distinct angles: full front view, full back view, full side view, and three-quarter view. Maintain consistent lighting and background across all views.`;
2723
  }
2724
  if (wantsVariantsCollage) {
2725
- prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS COLLAGE):** In a single, cohesive frame, display multiple models (or one model in different poses) showcasing the garment in exactly 3 or 4 distinct, realistic color variations (e.g., black, white, gray). Do NOT duplicate colors and do NOT invent unnatural colors. Each color variant must be shown exactly once.`;
2726
  }
2727
  if (wantsTextOverlay && textToOverlay) {
2728
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
@@ -2754,12 +2752,12 @@ function getPrompt() {
2754
  const eyeColor = document.getElementById('child_eyeColor').value;
2755
  shortPrompt += `${age} ${nationality} ${gender} child with ${hairColor} ${hairstyle}, ${eyeColor} `;
2756
  }
2757
- shortPrompt += `shot as ${shotType}, action: ${pose}, on a ${styleKey.replace(/_/g, ' ')} background, in strict vertical portrait orientation (9:16 aspect ratio)`;
2758
 
2759
  let addOns = [];
2760
  if (document.getElementById('child_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of clothing details");
2761
  if (document.getElementById('child_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2762
- if (document.getElementById('child_variantsCollage').checked) addOns.push("formatted as a collage showing exactly 3 or 4 distinct, realistic color variants, ensuring no duplicated colors and no unnatural hallucinated colors");
2763
 
2764
  const wantsTextOverlay = document.getElementById('child_textOverlayCheck').checked;
2765
  const textToOverlay = document.getElementById('child_textOverlayInput').value.trim();
@@ -2820,7 +2818,7 @@ function getPrompt() {
2820
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (4-VIEW COLLAGE):** Create a professional 4-view collage in a single image. The collage must clearly show the model wearing the garment from four distinct angles: full front view, full back view, full side view, and three-quarter view. Maintain consistent lighting and background across all views.`;
2821
  }
2822
  if (wantsVariantsCollage) {
2823
- prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS COLLAGE):** In a single, cohesive frame, display multiple models (or one model in different poses) showcasing the garment in exactly 3 or 4 distinct, realistic color variations (e.g., black, white, gray). Do NOT duplicate colors and do NOT invent unnatural colors. Each color variant must be shown exactly once.`;
2824
  }
2825
  if (wantsTextOverlay && textToOverlay) {
2826
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
@@ -2852,12 +2850,12 @@ function getPrompt() {
2852
  } else if (onMannequin) {
2853
  shortPrompt += "on a mannequin, ";
2854
  }
2855
- shortPrompt += `on a ${styleKey.replace(/_/g, ' ')} background, in strict vertical portrait orientation (9:16 aspect ratio)`;
2856
 
2857
  let addOns = [];
2858
  if (document.getElementById('object_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of material details");
2859
  if (document.getElementById('object_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2860
- if (document.getElementById('object_variantsCollage').checked) addOns.push("formatted as a collage showing exactly 3 or 4 distinct, realistic product color variants, ensuring no duplicated colors and no unnatural hallucinated colors");
2861
 
2862
  const wantsTextOverlay = document.getElementById('object_textOverlayCheck').checked;
2863
  const textToOverlay = document.getElementById('object_textOverlayInput').value.trim();
@@ -2937,7 +2935,7 @@ function getPrompt() {
2937
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (MULTI-ANGLE COLLAGE):** Create a professional multi-angle collage in a single image. The collage must clearly show the product from distinct angles: front view, back view, and side view. Maintain consistent lighting and background across all views.`;
2938
  }
2939
  if (wantsVariantsCollage) {
2940
- prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS SHOWCASE):** In a single, cohesive frame, display the product in exactly 3 or 4 distinct, realistic color variations. Do NOT duplicate colors and do NOT invent unnatural colors. Each color variant must be shown exactly once.`;
2941
  }
2942
  if (wantsTextOverlay && textToOverlay) {
2943
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
@@ -2963,12 +2961,12 @@ function getPrompt() {
2963
  shortPrompt += `(${document.getElementById('cosmeticsCelebrityName').value} lookalike) `;
2964
  }
2965
  shortPrompt += `applying it, shot as ${shotType}, `;
2966
- shortPrompt += `on a ${styleKey.replace(/_/g, ' ')} background, in strict vertical portrait orientation (9:16 aspect ratio)`;
2967
 
2968
  let addOns = [];
2969
  if (document.getElementById('cosmetics_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of product texture and smears");
2970
  if (document.getElementById('cosmetics_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles");
2971
- if (document.getElementById('cosmetics_variantsCollage').checked) addOns.push("formatted as a collage showing exactly 3 or 4 distinct, realistic shade variants, ensuring no duplicated shades and no unnatural hallucinated colors");
2972
 
2973
  const wantsTextOverlay = document.getElementById('cosmetics_textOverlayCheck').checked;
2974
  const textToOverlay = document.getElementById('cosmetics_textOverlayInput').value.trim();
@@ -3036,7 +3034,7 @@ function getPrompt() {
3036
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (MULTI-ANGLE COLLAGE):** Create a professional multi-angle collage in a single image showing the model and the applied product from different angles (front, slight profile).`;
3037
  }
3038
  if (wantsVariantsCollage) {
3039
- prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS SHOWCASE):** In a single, cohesive frame, display multiple models showcasing the product in exactly 3 or 4 distinct, realistic shade variations. Do NOT duplicate shades and do NOT invent unnatural colors. Each shade must be shown exactly once.`;
3040
  }
3041
  if (wantsTextOverlay && textToOverlay) {
3042
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography suitable for a beauty brand.`;
@@ -3280,7 +3278,7 @@ def create_environment():
3280
  "created_at": datetime.utcnow().isoformat(),
3281
  "archived": False
3282
  }
3283
- save_data(all_data)
3284
 
3285
  flash(f'Новая {env_type} среда с ID {new_id} создана.', 'success')
3286
  return redirect(url_for('admhosto'))
@@ -3346,137 +3344,4 @@ def get_env_stats(env_id):
3346
  env_data = data.get(env_id)
3347
 
3348
  if not env_data:
3349
- return jsonify({"error": "Среда не найдена"}), 404
3350
-
3351
- raw_logs = env_data.get("logs", [])
3352
- formatted_logs = []
3353
-
3354
- for log in reversed(raw_logs):
3355
- try:
3356
- utc_dt = datetime.fromisoformat(log['time'])
3357
- almaty_dt = utc_dt + timedelta(hours=5)
3358
- time_str = almaty_dt.strftime('%Y-%m-%d %H:%M:%S')
3359
- formatted_logs.append({
3360
- "time": time_str,
3361
- "ip": log.get('ip', 'unknown'),
3362
- "ua": log.get('ua', 'unknown')
3363
- })
3364
- except:
3365
- continue
3366
-
3367
- response_data = {
3368
- "id": env_id,
3369
- "keyword": env_data.get("keyword"),
3370
- "type": env_data.get("type", "closed"),
3371
- "hits": env_data.get("hits", 0),
3372
- "logs": formatted_logs
3373
- }
3374
- return jsonify(response_data)
3375
-
3376
- @app.route('/env/<env_id>')
3377
- def serve_env(env_id):
3378
- new_token_to_set = None
3379
- with data_lock:
3380
- data = load_data()
3381
- env_data = data.get(env_id)
3382
-
3383
- if not env_data or not isinstance(env_data, dict) or env_data.get("archived"):
3384
- return "Среда не найдена или заархивирована.", 404
3385
-
3386
- current_log = {
3387
- "time": datetime.utcnow().isoformat(),
3388
- "ip": request.headers.get('X-Forwarded-For', request.remote_addr),
3389
- "ua": request.headers.get('User-Agent', '')[:150]
3390
- }
3391
-
3392
- env_data['hits'] = env_data.get('hits', 0) + 1
3393
- if 'logs' not in env_data or not isinstance(env_data.get('logs'), list):
3394
- env_data['logs'] = []
3395
-
3396
- env_data['logs'].append(current_log)
3397
- if len(env_data['logs']) > 30:
3398
- env_data['logs'] = env_data['logs'][-30:]
3399
-
3400
- env_type = env_data.get("type", "closed")
3401
- if env_type == 'closed':
3402
- stored_token = env_data.get("device_token")
3403
- if not stored_token:
3404
- new_token_to_set = ''.join(random.choices(string.ascii_letters + string.digits, k=40))
3405
- env_data['device_token'] = new_token_to_set
3406
-
3407
- data[env_id] = env_data
3408
- save_data(data)
3409
-
3410
- keyword = env_data.get("keyword", "")
3411
- prompts_data = load_prompts()
3412
-
3413
- if env_type == 'open':
3414
- return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data)
3415
-
3416
- user_token = request.cookies.get(f'access_token_{env_id}')
3417
- stored_token = env_data.get("device_token")
3418
-
3419
- if new_token_to_set:
3420
- resp = make_response(render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data))
3421
- resp.set_cookie(f'access_token_{env_id}', new_token_to_set, max_age=31536000, httponly=True, samesite='Lax')
3422
- return resp
3423
- elif stored_token and user_token == stored_token:
3424
- return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data)
3425
- else:
3426
- return """
3427
- <!DOCTYPE html>
3428
- <html lang="ru">
3429
- <head>
3430
- <meta charset="UTF-8">
3431
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
3432
- <title>Доступ запрещен</title>
3433
- <style>
3434
- body {
3435
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
3436
- background: #111;
3437
- color: #eee;
3438
- display: flex;
3439
- align-items: center;
3440
- justify-content: center;
3441
- height: 100vh;
3442
- margin: 0;
3443
- text-align: center;
3444
- flex-direction: column;
3445
- }
3446
- .container {
3447
- padding: 40px;
3448
- background: #1a1a1a;
3449
- border-radius: 16px;
3450
- border: 1px solid #333;
3451
- box-shadow: 0 10px 30px rgba(0,0,0,0.5);
3452
- }
3453
- h1 {
3454
- color: #ff4d4d;
3455
- margin-top: 0;
3456
- margin-bottom: 15px;
3457
- font-size: 2.5rem;
3458
- }
3459
- p {
3460
- color: #aaa;
3461
- font-size: 1.1rem;
3462
- max-width: 400px;
3463
- }
3464
- </style>
3465
- </head>
3466
- <body>
3467
- <div class="container">
3468
- <h1>⛔ Доступ запрещен</h1>
3469
- <p>Эта ссылка уже привязана к другому устройству или браузеру.</p>
3470
- </div>
3471
- </body>
3472
- </html>
3473
- """, 403
3474
-
3475
- if __name__ == '__main__':
3476
- setup_initial_files()
3477
- download_db_from_hf()
3478
- if HF_TOKEN_WRITE:
3479
- backup_thread = threading.Thread(target=periodic_backup, daemon=True)
3480
- backup_thread.start()
3481
- port = int(os.environ.get('PORT', 7860))
3482
- app.run(debug=False, host='0.0.0.0', port=port)
 
1271
  <div class="form-group">
1272
  <label for="age" data-lang-key="age">Возраст</label>
1273
  <select id="age">
 
1274
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1275
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1276
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
 
1521
  <option value="toddler (2-4 years old)" data-lang-key="child_age_toddler">2-4 года</option>
1522
  <option value="child (5-8 years old)" data-lang-key="child_age_child">5-8 лет</option>
1523
  <option value="pre-teen (9-12 years old)" data-lang-key="child_age_preteen">9-12 лет</option>
1524
+ <option value="teenager (14-18 years old)" data-lang-key="age_teen">14-18 лет</option>
1525
  </select>
1526
  </div>
1527
  <div class="form-group">
 
1727
  <div class="form-group">
1728
  <label for="object_age" data-lang-key="age">Возраст</label>
1729
  <select id="object_age">
 
1730
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1731
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1732
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
 
1945
  <div class="form-group">
1946
  <label for="cosmetics_age" data-lang-key="age">Возраст</label>
1947
  <select id="cosmetics_age">
 
1948
  <option value="20-25 years old" selected data-lang-key="age_20_25">20-25 лет</option>
1949
  <option value="25-30 years old" data-lang-key="age_25_30">25-30 лет</option>
1950
  <option value="30-40 years old" data-lang-key="age_30_40">30-40 лет</option>
 
2283
  female_body_types: {'standard': 'Стандарттуу', 'very_slim': 'Абдан сымбаттуу (модель)', 'slim': 'Сымбаттуу (табигый)', 'slim_busty': 'Сымбаттуу, чоң төштүү', 'athletic': 'Атлетикалык', 'petite': 'Кичинекей', 'hourglass': 'Кум саат', 'fit_curvy': 'Спорттук (curvy)', 'plus_size': 'Толук', 'curvy': 'Жумшак (curvy)', 'full_figured': 'Плюс-сайз', 'pregnant': 'Кош бойлуу (кош бойлуулар үчүн кийим)'},
2284
  male_body_types: {'athletic': 'Атлетикалык', 'lean and toned': 'Чымыр', 'muscular build': 'Булчуңдуу', 'broad build': 'Чоң', 'slim build': 'Арык'},
2285
  female_hairstyles: {'long wavy hair': 'Узун толкундуу', 'short bob cut': 'Кыска боб', 'elegant updo': 'Элеганттуу түймөк', 'straight shoulder-length hair': 'Ийинге чейин түз', 'pixie cut': 'Пикси', 'messy bun': 'Шалакы түймөк', 'high ponytail': 'Бийик куйрук', 'braids': 'Өрүмдөр', 'curly afro': 'Афро тармал', 'bangs': 'Кекил менен', 'layered haircut': 'Каскад', 'wearing a hijab': 'Жоолукта'},
2286
+ male_hairstyles: {'short classic cut': 'Кыска классикалык', 'fade haircut': 'Фейд', 'slicked back hair': 'Артка тараган', 'textured crop': 'Текстуралуу кроп', 'quiff': 'Квифф', 'man bun': 'Эркектердин түймөгү', 'buzz cut': 'Таз', 'medium-length wavy hair': 'Орто узундуктагы толкундуу', 'side part': 'Жанынан бөлүнгөн', 'undercut': 'Андеркат'},
2287
  child_hairstyles_infant: {'wispy fine hair': 'Сейрек ичке чач', 'soft baby curls': 'Жумшак балдар тармалдары', 'almost bald': 'Ча��ы жокко эсе'},
2288
  child_hairstyles_girl: {'long wavy hair': 'Узун толкундуу', 'two pigtails': 'Эки куйрукча', 'braids': 'Өрүмдөр', 'bob cut': 'Карэ', 'high ponytail': 'Бийик куйрук'},
2289
  child_hairstyles_boy: {'short neat cut': 'Кыска тыкан', 'slightly messy hair': 'Жеңил иретсиз', 'капталдан бөлүнгөн': 'Капталдан бөлүнгөн', 'textured crop': 'Текстуралуу кроп'},
 
2520
  options = langData.child_hairstyles_boy;
2521
  } else {
2522
  options = langData.child_hairstyles_girl;
2523
+ if (age.includes('child') || age.includes('pre-teen') || age.includes('teenager')) {
2524
  defaultValue = 'long wavy hair';
2525
  }
2526
  }
 
2642
  } else {
2643
  shortPrompt += "model ";
2644
  }
2645
+ shortPrompt += `shot as ${shotType}, posing: ${pose}, on a ${styleKey.replace(/_/g, ' ')} background`;
2646
 
2647
  let addOns = [];
2648
  if (document.getElementById('detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of clothing details");
2649
  if (document.getElementById('anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2650
+ if (document.getElementById('variantsCollage').checked) addOns.push("formatted as a collage showing all color variants explicitly present in the reference image (strictly no duplicates, no omissions, and no hallucinated colors)");
2651
 
2652
  const wantsTextOverlay = document.getElementById('textOverlayCheck').checked;
2653
  const textToOverlay = document.getElementById('textOverlayInput').value.trim();
 
2720
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (4-VIEW COLLAGE):** Create a professional 4-view collage in a single image. The collage must clearly show the model wearing the garment from four distinct angles: full front view, full back view, full side view, and three-quarter view. Maintain consistent lighting and background across all views.`;
2721
  }
2722
  if (wantsVariantsCollage) {
2723
+ prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS COLLAGE):** In a single, cohesive frame, display multiple models (or one model in different poses) showcasing the garment in ALL the different colors present in the reference image. **CRITICAL COLOR PROTOCOL: Use ONLY the exact colors shown in the reference photo. You must include every color present, do not duplicate any colors, and absolutely DO NOT hallucinate, invent, or add new colors that are not explicitly present in the source image.** The result must be a harmonious and balanced collage.`;
2724
  }
2725
  if (wantsTextOverlay && textToOverlay) {
2726
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
 
2752
  const eyeColor = document.getElementById('child_eyeColor').value;
2753
  shortPrompt += `${age} ${nationality} ${gender} child with ${hairColor} ${hairstyle}, ${eyeColor} `;
2754
  }
2755
+ shortPrompt += `shot as ${shotType}, action: ${pose}, on a ${styleKey.replace(/_/g, ' ')} background`;
2756
 
2757
  let addOns = [];
2758
  if (document.getElementById('child_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of clothing details");
2759
  if (document.getElementById('child_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2760
+ if (document.getElementById('child_variantsCollage').checked) addOns.push("formatted as a collage showing all color variants explicitly present in the reference image (strictly no duplicates, no omissions, and no hallucinated colors)");
2761
 
2762
  const wantsTextOverlay = document.getElementById('child_textOverlayCheck').checked;
2763
  const textToOverlay = document.getElementById('child_textOverlayInput').value.trim();
 
2818
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (4-VIEW COLLAGE):** Create a professional 4-view collage in a single image. The collage must clearly show the model wearing the garment from four distinct angles: full front view, full back view, full side view, and three-quarter view. Maintain consistent lighting and background across all views.`;
2819
  }
2820
  if (wantsVariantsCollage) {
2821
+ prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS COLLAGE):** In a single, cohesive frame, display multiple models (or one model in different poses) showcasing the garment in ALL the different colors present in the reference image. **CRITICAL COLOR PROTOCOL: Use ONLY the exact colors shown in the reference photo. You must include every color present, do not duplicate any colors, and absolutely DO NOT hallucinate, invent, or add new colors that are not explicitly present in the source image.** The result must be a harmonious and balanced collage.`;
2822
  }
2823
  if (wantsTextOverlay && textToOverlay) {
2824
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
 
2850
  } else if (onMannequin) {
2851
  shortPrompt += "on a mannequin, ";
2852
  }
2853
+ shortPrompt += `on a ${styleKey.replace(/_/g, ' ')} background`;
2854
 
2855
  let addOns = [];
2856
  if (document.getElementById('object_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of material details");
2857
  if (document.getElementById('object_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles (front, back, side)");
2858
+ if (document.getElementById('object_variantsCollage').checked) addOns.push("formatted as a collage showing all product color variants explicitly present in the reference image (strictly no duplicates, no omissions, and no hallucinated colors)");
2859
 
2860
  const wantsTextOverlay = document.getElementById('object_textOverlayCheck').checked;
2861
  const textToOverlay = document.getElementById('object_textOverlayInput').value.trim();
 
2935
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (MULTI-ANGLE COLLAGE):** Create a professional multi-angle collage in a single image. The collage must clearly show the product from distinct angles: front view, back view, and side view. Maintain consistent lighting and background across all views.`;
2936
  }
2937
  if (wantsVariantsCollage) {
2938
+ prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS SHOWCASE):** In a single, cohesive frame, display the product in ALL the different colors present in the reference image. **CRITICAL COLOR PROTOCOL: Use ONLY the exact colors shown in the reference photo. You must include every color present, do not duplicate any colors, and absolutely DO NOT hallucinate, invent, or add new colors that are not explicitly present in the source image.** The result must be a harmonious and balanced showcase.`;
2939
  }
2940
  if (wantsTextOverlay && textToOverlay) {
2941
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography. The text should be legible but artistically placed to complement the image, not dominate it. Minimalist icons that enhance the text are permissible.`;
 
2961
  shortPrompt += `(${document.getElementById('cosmeticsCelebrityName').value} lookalike) `;
2962
  }
2963
  shortPrompt += `applying it, shot as ${shotType}, `;
2964
+ shortPrompt += `on a ${styleKey.replace(/_/g, ' ')} background`;
2965
 
2966
  let addOns = [];
2967
  if (document.getElementById('cosmetics_detailsCollage').checked) addOns.push("formatted as a split-screen collage with close-up macro shots of product texture and smears");
2968
  if (document.getElementById('cosmetics_anglesCollage').checked) addOns.push("formatted as a multi-panel collage showing different angles");
2969
+ if (document.getElementById('cosmetics_variantsCollage').checked) addOns.push("formatted as a collage showing all shade variants explicitly present in the reference image (strictly no duplicates, no omissions, and no hallucinated colors)");
2970
 
2971
  const wantsTextOverlay = document.getElementById('cosmetics_textOverlayCheck').checked;
2972
  const textToOverlay = document.getElementById('cosmetics_textOverlayInput').value.trim();
 
3034
  prompt += `\\n\\n**COMPOSITION DIRECTIVE (MULTI-ANGLE COLLAGE):** Create a professional multi-angle collage in a single image showing the model and the applied product from different angles (front, slight profile).`;
3035
  }
3036
  if (wantsVariantsCollage) {
3037
+ prompt += `\\n\\n**COMPOSITION DIRECTIVE (VARIANTS SHOWCASE):** In a single, cohesive frame, display multiple models showcasing ALL the different shades of the product present in the reference image. **CRITICAL COLOR PROTOCOL: Use ONLY the exact shades shown in the reference photo. You must include every shade present, do not duplicate any shades, and absolutely DO NOT hallucinate, invent, or add new shades that are not explicitly present in the source image.** The result must be a harmonious and balanced showcase.`;
3038
  }
3039
  if (wantsTextOverlay && textToOverlay) {
3040
  prompt += `\\n\\n**GRAPHIC OVERLAY:** Add the following text: "${textToOverlay}". Integrate it stylishly using modern, clean typography suitable for a beauty brand.`;
 
3278
  "created_at": datetime.utcnow().isoformat(),
3279
  "archived": False
3280
  }
3281
+ save_data(all_data)
3282
 
3283
  flash(f'Новая {env_type} среда с ID {new_id} создана.', 'success')
3284
  return redirect(url_for('admhosto'))
 
3344
  env_data = data.get(env_id)
3345
 
3346
  if not env_data:
3347
+ return jsonify({"error": "Среда не