#!/usr/bin/env bash # Создаёт 9 персональных уведомлений всех видов контура P для одного user_id. # Запускать на ВМ из каталога backend: /opt/han-chat/backend # # cd /opt/han-chat/backend # sed -i 's/\r$//' deployment/scripts/seed-personal-notifications-test.sh # chmod +x deployment/scripts/seed-personal-notifications-test.sh # ./deployment/scripts/seed-personal-notifications-test.sh # # Токен берётся из .env (NOTIFICATIONS_TOKEN_PRODUCER_TEST) — тот же, что у api-backend. # При старте api-backend синхронизирует hash токена в notification_sources. set -euo pipefail cd "$(dirname "$0")/../.." ENV_FILE="${ENV_FILE:-.env}" if [[ ! -f "$ENV_FILE" ]]; then echo "Не найден $ENV_FILE. Запускайте из каталога backend." >&2 exit 1 fi env_value() { python3 - "$ENV_FILE" "$1" <<'PY' import sys from pathlib import Path path, wanted = sys.argv[1:] for raw in Path(path).read_text(encoding="utf-8").splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) if key.strip() == wanted: value = value.strip() if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'": value = value[1:-1] print(value) break else: raise SystemExit(f"missing environment variable: {wanted}") PY } trim_token() { printf '%s' "$1" | tr -d '\r\n\t ' } TOKEN="$(trim_token "${NOTIFICATIONS_TOKEN_PRODUCER_TEST:-}")" if [[ -z "$TOKEN" ]]; then TOKEN="$(trim_token "$(env_value NOTIFICATIONS_TOKEN_PRODUCER_TEST 2>/dev/null || true)")" fi if [[ -z "$TOKEN" ]]; then read -rsp "NOTIFICATIONS_TOKEN_PRODUCER_TEST (из .env не найден): " TOKEN echo TOKEN="$(trim_token "$TOKEN")" fi read -rp "USER_ID клиента: " USER_ID USER_ID="$(trim_token "$USER_ID")" if [[ -z "${TOKEN}" || -z "${USER_ID}" ]]; then echo "TOKEN и USER_ID обязательны." >&2 exit 1 fi echo "Токен: ${#TOKEN} символов (первые 8: ${TOKEN:0:8}…)" PAYLOAD_DIR="$(mktemp -d)" trap 'rm -rf "$PAYLOAD_DIR"' EXIT BASE_TS="$(date +%s)" RUN_ID="manual-test-${BASE_TS}" NOW="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" DT_URGENT="$(date -u -d "${NOW} +0 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+0S +"%Y-%m-%dT%H:%M:%SZ")" DT_PAYMENT="$(date -u -d "${NOW} - 60 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-60S +"%Y-%m-%dT%H:%M:%SZ")" DT_DOCS_REQ="$(date -u -d "${NOW} - 120 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-120S +"%Y-%m-%dT%H:%M:%SZ")" DT_DOCS_READY="$(date -u -d "${NOW} - 180 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-180S +"%Y-%m-%dT%H:%M:%SZ")" DT_STATUS="$(date -u -d "${NOW} - 240 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-240S +"%Y-%m-%dT%H:%M:%SZ")" DT_REMINDER="$(date -u -d "${NOW} - 300 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-300S +"%Y-%m-%dT%H:%M:%SZ")" DT_NEWS="$(date -u -d "${NOW} - 360 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-360S +"%Y-%m-%dT%H:%M:%SZ")" DT_PROMO="$(date -u -d "${NOW} - 420 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-420S +"%Y-%m-%dT%H:%M:%SZ")" DT_ADS="$(date -u -d "${NOW} - 480 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v-480S +"%Y-%m-%dT%H:%M:%SZ")" DEADLINE_URGENT="$(date -u -d "${NOW} + 2 days" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+2d +"%Y-%m-%dT%H:%M:%SZ")" DEADLINE_DOCS="$(date -u -d "${NOW} + 5 days" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+5d +"%Y-%m-%dT%H:%M:%SZ")" DEADLINE_REMINDER="$(date -u -d "${NOW} + 1 day" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+1d +"%Y-%m-%dT%H:%M:%SZ")" EXPIRE_PAYMENT="$(date -u -d "${NOW} + 3 days" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+3d +"%Y-%m-%dT%H:%M:%SZ")" write_payload() { local name="$1" cat > "${PAYLOAD_DIR}/${name}.json" } create_notification() { local label="$1" local payload_file="${PAYLOAD_DIR}/${label}.json" if [[ ! -f "$payload_file" ]]; then echo "Нет payload: ${payload_file}" >&2 return 1 fi echo echo "========== ${label} ==========" docker run --rm \ --network han-chat-backend \ -v "${payload_file}:/payload.json:ro" \ curlimages/curl:latest \ -sS -i \ -X POST \ 'http://api-backend:8000/internal/notifications/v1/notifications' \ -H "Authorization: Bearer ${TOKEN}" \ -H 'Content-Type: application/json; charset=utf-8' \ --data-binary @/payload.json } prepare_docs_in_s3() { echo >&2 echo "========== PREP: загрузка тестовых документов в S3 для docs_ready ==========" >&2 docker compose --env-file "$ENV_FILE" exec -T \ -e "USER_ID=${USER_ID}" \ -e "RUN_ID=${RUN_ID}" \ api-backend python3 - <<'PY' import hashlib import os import uuid import boto3 from botocore.client import Config from app.settings import Settings USER_ID = os.environ["USER_ID"] settings = Settings() client = boto3.client( "s3", endpoint_url=str(settings.selectel_s3_endpoint_url), aws_access_key_id=settings.selectel_s3_access_key.get_secret_value(), aws_secret_access_key=settings.selectel_s3_secret_key.get_secret_value(), config=Config(signature_version="s3v4", s3={"addressing_style": "virtual"}), ) bucket = settings.selectel_s3_bucket_documents fixtures = [ { "prefix": "CONTRACT", "title": "Уведомление о постановке на миграционный учёт.pdf", "body": b"""%PDF-1.4 1 0 obj<>endobj 2 0 obj<>endobj 3 0 obj<>endobj xref 0 4 trailer<> startxref 100 %%EOF """, }, { "prefix": "RESULTS", "title": "Справка о соблюдении миграционного законодательства.pdf", "body": b"""%PDF-1.4 1 0 obj<>endobj 2 0 obj<>endobj 3 0 obj<>endobj xref 0 4 trailer<> startxref 100 %%EOF """, }, ] lines: list[str] = [] for item in fixtures: doc_id = str(uuid.uuid4()) key = f"documents/users/{USER_ID}/{doc_id}" body = item["body"] checksum = hashlib.sha256(body).hexdigest() client.put_object( Bucket=bucket, Key=key, Body=body, ContentType="application/pdf", ) p = item["prefix"] lines.append( f"{p}_KEY={key}\n" f"{p}_TITLE={item['title']}\n" f"{p}_SIZE={len(body)}\n" f"{p}_SHA256={checksum}" ) print("\n".join(lines)) PY } echo "Run ID: ${RUN_ID}" echo "User ID: ${USER_ID}" read -rp "Подготовить документы в S3 для docs_ready? [Y/n]: " PREP_DOCS PREP_DOCS="${PREP_DOCS:-Y}" CONTRACT_KEY="" CONTRACT_TITLE="" CONTRACT_SIZE="" CONTRACT_SHA256="" RESULTS_KEY="" RESULTS_TITLE="" RESULTS_SIZE="" RESULTS_SHA256="" if [[ "${PREP_DOCS^^}" != "N" ]]; then PREP_OUT="$(prepare_docs_in_s3)" echo "${PREP_OUT}" while IFS= read -r line; do [[ "$line" =~ ^([A-Z][A-Z0-9_]*)=(.*)$ ]] || continue declare "${BASH_REMATCH[1]}=${BASH_REMATCH[2]}" done <<< "${PREP_OUT}" fi # --- payloads --- write_payload urgent <