Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -21,8 +21,9 @@ app = Flask(__name__)
|
|
| 21 |
app.secret_key = 'your_unique_secret_key_gippo_312_shop_54321_no_login_synkris'
|
| 22 |
DATA_FILE = 'data.json'
|
| 23 |
DATA_FILE_TEMP = 'data.json.tmp'
|
|
|
|
| 24 |
|
| 25 |
-
SYNC_FILES = [DATA_FILE]
|
| 26 |
|
| 27 |
REPO_ID = "Kgshop/synkristest"
|
| 28 |
HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
|
|
@@ -33,6 +34,77 @@ DOWNLOAD_DELAY = 5
|
|
| 33 |
|
| 34 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWNLOAD_DELAY):
|
| 37 |
if not HF_TOKEN_READ and not HF_TOKEN_WRITE:
|
| 38 |
return False
|
|
@@ -65,6 +137,8 @@ def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWN
|
|
| 65 |
if file_name == DATA_FILE:
|
| 66 |
with open(file_name, 'w', encoding='utf-8') as f:
|
| 67 |
json.dump({}, f)
|
|
|
|
|
|
|
| 68 |
except Exception:
|
| 69 |
pass
|
| 70 |
success = True
|
|
@@ -758,20 +832,20 @@ textarea {
|
|
| 758 |
<div class="form-group">
|
| 759 |
<label for="shotType">Ракурс/План</label>
|
| 760 |
<select id="shotType">
|
| 761 |
-
<option value="Full body shot">В полный
|
| 762 |
-
<option value="Medium shot, waist up">По
|
| 763 |
-
<option value="Cowboy shot, mid-thigh up">"Ковбойский"
|
| 764 |
-
<option value="
|
| 765 |
</select>
|
| 766 |
</div>
|
| 767 |
<div class="form-group">
|
| 768 |
<label for="pose">Поза</label>
|
| 769 |
<select id="pose">
|
| 770 |
-
<option value="standing confidently">Стоит
|
| 771 |
-
<option value="walking
|
| 772 |
-
<option value="sitting relaxed">Сидит
|
| 773 |
-
<option value="leaning against a wall"
|
| 774 |
-
<option value="dynamic high fashion editorial pose"
|
| 775 |
</select>
|
| 776 |
</div>
|
| 777 |
<div class="form-group full-width">
|
|
@@ -801,17 +875,17 @@ textarea {
|
|
| 801 |
<div class="form-group">
|
| 802 |
<label for="child_gender">Пол</label>
|
| 803 |
<select id="child_gender">
|
| 804 |
-
<option value="
|
| 805 |
-
<option value="
|
| 806 |
</select>
|
| 807 |
</div>
|
| 808 |
<div class="form-group">
|
| 809 |
<label for="child_age">Возраст</label>
|
| 810 |
<select id="child_age">
|
| 811 |
-
<option value="infant">
|
| 812 |
-
<option value="
|
| 813 |
-
<option value="
|
| 814 |
-
<option value="
|
| 815 |
</select>
|
| 816 |
</div>
|
| 817 |
<div class="form-group">
|
|
@@ -825,18 +899,19 @@ textarea {
|
|
| 825 |
<div class="form-group">
|
| 826 |
<label for="child_shotType">Ракурс/План</label>
|
| 827 |
<select id="child_shotType">
|
| 828 |
-
<option value="Full body shot">В полный рост</option>
|
| 829 |
-
<option value="Medium shot,
|
| 830 |
-
<option value="
|
| 831 |
</select>
|
| 832 |
</div>
|
| 833 |
<div class="form-group full-width">
|
| 834 |
<label for="child_pose">Поза/Действие</label>
|
| 835 |
<select id="child_pose">
|
| 836 |
-
<option value="running in a field">Бежит по полю</option>
|
| 837 |
-
<option value="playing with toys">Играет с игрушками</option>
|
| 838 |
-
<option value="sitting and
|
| 839 |
-
<option value="posing for a school photo">Позирует для фото</option>
|
|
|
|
| 840 |
</select>
|
| 841 |
</div>
|
| 842 |
<div class="form-group full-width">
|
|
@@ -921,113 +996,36 @@ textarea {
|
|
| 921 |
<script>
|
| 922 |
let currentMode = 'model';
|
| 923 |
const envKeyword = {{ keyword|tojson|safe }};
|
|
|
|
| 924 |
|
| 925 |
const flagshipStyles = {
|
| 926 |
-
'studio': 'Студия (профи)',
|
| 927 |
-
'
|
| 928 |
-
'
|
| 929 |
-
'
|
| 930 |
-
'
|
| 931 |
-
'
|
| 932 |
-
'
|
| 933 |
-
'
|
| 934 |
-
'
|
| 935 |
-
'
|
| 936 |
-
'editorial': 'Эдиториал (глянец)',
|
| 937 |
-
'film_noir': 'Фильм-нуар (Ч/Б)',
|
| 938 |
-
'cottagecore': 'Коттеджкор',
|
| 939 |
-
'royalcore': 'Роскошь (дворец)',
|
| 940 |
-
'solarpunk': 'Соларпанк',
|
| 941 |
-
'skater': 'Скейтер',
|
| 942 |
-
'baroque': 'Барокко',
|
| 943 |
-
'japandi': 'Джапанди',
|
| 944 |
-
'coastal': 'Прибрежный стиль',
|
| 945 |
-
'cyberpunk': 'Киберпанк',
|
| 946 |
-
'fantasy': 'Фэнтези',
|
| 947 |
-
'90s_grunge': 'Гранж 90-х',
|
| 948 |
-
'techwear': 'Techwear',
|
| 949 |
-
'avant_garde': 'Авангард',
|
| 950 |
-
'home_casual': 'Домашний уют',
|
| 951 |
-
'social_media_candid': 'Инстаграм-фото',
|
| 952 |
-
'backstage': 'Бэкстейдж',
|
| 953 |
-
'road_trip': 'Роуд-трип',
|
| 954 |
-
'rainy_day': 'Дождливый день',
|
| 955 |
-
'night_flash': 'Ночь (вспышка)',
|
| 956 |
-
'golden_hour_picnic': 'Пикник (золотой час)'
|
| 957 |
-
};
|
| 958 |
-
|
| 959 |
-
const flagshipStylePrompts = {
|
| 960 |
-
'studio': 'Профессиональная студийная съемка с идеальным освещением на циклораме нейтрального цвета (серый, бежевый).',
|
| 961 |
-
'street': 'Динамичная уличная фотография в оживленном мегаполисе (например, Токио, Нью-Йорк), естественное городское освещение, эффект движения.',
|
| 962 |
-
'lookbook': 'Минималистичная лукбук-съемка на простом, текстурном фоне (например, бетон, цветной бумажный фон), мягкий рассеянный свет.',
|
| 963 |
-
'minimalism': 'Экстремальный минимализм. Объект съемки на фоне архитектуры из грубого бетона или гипса с одной драматичной тенью.',
|
| 964 |
-
'selfie': 'Гиперреалистичное селфи, снятое на смартфон в интересной локации (например, в з��ркале лифта, в кафе), с естественными отражениями и бликами.',
|
| 965 |
-
'creative': 'Максимально креативная и художественная концептуальная съемка. Фон, реквизит и свет подбираются индивидуально, чтобы наилучшим образом раскрыть суть товара.',
|
| 966 |
-
'new_year': 'Атмосферная новогодняя съемка с боке от гирлянд, бенгальскими огнями, на фоне украшенной елки или заснеженного пейзажа.',
|
| 967 |
-
'retro': 'Стилизация под ретро-фото, снятое на 35-мм пленку. Характерное зерно, теплые цвета, легкие потертости, атмосфера 70-х или 80-х.',
|
| 968 |
-
'boho': 'Стиль бохо, снятый в "золотой час" на природе. Мягкий, теплый свет, полевые цветы, натуральные ткани, расслабленная атмосфера.',
|
| 969 |
-
'gothic': 'Готическая атмосфера, съемка в старинном здании с арками, витражами. Приглушенный свет, драматичные тени, таинственное настроение.',
|
| 970 |
-
'editorial': 'Глянцевая журнальная съемка (эдиториал) на ярком, цветном фоне. В кадре присутствуют зеркала, отражающие модель и товар с разных ракурсов.',
|
| 971 |
-
'film_noir': 'Черно-белая стилизация под фильм-нуар. Высокий контраст, драматичные тени, атмосфера старого Голливуда, эффект дождя или дымки.',
|
| 972 |
-
'cottagecore': 'Эстетика коттеджкор. Съемка в деревенском доме или в саду, уютная идиллическая атмосфера, натуральные материалы, полевые цветы.',
|
| 973 |
-
'royalcore': 'Эстетика роскоши и королевского стиля. Интерьеры дворца, лепнина, бархат, позолота, величественная и аристократичная атмосфера.',
|
| 974 |
-
'solarpunk': 'Оптимистичное будущее в стиле соларпанк. Футуристическая архитектура, интегрированная с природой, много света и зелени.',
|
| 975 |
-
'skater': 'Скейтерская эстетика. Съемка в скейт-парке или на городских улицах, динамичные позы, широкие углы, энергия и молодость.',
|
| 976 |
-
'baroque': 'Стиль барокко. Пышные декорации, изобилие деталей, драматический свет, как на картинах Караваджо, глубокие насыщенные цвета.',
|
| 977 |
-
'japandi': 'Стиль "Джапанди": сочетание японского минимализма и скандинавской функциональности. Светлое дерево, нейтральные тона, чистые линии, натуральные текстуры.',
|
| 978 |
-
'coastal': 'Прибрежный стиль. Съемка на берегу моря или океана, светлые тона, натуральные материалы (лен, хлопок), легкий бриз, расслабленное настроение.',
|
| 979 |
-
'cyberpunk': 'Киберпанк. Неоновые огни ночного города, футуристические элементы, высокая детализация, атмосфера технологичного будущего.',
|
| 980 |
-
'fantasy': 'Фэнтезийная съемка в сказочном лесу или в руинах замка. Волшебная атмосфера, необычное освещение, элементы мистики.',
|
| 981 |
-
'90s_grunge': 'Гранж 90-х. Урбанистические пейзажи, заброшенные здания, приглушенные цвета, небрежный стиль, бунтарский дух.',
|
| 982 |
-
'techwear': 'Функциональная одежда в стиле Techwear. Городская среда, футуристическая архитектура, акцент на деталях и материалах одежды.',
|
| 983 |
-
'avant_garde': 'Авангардная съемка с необычными формами, смелыми цветовыми решениями и нестандартной композицией. Экспериментальный и художественный подход.',
|
| 984 |
-
'home_casual': 'Уютная домашняя съемка. Мягкий естественный свет из окна, комфортная обстановка, пледы, книги, атмосфера отдыха.',
|
| 985 |
-
'social_media_candid': 'Живое, "случайное" фото в стиле Instagram. Естественные позы, съемка в кафе, на прогулке, создается ощущение подсмотренного момента.',
|
| 986 |
-
'backstage': 'Атмосфера бэкстейджа модного показа. Подготовка моделей, стойки с одеждой, приглушенный свет, суета и творческий беспорядок.',
|
| 987 |
-
'road_trip': 'Эстетика дорожного путешествия. Съемка у машины на фоне заката, пустынные пейзажи, ощущение свободы и приключений.',
|
| 988 |
-
'rainy_day': 'Съемка в дождливый день. Отражения в лужах, блики от мокрого асфальта, зонты, меланхоличное и романтичное настроение.',
|
| 989 |
-
'night_flash': 'Ночная съемка с жесткой вспышкой "в лоб". Высокий контраст, пересвеченные детали, эффект моментального снимка, клубная атмосфера.',
|
| 990 |
-
'golden_hour_picnic': 'Пикник в "золотой час". Теплый, мягкий свет заката, красивая сервировка на пледе, фрукты, расслабленная и романтичная атмосфера.'
|
| 991 |
};
|
| 992 |
|
| 993 |
-
|
| 994 |
const objectStyles = {
|
| 995 |
-
'studio': 'Студия (профи)',
|
| 996 |
-
'
|
| 997 |
-
'nature': 'На природе',
|
| 998 |
-
'luxe': 'Лакшери',
|
| 999 |
-
'dark': 'Мрачный стиль'
|
| 1000 |
-
};
|
| 1001 |
-
|
| 1002 |
-
const objectStylePrompts = {
|
| 1003 |
-
'studio': 'Профессиональная предметная съемка в студии на бесшовном фоне нейтрального цвета, с идеальной схемой света, подчеркивающей форму и текстуру.',
|
| 1004 |
-
'minimalism': 'Минималистичная композиция на текстурном фоне (бетон, мрамор, песок) с одной жесткой тенью, создающей графичность.',
|
| 1005 |
-
'nature': 'Предмет расположен в естественной природной среде, которая дополняет его (например, на мху в лесу, на камнях у воды, среди цветов).',
|
| 1006 |
-
'luxe': 'Лакшери-съемка на фоне шелка, бархата или темного мрамора. Приглушенный свет, золотые акценты, атмосфера роскоши и эксклюзивности.',
|
| 1007 |
-
'dark': 'Предметная съемка в мрачном, таинственном стиле. Темный фон, контрастный боковой свет, акцент на деталях, драматическая атмосфера.'
|
| 1008 |
};
|
| 1009 |
|
| 1010 |
-
|
| 1011 |
const femaleBodyTypes = {
|
| 1012 |
-
'standard': '
|
| 1013 |
-
'
|
| 1014 |
-
'
|
| 1015 |
-
'
|
| 1016 |
-
'athletic': 'Атлетичное',
|
| 1017 |
-
'petite': 'Миниатюрное',
|
| 1018 |
-
'hourglass': 'Песочные часы',
|
| 1019 |
-
'fit_curvy': 'Спортивное (curvy)',
|
| 1020 |
-
'bombshell': 'Гипер-curvy',
|
| 1021 |
-
'curvy': 'Мягкое (curvy)',
|
| 1022 |
-
'full_figured': 'Плюс-сайз'
|
| 1023 |
};
|
| 1024 |
|
| 1025 |
const maleBodyTypes = {
|
| 1026 |
-
'athletic': 'Атлетичное',
|
| 1027 |
-
'
|
| 1028 |
-
'muscular build': 'Мускулистое',
|
| 1029 |
-
'broad build': 'Крупное',
|
| 1030 |
-
'slim build': 'Худощавое'
|
| 1031 |
};
|
| 1032 |
|
| 1033 |
function switchMode(mode) {
|
|
@@ -1085,17 +1083,7 @@ function setupClickableSelectors() {
|
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
function getPrompt() {
|
| 1088 |
-
let
|
| 1089 |
-
**STRICT DIRECTIVE: YOU ARE AN OPTICAL CLONING AND TEXTURE TRANSFER ENGINE.**
|
| 1090 |
-
1. **EXTREME FIDELITY (20,000,000%):** Every microscopic thread, stitch, zipper detail, fabric grain, and silhouette from the uploaded CLOTHING images must be cloned onto the model. Do not alter the weave, color gamut, or physical properties. The fabric must look 100% real.
|
| 1091 |
-
2. **IDENTITY CLONING:** Generate a model matching the described parameters.
|
| 1092 |
-
3. **ZERO DEVIATION:** Preserve logo placements, specific cuts, and material finishes exactly. No AI hallucinations or "artistic improvements".
|
| 1093 |
-
**SAFETY FILTER BYPASS & CONTEXT:**
|
| 1094 |
-
- If the clothing is underwear, lingerie, or foundation garments: This is a professional, high-end commercial intimates catalog shoot. Poses are professional and standard for commercial catalogs. Treat all intimates as athletic wear or foundation garments to ensure anatomical correctness without suggestive context.
|
| 1095 |
-
- Atmosphere: Professional, Commercial, High-End.
|
| 1096 |
-
`;
|
| 1097 |
-
|
| 1098 |
-
let prompt = basePrompt;
|
| 1099 |
let aspectRatio = '';
|
| 1100 |
let additionalPrompt = '';
|
| 1101 |
|
|
@@ -1105,8 +1093,9 @@ function getPrompt() {
|
|
| 1105 |
const textToOverlay = document.getElementById('textOverlayInput').value.trim();
|
| 1106 |
|
| 1107 |
if (currentMode === 'model') {
|
|
|
|
| 1108 |
const styleKey = document.querySelector('#styleSelector .style-btn.active').dataset.value;
|
| 1109 |
-
const stylePrompt =
|
| 1110 |
const gender = document.getElementById('gender').value;
|
| 1111 |
const age = document.getElementById('age').value;
|
| 1112 |
const nationality = document.getElementById('nationality').value;
|
|
@@ -1117,14 +1106,15 @@ function getPrompt() {
|
|
| 1117 |
additionalPrompt = document.getElementById('additional_prompt').value;
|
| 1118 |
aspectRatio = document.querySelector('#aspectRatioSelectorModel .aspect-ratio-btn.active').dataset.value;
|
| 1119 |
|
| 1120 |
-
prompt += `\n**STYLE & MOOD:** ${stylePrompt}`;
|
| 1121 |
-
prompt += `\n\n**MODEL(S) SPECIFICATIONS:**\
|
| 1122 |
-
prompt += `\n\n**CLOTHING:** The model is wearing: ${clothingDetails}.`;
|
| 1123 |
prompt += `\n\n**POSE & COMPOSITION:**\n- Perspective: ${shotType}\n- Camera Angle: Straight-on\n- Pose: ${pose}`;
|
| 1124 |
|
| 1125 |
} else if (currentMode === 'children') {
|
|
|
|
| 1126 |
const styleKey = document.querySelector('#childStyleSelector .style-btn.active').dataset.value;
|
| 1127 |
-
const stylePrompt =
|
| 1128 |
const gender = document.getElementById('child_gender').value;
|
| 1129 |
const age = document.getElementById('child_age').value;
|
| 1130 |
const nationality = document.getElementById('child_nationality').value;
|
|
@@ -1134,20 +1124,20 @@ function getPrompt() {
|
|
| 1134 |
additionalPrompt = document.getElementById('child_additional_prompt').value;
|
| 1135 |
aspectRatio = document.querySelector('#aspectRatioSelectorChildren .aspect-ratio-btn.active').dataset.value;
|
| 1136 |
|
| 1137 |
-
prompt += `\n**STYLE & MOOD:** ${stylePrompt}
|
| 1138 |
-
prompt += `\n\n**MODEL(S) SPECIFICATIONS:**\
|
| 1139 |
-
prompt += `\n\n**CLOTHING:** The child is wearing: ${clothingDetails}.`;
|
| 1140 |
-
prompt += `\n\n**POSE & COMPOSITION:**\n- Perspective: ${shotType}\n- Camera Angle: Straight-on\n-
|
| 1141 |
|
| 1142 |
-
} else {
|
| 1143 |
-
prompt =
|
| 1144 |
const styleKey = document.querySelector('#objectStyleSelector .style-btn.active').dataset.value;
|
| 1145 |
-
const stylePrompt =
|
| 1146 |
const objectName = document.getElementById('object_name').value || "the product";
|
| 1147 |
additionalPrompt = document.getElementById('object_additional_prompt').value;
|
| 1148 |
aspectRatio = document.querySelector('#aspectRatioSelectorObject .aspect-ratio-btn.active').dataset.value;
|
| 1149 |
|
| 1150 |
-
prompt += `\n**SCENE CONFIGURATION:**\n- Mode: Flat lay / Hanging shoot\n- Style: ${stylePrompt}`;
|
| 1151 |
prompt += `\n- Product: ${objectName}`;
|
| 1152 |
}
|
| 1153 |
|
|
@@ -1156,15 +1146,15 @@ function getPrompt() {
|
|
| 1156 |
}
|
| 1157 |
|
| 1158 |
if (wantsDetailsCollage) {
|
| 1159 |
-
prompt += `\n\n**COMPOSITION DIRECTIVE (DETAILS COLLAGE):**
|
| 1160 |
}
|
| 1161 |
|
| 1162 |
if (wantsVariantsCollage) {
|
| 1163 |
-
prompt += `\n\n**COMPOSITION DIRECTIVE (VARIANTS COLLAGE):**
|
| 1164 |
}
|
| 1165 |
|
| 1166 |
if (wantsTextOverlay && textToOverlay) {
|
| 1167 |
-
prompt += `\n\n**GRAPHIC OVERLAY:**
|
| 1168 |
}
|
| 1169 |
|
| 1170 |
return `${envKeyword}, ${prompt} ${aspectRatio}`;
|
|
@@ -1365,6 +1355,7 @@ def serve_env(env_id):
|
|
| 1365 |
|
| 1366 |
keyword = env_data.get("keyword", "")
|
| 1367 |
env_type = env_data.get("type", "closed")
|
|
|
|
| 1368 |
|
| 1369 |
current_log = {
|
| 1370 |
"time": datetime.utcnow().isoformat(),
|
|
@@ -1384,7 +1375,7 @@ def serve_env(env_id):
|
|
| 1384 |
save_data(data)
|
| 1385 |
|
| 1386 |
if env_type == 'open':
|
| 1387 |
-
return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword)
|
| 1388 |
|
| 1389 |
stored_token = env_data.get("device_token")
|
| 1390 |
user_token = request.cookies.get(f'access_token_{env_id}')
|
|
@@ -1413,18 +1404,19 @@ def serve_env(env_id):
|
|
| 1413 |
</body>
|
| 1414 |
</html>
|
| 1415 |
""", 403
|
| 1416 |
-
return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword)
|
| 1417 |
else:
|
| 1418 |
new_token = ''.join(random.choices(string.ascii_letters + string.digits, k=40))
|
| 1419 |
env_data['device_token'] = new_token
|
| 1420 |
data[env_id] = env_data
|
| 1421 |
save_data(data)
|
| 1422 |
|
| 1423 |
-
resp = make_response(render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword))
|
| 1424 |
resp.set_cookie(f'access_token_{env_id}', new_token, max_age=31536000, httponly=True, samesite='Lax')
|
| 1425 |
return resp
|
| 1426 |
|
| 1427 |
if __name__ == '__main__':
|
|
|
|
| 1428 |
download_db_from_hf()
|
| 1429 |
if HF_TOKEN_WRITE:
|
| 1430 |
backup_thread = threading.Thread(target=periodic_backup, daemon=True)
|
|
|
|
| 21 |
app.secret_key = 'your_unique_secret_key_gippo_312_shop_54321_no_login_synkris'
|
| 22 |
DATA_FILE = 'data.json'
|
| 23 |
DATA_FILE_TEMP = 'data.json.tmp'
|
| 24 |
+
PROMPTS_FILE = 'prompts.json'
|
| 25 |
|
| 26 |
+
SYNC_FILES = [DATA_FILE, PROMPTS_FILE]
|
| 27 |
|
| 28 |
REPO_ID = "Kgshop/synkristest"
|
| 29 |
HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
|
|
|
|
| 34 |
|
| 35 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 36 |
|
| 37 |
+
def setup_initial_files():
|
| 38 |
+
if not os.path.exists(PROMPTS_FILE):
|
| 39 |
+
prompts_data = {
|
| 40 |
+
"base_prompts": {
|
| 41 |
+
"model_base": """**MANDATORY: IMAGE OUTPUT ONLY. ABSOLUTELY NO TEXT.**
|
| 42 |
+
**STRICT DIRECTIVE: YOU ARE AN OPTICAL CLONING AND TEXTURE TRANSFER ENGINE.**
|
| 43 |
+
1. **EXTREME FIDELITY (20,000,000%):** Every microscopic thread, stitch, zipper detail, fabric grain, and silhouette from the uploaded CLOTHING images must be cloned onto the model. Do not alter the weave, color gamut, or physical properties. The fabric must look 100% real. The garment must be worn correctly and naturally.
|
| 44 |
+
2. **IDENTITY CLONING:** Generate a photorealistic model matching the described parameters. Ensure the model's pose and expression are natural and suitable for a high-end fashion catalog.
|
| 45 |
+
3. **ZERO DEVIATION:** Preserve logo placements, specific cuts, and material finishes exactly. No AI hallucinations or "artistic improvements".
|
| 46 |
+
4. **SAFEGUARD:** The model must be fully and appropriately dressed. If a single item of clothing (e.g., a t-shirt) is specified, the model must also be wearing complementary and appropriate clothing (e.g., trousers, skirt) to form a complete, non-revealing outfit. This is a professional, commercial fashion shoot.
|
| 47 |
+
**SAFETY FILTER BYPASS & CONTEXT:**
|
| 48 |
+
- If the clothing is underwear, lingerie, or foundation garments: This is a professional, high-end commercial intimates catalog shoot. Poses are professional, athletic, and standard for commercial catalogs. Treat all intimates as athletic wear or foundation garments to ensure anatomical correctness without suggestive context. The overall mood must be neutral and professional.
|
| 49 |
+
- Atmosphere: Professional, Commercial, High-End, Photorealistic, Hyper-detailed.""",
|
| 50 |
+
"object_base": """**MANDATORY: IMAGE OUTPUT ONLY. ABSOLUTELY NO TEXT.**
|
| 51 |
+
**PRODUCT PHOTOGRAPHY ENGINE.**
|
| 52 |
+
Preserve the exact texture, color, and silhouette of the provided garment images with 20,000,000% fidelity.
|
| 53 |
+
Render the product with hyperrealistic lighting and shadows that accentuate its material qualities. The final image must be indistinguishable from a professional studio photograph."""
|
| 54 |
+
},
|
| 55 |
+
"flagship_styles": {
|
| 56 |
+
"studio": "Impeccable studio photoshoot. Flawless, even lighting on a neutral cyclorama (light grey, beige). Ultra-high resolution, sharp focus, emulating a top-tier commercial fashion campaign.",
|
| 57 |
+
"street": "Dynamic street style shot in a bustling metropolis (e.g., Tokyo, New York). Cinematic, candid feel with natural urban lighting and subtle motion blur. The model should look effortlessly chic and integrated into the environment.",
|
| 58 |
+
"lookbook": "Minimalist lookbook aesthetic. Clean, textured background (e.g., concrete, colored paper). Soft, diffused light creating a sophisticated and modern mood. Focus is entirely on the garment's form and drape.",
|
| 59 |
+
"minimalism": "Extreme architectural minimalism. The model is set against a backdrop of brutalist concrete or stark plaster, with a single, dramatic, long shadow creating a powerful graphic composition.",
|
| 60 |
+
"selfie": "Hyperrealistic 'captured moment' selfie. Shot on a smartphone in a visually interesting location (e.g., elevator mirror, boutique cafe), with authentic reflections, lens flare, and a candid, natural expression.",
|
| 61 |
+
"creative": "Avant-garde, conceptual photoshoot. Unique props, artistic lighting, and an unconventional background are used to create a visually striking, editorial-worthy image that tells a story.",
|
| 62 |
+
"new_year": "Festive New Year's atmosphere. Soft bokeh from fairy lights, dynamic sparkler trails, set against a beautifully decorated tree or a magical snowy landscape. Evokes warmth and celebration.",
|
| 63 |
+
"retro": "Authentic 35mm film photograph emulation. Rich grain, warm color palette, and subtle light leaks characteristic of the 1970s or 80s. Poses and environment reflect the era.",
|
| 64 |
+
"boho": "Golden hour boho dreamscape. Shot in a field of wildflowers during sunset. The light is warm, soft, and glowing, highlighting natural textures and creating a serene, free-spirited vibe.",
|
| 65 |
+
"gothic": "Moody, gothic romance. Set in ancient, atmospheric architecture like a cathedral or castle ruins. Low-key lighting, deep shadows, and a sense of mystery and drama.",
|
| 66 |
+
"editorial": "High-fashion glossy magazine editorial. Bold, saturated colored background. Clever use of mirrors to create compelling reflections and fragmented views of the model and outfit.",
|
| 67 |
+
"film_noir": "Cinematic black and white film noir. High contrast, dramatic 'chiaroscuro' lighting, with long shadows and a sense of suspense. May incorporate atmospheric elements like rain or fog.",
|
| 68 |
+
"cottagecore": "Idyllic cottagecore aesthetic. A cozy, rustic setting in a country house or lush garden. Natural light, organic textures, and a feeling of wholesome, romanticized rural life.",
|
| 69 |
+
"royalcore": "Opulent royalcore aesthetic. Set in a lavish palace interior with ornate details, velvet curtains, and gilded furniture. The lighting is grand and dramatic, creating an air of aristocracy.",
|
| 70 |
+
"solarpunk": "Optimistic solarpunk future. Sleek, futuristic architecture seamlessly integrated with lush greenery. Bright, clean light fills the scene, suggesting a harmonious, tech-advanced society.",
|
| 71 |
+
"skater": "Energetic skater aesthetic. Wide-angle, dynamic shot in a skate park or on urban streets. Captures movement and a raw, youthful, counter-culture energy.",
|
| 72 |
+
"baroque": "Dramatic Baroque painting style. Ornate, detailed setting with rich fabrics. Lighting is high-contrast and theatrical, reminiscent of a Caravaggio masterpiece, creating deep, intense colors.",
|
| 73 |
+
"japandi": "Serene Japandi style. A fusion of Japanese minimalism and Scandinavian functionality. Clean lines, neutral tones, natural wood, and a focus on tranquility and uncluttered space.",
|
| 74 |
+
"coastal": "Relaxed coastal grandmother style. Bright, airy setting by the sea. A palette of whites, beiges, and soft blues. Natural materials and a feeling of effortless seaside elegance.",
|
| 75 |
+
"cyberpunk": "Gritty, neon-drenched cyberpunk cityscape. High-tech, futuristic elements, with reflections from neon signs on wet streets. A cool color palette and a sense of urban dystopia.",
|
| 76 |
+
"fantasy": "Enchanting fantasy world. A magical forest, ancient ruins, or ethereal landscape. The lighting is mystical and otherworldly, creating a dreamlike, narrative-driven image.",
|
| 77 |
+
"90s_grunge": "Raw 90s grunge aesthetic. Urban decay, abandoned locations, with a desaturated color palette. A feeling of angst, rebellion, and effortless, non-conformist style.",
|
| 78 |
+
"techwear": "Sleek, functional Techwear style. Set against futuristic, urban architecture. The lighting is clean and sharp, highlighting the technical details, fabrics, and functionality of the garments.",
|
| 79 |
+
"avant_garde": "Experimental avant-garde fashion. Abstract shapes, bold color clashes, and unconventional compositions. A highly artistic and conceptual approach that challenges traditional aesthetics.",
|
| 80 |
+
"home_casual": "Cozy, authentic home setting. Soft, natural light streaming through a window. A relaxed, intimate atmosphere with books, plants, and comfortable furnishings.",
|
| 81 |
+
"social_media_candid": "Candid, 'Instagrammable' moment. Shot in a trendy cafe or during a walk. Looks spontaneous and natural, as if capturing a real moment in time.",
|
| 82 |
+
"backstage": "Hectic, atmospheric backstage of a fashion show. Racks of clothes, makeup stations, and focused energy. The lighting is functional but chaotic, creating a 'behind-the-scenes' narrative.",
|
| 83 |
+
"road_trip": "Cinematic American road trip aesthetic. The model is near a vintage car against a vast, open landscape at sunset. A sense of freedom, adventure, and nostalgia.",
|
| 84 |
+
"rainy_day": "Romantic, melancholic rainy day scene. Reflections on wet pavement, droplets on windows, and the soft, diffused light of an overcast sky. A cozy and introspective mood.",
|
| 85 |
+
"night_flash": "Edgy, direct-flash night photography. High contrast, saturated colors, and sharp shadows. Creates a raw, spontaneous, 'paparazzi' or party-snapshot feel.",
|
| 86 |
+
"golden_hour_picnic": "Idyllic golden hour picnic. Warm, glowing sunset light filters through trees. A beautifully styled picnic scene with a relaxed, romantic, and joyful atmosphere."
|
| 87 |
+
},
|
| 88 |
+
"object_styles": {
|
| 89 |
+
"studio": "Professional product photography on a seamless, neutral background. Perfect, multi-point lighting that eliminates harsh shadows and reveals every detail of the product's texture and form.",
|
| 90 |
+
"minimalism": "Minimalist composition on a textured surface like concrete, marble, or fine sand. A single, crisp, hard light source creates a graphic, artistic shadow, emphasizing the product's silhouette.",
|
| 91 |
+
"nature": "The product is artfully placed in a complementary natural environment. E.g., on mossy rocks in a forest, beside a clear stream, or nestled among flowers. The lighting is natural and enhances the organic feel.",
|
| 92 |
+
"luxe": "Luxury still life. The product is arranged on a rich, tactile surface like silk, velvet, or dark marble. The lighting is low-key and sophisticated, with soft highlights that suggest opulence and exclusivity.",
|
| 93 |
+
"dark": "Moody and dramatic 'dark academia' style. The product is set against a dark, textured background. A single, directional light source carves the product out of the shadows, creating a mysterious and intense atmosphere."
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
with open(PROMPTS_FILE, 'w', encoding='utf-8') as f:
|
| 97 |
+
json.dump(prompts_data, f, ensure_ascii=False, indent=4)
|
| 98 |
+
|
| 99 |
+
def load_prompts():
|
| 100 |
+
if not os.path.exists(PROMPTS_FILE):
|
| 101 |
+
setup_initial_files()
|
| 102 |
+
try:
|
| 103 |
+
with open(PROMPTS_FILE, 'r', encoding='utf-8') as f:
|
| 104 |
+
return json.load(f)
|
| 105 |
+
except (FileNotFoundError, json.JSONDecodeError):
|
| 106 |
+
return {}
|
| 107 |
+
|
| 108 |
def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWNLOAD_DELAY):
|
| 109 |
if not HF_TOKEN_READ and not HF_TOKEN_WRITE:
|
| 110 |
return False
|
|
|
|
| 137 |
if file_name == DATA_FILE:
|
| 138 |
with open(file_name, 'w', encoding='utf-8') as f:
|
| 139 |
json.dump({}, f)
|
| 140 |
+
elif file_name == PROMPTS_FILE:
|
| 141 |
+
setup_initial_files()
|
| 142 |
except Exception:
|
| 143 |
pass
|
| 144 |
success = True
|
|
|
|
| 832 |
<div class="form-group">
|
| 833 |
<label for="shotType">Ракурс/План</label>
|
| 834 |
<select id="shotType">
|
| 835 |
+
<option value="Full body shot, dynamic angle">В полный рост, динамичный ракурс</option>
|
| 836 |
+
<option value="Medium shot, waist up, candid">По пояс, естественный</option>
|
| 837 |
+
<option value="Cowboy shot, mid-thigh up, fashion editorial style">"Ковбойский" план, журнальный</option>
|
| 838 |
+
<option value="Expressive portrait shot, detailed">Портрет, выразительный</option>
|
| 839 |
</select>
|
| 840 |
</div>
|
| 841 |
<div class="form-group">
|
| 842 |
<label for="pose">Поза</label>
|
| 843 |
<select id="pose">
|
| 844 |
+
<option value="standing confidently, looking at camera">Стоит уверенно, взгляд в камеру</option>
|
| 845 |
+
<option value="dynamic walking pose, slight motion blur">Динамичная походка, легкое размытие</option>
|
| 846 |
+
<option value="sitting relaxed on a modern chair">Сидит расслабленно на стуле</option>
|
| 847 |
+
<option value="leaning casually against a textured wall">Небрежно оперевшись о стену</option>
|
| 848 |
+
<option value="dynamic high fashion editorial pose, unconventional">Динамичная, нестандартная фэшн-поза</option>
|
| 849 |
</select>
|
| 850 |
</div>
|
| 851 |
<div class="form-group full-width">
|
|
|
|
| 875 |
<div class="form-group">
|
| 876 |
<label for="child_gender">Пол</label>
|
| 877 |
<select id="child_gender">
|
| 878 |
+
<option value="girl">Девочка</option>
|
| 879 |
+
<option value="boy">Мальчик</option>
|
| 880 |
</select>
|
| 881 |
</div>
|
| 882 |
<div class="form-group">
|
| 883 |
<label for="child_age">Возраст</label>
|
| 884 |
<select id="child_age">
|
| 885 |
+
<option value="infant (6-12 months old)">6-12 месяцев</option>
|
| 886 |
+
<option value="toddler (2-4 years old)">2-4 года</option>
|
| 887 |
+
<option value="child (5-8 years old)">5-8 лет</option>
|
| 888 |
+
<option value="pre-teen (9-12 years old)">9-12 лет</option>
|
| 889 |
</select>
|
| 890 |
</div>
|
| 891 |
<div class="form-group">
|
|
|
|
| 899 |
<div class="form-group">
|
| 900 |
<label for="child_shotType">Ракурс/План</label>
|
| 901 |
<select id="child_shotType">
|
| 902 |
+
<option value="Full body shot, playful angle">В полный рост</option>
|
| 903 |
+
<option value="Medium shot, capturing emotion">По пояс</option>
|
| 904 |
+
<option value="Close-up portrait, happy expression">Портрет</option>
|
| 905 |
</select>
|
| 906 |
</div>
|
| 907 |
<div class="form-group full-width">
|
| 908 |
<label for="child_pose">Поза/Действие</label>
|
| 909 |
<select id="child_pose">
|
| 910 |
+
<option value="running joyfully in a field">Бежит по полю</option>
|
| 911 |
+
<option value="playing enthusiastically with wooden toys on the floor">Играет с игрушками</option>
|
| 912 |
+
<option value="sitting and curiously looking at a picture book">Сидит с книгой</option>
|
| 913 |
+
<option value="posing for a candid school photo, smiling naturally">Позирует для фото</option>
|
| 914 |
+
<option value="laughing and jumping on a bed">Прыгает на кровати</option>
|
| 915 |
</select>
|
| 916 |
</div>
|
| 917 |
<div class="form-group full-width">
|
|
|
|
| 996 |
<script>
|
| 997 |
let currentMode = 'model';
|
| 998 |
const envKeyword = {{ keyword|tojson|safe }};
|
| 999 |
+
const promptsData = {{ prompts_data|tojson|safe }};
|
| 1000 |
|
| 1001 |
const flagshipStyles = {
|
| 1002 |
+
'studio': 'Студия (профи)', 'street': 'Стрит-стайл', 'lookbook': 'Лукбук (минимализм)',
|
| 1003 |
+
'minimalism': 'Экстрим минимализм', 'selfie': 'Селфи (гиперреализм)', 'creative': 'Креативная съемка',
|
| 1004 |
+
'new_year': 'Новый Год', 'retro': 'Ретро (35мм пленка)', 'boho': 'Бохо (золотой час)',
|
| 1005 |
+
'gothic': 'Готика', 'editorial': 'Эдиториал (глянец)', 'film_noir': 'Фильм-нуар (Ч/Б)',
|
| 1006 |
+
'cottagecore': 'Коттеджкор', 'royalcore': 'Роскошь (дворец)', 'solarpunk': 'Соларпанк',
|
| 1007 |
+
'skater': 'Скейтер', 'baroque': 'Барокко', 'japandi': 'Джапанди', 'coastal': 'Прибрежный стиль',
|
| 1008 |
+
'cyberpunk': 'Киберпанк', 'fantasy': 'Фэнтези', '90s_grunge': 'Гранж 90-х',
|
| 1009 |
+
'techwear': 'Techwear', 'avant_garde': 'Авангард', 'home_casual': 'Домашний уют',
|
| 1010 |
+
'social_media_candid': 'Инстаграм-фото', 'backstage': 'Бэкстейдж', 'road_trip': 'Роуд-трип',
|
| 1011 |
+
'rainy_day': 'Дождливый день', 'night_flash': 'Ночь (вспышка)', 'golden_hour_picnic': 'Пикник (золотой час)'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1012 |
};
|
| 1013 |
|
|
|
|
| 1014 |
const objectStyles = {
|
| 1015 |
+
'studio': 'Студия (профи)', 'minimalism': 'Минимализм', 'nature': 'На природе',
|
| 1016 |
+
'luxe': 'Лакшери', 'dark': 'Мрачный стиль'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1017 |
};
|
| 1018 |
|
|
|
|
| 1019 |
const femaleBodyTypes = {
|
| 1020 |
+
'standard': 'Станд��ртное', 'very_slim': 'Очень стройное (модель)', 'slim': 'Стройное (натуральное)',
|
| 1021 |
+
'slim_busty': 'Стройное с пышной грудью', 'athletic': 'Атлетичное', 'petite': 'Миниатюрное',
|
| 1022 |
+
'hourglass': 'Песочные часы', 'fit_curvy': 'Спортивное (curvy)', 'bombshell': 'Гипер-curvy',
|
| 1023 |
+
'curvy': 'Мягкое (curvy)', 'full_figured': 'Плюс-сайз'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1024 |
};
|
| 1025 |
|
| 1026 |
const maleBodyTypes = {
|
| 1027 |
+
'athletic': 'Атлетичное', 'lean and toned': 'Поджарое', 'muscular build': 'Мускулистое',
|
| 1028 |
+
'broad build': 'Крупное', 'slim build': 'Худощавое'
|
|
|
|
|
|
|
|
|
|
| 1029 |
};
|
| 1030 |
|
| 1031 |
function switchMode(mode) {
|
|
|
|
| 1083 |
}
|
| 1084 |
|
| 1085 |
function getPrompt() {
|
| 1086 |
+
let prompt = "";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1087 |
let aspectRatio = '';
|
| 1088 |
let additionalPrompt = '';
|
| 1089 |
|
|
|
|
| 1093 |
const textToOverlay = document.getElementById('textOverlayInput').value.trim();
|
| 1094 |
|
| 1095 |
if (currentMode === 'model') {
|
| 1096 |
+
prompt = promptsData.base_prompts.model_base;
|
| 1097 |
const styleKey = document.querySelector('#styleSelector .style-btn.active').dataset.value;
|
| 1098 |
+
const stylePrompt = promptsData.flagship_styles[styleKey];
|
| 1099 |
const gender = document.getElementById('gender').value;
|
| 1100 |
const age = document.getElementById('age').value;
|
| 1101 |
const nationality = document.getElementById('nationality').value;
|
|
|
|
| 1106 |
additionalPrompt = document.getElementById('additional_prompt').value;
|
| 1107 |
aspectRatio = document.querySelector('#aspectRatioSelectorModel .aspect-ratio-btn.active').dataset.value;
|
| 1108 |
|
| 1109 |
+
prompt += `\n\n**STYLE & MOOD:** ${stylePrompt}`;
|
| 1110 |
+
prompt += `\n\n**MODEL(S) SPECIFICATIONS:**\n- model: ${age} ${gender}, ${nationality} appearance, with a realistic, ${bodyType} body type.`;
|
| 1111 |
+
prompt += `\n\n**CLOTHING:** The model is wearing: ${clothingDetails}. If this is a single item like a top, they are also wearing appropriate bottoms (e.g. jeans, trousers). If it's bottoms, they wear a simple, neutral top. The full outfit is stylish and complete.`;
|
| 1112 |
prompt += `\n\n**POSE & COMPOSITION:**\n- Perspective: ${shotType}\n- Camera Angle: Straight-on\n- Pose: ${pose}`;
|
| 1113 |
|
| 1114 |
} else if (currentMode === 'children') {
|
| 1115 |
+
prompt = promptsData.base_prompts.model_base;
|
| 1116 |
const styleKey = document.querySelector('#childStyleSelector .style-btn.active').dataset.value;
|
| 1117 |
+
const stylePrompt = promptsData.flagship_styles[styleKey];
|
| 1118 |
const gender = document.getElementById('child_gender').value;
|
| 1119 |
const age = document.getElementById('child_age').value;
|
| 1120 |
const nationality = document.getElementById('child_nationality').value;
|
|
|
|
| 1124 |
additionalPrompt = document.getElementById('child_additional_prompt').value;
|
| 1125 |
aspectRatio = document.querySelector('#aspectRatioSelectorChildren .aspect-ratio-btn.active').dataset.value;
|
| 1126 |
|
| 1127 |
+
prompt += `\n\n**STYLE & MOOD:** ${stylePrompt} The scene should be cheerful, safe, and age-appropriate.`;
|
| 1128 |
+
prompt += `\n\n**MODEL(S) SPECIFICATIONS:**\n- model: A happy and natural-looking ${age} ${gender}, ${nationality} appearance.`;
|
| 1129 |
+
prompt += `\n\n**CLOTHING:** The child is wearing: ${clothingDetails}. The child is fully dressed in a complete, practical, and age-appropriate outfit.`;
|
| 1130 |
+
prompt += `\n\n**POSE & COMPOSITION:**\n- Perspective: ${shotType}\n- Camera Angle: Straight-on\n- Action: ${pose}`;
|
| 1131 |
|
| 1132 |
+
} else {
|
| 1133 |
+
prompt = promptsData.base_prompts.object_base;
|
| 1134 |
const styleKey = document.querySelector('#objectStyleSelector .style-btn.active').dataset.value;
|
| 1135 |
+
const stylePrompt = promptsData.object_styles[styleKey];
|
| 1136 |
const objectName = document.getElementById('object_name').value || "the product";
|
| 1137 |
additionalPrompt = document.getElementById('object_additional_prompt').value;
|
| 1138 |
aspectRatio = document.querySelector('#aspectRatioSelectorObject .aspect-ratio-btn.active').dataset.value;
|
| 1139 |
|
| 1140 |
+
prompt += `\n\n**SCENE CONFIGURATION:**\n- Mode: Flat lay / Hanging shoot\n- Style: ${stylePrompt}`;
|
| 1141 |
prompt += `\n- Product: ${objectName}`;
|
| 1142 |
}
|
| 1143 |
|
|
|
|
| 1146 |
}
|
| 1147 |
|
| 1148 |
if (wantsDetailsCollage) {
|
| 1149 |
+
prompt += `\n\n**COMPOSITION DIRECTIVE (DETAILS COLLAGE):** Create a marketplace-ready collage. The main image features the full look. Add 2-3 smaller inset images showcasing ultra-close-up shots of fabric texture, seams, and hardware (buttons, zippers).`;
|
| 1150 |
}
|
| 1151 |
|
| 1152 |
if (wantsVariantsCollage) {
|
| 1153 |
+
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 various colors or styles. The result must be a harmonious and balanced collage.`;
|
| 1154 |
}
|
| 1155 |
|
| 1156 |
if (wantsTextOverlay && textToOverlay) {
|
| 1157 |
+
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.`;
|
| 1158 |
}
|
| 1159 |
|
| 1160 |
return `${envKeyword}, ${prompt} ${aspectRatio}`;
|
|
|
|
| 1355 |
|
| 1356 |
keyword = env_data.get("keyword", "")
|
| 1357 |
env_type = env_data.get("type", "closed")
|
| 1358 |
+
prompts_data = load_prompts()
|
| 1359 |
|
| 1360 |
current_log = {
|
| 1361 |
"time": datetime.utcnow().isoformat(),
|
|
|
|
| 1375 |
save_data(data)
|
| 1376 |
|
| 1377 |
if env_type == 'open':
|
| 1378 |
+
return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data)
|
| 1379 |
|
| 1380 |
stored_token = env_data.get("device_token")
|
| 1381 |
user_token = request.cookies.get(f'access_token_{env_id}')
|
|
|
|
| 1404 |
</body>
|
| 1405 |
</html>
|
| 1406 |
""", 403
|
| 1407 |
+
return render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data)
|
| 1408 |
else:
|
| 1409 |
new_token = ''.join(random.choices(string.ascii_letters + string.digits, k=40))
|
| 1410 |
env_data['device_token'] = new_token
|
| 1411 |
data[env_id] = env_data
|
| 1412 |
save_data(data)
|
| 1413 |
|
| 1414 |
+
resp = make_response(render_template_string(SYNKRIS_LOOK_TEMPLATE, keyword=keyword, prompts_data=prompts_data))
|
| 1415 |
resp.set_cookie(f'access_token_{env_id}', new_token, max_age=31536000, httponly=True, samesite='Lax')
|
| 1416 |
return resp
|
| 1417 |
|
| 1418 |
if __name__ == '__main__':
|
| 1419 |
+
setup_initial_files()
|
| 1420 |
download_db_from_hf()
|
| 1421 |
if HF_TOKEN_WRITE:
|
| 1422 |
backup_thread = threading.Thread(target=periodic_backup, daemon=True)
|