Add voice transcription admin review flow
All checks were successful
Build and deploy Backend / build (push) Successful in 7m29s

This commit is contained in:
Ruslan Bakiev
2026-05-14 08:44:20 +07:00
parent 0668660e85
commit 3a072a7165
13 changed files with 355 additions and 69 deletions

View File

@@ -7,7 +7,7 @@ on:
jobs:
build:
runs-on: build-host
runs-on: builder
env:
SERVICE_NAME: backend
IMAGE_SHA: gitea.dsrptlab.com/mapflow/backend:${{ github.sha }}
@@ -25,12 +25,6 @@ jobs:
- name: Build and push image
run: |
set -euo pipefail
builder="builder"
if ! docker buildx inspect "$builder" >/dev/null 2>&1; then
docker buildx create --name "$builder" --driver docker-container --buildkitd-config /etc/buildkit/buildkitd.toml
fi
docker buildx use "$builder"
docker buildx inspect --bootstrap
docker buildx build --push --provenance=false --tag "$IMAGE_SHA" --tag "$IMAGE_LATEST" .
- name: Skip stale deployment
@@ -58,8 +52,3 @@ jobs:
-d "$payload")"
cat "$response_file"
[ "$status_code" = "200" ]
- name: Prune shared BuildKit cache
run: |
set -euo pipefail
docker buildx prune --builder builder --all --max-used-space 40gb -f

View File

@@ -0,0 +1,10 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "isAdmin" BOOLEAN NOT NULL DEFAULT false;
-- AlterTable
ALTER TABLE "VoiceExperience" ADD COLUMN "audioAccessToken" TEXT,
ADD COLUMN "audioContentBase64" TEXT,
ADD COLUMN "audioMimeType" TEXT;
-- CreateIndex
CREATE UNIQUE INDEX "VoiceExperience_audioAccessToken_key" ON "VoiceExperience"("audioAccessToken");

View File

