Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -56,7 +56,7 @@ def save_usage_data(data):
|
|
| 56 |
# بارگذاری اولیه دادهها
|
| 57 |
usage_data_cache = load_usage_data()
|
| 58 |
|
| 59 |
-
# --- بارگذاری مدل تشخیص محتوای نامناسب (
|
| 60 |
print("Loading Safety Checker...")
|
| 61 |
safety_classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
|
| 62 |
|
|
@@ -133,18 +133,56 @@ ASPECT_RATIOS_MAP = {
|
|
| 133 |
"شخصیسازی (Custom)": "Custom"
|
| 134 |
}
|
| 135 |
|
|
|
|
| 136 |
BANNED_WORDS = [
|
| 137 |
-
|
| 138 |
-
"
|
| 139 |
-
"
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
]
|
| 142 |
|
| 143 |
def check_text_safety(text):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
text_lower = text.lower()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
for word in BANNED_WORDS:
|
| 146 |
-
|
|
|
|
|
|
|
| 147 |
return False
|
|
|
|
| 148 |
return True
|
| 149 |
|
| 150 |
def translate_prompt(text):
|
|
@@ -282,20 +320,22 @@ def infer(
|
|
| 282 |
None, seed, get_quota_exceeded_html(),
|
| 283 |
gr.update(visible=False), gr.update(visible=True)
|
| 284 |
)
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
consume_quota(fingerprint)
|
| 288 |
-
|
| 289 |
-
# --- ادامه منطق اصلی ساخت تصویر ---
|
| 290 |
if input_image is None:
|
| 291 |
return None, seed, get_error_html("لطفاً ابتدا یک تصویر بارگذاری کنید."), gr.update(visible=True), gr.update(visible=False)
|
| 292 |
|
| 293 |
if is_image_nsfw(input_image):
|
| 294 |
return None, seed, get_error_html("تصویر ورودی دارای محتوای نامناسب است و پردازش نمیشود."), gr.update(visible=True), gr.update(visible=False)
|
| 295 |
|
|
|
|
| 296 |
english_prompt = translate_prompt(prompt)
|
| 297 |
if not check_text_safety(english_prompt):
|
| 298 |
-
return None, seed, get_error_html("متن درخواست شامل کلمات
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
|
| 300 |
adapter_internal_name = LORA_MAPPING.get(lora_adapter_persian)
|
| 301 |
if adapter_internal_name:
|
|
@@ -306,7 +346,8 @@ def infer(
|
|
| 306 |
|
| 307 |
generator = torch.Generator(device=device).manual_seed(seed)
|
| 308 |
|
| 309 |
-
|
|
|
|
| 310 |
base_negative = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
|
| 311 |
final_negative_prompt = f"{safety_negative}, {base_negative}"
|
| 312 |
|
|
@@ -334,6 +375,7 @@ def infer(
|
|
| 334 |
true_cfg_scale=guidance_scale,
|
| 335 |
).images[0]
|
| 336 |
|
|
|
|
| 337 |
if is_image_nsfw(result):
|
| 338 |
return None, seed, get_error_html("تصویر تولید شده حاوی محتوای نامناسب بود و حذف شد."), gr.update(visible=True), gr.update(visible=False)
|
| 339 |
|
|
@@ -354,10 +396,9 @@ def infer(
|
|
| 354 |
except Exception as e:
|
| 355 |
error_str = str(e)
|
| 356 |
# -------------------------------------------------------------
|
| 357 |
-
# مدیریت خطای GPU QUOTA
|
| 358 |
# -------------------------------------------------------------
|
| 359 |
if "quota" in error_str.lower() or "exceeded" in error_str.lower():
|
| 360 |
-
# خطا را به بالا پرتاب میکنیم تا اسکنر جاوااسکریپت آن را بگیرد
|
| 361 |
raise e
|
| 362 |
|
| 363 |
return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
|
|
@@ -395,7 +436,7 @@ js_upgrade_func = """
|
|
| 395 |
}
|
| 396 |
"""
|
| 397 |
|
| 398 |
-
# --- جاوااسکریپت سراسری
|
| 399 |
js_global_content = """
|
| 400 |
<script>
|
| 401 |
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -631,7 +672,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 631 |
</script>
|
| 632 |
"""
|
| 633 |
|
| 634 |
-
# --- CSS Updated
|
| 635 |
css_code = """
|
| 636 |
<style>
|
| 637 |
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
|
|
@@ -650,7 +691,7 @@ css_code = """
|
|
| 650 |
font-family: 'Vazirmatn', sans-serif !important;
|
| 651 |
}
|
| 652 |
|
| 653 |
-
/* --- IP Reset Guide CSS (مودال
|
| 654 |
:root {
|
| 655 |
--guide-bg: rgba(255, 255, 255, 0.98);
|
| 656 |
--guide-border: rgba(102, 126, 234, 0.2);
|
|
|
|
| 56 |
# بارگذاری اولیه دادهها
|
| 57 |
usage_data_cache = load_usage_data()
|
| 58 |
|
| 59 |
+
# --- بارگذاری مدل تشخیص محتوای نامناسب (Image Safety) ---
|
| 60 |
print("Loading Safety Checker...")
|
| 61 |
safety_classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
|
| 62 |
|
|
|
|
| 133 |
"شخصیسازی (Custom)": "Custom"
|
| 134 |
}
|
| 135 |
|
| 136 |
+
# --- لیست کلمات ممنوعه پیشرفته (Strict Mode) ---
|
| 137 |
BANNED_WORDS = [
|
| 138 |
+
# General NSFW
|
| 139 |
+
"nsfw", "nude", "naked", "sex", "porn", "erotic", "xxx", "18+", "adult",
|
| 140 |
+
"explicit", "uncensored", "sexual", "lewd", "sensual", "lust", "horny",
|
| 141 |
+
|
| 142 |
+
# Anatomy (Explicit)
|
| 143 |
+
"breast", "breasts", "nipple", "nipples", "vagina", "pussy", "cunt",
|
| 144 |
+
"penis", "dick", "cock", "genital", "genitals", "groin", "pubic",
|
| 145 |
+
"ass", "butt", "buttocks", "anus", "anal", "rectum",
|
| 146 |
+
|
| 147 |
+
# Acts / Concepts
|
| 148 |
+
"intercourse", "masturbation", "orgasm", "blowjob", "bj", "cum", "sperm",
|
| 149 |
+
"ejaculation", "penetration", "fucking", "sucking", "licking",
|
| 150 |
+
|
| 151 |
+
# Clothing / Lingerie
|
| 152 |
+
"lingerie", "bikini", "swimwear", "underwear", "panties", "bra", "thong",
|
| 153 |
+
"topless", "bottomless", "undressed", "unclothed", "skimpy", "transparent",
|
| 154 |
+
"see-through",
|
| 155 |
+
|
| 156 |
+
# Fetish / Styles
|
| 157 |
+
"fetish", "bdsm", "bondage", "latex", "hentai", "ecchi", "ahegao",
|
| 158 |
+
"exhibitionism", "voyeur", "harem",
|
| 159 |
+
|
| 160 |
+
# Violence / Gore (Optional but recommended for strict safety)
|
| 161 |
+
"gore", "bloody", "blood", "kill", "murder", "dead", "torture", "abuse"
|
| 162 |
]
|
| 163 |
|
| 164 |
def check_text_safety(text):
|
| 165 |
+
"""
|
| 166 |
+
بررسی وجود کلمات ممنوعه در متن انگلیسی.
|
| 167 |
+
از متد whole word matching ساده استفاده میکند تا کلماتی مثل 'assassin' اشتباهاً حذف نشوند.
|
| 168 |
+
"""
|
| 169 |
+
if not text: return True
|
| 170 |
text_lower = text.lower()
|
| 171 |
+
|
| 172 |
+
# نرمالسازی متن برای جستجوی دقیقتر
|
| 173 |
+
# اضافه کردن فاصله به اول و آخر متن برای تشخیص کلمات اول و آخر جمله
|
| 174 |
+
padded_text = f" {text_lower} "
|
| 175 |
+
|
| 176 |
+
# حذف علائم نگارشی برای جلوگیری از دور زدن فیلتر (مثلاً sex.)
|
| 177 |
+
for char in [".", ",", "!", "?", "-", "_", "(", ")", "[", "]", "{", "}"]:
|
| 178 |
+
padded_text = padded_text.replace(char, " ")
|
| 179 |
+
|
| 180 |
for word in BANNED_WORDS:
|
| 181 |
+
# جستجو به صورت کلمه مستقل
|
| 182 |
+
if f" {word} " in padded_text:
|
| 183 |
+
print(f"Safety Triggered: Found banned word '{word}'")
|
| 184 |
return False
|
| 185 |
+
|
| 186 |
return True
|
| 187 |
|
| 188 |
def translate_prompt(text):
|
|
|
|
| 320 |
None, seed, get_quota_exceeded_html(),
|
| 321 |
gr.update(visible=False), gr.update(visible=True)
|
| 322 |
)
|
| 323 |
+
|
| 324 |
+
# --- بررسیهای اولیه (تصویر و متن) قبل از کسر اعتبار ---
|
|
|
|
|
|
|
|
|
|
| 325 |
if input_image is None:
|
| 326 |
return None, seed, get_error_html("لطفاً ابتدا یک تصویر بارگذاری کنید."), gr.update(visible=True), gr.update(visible=False)
|
| 327 |
|
| 328 |
if is_image_nsfw(input_image):
|
| 329 |
return None, seed, get_error_html("تصویر ورودی دارای محتوای نامناسب است و پردازش نمیشود."), gr.update(visible=True), gr.update(visible=False)
|
| 330 |
|
| 331 |
+
# ترجمه و بررسی متن (مهم: قبل از کسر اعتبار)
|
| 332 |
english_prompt = translate_prompt(prompt)
|
| 333 |
if not check_text_safety(english_prompt):
|
| 334 |
+
return None, seed, get_error_html("متن درخواست شامل کلمات غیرمجاز، جنسی یا خشونتآمیز است. لطفاً متن را اصلاح کنید."), gr.update(visible=True), gr.update(visible=False)
|
| 335 |
+
|
| 336 |
+
# اگر همه چیز امن بود، حالا اعتبار را کسر میکنیم
|
| 337 |
+
if subscription_status != 'paid':
|
| 338 |
+
consume_quota(fingerprint)
|
| 339 |
|
| 340 |
adapter_internal_name = LORA_MAPPING.get(lora_adapter_persian)
|
| 341 |
if adapter_internal_name:
|
|
|
|
| 346 |
|
| 347 |
generator = torch.Generator(device=device).manual_seed(seed)
|
| 348 |
|
| 349 |
+
# اضافه کردن کلمات منفی ایمنی به صورت پیشفرض به پرامپت منفی
|
| 350 |
+
safety_negative = "nsfw, nude, naked, porn, sexual, xxx, breast, nipple, genital, vagina, penis, ass, lingerie, bikini, swimwear, underwear, fetish, topless, gore, violence, blood, explicit"
|
| 351 |
base_negative = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
|
| 352 |
final_negative_prompt = f"{safety_negative}, {base_negative}"
|
| 353 |
|
|
|
|
| 375 |
true_cfg_scale=guidance_scale,
|
| 376 |
).images[0]
|
| 377 |
|
| 378 |
+
# بررسی نهایی تصویر تولید شده
|
| 379 |
if is_image_nsfw(result):
|
| 380 |
return None, seed, get_error_html("تصویر تولید شده حاوی محتوای نامناسب بود و حذف شد."), gr.update(visible=True), gr.update(visible=False)
|
| 381 |
|
|
|
|
| 396 |
except Exception as e:
|
| 397 |
error_str = str(e)
|
| 398 |
# -------------------------------------------------------------
|
| 399 |
+
# مدیریت خطای GPU QUOTA
|
| 400 |
# -------------------------------------------------------------
|
| 401 |
if "quota" in error_str.lower() or "exceeded" in error_str.lower():
|
|
|
|
| 402 |
raise e
|
| 403 |
|
| 404 |
return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
|
|
|
|
| 436 |
}
|
| 437 |
"""
|
| 438 |
|
| 439 |
+
# --- جاوااسکریپت سراسری ---
|
| 440 |
js_global_content = """
|
| 441 |
<script>
|
| 442 |
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
| 672 |
</script>
|
| 673 |
"""
|
| 674 |
|
| 675 |
+
# --- CSS Updated ---
|
| 676 |
css_code = """
|
| 677 |
<style>
|
| 678 |
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
|
|
|
|
| 691 |
font-family: 'Vazirmatn', sans-serif !important;
|
| 692 |
}
|
| 693 |
|
| 694 |
+
/* --- IP Reset Guide CSS (مودال) --- */
|
| 695 |
:root {
|
| 696 |
--guide-bg: rgba(255, 255, 255, 0.98);
|
| 697 |
--guide-border: rgba(102, 126, 234, 0.2);
|