лучшения в приложении: 1. обавлены реальные ссылки на политику конфиденциальности и пользовательское соглашение 2. лучшена логика проверки перед генерацией стикеров: добавлены проверки выбора пресета и ввода текста, запрет на повторную генерацию одной и той же комбинации параметров подряд, отладочное логирование
This commit is contained in:
parent
0e586e693a
commit
a3c9717f9e
@ -4,7 +4,7 @@
|
||||
|
||||
API предоставляет функциональность для работы со стикерами в Telegram, включая генерацию изображений, создание стикерпаков и управление ими. Также API поддерживает отслеживание позиций задач в очереди.
|
||||
|
||||
Базовый URL: `http://localhost:8001`
|
||||
Базовый URL: `https://stickerserver.gymnasticstuff.uk`
|
||||
|
||||
## Эндпоинты
|
||||
|
||||
@ -14,11 +14,9 @@ API предоставляет функциональность для рабо
|
||||
|
||||
Проверяет работоспособность API.
|
||||
|
||||
**Ответ:**
|
||||
```json
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
**Ответ (200 OK):**
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
### Управление пользователями
|
||||
@ -54,7 +52,7 @@ API предоставляет функциональность для рабо
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 400 Bad Request: Пользователь с таким chat_id уже существует
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /users/{user_id}
|
||||
|
||||
@ -75,6 +73,7 @@ API предоставляет функциональность для рабо
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
### Генерация изображений и управление очередью
|
||||
|
||||
@ -85,32 +84,26 @@ API предоставляет функциональность для рабо
|
||||
**Тело запроса:**
|
||||
```json
|
||||
{
|
||||
"tag": "image_generation",
|
||||
"user_id": 123456789,
|
||||
"workflow": {
|
||||
// Объект workflow для ComfyUI
|
||||
},
|
||||
"tag": "image_generation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation")
|
||||
- `user_id` (integer, обязательный): ID пользователя
|
||||
- `workflow` (object, обязательный): Объект workflow для ComfyUI
|
||||
- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation")
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Ваше изображение генерируется, пожалуйста подождите, готовое изображение будет у вас в галереи",
|
||||
"Task_ID": "123",
|
||||
"queue_position": 5
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 400 Bad Request: Недопустимый тег
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 500 Internal Server Error: Ошибка при создании задачи или отправке сообщения
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /user_pending_tasks/{user_id}
|
||||
|
||||
@ -120,30 +113,12 @@ API предоставляет функциональность для рабо
|
||||
- `user_id` (integer, обязательный): ID пользователя
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"task_id": 123,
|
||||
"prompt_id": "prompt_id_from_comfyui",
|
||||
"status": "PENDING",
|
||||
"created_at": "2025-03-13T11:15:00",
|
||||
"queue_position": 3,
|
||||
"updated_at": "2025-03-13T11:20:00"
|
||||
},
|
||||
{
|
||||
"task_id": 124,
|
||||
"prompt_id": "prompt_id_from_comfyui_2",
|
||||
"status": "STARTED",
|
||||
"created_at": "2025-03-13T11:10:00",
|
||||
"queue_position": null,
|
||||
"updated_at": "2025-03-13T11:20:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 500 Internal Server Error: Внутренняя ошибка сервера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /task_position/{task_id}
|
||||
|
||||
@ -153,17 +128,12 @@ API предоставляет функциональность для рабо
|
||||
- `task_id` (integer, обязательный): ID задачи
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"task_id": 123,
|
||||
"status": "PENDING",
|
||||
"queue_position": 3
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Задача не найдена
|
||||
- 500 Internal Server Error: Внутренняя ошибка сервера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /images_links/{user_id}
|
||||
|
||||
@ -188,6 +158,7 @@ API предоставляет функциональность для рабо
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
### Управление стикерами
|
||||
|
||||
@ -209,13 +180,11 @@ API предоставляет функциональность для рабо
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"file_id": "file_id_from_telegram"
|
||||
}
|
||||
{}
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при загрузке файла на сервер Telegram
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /create_sticker_set
|
||||
|
||||
@ -244,15 +213,12 @@ API предоставляет функциональность для рабо
|
||||
- `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Новый набор стикеров успешно создан!",
|
||||
"name": "example_set_by_bot_name"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при создании набора стикеров
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /add_sticker_to_set
|
||||
|
||||
@ -263,6 +229,7 @@ API предоставляет функциональность для рабо
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"sticker_set_name": "example_set",
|
||||
"title": "Example Sticker Set",
|
||||
"file_id": "file_id_from_telegram",
|
||||
"emojis": "😀",
|
||||
"is_animated": false,
|
||||
@ -273,20 +240,19 @@ API предоставляет функциональность для рабо
|
||||
**Параметры:**
|
||||
- `user_id` (integer, обязательный): ID пользователя
|
||||
- `sticker_set_name` (string, обязательный): Название набора стикеров (без суффикса _by_bot)
|
||||
- `title` (string, обязательный): Заголовок набора стикеров
|
||||
- `file_id` (string, обязательный): File_id загруженного стикера
|
||||
- `emojis` (string, обязательный): Список эмодзи для стикера
|
||||
- `is_animated` (boolean, опциональный, по умолчанию false): Флаг анимированного стикера
|
||||
- `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Стикер успешно добавлен в набор!"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при добавлении стикера в набор
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /check_sticker_set_name/{sticker_set_name}
|
||||
|
||||
@ -296,14 +262,12 @@ API предоставляет функциональность для рабо
|
||||
- `sticker_set_name` (string, обязательный): Название набора стикеров
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"exists": true
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при проверке существования набора стикеров
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /delete_sticker_from_set
|
||||
|
||||
@ -320,14 +284,12 @@ API предоставляет функциональность для рабо
|
||||
- `file_id` (string, обязательный): File_id стикера
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Стикер успешно удален из набора!"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при удалении стикера из набора
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /set_sticker_position_in_set
|
||||
|
||||
@ -336,24 +298,22 @@ API предоставляет функциональность для рабо
|
||||
**Тело запроса:**
|
||||
```json
|
||||
{
|
||||
"sticker_file_id": "file_id_from_telegram",
|
||||
"file_id": "file_id_from_telegram",
|
||||
"position": 0
|
||||
}
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `sticker_file_id` (string, обязательный): File_id стикера
|
||||
- `file_id` (string, обязательный): File_id стикера
|
||||
- `position` (integer, обязательный): Новая позиция стикера (0 - первая позиция)
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Позиция стикера успешно изменена!"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при изменении позиции стикера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /delete_sticker_set
|
||||
|
||||
@ -370,14 +330,12 @@ API предоставляет функциональность для рабо
|
||||
- `sticker_set_name` (string, обязательный): Полное название набора стикеров (включая суффикс _by_bot)
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"message": "Набор стикеров успешно удален!"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при удалении набора стикеров
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /create_sticker_set_db
|
||||
|
||||
@ -405,9 +363,7 @@ API предоставляет функциональность для рабо
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 400 Bad Request: Ошибка валидации
|
||||
- 500 Internal Server Error: Внутренняя ошибка сервера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /user_sticker_sets/{user_id}
|
||||
|
||||
@ -428,8 +384,7 @@ API предоставляет функциональность для рабо
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Пользователь не найден
|
||||
- 500 Internal Server Error: Внутренняя ошибка сервера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
### Прокси для Telegram API
|
||||
|
||||
@ -442,23 +397,12 @@ API предоставляет функциональность для рабо
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"name": "example_set_by_bot_name",
|
||||
"title": "Example Sticker Set",
|
||||
"sticker_type": "regular",
|
||||
"thumbnail_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram",
|
||||
"share_url": "https://t.me/addstickers/example_set_by_bot_name",
|
||||
"stickers": [
|
||||
{
|
||||
"file_id": "file_id_from_telegram",
|
||||
"emoji": "😀",
|
||||
"position": 0,
|
||||
"file_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram"
|
||||
}
|
||||
]
|
||||
}
|
||||
{}
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### GET /stickers/proxy/sticker/{file_id}
|
||||
|
||||
Прокси для получения изображения стикера без раскрытия токена бота.
|
||||
@ -467,14 +411,12 @@ API предоставляет функциональность для рабо
|
||||
- `file_id` (string, обязательный): File ID стикера
|
||||
|
||||
**Ответ (200 OK):**
|
||||
Изображение стикера в формате WebP с заголовками:
|
||||
- Content-Type: image/webp
|
||||
- Content-Disposition: inline
|
||||
- Cache-Control: public, max-age=86400
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 404 Not Found: Стикер не найден
|
||||
- 500 Internal Server Error: Ошибка при получении стикера
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
#### POST /stickers/test/upload
|
||||
|
||||
@ -485,67 +427,63 @@ API предоставляет функциональность для рабо
|
||||
- `image_url` (string, обязательный): URL изображения для загрузки
|
||||
|
||||
**Ответ (200 OK):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"file_id": "file_id_from_telegram",
|
||||
"file_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram"
|
||||
}
|
||||
```
|
||||
"string"
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- 500 Internal Server Error: Ошибка при загрузке изображения
|
||||
- 422 Validation Error: Ошибка валидации данных
|
||||
|
||||
## Модели данных
|
||||
|
||||
### UserBase
|
||||
```json
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"username": "example_user",
|
||||
"user_id": 1,
|
||||
"username": "john_doe",
|
||||
"chat_id": 123456789,
|
||||
"balance": 0
|
||||
"balance": 100
|
||||
}
|
||||
```
|
||||
|
||||
### UserCreate
|
||||
```json
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"username": "example_user",
|
||||
"user_id": 1,
|
||||
"username": "john_doe",
|
||||
"chat_id": 123456789,
|
||||
"balance": 0
|
||||
"balance": 100
|
||||
}
|
||||
```
|
||||
|
||||
### ImageBase
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"link": "file_id_from_telegram",
|
||||
"prompt_id": "prompt_id_from_comfyui",
|
||||
"status": "COMPLETED",
|
||||
"created_at": "2025-03-12T12:00:00",
|
||||
"sticker_set_id": null
|
||||
"id": 0,
|
||||
"link": "string",
|
||||
"prompt_id": "string",
|
||||
"status": "string",
|
||||
"created_at": "2025-03-19T12:15:53.248Z",
|
||||
"sticker_set_id": 0
|
||||
}
|
||||
```
|
||||
|
||||
### StickerUploadRequest
|
||||
```json
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"link": "https://example.com/image.png"
|
||||
"user_id": 0,
|
||||
"link": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### StickerSetRequest
|
||||
```json
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"sticker_set_name": "example_set",
|
||||
"title": "Example Sticker Set",
|
||||
"file_id": "file_id_from_telegram",
|
||||
"emojis": "😀",
|
||||
"user_id": 0,
|
||||
"sticker_set_name": "string",
|
||||
"title": "string",
|
||||
"file_id": "string",
|
||||
"emojis": "string",
|
||||
"is_animated": false,
|
||||
"is_video": false
|
||||
}
|
||||
@ -554,14 +492,14 @@ API предоставляет функциональность для рабо
|
||||
### StickerFileID
|
||||
```json
|
||||
{
|
||||
"file_id": "file_id_from_telegram"
|
||||
"file_id": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### StickerSetPosition
|
||||
```json
|
||||
{
|
||||
"sticker_file_id": "file_id_from_telegram",
|
||||
"file_id": "string",
|
||||
"position": 0
|
||||
}
|
||||
```
|
||||
@ -569,7 +507,7 @@ API предоставляет функциональность для рабо
|
||||
### StickerSetName
|
||||
```json
|
||||
{
|
||||
"sticker_set_name": "example_set_by_bot_name"
|
||||
"sticker_set_name": "string"
|
||||
}
|
||||
```
|
||||
|
||||
@ -577,46 +515,51 @@ API предоставляет функциональность для рабо
|
||||
```json
|
||||
{
|
||||
"tag": "image_generation",
|
||||
"user_id": 123456789,
|
||||
"workflow": {
|
||||
// Объект workflow для ComfyUI
|
||||
}
|
||||
"user_id": 0,
|
||||
"workflow": {}
|
||||
}
|
||||
```
|
||||
|
||||
### CreateStickerSetDBRequest
|
||||
```json
|
||||
{
|
||||
"user_id": 123456789,
|
||||
"sticker_set_name": "example_set_by_bot_name"
|
||||
"user_id": 0,
|
||||
"sticker_set_name": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### StickerSetResponse
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"set_name": "example_set_by_bot_name",
|
||||
"user_id": 123456789
|
||||
"id": 0,
|
||||
"set_name": "string",
|
||||
"user_id": 0
|
||||
}
|
||||
```
|
||||
|
||||
### TaskPosition
|
||||
### HTTPValidationError
|
||||
```json
|
||||
{
|
||||
"task_id": 123,
|
||||
"status": "PENDING",
|
||||
"queue_position": 3
|
||||
"detail": [
|
||||
{
|
||||
"loc": [
|
||||
"string",
|
||||
0
|
||||
],
|
||||
"msg": "string",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### PendingTask
|
||||
### ValidationError
|
||||
```json
|
||||
{
|
||||
"task_id": 123,
|
||||
"prompt_id": "prompt_id_from_comfyui",
|
||||
"status": "PENDING",
|
||||
"created_at": "2025-03-13T11:15:00",
|
||||
"queue_position": 3,
|
||||
"updated_at": "2025-03-13T11:20:00"
|
||||
"loc": [
|
||||
"string",
|
||||
0
|
||||
],
|
||||
"msg": "string",
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import umbrella from './umbrella250x.png';
|
||||
import defaultAvatar from './default-avatar.svg';
|
||||
import shieldIcon from './shield-icon.png';
|
||||
import reactLogo from './react.svg';
|
||||
import tokenIcon from './token_ico.png';
|
||||
|
||||
export const images = {
|
||||
ahareBot,
|
||||
@ -67,5 +68,6 @@ export const images = {
|
||||
umbrella,
|
||||
defaultAvatar,
|
||||
shieldIcon,
|
||||
reactLogo
|
||||
reactLogo,
|
||||
tokenIcon
|
||||
};
|
||||
|
||||
BIN
src/assets/token_ico.png
Normal file
BIN
src/assets/token_ico.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@ -1,6 +1,6 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
margin: 0 calc(-1 * var(--spacing-medium));
|
||||
padding: var(--spacing-medium);
|
||||
@ -16,6 +16,7 @@
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scroll-snap-type: x mandatory;
|
||||
gap: calc(var(--spacing-medium) * 0.75);
|
||||
padding-left: 3px; /* Отступ для обводки первых кнопок */
|
||||
padding-bottom: var(--spacing-small); /* Для градиента */
|
||||
padding-right: var(--spacing-medium); /* Отступ для последнего элемента */
|
||||
margin-right: calc(-1 * var(--spacing-medium)); /* Компенсация отступа контейнера */
|
||||
@ -32,7 +33,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 120px; /* Фиксированная ширина для кнопок */
|
||||
width: 120px; /* Уменьшенная ширина для кнопок */
|
||||
}
|
||||
|
||||
/* Добавляем градиент-индикатор скролла справа */
|
||||
|
||||
@ -35,7 +35,6 @@
|
||||
.selected {
|
||||
border-color: var(--color-primary);
|
||||
border-width: 3px; /* Увеличиваем толщину с 2px до 3px */
|
||||
transform: translateY(-2px); /* Добавляем эффект приподнятия */
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Добавляем тень как при hover */
|
||||
}
|
||||
|
||||
@ -51,7 +50,6 @@
|
||||
border-color: var(--color-primary);
|
||||
border-width: 3px;
|
||||
box-shadow: 0 0 0 3px var(--color-primary), 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,9 +59,9 @@
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
/* Предотвращаем двойное приподнятие при наведении на выбранную кнопку */
|
||||
/* Стиль для наведения на выбранную кнопку */
|
||||
.selected:hover {
|
||||
transform: translateY(-2px); /* Оставляем то же приподнятие */
|
||||
transform: none; /* Убираем эффект приподнятия */
|
||||
}
|
||||
|
||||
.button:active {
|
||||
|
||||
@ -102,6 +102,15 @@
|
||||
.balanceIcon {
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tokenImage {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.balanceValue {
|
||||
|
||||
@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { MOCK_USER } from '../../constants/mock';
|
||||
import { getUserInfo, isTelegramWebAppAvailable } from '../../constants/user';
|
||||
import { images } from '../../assets';
|
||||
import styles from './Header.module.css';
|
||||
|
||||
const Header: React.FC = () => {
|
||||
@ -50,7 +51,9 @@ const Header: React.FC = () => {
|
||||
onClick={() => alert('Пополнить баланс')}
|
||||
title="Нажмите чтобы пополнить баланс"
|
||||
>
|
||||
<span className={styles.balanceIcon}>💎</span>
|
||||
<span className={styles.balanceIcon}>
|
||||
<img src={images.tokenIcon} alt="Токены" className={styles.tokenImage} />
|
||||
</span>
|
||||
<span className={styles.balanceValue}>
|
||||
{user.balance}
|
||||
</span>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export const baseWorkflow = {
|
||||
"305": {
|
||||
"inputs": {
|
||||
"ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors"
|
||||
"ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple",
|
||||
"_meta": {
|
||||
|
||||
@ -8,6 +8,14 @@ import { stylePresets } from '../config/stylePresets';
|
||||
import apiService from '../services/api';
|
||||
import NotificationModal from '../components/shared/NotificationModal';
|
||||
|
||||
// Интерфейс для хранения данных о последней генерации
|
||||
interface LastGenerationData {
|
||||
imageData?: string;
|
||||
style?: string;
|
||||
presetId?: string;
|
||||
customPrompt?: string;
|
||||
}
|
||||
|
||||
const Home: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -35,6 +43,9 @@ const Home: React.FC = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [promptText, setPromptText] = useState('');
|
||||
|
||||
// Состояние для хранения данных о последней успешной генерации
|
||||
const [lastGenerationData, setLastGenerationData] = useState<LastGenerationData>({});
|
||||
|
||||
// Обработчики для модального окна
|
||||
const handleGalleryClick = useCallback(() => {
|
||||
setIsNotificationVisible(false);
|
||||
@ -63,8 +74,63 @@ const Home: React.FC = () => {
|
||||
|
||||
if (actionType === 'function') {
|
||||
if (actionValue === 'startGeneration') {
|
||||
// Проверка наличия изображения
|
||||
if (!imageData) {
|
||||
alert('Сначала загрузите изображение');
|
||||
setNotificationTitle('Внимание');
|
||||
setNotificationMessage('Сначала загрузите изображение');
|
||||
setIsLoading(false);
|
||||
setIsNotificationVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверка выбора пресета промпта
|
||||
if (!selectedPresetId) {
|
||||
setNotificationTitle('Внимание');
|
||||
setNotificationMessage('Выберите образ для генерации');
|
||||
setIsLoading(false);
|
||||
setIsNotificationVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверка ввода текста, если выбран "Свой промпт"
|
||||
if (selectedPresetId === 'customPrompt' && !customPrompt.trim()) {
|
||||
setNotificationTitle('Внимание');
|
||||
setNotificationMessage('Введите текст промпта');
|
||||
setIsLoading(false);
|
||||
setIsNotificationVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Добавляем логирование для отладки
|
||||
console.log('Comparing generations:', {
|
||||
current: {
|
||||
imageDataLength: imageData?.length,
|
||||
style: selectedStyle,
|
||||
presetId: selectedPresetId,
|
||||
customPrompt
|
||||
},
|
||||
last: {
|
||||
imageDataLength: lastGenerationData.imageData?.length,
|
||||
style: lastGenerationData.style,
|
||||
presetId: lastGenerationData.presetId,
|
||||
customPrompt: lastGenerationData.customPrompt
|
||||
}
|
||||
});
|
||||
|
||||
// Проверка на повторную генерацию той же комбинации
|
||||
const isSameGeneration =
|
||||
lastGenerationData.imageData === imageData &&
|
||||
lastGenerationData.style === selectedStyle &&
|
||||
lastGenerationData.presetId === selectedPresetId &&
|
||||
(selectedPresetId !== 'customPrompt' || lastGenerationData.customPrompt === customPrompt);
|
||||
|
||||
console.log('Is same generation:', isSameGeneration);
|
||||
|
||||
if (isSameGeneration) {
|
||||
setNotificationTitle('Внимание');
|
||||
setNotificationMessage('Нельзя отправить одну и ту же комбинацию изображения и образа подряд. Пожалуйста, измените изображение или выберите другой образ.');
|
||||
setIsLoading(false);
|
||||
setIsNotificationVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -83,6 +149,14 @@ const Home: React.FC = () => {
|
||||
const response = await apiService.generateImage(imageData, selectedStyle, selectedPresetId, userPrompt);
|
||||
console.log('Generation response:', response);
|
||||
|
||||
// Сохраняем данные о текущей генерации
|
||||
setLastGenerationData({
|
||||
imageData,
|
||||
style: selectedStyle,
|
||||
presetId: selectedPresetId,
|
||||
customPrompt: userPrompt
|
||||
});
|
||||
|
||||
// Проверяем, была ли ошибка перевода
|
||||
if (response.translationFailed) {
|
||||
setNotificationTitle('Недопустимый промпт');
|
||||
@ -157,7 +231,7 @@ const Home: React.FC = () => {
|
||||
|
||||
// Если выбрана любая другая кнопка, скрываем поле ввода
|
||||
setIsInputVisible(false);
|
||||
}, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt]);
|
||||
}, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt, lastGenerationData]);
|
||||
|
||||
// Эффект для обновления window.history.state при загрузке из localStorage
|
||||
useEffect(() => {
|
||||
|
||||
@ -34,8 +34,22 @@ const TermsAndConditions: React.FC = () => {
|
||||
</p>
|
||||
|
||||
<div className={styles.links}>
|
||||
<a href="#" className={styles.link}>Условия использования</a>
|
||||
<a href="#" className={styles.link}>Политика конфиденциальности</a>
|
||||
<a
|
||||
href="https://telegra.ph/Polzovatelskoe-soglashenie-03-19-13"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Условия использования
|
||||
</a>
|
||||
<a
|
||||
href="https://telegra.ph/Politika-konfidencialnosti-03-19-10"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Политика конфиденциальности
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className={styles.buttonsContainer}>
|
||||
|
||||
@ -90,7 +90,8 @@ export class StickerService {
|
||||
file_id: firstSticker,
|
||||
emojis: firstEmoji,
|
||||
is_animated: false,
|
||||
is_video: false
|
||||
is_video: false,
|
||||
format: "static" // Добавляем поле format для соответствия требованиям API
|
||||
};
|
||||
|
||||
// Логируем данные запроса
|
||||
@ -203,7 +204,8 @@ export class StickerService {
|
||||
file_id: fileId,
|
||||
emojis: emoji,
|
||||
is_animated: false,
|
||||
is_video: false
|
||||
is_video: false,
|
||||
format: "static" // Добавляем поле format для соответствия требованиям API
|
||||
};
|
||||
|
||||
// Логируем данные запроса
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"305": {
|
||||
"inputs": {
|
||||
"ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors"
|
||||
"ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple",
|
||||
"_meta": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user