From aaaa29a5a5706b9d548720c4650a951ec834e67f Mon Sep 17 00:00:00 2001 From: Egor Matveev Date: Mon, 24 Nov 2025 02:36:02 +0300 Subject: [PATCH] intiial --- .deploy/deploy-dev.yaml | 20 +++++ .gitea/workflows/deploy-dev.yaml | 41 ++++++++++ .gitignore | 120 ++++++++++++++++++++++++++++ Dockerfile | 13 ++++ main.py | 69 +++++++++++++++++ requirements.txt | 18 +++++ templates/call.html | 129 +++++++++++++++++++++++++++++++ templates/index.html | 25 ++++++ 8 files changed, 435 insertions(+) create mode 100644 .deploy/deploy-dev.yaml create mode 100644 .gitea/workflows/deploy-dev.yaml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 main.py create mode 100644 requirements.txt create mode 100644 templates/call.html create mode 100644 templates/index.html diff --git a/.deploy/deploy-dev.yaml b/.deploy/deploy-dev.yaml new file mode 100644 index 0000000..36af343 --- /dev/null +++ b/.deploy/deploy-dev.yaml @@ -0,0 +1,20 @@ +version: "3.4" + + +services: + + caller-nginx: + image: mathwave/sprint-repo:caller + networks: + - common-infra-nginx-development + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + +networks: + common-infra-nginx-development: + external: true diff --git a/.gitea/workflows/deploy-dev.yaml b/.gitea/workflows/deploy-dev.yaml new file mode 100644 index 0000000..b818fc0 --- /dev/null +++ b/.gitea/workflows/deploy-dev.yaml @@ -0,0 +1,41 @@ +name: Deploy Dev + +on: + pull_request: + branches: + - dev + types: [closed] + +jobs: + build: + name: Build + runs-on: [ dev ] + steps: + - name: login + run: docker login -u mathwave -p ${{ secrets.DOCKERHUB_PASSWORD }} + - name: checkout + uses: actions/checkout@v4 + with: + ref: dev + - name: build + run: docker build -t mathwave/sprint-repo:callter . + push: + name: Push + runs-on: [ dev ] + needs: build + steps: + - name: push + run: docker push mathwave/sprint-repo:caller + deploy-dev: + name: Deploy dev + runs-on: [prod] + needs: push + steps: + - name: login + run: docker login -u mathwave -p ${{ secrets.DOCKERHUB_PASSWORD }} + - name: checkout + uses: actions/checkout@v4 + with: + ref: dev + - name: deploy + run: docker stack deploy --with-registry-auth -c ./.deploy/deploy-dev.yaml caller-development diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21dbd35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,120 @@ +# Django # +*.log +*.pot +*.pyc +__pycache__ +db.sqlite3 +media +data +*/__pycache__ + +# Backup files # +*.bak + +# If you are using PyCharm # +.idea +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/gradle.xml +.idea/**/libraries +*.iws /out/ + +# Python # +*.py[cod] +*$py.class + +# Distribution / packaging +.Python build/ +develop-eggs/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache/ +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +postgres-data + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery +celerybeat-schedule.* + +# SageMath parsed files +*.sage.py + +# Environments +.venv +env/ +ENV/ +venv/ +env.bak/ +venv.bak/ + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Sublime Text # +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache +*.sublime-workspace +*.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files Package +Control.last-run +Control.ca-list +Control.ca-bundle +Control.system-ca-bundle +GitHub.sublime-settings + +# Visual Studio Code # +.vscode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history +.DS_Store \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7b98d52 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.10 + +RUN mkdir /usr/src/app +WORKDIR /usr/src/app + +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt + +COPY . . + +ENV PYTHONUNBUFFERED=1 + +ENTRYPOINT ["python", "main.py"] \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..dc9250d --- /dev/null +++ b/main.py @@ -0,0 +1,69 @@ +from uuid import UUID, uuid4 +import fastapi +from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi.templating import Jinja2Templates +from pydantic import BaseModel +import uvicorn + +app = fastapi.FastAPI(debug=True) +templates = Jinja2Templates(directory="templates") + + +calls = {} + + +class CallPostResponse(BaseModel): + call_id: UUID + + +@app.post("/call") +async def create_call() -> CallPostResponse: + call_id = uuid4() + calls[call_id] = {} + return CallPostResponse(call_id=call_id) + + +@app.get("/call", response_class=HTMLResponse) +async def call(request: fastapi.Request, call_id: UUID = fastapi.Query(), session_id: UUID | None = fastapi.Cookie(None)): + if not session_id: + session_id = uuid4() + response = RedirectResponse(f"/call?call_id={call_id}") + response.set_cookie("session_id", str(session_id)) + return response + if call_id not in calls: + return RedirectResponse("/") + + return templates.TemplateResponse( + "call.html", + context={"request": request} + ) + + +@app.websocket("/connect") +async def connect(websocket: fastapi.WebSocket, call_id: UUID = fastapi.Query(), session_id: UUID | None = fastapi.Cookie(None)): + await websocket.accept() + calls[call_id][session_id] = websocket + another_websocket: fastapi.WebSocket | None = None + while True: + data = await websocket.receive_bytes() + print("RECEIVED") + if not another_websocket: + if len(calls[call_id]) == 1: + continue + for sess_id, ws in calls[call_id].items(): + if sess_id != session_id: + another_websocket = ws + print("SENDING DATA") + await another_websocket.send_bytes(data) + + +@app.get("/", response_class=HTMLResponse) +async def home(request: fastapi.Request): + return templates.TemplateResponse( + "index.html", + context={"request": request} + ) + + +if __name__ == '__main__': + uvicorn.run(app, host="0.0.0.0", port=1239) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..aa67a46 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ +annotated-doc==0.0.4 +annotated-types==0.7.0 +anyio==4.11.0 +click==8.3.1 +exceptiongroup==1.3.1 +fastapi==0.121.3 +h11==0.16.0 +idna==3.11 +Jinja2==3.1.6 +MarkupSafe==3.0.3 +pydantic==2.12.4 +pydantic_core==2.41.5 +sniffio==1.3.1 +starlette==0.50.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +uvicorn==0.38.0 +websockets==15.0.1 diff --git a/templates/call.html b/templates/call.html new file mode 100644 index 0000000..53ae1f0 --- /dev/null +++ b/templates/call.html @@ -0,0 +1,129 @@ + + + + + +

Micro is off

+ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..4897ea6 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,25 @@ + + + + + + + + + \ No newline at end of file