@@ -17,31 +17,32 @@ enum VoiceExperienceStatus {
}
model Place {
id String @id @default(cuid())
googlePlaceId String @unique
name String
latitude Float
longitude Float
id String @id @default(cuid())
googlePlaceId String @unique
name String
latitude Float
longitude Float
googlePrimaryType String?
googleTypes String[] @default([])
experiences VoiceExperience[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
experiences VoiceExperience[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model User {
id String @id @default(cuid())
telegramId String @unique
username String?
firstName String?
lastName String?
photoUrl String?
languageCode String?
sessions UserSession[]
loginRequests TelegramLoginRequest[]
id String @id @default(cuid())
telegramId String @unique
username String?
firstName String?
lastName String?
photoUrl String?
languageCode String?
isAdmin Boolean @default(false)
sessions UserSession[]
loginRequests TelegramLoginRequest[]
voiceExperiences VoiceExperience[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model UserSession {
@@ -68,16 +69,19 @@ model TelegramLoginRequest {
}
model VoiceExperience {
id String @id @default(cuid())
placeId String
place Place @relation(fields: [placeId], references: [id])
userId String?
user User? @relation(fields: [userId], references: [id])
durationSeconds Int
audioObjectKey String
status VoiceExperienceStatus @default(UPLOADED)
transcript String?
analysis Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
placeId String
place Place @relation(fields: [placeId], references: [id])
userId String?
user User? @relation(fields: [userId], references: [id])
durationSeconds Int
audioObjectKey String
audioContentBase64 String?
audioMimeType String?
audioAccessToken String? @unique
status VoiceExperienceStatus @default(UPLOADED)
transcript String?
analysis Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

View File

@@ -196,3 +196,12 @@ export async function requireTelegramUser(authData: TelegramAuthData) {
throw new Error('Telegram authorization is required.');
}
export async function requireAdminTelegramUser(authData: TelegramAuthData) {
const user = await requireTelegramUser(authData);
if (!user.isAdmin) {
throw new Error('MapFlow admin access is required.');
}
return user;
}

File diff suppressed because one or more lines are too long

View File

@@ -140,6 +140,7 @@ exports.Prisma.UserScalarFieldEnum = {
lastName: 'lastName',
photoUrl: 'photoUrl',
languageCode: 'languageCode',
isAdmin: 'isAdmin',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
@@ -171,6 +172,9 @@ exports.Prisma.VoiceExperienceScalarFieldEnum = {
userId: 'userId',
durationSeconds: 'durationSeconds',
audioObjectKey: 'audioObjectKey',
audioContentBase64: 'audioContentBase64',
audioMimeType: 'audioMimeType',
audioAccessToken: 'audioAccessToken',
status: 'status',
transcript: 'transcript',
analysis: 'analysis',

View File

@@ -2509,6 +2509,7 @@ export namespace Prisma {
lastName: string | null
photoUrl: string | null
languageCode: string | null
isAdmin: boolean | null
createdAt: Date | null
updatedAt: Date | null
}
@@ -2521,6 +2522,7 @@ export namespace Prisma {
lastName: string | null
photoUrl: string | null
languageCode: string | null
isAdmin: boolean | null
createdAt: Date | null
updatedAt: Date | null
}
@@ -2533,6 +2535,7 @@ export namespace Prisma {
lastName: number
photoUrl: number
languageCode: number
isAdmin: number
createdAt: number
updatedAt: number
_all: number
@@ -2547,6 +2550,7 @@ export namespace Prisma {
lastName?: true
photoUrl?: true
languageCode?: true
isAdmin?: true
createdAt?: true
updatedAt?: true
}
@@ -2559,6 +2563,7 @@ export namespace Prisma {
lastName?: true
photoUrl?: true
languageCode?: true
isAdmin?: true
createdAt?: true
updatedAt?: true
}
@@ -2571,6 +2576,7 @@ export namespace Prisma {
lastName?: true
photoUrl?: true
languageCode?: true
isAdmin?: true
createdAt?: true
updatedAt?: true
_all?: true
@@ -2656,6 +2662,7 @@ export namespace Prisma {
lastName: string | null
photoUrl: string | null
languageCode: string | null
isAdmin: boolean
createdAt: Date
updatedAt: Date
_count: UserCountAggregateOutputType | null
@@ -2685,6 +2692,7 @@ export namespace Prisma {
lastName?: boolean
photoUrl?: boolean
languageCode?: boolean
isAdmin?: boolean
createdAt?: boolean
updatedAt?: boolean
sessions?: boolean | User$sessionsArgs<ExtArgs>
@@ -2701,6 +2709,7 @@ export namespace Prisma {
lastName?: boolean
photoUrl?: boolean
languageCode?: boolean
isAdmin?: boolean
createdAt?: boolean
updatedAt?: boolean
}, ExtArgs["result"]["user"]>
@@ -2713,6 +2722,7 @@ export namespace Prisma {
lastName?: boolean
photoUrl?: boolean
languageCode?: boolean
isAdmin?: boolean
createdAt?: boolean
updatedAt?: boolean
}, ExtArgs["result"]["user"]>
@@ -2725,11 +2735,12 @@ export namespace Prisma {
lastName?: boolean
photoUrl?: boolean
languageCode?: boolean
isAdmin?: boolean
createdAt?: boolean
updatedAt?: boolean
}
export type UserOmit<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = $Extensions.GetOmit<"id" | "telegramId" | "username" | "firstName" | "lastName" | "photoUrl" | "languageCode" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]>
export type UserOmit<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = $Extensions.GetOmit<"id" | "telegramId" | "username" | "firstName" | "lastName" | "photoUrl" | "languageCode" | "isAdmin" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]>
export type UserInclude<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = {
sessions?: boolean | User$sessionsArgs<ExtArgs>
loginRequests?: boolean | User$loginRequestsArgs<ExtArgs>
@@ -2754,6 +2765,7 @@ export namespace Prisma {
lastName: string | null
photoUrl: string | null
languageCode: string | null
isAdmin: boolean
createdAt: Date
updatedAt: Date
}, ExtArgs["result"]["user"]>
@@ -3189,6 +3201,7 @@ export namespace Prisma {
readonly lastName: FieldRef<"User", 'String'>
readonly photoUrl: FieldRef<"User", 'String'>
readonly languageCode: FieldRef<"User", 'String'>
readonly isAdmin: FieldRef<"User", 'Boolean'>
readonly createdAt: FieldRef<"User", 'DateTime'>
readonly updatedAt: FieldRef<"User", 'DateTime'>
}
@@ -5944,6 +5957,9 @@ export namespace Prisma {
userId: string | null
durationSeconds: number | null
audioObjectKey: string | null
audioContentBase64: string | null
audioMimeType: string | null
audioAccessToken: string | null
status: $Enums.VoiceExperienceStatus | null
transcript: string | null
createdAt: Date | null
@@ -5956,6 +5972,9 @@ export namespace Prisma {
userId: string | null
durationSeconds: number | null
audioObjectKey: string | null
audioContentBase64: string | null
audioMimeType: string | null
audioAccessToken: string | null
status: $Enums.VoiceExperienceStatus | null
transcript: string | null
createdAt: Date | null
@@ -5968,6 +5987,9 @@ export namespace Prisma {
userId: number
durationSeconds: number
audioObjectKey: number
audioContentBase64: number
audioMimeType: number
audioAccessToken: number
status: number
transcript: number
analysis: number
@@ -5991,6 +6013,9 @@ export namespace Prisma {
userId?: true
durationSeconds?: true
audioObjectKey?: true
audioContentBase64?: true
audioMimeType?: true
audioAccessToken?: true
status?: true
transcript?: true
createdAt?: true
@@ -6003,6 +6028,9 @@ export namespace Prisma {
userId?: true
durationSeconds?: true
audioObjectKey?: true
audioContentBase64?: true
audioMimeType?: true
audioAccessToken?: true
status?: true
transcript?: true
createdAt?: true
@@ -6015,6 +6043,9 @@ export namespace Prisma {
userId?: true
durationSeconds?: true
audioObjectKey?: true
audioContentBase64?: true
audioMimeType?: true
audioAccessToken?: true
status?: true
transcript?: true
analysis?: true
@@ -6115,6 +6146,9 @@ export namespace Prisma {
userId: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64: string | null
audioMimeType: string | null
audioAccessToken: string | null
status: $Enums.VoiceExperienceStatus
transcript: string | null
analysis: JsonValue | null
@@ -6147,6 +6181,9 @@ export namespace Prisma {
userId?: boolean
durationSeconds?: boolean
audioObjectKey?: boolean
audioContentBase64?: boolean
audioMimeType?: boolean
audioAccessToken?: boolean
status?: boolean
transcript?: boolean
analysis?: boolean
@@ -6162,6 +6199,9 @@ export namespace Prisma {
userId?: boolean
durationSeconds?: boolean
audioObjectKey?: boolean
audioContentBase64?: boolean
audioMimeType?: boolean
audioAccessToken?: boolean
status?: boolean
transcript?: boolean
analysis?: boolean
@@ -6177,6 +6217,9 @@ export namespace Prisma {
userId?: boolean
durationSeconds?: boolean
audioObjectKey?: boolean
audioContentBase64?: boolean
audioMimeType?: boolean
audioAccessToken?: boolean
status?: boolean
transcript?: boolean
analysis?: boolean
@@ -6192,6 +6235,9 @@ export namespace Prisma {
userId?: boolean
durationSeconds?: boolean
audioObjectKey?: boolean
audioContentBase64?: boolean
audioMimeType?: boolean
audioAccessToken?: boolean
status?: boolean
transcript?: boolean
analysis?: boolean
@@ -6199,7 +6245,7 @@ export namespace Prisma {
updatedAt?: boolean
}
export type VoiceExperienceOmit<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = $Extensions.GetOmit<"id" | "placeId" | "userId" | "durationSeconds" | "audioObjectKey" | "status" | "transcript" | "analysis" | "createdAt" | "updatedAt", ExtArgs["result"]["voiceExperience"]>
export type VoiceExperienceOmit<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = $Extensions.GetOmit<"id" | "placeId" | "userId" | "durationSeconds" | "audioObjectKey" | "audioContentBase64" | "audioMimeType" | "audioAccessToken" | "status" | "transcript" | "analysis" | "createdAt" | "updatedAt", ExtArgs["result"]["voiceExperience"]>
export type VoiceExperienceInclude<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = {
place?: boolean | PlaceDefaultArgs<ExtArgs>
user?: boolean | VoiceExperience$userArgs<ExtArgs>
@@ -6225,6 +6271,9 @@ export namespace Prisma {
userId: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64: string | null
audioMimeType: string | null
audioAccessToken: string | null
status: $Enums.VoiceExperienceStatus
transcript: string | null
analysis: Prisma.JsonValue | null
@@ -6660,6 +6709,9 @@ export namespace Prisma {
readonly userId: FieldRef<"VoiceExperience", 'String'>
readonly durationSeconds: FieldRef<"VoiceExperience", 'Int'>
readonly audioObjectKey: FieldRef<"VoiceExperience", 'String'>
readonly audioContentBase64: FieldRef<"VoiceExperience", 'String'>
readonly audioMimeType: FieldRef<"VoiceExperience", 'String'>
readonly audioAccessToken: FieldRef<"VoiceExperience", 'String'>
readonly status: FieldRef<"VoiceExperience", 'VoiceExperienceStatus'>
readonly transcript: FieldRef<"VoiceExperience", 'String'>
readonly analysis: FieldRef<"VoiceExperience", 'Json'>
@@ -7140,6 +7192,7 @@ export namespace Prisma {
lastName: 'lastName',
photoUrl: 'photoUrl',
languageCode: 'languageCode',
isAdmin: 'isAdmin',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
@@ -7180,6 +7233,9 @@ export namespace Prisma {
userId: 'userId',
durationSeconds: 'durationSeconds',
audioObjectKey: 'audioObjectKey',
audioContentBase64: 'audioContentBase64',
audioMimeType: 'audioMimeType',
audioAccessToken: 'audioAccessToken',
status: 'status',
transcript: 'transcript',
analysis: 'analysis',
@@ -7278,6 +7334,13 @@ export namespace Prisma {
/**
* Reference to a field of type 'Boolean'
*/
export type BooleanFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Boolean'>
/**
* Reference to a field of type 'Int'
*/
@@ -7411,6 +7474,7 @@ export namespace Prisma {
lastName?: StringNullableFilter<"User"> | string | null
photoUrl?: StringNullableFilter<"User"> | string | null
languageCode?: StringNullableFilter<"User"> | string | null
isAdmin?: BoolFilter<"User"> | boolean
createdAt?: DateTimeFilter<"User"> | Date | string
updatedAt?: DateTimeFilter<"User"> | Date | string
sessions?: UserSessionListRelationFilter
@@ -7426,6 +7490,7 @@ export namespace Prisma {
lastName?: SortOrderInput | SortOrder
photoUrl?: SortOrderInput | SortOrder
languageCode?: SortOrderInput | SortOrder
isAdmin?: SortOrder
createdAt?: SortOrder
updatedAt?: SortOrder
sessions?: UserSessionOrderByRelationAggregateInput
@@ -7444,6 +7509,7 @@ export namespace Prisma {
lastName?: StringNullableFilter<"User"> | string | null
photoUrl?: StringNullableFilter<"User"> | string | null
languageCode?: StringNullableFilter<"User"> | string | null
isAdmin?: BoolFilter<"User"> | boolean
createdAt?: DateTimeFilter<"User"> | Date | string
updatedAt?: DateTimeFilter<"User"> | Date | string
sessions?: UserSessionListRelationFilter
@@ -7459,6 +7525,7 @@ export namespace Prisma {
lastName?: SortOrderInput | SortOrder
photoUrl?: SortOrderInput | SortOrder
languageCode?: SortOrderInput | SortOrder
isAdmin?: SortOrder
createdAt?: SortOrder
updatedAt?: SortOrder
_count?: UserCountOrderByAggregateInput
@@ -7477,6 +7544,7 @@ export namespace Prisma {
lastName?: StringNullableWithAggregatesFilter<"User"> | string | null
photoUrl?: StringNullableWithAggregatesFilter<"User"> | string | null
languageCode?: StringNullableWithAggregatesFilter<"User"> | string | null
isAdmin?: BoolWithAggregatesFilter<"User"> | boolean
createdAt?: DateTimeWithAggregatesFilter<"User"> | Date | string
updatedAt?: DateTimeWithAggregatesFilter<"User"> | Date | string
}
@@ -7627,6 +7695,9 @@ export namespace Prisma {
userId?: StringNullableFilter<"VoiceExperience"> | string | null
durationSeconds?: IntFilter<"VoiceExperience"> | number
audioObjectKey?: StringFilter<"VoiceExperience"> | string
audioContentBase64?: StringNullableFilter<"VoiceExperience"> | string | null
audioMimeType?: StringNullableFilter<"VoiceExperience"> | string | null
audioAccessToken?: StringNullableFilter<"VoiceExperience"> | string | null
status?: EnumVoiceExperienceStatusFilter<"VoiceExperience"> | $Enums.VoiceExperienceStatus
transcript?: StringNullableFilter<"VoiceExperience"> | string | null
analysis?: JsonNullableFilter<"VoiceExperience">
@@ -7642,6 +7713,9 @@ export namespace Prisma {
userId?: SortOrderInput | SortOrder
durationSeconds?: SortOrder
audioObjectKey?: SortOrder
audioContentBase64?: SortOrderInput | SortOrder
audioMimeType?: SortOrderInput | SortOrder
audioAccessToken?: SortOrderInput | SortOrder
status?: SortOrder
transcript?: SortOrderInput | SortOrder
analysis?: SortOrderInput | SortOrder
@@ -7653,6 +7727,7 @@ export namespace Prisma {
export type VoiceExperienceWhereUniqueInput = Prisma.AtLeast<{
id?: string
audioAccessToken?: string
AND?: VoiceExperienceWhereInput | VoiceExperienceWhereInput[]
OR?: VoiceExperienceWhereInput[]
NOT?: VoiceExperienceWhereInput | VoiceExperienceWhereInput[]
@@ -7660,6 +7735,8 @@ export namespace Prisma {
userId?: StringNullableFilter<"VoiceExperience"> | string | null
durationSeconds?: IntFilter<"VoiceExperience"> | number
audioObjectKey?: StringFilter<"VoiceExperience"> | string
audioContentBase64?: StringNullableFilter<"VoiceExperience"> | string | null
audioMimeType?: StringNullableFilter<"VoiceExperience"> | string | null
status?: EnumVoiceExperienceStatusFilter<"VoiceExperience"> | $Enums.VoiceExperienceStatus
transcript?: StringNullableFilter<"VoiceExperience"> | string | null
analysis?: JsonNullableFilter<"VoiceExperience">
@@ -7667,7 +7744,7 @@ export namespace Prisma {
updatedAt?: DateTimeFilter<"VoiceExperience"> | Date | string
place?: XOR<PlaceScalarRelationFilter, PlaceWhereInput>
user?: XOR<UserNullableScalarRelationFilter, UserWhereInput> | null
}, "id">
}, "id" | "audioAccessToken">
export type VoiceExperienceOrderByWithAggregationInput = {
id?: SortOrder
@@ -7675,6 +7752,9 @@ export namespace Prisma {
userId?: SortOrderInput | SortOrder
durationSeconds?: SortOrder
audioObjectKey?: SortOrder
audioContentBase64?: SortOrderInput | SortOrder
audioMimeType?: SortOrderInput | SortOrder
audioAccessToken?: SortOrderInput | SortOrder
status?: SortOrder
transcript?: SortOrderInput | SortOrder
analysis?: SortOrderInput | SortOrder
@@ -7696,6 +7776,9 @@ export namespace Prisma {
userId?: StringNullableWithAggregatesFilter<"VoiceExperience"> | string | null
durationSeconds?: IntWithAggregatesFilter<"VoiceExperience"> | number
audioObjectKey?: StringWithAggregatesFilter<"VoiceExperience"> | string
audioContentBase64?: StringNullableWithAggregatesFilter<"VoiceExperience"> | string | null
audioMimeType?: StringNullableWithAggregatesFilter<"VoiceExperience"> | string | null
audioAccessToken?: StringNullableWithAggregatesFilter<"VoiceExperience"> | string | null
status?: EnumVoiceExperienceStatusWithAggregatesFilter<"VoiceExperience"> | $Enums.VoiceExperienceStatus
transcript?: StringNullableWithAggregatesFilter<"VoiceExperience"> | string | null
analysis?: JsonNullableWithAggregatesFilter<"VoiceExperience">
@@ -7799,6 +7882,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionCreateNestedManyWithoutUserInput
@@ -7814,6 +7898,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionUncheckedCreateNestedManyWithoutUserInput
@@ -7829,6 +7914,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUpdateManyWithoutUserNestedInput
@@ -7844,6 +7930,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUncheckedUpdateManyWithoutUserNestedInput
@@ -7859,6 +7946,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
}
@@ -7871,6 +7959,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
}
@@ -7883,6 +7972,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
}
@@ -8036,6 +8126,9 @@ export namespace Prisma {
id?: string
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8051,6 +8144,9 @@ export namespace Prisma {
userId?: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8062,6 +8158,9 @@ export namespace Prisma {
id?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8077,6 +8176,9 @@ export namespace Prisma {
userId?: NullableStringFieldUpdateOperationsInput | string | null
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8090,6 +8192,9 @@ export namespace Prisma {
userId?: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8101,6 +8206,9 @@ export namespace Prisma {
id?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8114,6 +8222,9 @@ export namespace Prisma {
userId?: NullableStringFieldUpdateOperationsInput | string | null
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -8306,6 +8417,11 @@ export namespace Prisma {
_max?: NestedDateTimeFilter<$PrismaModel>
}
export type BoolFilter<$PrismaModel = never> = {
equals?: boolean | BooleanFieldRefInput<$PrismaModel>
not?: NestedBoolFilter<$PrismaModel> | boolean
}
export type UserSessionListRelationFilter = {
every?: UserSessionWhereInput
some?: UserSessionWhereInput
@@ -8334,6 +8450,7 @@ export namespace Prisma {
lastName?: SortOrder
photoUrl?: SortOrder
languageCode?: SortOrder
isAdmin?: SortOrder
createdAt?: SortOrder
updatedAt?: SortOrder
}
@@ -8346,6 +8463,7 @@ export namespace Prisma {
lastName?: SortOrder
photoUrl?: SortOrder
languageCode?: SortOrder
isAdmin?: SortOrder
createdAt?: SortOrder
updatedAt?: SortOrder
}
@@ -8358,10 +8476,19 @@ export namespace Prisma {
lastName?: SortOrder
photoUrl?: SortOrder
languageCode?: SortOrder
isAdmin?: SortOrder
createdAt?: SortOrder
updatedAt?: SortOrder
}
export type BoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | BooleanFieldRefInput<$PrismaModel>
not?: NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: NestedIntFilter<$PrismaModel>
_min?: NestedBoolFilter<$PrismaModel>
_max?: NestedBoolFilter<$PrismaModel>
}
export type UserScalarRelationFilter = {
is?: UserWhereInput
isNot?: UserWhereInput
@@ -8522,6 +8649,9 @@ export namespace Prisma {
userId?: SortOrder
durationSeconds?: SortOrder
audioObjectKey?: SortOrder
audioContentBase64?: SortOrder
audioMimeType?: SortOrder
audioAccessToken?: SortOrder
status?: SortOrder
transcript?: SortOrder
analysis?: SortOrder
@@ -8539,6 +8669,9 @@ export namespace Prisma {
userId?: SortOrder
durationSeconds?: SortOrder
audioObjectKey?: SortOrder
audioContentBase64?: SortOrder
audioMimeType?: SortOrder
audioAccessToken?: SortOrder
status?: SortOrder
transcript?: SortOrder
createdAt?: SortOrder
@@ -8551,6 +8684,9 @@ export namespace Prisma {
userId?: SortOrder
durationSeconds?: SortOrder
audioObjectKey?: SortOrder
audioContentBase64?: SortOrder
audioMimeType?: SortOrder
audioAccessToken?: SortOrder
status?: SortOrder
transcript?: SortOrder
createdAt?: SortOrder
@@ -8726,6 +8862,10 @@ export namespace Prisma {
connect?: VoiceExperienceWhereUniqueInput | VoiceExperienceWhereUniqueInput[]
}
export type BoolFieldUpdateOperationsInput = {
set?: boolean
}
export type UserSessionUpdateManyWithoutUserNestedInput = {
create?: XOR<UserSessionCreateWithoutUserInput, UserSessionUncheckedCreateWithoutUserInput> | UserSessionCreateWithoutUserInput[] | UserSessionUncheckedCreateWithoutUserInput[]
connectOrCreate?: UserSessionCreateOrConnectWithoutUserInput | UserSessionCreateOrConnectWithoutUserInput[]
@@ -9026,6 +9166,19 @@ export namespace Prisma {
_max?: NestedDateTimeFilter<$PrismaModel>
}
export type NestedBoolFilter<$PrismaModel = never> = {
equals?: boolean | BooleanFieldRefInput<$PrismaModel>
not?: NestedBoolFilter<$PrismaModel> | boolean
}
export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | BooleanFieldRefInput<$PrismaModel>
not?: NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: NestedIntFilter<$PrismaModel>
_min?: NestedBoolFilter<$PrismaModel>
_max?: NestedBoolFilter<$PrismaModel>
}
export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | IntFieldRefInput<$PrismaModel> | null
in?: number[] | ListIntFieldRefInput<$PrismaModel> | null
@@ -9113,6 +9266,9 @@ export namespace Prisma {
id?: string
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9126,6 +9282,9 @@ export namespace Prisma {
userId?: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9168,6 +9327,9 @@ export namespace Prisma {
userId?: StringNullableFilter<"VoiceExperience"> | string | null
durationSeconds?: IntFilter<"VoiceExperience"> | number
audioObjectKey?: StringFilter<"VoiceExperience"> | string
audioContentBase64?: StringNullableFilter<"VoiceExperience"> | string | null
audioMimeType?: StringNullableFilter<"VoiceExperience"> | string | null
audioAccessToken?: StringNullableFilter<"VoiceExperience"> | string | null
status?: EnumVoiceExperienceStatusFilter<"VoiceExperience"> | $Enums.VoiceExperienceStatus
transcript?: StringNullableFilter<"VoiceExperience"> | string | null
analysis?: JsonNullableFilter<"VoiceExperience">
@@ -9237,6 +9399,9 @@ export namespace Prisma {
id?: string
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9250,6 +9415,9 @@ export namespace Prisma {
placeId: string
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9350,6 +9518,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
loginRequests?: TelegramLoginRequestCreateNestedManyWithoutUserInput
@@ -9364,6 +9533,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
loginRequests?: TelegramLoginRequestUncheckedCreateNestedManyWithoutUserInput
@@ -9394,6 +9564,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
loginRequests?: TelegramLoginRequestUpdateManyWithoutUserNestedInput
@@ -9408,6 +9579,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
loginRequests?: TelegramLoginRequestUncheckedUpdateManyWithoutUserNestedInput
@@ -9422,6 +9594,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionCreateNestedManyWithoutUserInput
@@ -9436,6 +9609,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionUncheckedCreateNestedManyWithoutUserInput
@@ -9466,6 +9640,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUpdateManyWithoutUserNestedInput
@@ -9480,6 +9655,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUncheckedUpdateManyWithoutUserNestedInput
@@ -9523,6 +9699,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionCreateNestedManyWithoutUserInput
@@ -9537,6 +9714,7 @@ export namespace Prisma {
lastName?: string | null
photoUrl?: string | null
languageCode?: string | null
isAdmin?: boolean
createdAt?: Date | string
updatedAt?: Date | string
sessions?: UserSessionUncheckedCreateNestedManyWithoutUserInput
@@ -9602,6 +9780,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUpdateManyWithoutUserNestedInput
@@ -9616,6 +9795,7 @@ export namespace Prisma {
lastName?: NullableStringFieldUpdateOperationsInput | string | null
photoUrl?: NullableStringFieldUpdateOperationsInput | string | null
languageCode?: NullableStringFieldUpdateOperationsInput | string | null
isAdmin?: BoolFieldUpdateOperationsInput | boolean
createdAt?: DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string
sessions?: UserSessionUncheckedUpdateManyWithoutUserNestedInput
@@ -9627,6 +9807,9 @@ export namespace Prisma {
userId?: string | null
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9638,6 +9821,9 @@ export namespace Prisma {
id?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9651,6 +9837,9 @@ export namespace Prisma {
userId?: NullableStringFieldUpdateOperationsInput | string | null
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9663,6 +9852,9 @@ export namespace Prisma {
userId?: NullableStringFieldUpdateOperationsInput | string | null
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9694,6 +9886,9 @@ export namespace Prisma {
placeId: string
durationSeconds: number
audioObjectKey: string
audioContentBase64?: string | null
audioMimeType?: string | null
audioAccessToken?: string | null
status?: $Enums.VoiceExperienceStatus
transcript?: string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9762,6 +9957,9 @@ export namespace Prisma {
id?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9775,6 +9973,9 @@ export namespace Prisma {
placeId?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue
@@ -9787,6 +9988,9 @@ export namespace Prisma {
placeId?: StringFieldUpdateOperationsInput | string
durationSeconds?: IntFieldUpdateOperationsInput | number
audioObjectKey?: StringFieldUpdateOperationsInput | string
audioContentBase64?: NullableStringFieldUpdateOperationsInput | string | null
audioMimeType?: NullableStringFieldUpdateOperationsInput | string | null
audioAccessToken?: NullableStringFieldUpdateOperationsInput | string | null
status?: EnumVoiceExperienceStatusFieldUpdateOperationsInput | $Enums.VoiceExperienceStatus
transcript?: NullableStringFieldUpdateOperationsInput | string | null
analysis?: NullableJsonNullValueInput | InputJsonValue

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"name": "prisma-client-410efc9d12118d43a80a319e7db6d1bb75111f120bc5d6445b1056062f5567cd",
"name": "prisma-client-af7d1a24a80c81a94e157e22f4f12e91cca6099374f7a2346452663b0168688a",
"main": "index.js",
"types": "index.d.ts",
"browser": "default.js",

View File

@@ -37,6 +37,7 @@ model User {
lastName String?
photoUrl String?
languageCode String?
isAdmin Boolean @default(false)
sessions UserSession[]
loginRequests TelegramLoginRequest[]
voiceExperiences VoiceExperience[]
@@ -68,16 +69,19 @@ model TelegramLoginRequest {
}
model VoiceExperience {
id String @id @default(cuid())
placeId String
place Place @relation(fields: [placeId], references: [id])
userId String?
user User? @relation(fields: [userId], references: [id])
durationSeconds Int
audioObjectKey String
status VoiceExperienceStatus @default(UPLOADED)
transcript String?
analysis Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
placeId String
place Place @relation(fields: [placeId], references: [id])
userId String?
user User? @relation(fields: [userId], references: [id])
durationSeconds Int
audioObjectKey String
audioContentBase64 String?
audioMimeType String?
audioAccessToken String? @unique
status VoiceExperienceStatus @default(UPLOADED)
transcript String?
analysis Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

View File

@@ -2,6 +2,7 @@ import { GraphQLJSONObject } from './scalars.js';
import {
getOrCreateTelegramLoginUser,
getOrCreateTelegramUser,
requireAdminTelegramUser,
requireTelegramUser,
type TelegramLoginData,
} from '../auth/telegram.js';
@@ -53,6 +54,7 @@ export const schema = /* GraphQL */ `
lastName: String
photoUrl: String
languageCode: String
isAdmin: Boolean!
}
type VoiceExperience {
@@ -74,6 +76,8 @@ export const schema = /* GraphQL */ `
longitude: Float!
durationSeconds: Int!
audioObjectKey: String!
audioContentBase64: String!
audioMimeType: String!
}
input NearbyPlacesInput {
@@ -152,7 +156,7 @@ export const resolvers = {
},
voiceExperiences: async (_: unknown, __: unknown, context: unknown) => {
const graphqlContext = context as GraphqlContext;
await requireTelegramUser(graphqlContext);
await requireAdminTelegramUser(graphqlContext);
return listVoiceExperiences();
},
},

View File

@@ -1,3 +1,5 @@
import { randomBytes } from 'node:crypto';
import { enqueueVoiceExperience } from '../hatchet/enqueue-voice-experience.js';
import { prisma } from '../prisma.js';
@@ -10,8 +12,14 @@ export type CreateVoiceExperienceInput = {
longitude: number;
durationSeconds: number;
audioObjectKey: string;
audioContentBase64: string;
audioMimeType: string;
};
function randomAudioAccessToken() {
return randomBytes(32).toString('base64url');
}
export async function createVoiceExperience(
input: CreateVoiceExperienceInput,
userId: string,
@@ -27,6 +35,12 @@ export async function createVoiceExperience(
if (googleName === '') {
throw new Error('Google place name is required.');
}
if (input.audioContentBase64.trim() === '') {
throw new Error('Voice experience audio is required.');
}
if (input.audioMimeType.trim() === '') {
throw new Error('Voice experience audio MIME type is required.');
}
const place = await prisma.place.upsert({
where: { googlePlaceId },
@@ -49,6 +63,9 @@ export async function createVoiceExperience(
userId,
durationSeconds: input.durationSeconds,
audioObjectKey: input.audioObjectKey,
audioContentBase64: input.audioContentBase64,
audioMimeType: input.audioMimeType,
audioAccessToken: randomAudioAccessToken(),
status: 'UPLOADED',
},
include: { place: true, user: true },

View File

@@ -9,7 +9,10 @@ import {
handleTelegramBotWebhook,
} from './auth/telegram-bot-login.js';
const app = Fastify({ logger: true });
const app = Fastify({
logger: true,
bodyLimit: 25 * 1024 * 1024,
});
app.register(mercurius, {
schema,
@@ -46,6 +49,36 @@ app.get('/telegram/photo/:fileId', async (request, reply) => {
return reply.send(photo.bytes);
});
app.get('/audio/voice-experiences/:experienceId', async (request, reply) => {
const params = request.params as { experienceId: string };
const query = request.query as { token?: string };
if (!query.token) {
return reply.code(401).send({ error: 'Audio token is required.' });
}
const experience = await prisma.voiceExperience.findUnique({
where: { id: params.experienceId },
select: {
audioAccessToken: true,
audioContentBase64: true,
audioMimeType: true,
},
});
if (
!experience ||
experience.audioAccessToken !== query.token ||
!experience.audioContentBase64 ||
!experience.audioMimeType
) {
return reply.code(404).send({ error: 'Audio was not found.' });
}
reply.header('content-type', experience.audioMimeType);
reply.header('cache-control', 'no-store');
return reply.send(Buffer.from(experience.audioContentBase64, 'base64'));
});
app.addHook('onClose', async () => {
await prisma.$disconnect();
});