@@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-21 16:56+0300\n" +"POT-Creation-Date: 2025-04-28 20:38+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -44,8 +44,8 @@ msgid "Description" msgstr "Описание" #: achievements/models.py:43 authentication/models/business_host.py:21 -#: authentication/models/email_token.py:12 authentication/models/user.py:245 -#: authentication/models/user.py:246 authentication/models/user_telegram.py:22 +#: authentication/models/email_token.py:12 authentication/models/user.py:246 +#: authentication/models/user.py:247 authentication/models/user_telegram.py:22 #: authentication/models/user_vk.py:12 payments/models/invoice.py:15 #: payments/models/payment.py:26 payments/models/payment_plan.py:61 msgid "User" @@ -159,7 +159,7 @@ msgstr "Бизнес Группы" msgid "Affiliated by" msgstr "Кем привлечена" -#: authentication/models/business_host.py:35 authentication/models/user.py:151 +#: authentication/models/business_host.py:35 authentication/models/user.py:152 #: authentication/models/whitelist.py:16 ml_model/models.py:163 #: payments/models/promocode.py:85 msgid "Is active" @@ -310,43 +310,43 @@ msgstr "Email Токен" msgid "Email Tokens" msgstr "Email Токены" -#: authentication/models/user.py:124 authentication/models/user_telegram.py:9 +#: authentication/models/user.py:125 authentication/models/user_telegram.py:9 msgid "First name" msgstr "Имя" -#: authentication/models/user.py:131 authentication/models/user_telegram.py:10 +#: authentication/models/user.py:132 authentication/models/user_telegram.py:10 msgid "Last name" msgstr "Фамилия" -#: authentication/models/user.py:138 authentication/models/user_telegram.py:11 +#: authentication/models/user.py:139 authentication/models/user_telegram.py:11 msgid "Username" msgstr "Имя пользователя" -#: authentication/models/user.py:145 +#: authentication/models/user.py:146 msgid "Email" msgstr "Email" -#: authentication/models/user.py:153 +#: authentication/models/user.py:154 msgid "Is staff" msgstr "Административный" -#: authentication/models/user.py:154 +#: authentication/models/user.py:155 msgid "Is superuser" msgstr "Суперюзер" -#: authentication/models/user.py:155 +#: authentication/models/user.py:156 msgid "Is email confirmed" msgstr "Email подтвержден" -#: authentication/models/user.py:156 +#: authentication/models/user.py:157 msgid "Is subscribed" msgstr "Подписан на уведомления" -#: authentication/models/user.py:162 +#: authentication/models/user.py:163 msgid "Picture name" msgstr "Имя аватара" -#: authentication/models/user.py:171 authentication/models/utm.py:21 +#: authentication/models/user.py:172 authentication/models/utm.py:21 msgid "UTM" msgstr "UTM" @@ -447,18 +447,30 @@ msgstr "Пользователь бизнес-аккаунта не зареги msgid "No user with this uid found" msgstr "Не найден пользователь с данным ID" -#: authentication/services/business_account_service.py:58 +#: authentication/services/business_account_service.py:60 msgid "BusinessAccount for this user doesn't exist" msgstr "Бизнес-аккаунт для данного юзера не найден" -#: authentication/services/business_account_service.py:68 +#: authentication/services/business_account_service.py:76 msgid "Invited account can either accept or reject an invitation" msgstr "Приглашенный аккаунт может принять или отклонить приглашение" -#: authentication/services/business_account_service.py:73 +#: authentication/services/business_account_service.py:81 msgid "Account is already confirmed" msgstr "Аккаунт уже подтвержден" +#: authentication/services/business_account_service.py:100 +#, fuzzy +#| msgid "Passwords do not match" +msgid "Passwords don't match" +msgstr "Пароли не совпадают" + +#: authentication/services/business_account_service.py:103 +#: authentication/services/business_account_service.py:106 +#: authentication/services/business_host_service.py:284 +msgid "You do not have sufficient rights to perform this action" +msgstr "У вас недостаточно прав для выполнения этого действия" + #: authentication/services/business_host_service.py:174 msgid "No user_email is provided" msgstr "" @@ -467,54 +479,59 @@ msgstr "" msgid "No business account by this uid at your company" msgstr "Такого аккаунта нет в вашей компании" -#: authentication/services/email_service.py:45 +#: authentication/services/email_service.py:49 msgid "Error occured when proceed email sending" msgstr "Случилась ошибка во время отправки email" -#: authentication/services/email_service.py:122 +#: authentication/services/email_service.py:126 +#: authentication/services/email_service.py:148 msgid "Regular users cannot send introductory letters" msgstr "Обычные пользователи не могут отсылать письма" -#: authentication/services/email_service.py:141 +#: authentication/services/email_service.py:165 msgid "Regular users cannot send invitation letters" msgstr "Обычные пользователи не могут отправлять письма для приглашений" -#: authentication/services/user_services.py:164 +#: authentication/services/user_services.py:166 msgid "No user like this in a database" msgstr "Такой пользователь отсутствует" -#: authentication/services/user_services.py:181 +#: authentication/services/user_services.py:183 msgid "token is not provided" msgstr "" -#: authentication/services/user_services.py:185 +#: authentication/services/user_services.py:187 msgid "No user token like this in a database" msgstr "" -#: authentication/services/user_services.py:205 +#: authentication/services/user_services.py:207 msgid "No email token provided" msgstr "Токен не получен" -#: authentication/services/user_services.py:209 +#: authentication/services/user_services.py:211 msgid "No token like this in a database" msgstr "Не найдено такого токена" -#: authentication/services/user_services.py:215 +#: authentication/services/user_services.py:217 msgid "Passwords do not match" msgstr "Пароли не совпадают" -#: authentication/services/user_services.py:253 +#: authentication/services/user_services.py:255 msgid "Current password is wrong" msgstr "Текущий пароль неверен" -#: authentication/views.py:107 authentication/views.py:214 +#: authentication/views.py:110 authentication/views.py:217 msgid "Unexpected error" msgstr "Непредвиденная ошибка" -#: authentication/views.py:211 +#: authentication/views.py:214 msgid "Email not found" msgstr "Email не найден" +#: authentication/views.py:329 +msgid "Business account has been re-invited" +msgstr "Повторное приглашение сотруднику успешно отправлено" + #: backend/urls.py:30 msgid "Requested object does not exists" msgstr "" @@ -536,6 +553,10 @@ msgstr "Файл не может быть размером больше %(max_mb msgid "Neuron Models" msgstr "Нейронные Модели" +#: ml_model/exceptions.py:18 +msgid "File extension not supported" +msgstr "Файл с таким расширением не поддерживается" + #: ml_model/models.py:28 ml_model/models.py:80 msgid "Category" msgstr "Категория" @@ -1063,7 +1084,7 @@ msgstr "Медиа" msgid "Feed" msgstr "Шейр пользователей" -#: tools/chats/apis.py:160 tools/public_api/views/base.py:90 +#: tools/chats/apis.py:163 tools/public_api/views/base.py:90 msgid "" "Error occured when create generation. It may cause NSFW-content not allowed, " "retry again" @@ -1113,9 +1134,3 @@ msgid "Model is blocked by outdating or temporary block, please retry later" msgstr "" "Модель заблокирована, т.к перестала обновляться или временно, попробуйте " "позже" - -msgid "Business account has been re-invited" -msgstr "Повторное приглашение сотруднику успешно отправлено" - -msgid "You do not have sufficient rights to perform this action" -msgstr "У вас недостаточно прав для выполнения этого действия" @@ -1,4 +1,5 @@ import base64 +import os import time from datetime import timedelta from decimal import Decimal @@ -11,6 +12,7 @@ from PIL import Image from messages.models import Message from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run +from ml_model.exceptions import FileExtensionNotSupported from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -65,10 +67,13 @@ class Claude(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) image = input_message.file if image: + image_extension = os.path.splitext(image.name)[1] + if image_extension not in ('.png', '.jpg', '.jpeg'): + raise FileExtensionNotSupported kind = filetype.guess(image.read(20)) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(image) - format = 'jpeg' if kind.extension == 'jpg' else kind.extension + format = 'jpeg' if kind and kind.extension == 'jpg' else kind.extension buf = BytesIO() normalized_image.save(buf, format=format) image_url = f'data:{mime};base64,{base64.b64encode(buf.getvalue()).decode("utf-8")}' @@ -1,4 +1,5 @@ import base64 +import os import time from datetime import timedelta from decimal import Decimal @@ -11,6 +12,7 @@ from PIL import Image from messages.models import Message from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run +from ml_model.exceptions import FileExtensionNotSupported from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -64,10 +66,13 @@ class Gemini(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) image = input_message.file if image: + image_extension = os.path.splitext(image.name)[1] + if image_extension not in ('.png', '.jpg', '.jpeg'): + raise FileExtensionNotSupported kind = filetype.guess(image.read(20)) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(image) - format = 'jpeg' if kind.extension == 'jpg' else kind.extension + format = 'jpeg' if kind and kind.extension == 'jpg' else kind.extension buf = BytesIO() normalized_image.save(buf, format=format) image_url = f'data:{mime};base64,{base64.b64encode(buf.getvalue()).decode("utf-8")}' @@ -1,9 +1,9 @@ import base64 +import os import time from datetime import timedelta from decimal import Decimal from io import BytesIO -from typing import Any, Dict, Iterator import filetype from django.db.models.fields.files import FieldFile @@ -12,6 +12,7 @@ from PIL import Image from messages.models import Message from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run +from ml_model.exceptions import FileExtensionNotSupported from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -42,7 +43,7 @@ class Grok(SimpleService): price += price_map['input_imgs'] / 1_000 return price.quantize(Decimal('0.1'), rounding='ROUND_UP') - def save_results(self, content: Iterator[Any], t: timedelta, save: bool = True) -> list[Message]: + def save_results(self, content: str, t: timedelta, save: bool = True) -> list[Message]: msgs = [ Message( content=content, @@ -62,10 +63,13 @@ class Grok(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) image = input_message.file if image: + image_extension = os.path.splitext(image.name)[1] + if image_extension not in ('.png', '.jpg', '.jpeg'): + raise FileExtensionNotSupported kind = filetype.guess(image.read(20)) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(image) - format = 'jpeg' if kind.extension == 'jpg' else kind.extension + format = 'jpeg' if kind and kind.extension == 'jpg' else kind.extension buf = BytesIO() normalized_image.save(buf, format=format) image_url = f'data:{mime};base64,{base64.b64encode(buf.getvalue()).decode("utf-8")}' @@ -1,4 +1,5 @@ import base64 +import os import time from io import BytesIO @@ -12,6 +13,7 @@ from django.db.models.fields.files import FieldFile from messages.models import Message from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run +from ml_model.exceptions import FileExtensionNotSupported from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -67,10 +69,13 @@ class Llama(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) image = input_message.file if image: + image_extension = os.path.splitext(image.name)[1] + if image_extension not in ('.png', '.jpg', '.jpeg'): + raise FileExtensionNotSupported kind = filetype.guess(image.read(20)) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(image) - format = 'jpeg' if kind.extension == 'jpg' else kind.extension + format = 'jpeg' if kind and kind.extension == 'jpg' else kind.extension buf = BytesIO() normalized_image.save(buf, format=format) image_url = f'data:{mime};base64,{base64.b64encode(buf.getvalue()).decode("utf-8")}' @@ -1,4 +1,5 @@ import base64 +import os import time from datetime import timedelta from decimal import Decimal @@ -11,6 +12,7 @@ from PIL import Image from messages.models import Message from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run +from ml_model.exceptions import FileExtensionNotSupported from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -61,6 +63,9 @@ class Mistral(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) image = input_message.file if image: + image_extension = os.path.splitext(image.name)[1] + if image_extension not in ('.png', '.jpg', '.jpeg'): + raise FileExtensionNotSupported kind = filetype.guess(image.read(20)) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(image) @@ -1,3 +1,4 @@ +from django.utils.translation import gettext as _ # накинуть перевод через gettext_lazy @@ -10,3 +11,8 @@ class NSFWDetectedException(Exception): ... class LargeResourceConsumptionException(Exception): ... + + +class FileExtensionNotSupported(Exception): + def __str__(self): + return _('File extension not supported') @@ -11,12 +11,13 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.status import ( HTTP_402_PAYMENT_REQUIRED, - HTTP_500_INTERNAL_SERVER_ERROR, + HTTP_500_INTERNAL_SERVER_ERROR, HTTP_400_BAD_REQUEST, ) from rest_framework.views import APIView from messages.models import Message from messages.serializers import MessageSerializer +from ml_model.exceptions import FileExtensionNotSupported from ml_model.services.base import SimpleService from payments.exceptions.insufficient_balance import InsufficientBalance from tools.chats.models import Chat @@ -148,6 +149,8 @@ class MessagesAPIView(APIView): ) try: output_messages = service(chat).make(input_message) + except FileExtensionNotSupported as exc: + return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST) except Exception as exc: input_message.is_sent = False input_message.save()