Spaces:
Running
Running
Update app.py
Browse files
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': 'Кыска классикалы
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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": "Среда не
|
| 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": "Среда не
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|