diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 420d3f1..0000000 --- a/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# Чтоб применить изменения в JetBrains, надо нажать "Code" -> "Reformat Code" (или Ctrl+Alt+L) - -root = true # Главный конфиг. Если в другом каталоге будет другой, то применять этот - -[*] -charset = utf-8 # Кодировка ютф8 -indent_style = tab # Табуляция пробелами или табуляциями. "space" или "tab" -#indent_size = 4 # Для пробелов -tab_width = 4 # Для табов -insert_final_newline = true # При сохранении файла в конце должна быть пустая строка -trim_trailing_whitespace = true # При сохранении файла удалить все лишние пробелы в конце строк -end_of_line = lf # Символ конца строки для linux. Этот символ говорит, когда перенос строки происходит -#max_line_length = 100 # Форматирование этим параметром меняет файлы в гите. Включать там где надо, а не * diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index 1f69b35..59a48b4 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -33,8 +33,8 @@ jobs: file: docker/Dockerfile_back push: true tags: ${{ steps.set-vars.outputs.CHAT_BACK_IMAGE }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha + cache-to: type=gha,mode=max - name: Build and push celery @@ -44,15 +44,15 @@ jobs: file: docker/Dockerfile_celery push: true tags: ${{ steps.set-vars.outputs.CELERY_IMAGE }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha + cache-to: type=gha,mode=max + - deploy: runs-on: deploy needs: - build - + steps: - name: Checkout repo uses: https://git.urec56.ru/urec/checkout@v4 @@ -69,7 +69,7 @@ jobs: touch .env echo 'MODE=${{ vars.MODE }}' >> .env - + echo 'DB_HOST=${{ secrets.DB_HOST }}' >> .env echo 'DB_PORT=${{ secrets.DB_PORT }}' >> .env echo 'DB_USER=${{ secrets.DB_USER }}' >> .env @@ -113,4 +113,3 @@ jobs: docker compose -f docker/deploy-docker-compose.yml up -d --force-recreate - diff --git a/app/coords/router.py b/app/coords/router.py new file mode 100644 index 0000000..75419a8 --- /dev/null +++ b/app/coords/router.py @@ -0,0 +1,89 @@ +from fastapi import APIRouter, status, UploadFile, HTTPException +from fastapi.responses import StreamingResponse +from io import BytesIO, StringIO +import simplekml +import gpxpy +import re + +router = APIRouter(prefix="/coords", tags=["Координаты для жижи"]) + + + + +@router.post( + "/map.kmz", + status_code=status.HTTP_200_OK, +) +async def create_chat(track_name: str, file: UploadFile): + try: + file = await file.read() + file = StringIO(file.decode("utf-8")) + kml = generate_kml(file, track_name) + + + kml.seek(0) + + return StreamingResponse( + content=kml, + media_type="application/vnd.google-earth.kmz", + headers={"Content-Disposition": "attachment; filename=generated.kmz"} + ) + except: + raise HTTPException(status_code=409, detail="Ты передал какую-то хуйню") + +def generate_kml(file: StringIO, track_name: str): + buffer = BytesIO() + waypoints = [] + kml = simplekml.Kml() + + points = [] + + for line in file.readlines(): + coords = line.split(":") + coord = coords[0].strip() + current_label = int(coords[1].strip()) + lat, lon = parse_dms_string(coord) + name = f"Опора №{current_label}" + wpt = gpxpy.gpx.GPXWaypoint(latitude=lat, longitude=lon, name=name) + waypoints.append(wpt) + points.append((lon,lat)) + + linestring = kml.newlinestring(name=track_name) + linestring.coords = points + linestring.style.linestyle.width = 3 + linestring.style.linestyle.color = simplekml.Color.red + + + + for wpt in waypoints: + lat = wpt.latitude + lon = wpt.longitude + name = wpt.name + pnt = kml.newpoint(name=name, coords=[(lon, lat)]) # KML ожидает (lon, lat) + pnt.style.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png' + + kml.savekmz(buffer) + + return buffer + + + +def parse_dms_string(dms_str): + pattern = r"(\d{1,3})°(\d{1,2})'(\d{1,2})\"([NSEW])" + matches = re.findall(pattern, dms_str) + if len(matches) != 2: + raise ValueError("Ожидалось две координаты в формате DMS") + + def to_decimal(d, m, s, direction): + decimal = int(d) + int(m) / 60 + int(s) / 3600 + if direction in ['S', 'W']: + decimal = -decimal + return decimal + + lat = to_decimal(*matches[0]) + lon = to_decimal(*matches[1]) + return round(lat, 6), round(lon, 6) + + + + diff --git a/app/main.py b/app/main.py index f4d9719..41a6aae 100644 --- a/app/main.py +++ b/app/main.py @@ -4,6 +4,7 @@ from fastapi.middleware.cors import CORSMiddleware from app.chat.websocket import router as websocket_router from app.images.router import router as image_router from app.users.router import router as user_router +from app.coords.router import router as coords_router # sentry_sdk.init( # dsn=settings.SENTRY_DSN, @@ -16,6 +17,7 @@ app = FastAPI(title="Чат BP", root_path="/api") app.include_router(websocket_router) app.include_router(user_router) app.include_router(image_router) +app.include_router(coords_router) origins = ["http://localhost:5173", "http://localhost:3000", "https://chat.black-phoenix.ru"] headers = [ diff --git a/requirements.txt b/requirements.txt index 2f7644e..295b39d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,6 +31,7 @@ flake8==7.0.0 flower==2.0.1 frozenlist==1.4.1 gevent==23.9.1 +gpxpy==1.6.2 greenlet==3.0.3 gunicorn==21.2.0 h11==0.14.0 @@ -95,6 +96,7 @@ ruff==0.4.7 sentry-sdk==1.39.2 setuptools==70.0.0 shellingham==1.5.4 +simplekml==1.3.6 six==1.16.0 sniffio==1.3.0 sqladmin==0.16.0