создана часть бекенда
This commit is contained in:
+5
-3
@@ -1,3 +1,5 @@
|
||||
from my_loggers import *
|
||||
from for_DB import *
|
||||
from password import *
|
||||
from .loggers import *
|
||||
from .for_DB import *
|
||||
from .password import *
|
||||
from .image import *
|
||||
from .safe_filemane import *
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,60 @@
|
||||
from utils.loggers import logger
|
||||
|
||||
# def saveImage(imageData, fileName: str):
|
||||
# try:
|
||||
# imageFormat = imageData.split(';')[0].split('/')[1]
|
||||
# if imageFormat != 'png':
|
||||
# logger.error(f"Неподдерживаемый формат изображения: {imageFormat}")
|
||||
# return False
|
||||
# imageData = imageData.split(';base64,')[1]
|
||||
# with open(f"static/images/{fileName}", "wb") as f:
|
||||
# f.write(base64.b64decode(imageData))
|
||||
# logger.info(f"Изображение {fileName} успешно сохранено")
|
||||
# return True
|
||||
# except Exception as e:
|
||||
# logger.error(f"Ошибка сохранения изображения: {str(e)}")
|
||||
# return False
|
||||
|
||||
# UPLOAD_DIR = "uploads"
|
||||
# os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def saveImage(file_bytes, fileName: str):
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
# Загружаем изображение через Pillow
|
||||
try:
|
||||
img = Image.open(io.BytesIO(file_bytes))
|
||||
except Exception:
|
||||
logger.error("Неподдерживаемый формат изображения")
|
||||
return False
|
||||
|
||||
# Конвертация (если нужно)
|
||||
if img.mode not in ("RGB", "RGBA", "P"):
|
||||
img = img.convert("RGB")
|
||||
|
||||
# Сохранение в выбранный формат
|
||||
try:
|
||||
logger.info(f"Сохраняем изображение {fileName}")
|
||||
img.save(fileName, "PNG")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка сохранения изображения: {str(e)}")
|
||||
return False
|
||||
|
||||
logger.info(f"Изображение {fileName} успешно сохранено")
|
||||
return True
|
||||
|
||||
def deleteImage(fileName: str):
|
||||
if fileName.endswith("default.png"):
|
||||
return True
|
||||
try:
|
||||
import os
|
||||
|
||||
logger.info(f"Удаляем изображение {fileName}")
|
||||
os.remove(f"static/images/{fileName}")
|
||||
logger.info(f"Изображение {fileName} успешно удалено")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка удаления изображения: {str(e)}")
|
||||
return False
|
||||
@@ -0,0 +1,35 @@
|
||||
import logging
|
||||
import logging.config
|
||||
import json
|
||||
|
||||
|
||||
class SmartLogger(logging.Logger):
|
||||
def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False, stacklevel=2):
|
||||
# Увеличиваем stacklevel до 2, чтобы показать реального вызывающего
|
||||
if isinstance(msg, (dict, list)):
|
||||
msg = json.dumps(msg, indent=4, ensure_ascii=False)
|
||||
super()._log(level, msg, args, exc_info, extra, stack_info, stacklevel)
|
||||
|
||||
|
||||
logging.setLoggerClass(SmartLogger)
|
||||
logging.config.fileConfig("config/log.ini")
|
||||
|
||||
logger = logging.getLogger("toolbox")
|
||||
|
||||
def setLogLevel(level: str = ""):
|
||||
match level:
|
||||
case "DEBUG":
|
||||
loggerLevel = logging.DEBUG
|
||||
case "WARNING":
|
||||
loggerLevel = logging.WARNING
|
||||
case "ERROR":
|
||||
loggerLevel = logging.ERROR
|
||||
case _:
|
||||
loggerLevel = logging.INFO
|
||||
|
||||
root_logger = logging.getLogger()
|
||||
for handler in root_logger.handlers:
|
||||
handler.setLevel(loggerLevel)
|
||||
|
||||
# Также меняем уровень самого логгера
|
||||
logger.setLevel(loggerLevel)
|
||||
@@ -1,9 +0,0 @@
|
||||
import logging
|
||||
import logging.config
|
||||
|
||||
logging.config.fileConfig("config/log.ini")
|
||||
|
||||
# loggers
|
||||
logger = logging.getLogger("Tools Stock")
|
||||
loggerDB = logging.getLogger("DB operations")
|
||||
logger = logging.getLogger("UI operations")
|
||||
+1
-1
@@ -9,7 +9,7 @@ def pwd_hash(pwd_plant: str) -> str:
|
||||
|
||||
|
||||
def pwd_verify(pwd_plant: str, pwd_hash: str) -> bool:
|
||||
from my_loggers import logger
|
||||
from utils.loggers import logger
|
||||
|
||||
try:
|
||||
return pwd_context.verify(pwd_plant, pwd_hash)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import re
|
||||
import time
|
||||
|
||||
# Простая транслитерация
|
||||
TRANSLIT_MAP = {
|
||||
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd',
|
||||
'е': 'e', 'ё': 'yo', 'ж': 'zh', 'з': 'z', 'и': 'i',
|
||||
'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n',
|
||||
'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't',
|
||||
'у': 'u', 'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch',
|
||||
'ш': 'sh', 'щ': 'sch', 'ъ': '', 'ы': 'y', 'ь': '',
|
||||
'э': 'e', 'ю': 'yu', 'я': 'ya'
|
||||
}
|
||||
|
||||
# Заглавные буквы → в ту же латиницу, но без capital (ниже мы в lower() всё равно переводим)
|
||||
TRANSLIT_MAP.update({k.upper(): v for k, v in TRANSLIT_MAP.items()})
|
||||
|
||||
def transliterate(text: str) -> str:
|
||||
return ''.join(TRANSLIT_MAP.get(ch, ch) for ch in text)
|
||||
|
||||
def safeFilename(name: str) -> str:
|
||||
# 1. Транслитерация кириллицы
|
||||
name = transliterate(name)
|
||||
|
||||
# 2. Приводим к нижнему регистру
|
||||
name = name.lower()
|
||||
|
||||
# 3. Заменяем всё, что не буква/цифра, на "_"
|
||||
name = re.sub(r'[^a-z0-9]+', '_', name)
|
||||
|
||||
# 4. Убираем повторяющиеся "_"
|
||||
name = re.sub(r'_+', '_', name).strip('_')
|
||||
|
||||
# 5. Ограничиваем длину
|
||||
name = name[:80] or "file"
|
||||
|
||||
# 6. Добавляем таймштамп
|
||||
timestamp = int(time.time() * 1000) # миллисекунды
|
||||
return f"{name}_{timestamp}"
|
||||
Reference in New Issue
Block a user