@@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-06 17:58+0300\n" +"POT-Creation-Date: 2026-05-14 12:31+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -752,6 +752,10 @@ msgstr "Доступно только в платном тарифе" msgid "Face not found in the image. Please try another image with a face." msgstr "Не найдено лицо на картинке. Попробуйте другую картинку с лицом." +#: ml_model/exceptions.py:168 +msgid "The input image may contain real person." +msgstr "Загруженное изображение может содержать реального человека." + #: ml_model/models.py:18 ml_model/models.py:38 ml_model/models.py:70 #: ml_model/models.py:182 tools/media/models.py:67 msgid "Slug" @@ -1047,7 +1051,7 @@ msgstr "Соответствующая версия не найдена" msgid "Image is ready" msgstr "Изображение готово" -#: ml_model/services/elevenlabs_music.py:46 +#: ml_model/services/elevenlabs_music.py:45 msgid "Duration cannot be less than 5 seconds" msgstr "Длительность не может быть меньше 5 секунд" @@ -1065,20 +1069,23 @@ msgstr "" "Режим «Плавное движение» доступен только для 5-секундных видео в качестве " "540p и 720p" -#: ml_model/services/minimaxmusic.py:58 -#: ml_model/services/minimaxmusic_lite.py:62 -msgid "Lyrics is too long" -msgstr "Текст песни слишком длинный" - #: ml_model/services/minio_service.py:37 ml_model/services/minio_service.py:55 #: ml_model/services/minio_service.py:63 ml_model/services/minio_service.py:72 msgid "Unknown bucket destination" msgstr "Неизвестный бакет для загрузки" +#: ml_model/services/seedance_2_dreamina.py:108 +msgid "1080p output is not supported for Seedance Dreamina 2.0 Fast." +msgstr "" + #: ml_model/services/upscaleai.py:124 msgid "No image given for improving" msgstr "Нет изображения для улучшения" +#: ml_model/tasks.py:137 +msgid "Lyrics is too long" +msgstr "Текст песни слишком длинный" + #: ml_model/views.py:65 msgid "Model data cannot be retrieved" msgstr "Невозможно получить данные модели" @@ -1377,7 +1384,7 @@ msgstr "Публичный API" msgid "Media" msgstr "Медиа" -#: tools/chats/apis.py:201 tools/media/apis.py:207 +#: tools/chats/apis.py:201 tools/media/apis.py:209 #: tools/public_api/views/base.py:100 msgid "" "An unexpected generation error has occurred. Please try again later or use a " @@ -1399,12 +1406,12 @@ msgstr "Чат %(id)s" msgid "Chat" msgstr "Чат" -#: tools/media/apis.py:175 +#: tools/media/apis.py:176 msgid "" "Temporary issues with the service, we are already working on a solution." msgstr "Временные неполадки с сервисом, мы уже работаем над их решением." -#: tools/media/apis.py:254 tools/public_api/views/ml_service.py:63 +#: tools/media/apis.py:256 tools/public_api/views/ml_service.py:63 #: tools/public_api/views/ml_service.py:107 msgid "Voice not found." msgstr "Голос не найден." @@ -9,6 +9,7 @@ from backend import settings from ml_model.exceptions import ( FileExtensionNotSupported, GenerationException, + RealPersonDetectedError, RequestBlocked, ) from poller.models import Proxy @@ -276,6 +277,12 @@ class BytedanceModelArkAdapter: raise GenerationException if data.get('id') or data.get('task_id'): return data + if error_code := data.get('error', {}).get('code', None): + match error_code: + case 'InputImageSensitiveContentDetected.PrivacyInformation': + raise RealPersonDetectedError + case _: + raise GenerationException raise GenerationException @@ -3,12 +3,13 @@ import time from datetime import timedelta from decimal import Decimal from io import BytesIO +from pathlib import Path import filetype from PIL import Image from messages.models import Message -from ml_model.exceptions import FileExtensionNotSupported +from ml_model.exceptions import CorruptedFileError, FileExtensionNotSupported from ml_model.services.EmbeddingService import EmbeddingService from ml_model.services.FileService import FileProcessingService from ml_model.services.base import SimpleService @@ -84,9 +85,14 @@ class Gemini_3_1(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) embedding_tokens = 0 if input_message.file: + supported_extensions = ['PDF', 'DOC', 'DOCX', 'XLSX', 'JPG', 'JPEG', 'PNG', 'WEBP'] file_service = FileProcessingService file_bytes = input_message.file.read() kind = filetype.guess(file_bytes[:550]) + if not kind: + if Path(input_message.file.name).suffix[1:].upper() not in supported_extensions: + raise FileExtensionNotSupported(supported_extensions) + raise CorruptedFileError raw_file_extension = kind.extension file_extension = file_service.get_file_extension(raw_file_extension, file_bytes) if file_extension in ('pdf', 'doc', 'docx', 'xlsx'): @@ -127,7 +133,7 @@ class Gemini_3_1(SimpleService): {'type': 'image_url', 'image_url': {'url': image_url}}, ] else: - raise FileExtensionNotSupported(['PDF', 'DOC', 'DOCX', 'XLSX', 'JPG', 'JPEG', 'PNG', 'WEBP']) + raise FileExtensionNotSupported(supported_extensions) start_time = time.time() result = openrouter_run(f'google/{version}:online', messages, callback_data, 'Gemini 3.1') process_time = timedelta(seconds=(time.time() - start_time)) @@ -161,3 +161,8 @@ class PaidPlanRequiredError(Exception): class FaceNotFoundError(Exception): def __str__(self) -> str: return _('Face not found in the image. Please try another image with a face.') + + +class RealPersonDetectedError(Exception): + def __str__(self) -> str: + return _('The input image may contain real person.') @@ -0,0 +1,17 @@ +# Generated by Django 5.0.11 on 2025-12-19 15:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('payments', '0029_remove_paymentmethod_card_type_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='paymentplan', + name='points', + ), + ] @@ -20,13 +20,6 @@ class PaymentPlan(BaseModel): is_corporate = models.BooleanField(default=False, verbose_name=_('Is corporate')) individual = models.BooleanField(default=False, verbose_name=_('Individual')) is_visible = models.BooleanField(default=True, verbose_name=_('Is visible')) - points = ArrayField( - default=list, - blank=True, - base_field=models.CharField(), - verbose_name='Поинты', - help_text='Перечислять через запятую', - ) @property def accessed_models(self): @@ -196,7 +196,6 @@ async def list_payment_plans(request): price=plan.price, tokens_per_plan=plan.tokens_per_plan, is_corporate=plan.is_corporate, - points=plan.points, grouped_features=[{'name': cat, 'features': feats} for cat, feats in grouped.items()], individual=plan.individual, ) @@ -130,7 +130,6 @@ class PlansAPITest(BaseAuthorizedAPITest): 'price', 'tokens_per_plan', 'is_corporate', - 'points', 'grouped_features', 'accessed_models', 'individual', @@ -25,7 +25,6 @@ class PaymentPlanSchema(Schema): price: condecimal(max_digits=10, decimal_places=2) tokens_per_plan: condecimal(max_digits=10, decimal_places=2) is_corporate: bool - points: list[str] grouped_features: list[GroupedPlanFeatureSchema] = [] accessed_models: list[str] = [] individual: bool @@ -27,6 +27,7 @@ from ml_model.exceptions import ( RequestBlocked, ServiceHighDemandError, UnsupportedSize, + RealPersonDetectedError ) from ml_model.models import NeuronModel from ml_model.services.base import SimpleService @@ -198,6 +199,7 @@ class MediaAPIView(APIView): ImageAnalysisError, UnrecognizedFileError, FaceNotFoundError, + RealPersonDetectedError, ), ): return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST)