frontAnswerer/lib/api/quizRelase.ts

331 lines
8.5 KiB
TypeScript
Raw Normal View History

import { GetQuizDataResponse, parseQuizData } from "@model/api/getQuizData";
2024-01-29 11:16:21 +00:00
import axios from "axios";
2024-05-31 16:41:18 +00:00
import MobileDetect from "mobile-detect";
import device from "current-device";
2024-01-29 11:16:21 +00:00
import type { AxiosError } from "axios";
import { replaceSpacesToEmptyLines } from "../components/ViewPublicationPage/tools/replaceSpacesToEmptyLines";
import { QuizSettings } from "@model/settingsData";
import * as Bowser from "bowser";
import { domain } from "../utils/defineDomain";
import { statusOfQuiz } from "@/utils/hooks/useQuestionFlowControl";
2024-01-29 11:16:21 +00:00
let SESSIONS = "";
const md = new MobileDetect(window.navigator.userAgent);
2024-04-02 13:09:13 +00:00
const userAgent = navigator.userAgent;
//операционная система
2024-04-02 13:09:13 +00:00
let OSDevice: string | undefined;
2024-05-31 16:41:18 +00:00
if (userAgent.toLowerCase().includes("linux")) {
OSDevice = "Linux";
}
if (userAgent.toLowerCase().includes("windows")) {
OSDevice = "Windows";
}
if (/iPad|iPhone|iPod/.test(userAgent)) {
OSDevice = "IOS";
}
if (userAgent.toLowerCase().includes("macintosh")) {
OSDevice = "Mac OS";
}
if (OSDevice === undefined) {
OSDevice = userAgent;
}
//браузер
2024-04-02 13:09:13 +00:00
let browserUser: string;
if (Bowser.name === "Chrome") {
2024-05-31 16:41:18 +00:00
browserUser = "Chrome";
2024-04-02 13:09:13 +00:00
} else if (Bowser.name === "Firefox") {
2024-05-31 16:41:18 +00:00
browserUser = "Firefox";
2024-04-02 13:09:13 +00:00
} else if (Bowser.name === "Safari") {
2024-05-31 16:41:18 +00:00
browserUser = "Safari";
2024-04-11 12:49:55 +00:00
} else if (Bowser.name === "Yandex Browser") {
2024-05-31 16:41:18 +00:00
browserUser = "Yandex Browser";
} else {
browserUser = userAgent;
}
2024-04-02 13:09:13 +00:00
const DeviceType = device.type;
2024-04-02 13:09:13 +00:00
let Device = md.mobile();
2024-05-31 16:41:18 +00:00
if (Device === null) {
Device = userAgent;
}
2024-04-17 16:08:40 +00:00
type PublicationMakeRequestParams = {
2024-05-31 16:41:18 +00:00
url: string;
body: FormData;
method: "POST";
2024-05-01 08:12:06 +00:00
};
2024-04-17 16:08:40 +00:00
2025-06-04 15:07:55 +00:00
const urlParams = new URLSearchParams(window.location.search);
const paudParam = urlParams.get("_paud");
2024-04-17 16:08:40 +00:00
export const publicationMakeRequest = ({ url, body }: PublicationMakeRequestParams) => {
2024-05-31 16:41:18 +00:00
return axios(url, {
data: body,
headers: {
"X-Sessionkey": SESSIONS,
"Content-Type": "multipart/form-data",
DeviceType: DeviceType,
Device: Device,
OS: OSDevice,
Browser: browserUser,
},
method: "POST",
});
2024-01-29 11:16:21 +00:00
};
2025-05-01 13:23:10 +00:00
// Глобальные переменные для хранения состояния между вызовами
let globalStatus: string | null = null;
let isFirstRequest = true;
/*
если запросить 0 вопросов - придёт items: null
если не запрашивать конфиг - поле конфига вообще не придёт
*/
interface GetDataProps {
quizId: string;
limit: number;
page: number;
needConfig: boolean;
}
export async function getData({ quizId, limit, page, needConfig }: GetDataProps): Promise<{
data: GetQuizDataResponse | null;
isRecentlyCompleted: boolean;
error?: AxiosError;
}> {
2025-06-04 15:07:55 +00:00
const body = {
quiz_id: quizId,
limit,
page,
need_config: needConfig,
2025-06-04 15:07:55 +00:00
} as any;
if (paudParam) body.auditory = Number(paudParam);
try {
const { data, headers } = await axios<GetQuizDataResponse>(
domain + `/answer/v1.0.0/settings${window.location.search}`,
{
method: "POST",
headers: {
"X-Sessionkey": SESSIONS,
"Content-Type": "application/json",
DeviceType: DeviceType,
Device: Device,
OS: OSDevice,
Browser: userAgent,
},
data: body,
}
);
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
//Тут ещё проверка на антифрод без парса конфига. Нам не интересно время если не нужно запрещать проходить чаще чем в сутки
if (
needConfig &&
data?.settings !== undefined &&
typeof sessions[quizId] === "number" &&
data.settings.cfg.includes('antifraud":true')
) {
// unix время. Если меньше суток прошло - выводить ошибку, иначе пустить дальше
if (Date.now() - sessions[quizId] < 86400000) {
return { data, isRecentlyCompleted: true };
}
}
SESSIONS = headers["x-sessionkey"] ? headers["x-sessionkey"] : SESSIONS;
return { data, isRecentlyCompleted: false };
} catch (nativeError) {
const error = nativeError as AxiosError;
return { data: null, isRecentlyCompleted: false, error: error };
}
}
export async function getAndParceData(props: GetDataProps) {
if (!props.quizId) throw new Error("No quiz id");
const response = await getData(props);
2024-05-31 16:41:18 +00:00
const quizDataResponse = response.data;
if (response.error) {
2025-05-20 10:56:34 +00:00
const axiosError = response.error as AxiosError;
if (axiosError.response?.data) {
throw new Error(
typeof axiosError.response.data === "string"
? axiosError.response.data
: JSON.stringify(axiosError.response.data)
);
}
throw axiosError;
2024-05-31 16:41:18 +00:00
}
if (!quizDataResponse) {
throw new Error("Quiz not found");
}
//Парсим строки в строках
2024-05-31 16:41:18 +00:00
const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse));
//Единоразово стрингифаим ВСЁ распаршенное и удаляем лишние пробелы
2024-05-31 16:41:18 +00:00
const res = JSON.parse(
JSON.stringify({ data: quizSettings })
.replaceAll(/\\" \\"/g, '""')
.replaceAll(/" "/g, '""')
).data as QuizSettings;
res.recentlyCompleted = response.isRecentlyCompleted;
return res;
}
2024-04-17 16:08:40 +00:00
type SendAnswerProps = {
2024-05-31 16:41:18 +00:00
questionId: string;
body: string | string[];
qid: string;
preview?: boolean;
2024-05-01 08:12:06 +00:00
};
2024-04-17 16:08:40 +00:00
export function sendAnswer({ questionId, body, qid, preview = false }: SendAnswerProps) {
2024-05-31 16:41:18 +00:00
if (preview) return;
const formData = new FormData();
const answers = [
{
question_id: questionId,
//Для АИ квизов нельзя слать пустые строки
content: statusOfQuiz != "ai" ? body : body.length ? body : "-", //тут массив с ответом
2024-05-31 16:41:18 +00:00
},
];
formData.append("answers", JSON.stringify(answers));
formData.append("qid", qid);
return publicationMakeRequest({
2024-06-02 09:55:23 +00:00
url: domain + `/answer/v1.0.0/answer`,
2024-05-31 16:41:18 +00:00
body: formData,
method: "POST",
});
}
//body ={file, filename}
2024-04-17 16:08:40 +00:00
type SendFileParams = {
2024-05-31 16:41:18 +00:00
questionId: string;
body: {
name: string;
file: File;
preview: boolean;
};
qid: string;
2024-05-01 08:12:06 +00:00
};
2024-04-17 16:08:40 +00:00
type Answer = {
2024-05-31 16:41:18 +00:00
question_id: string;
content: string;
2024-04-17 16:08:40 +00:00
};
export function sendFile({ questionId, body, qid }: SendFileParams) {
2024-05-31 16:41:18 +00:00
if (body.preview) return;
const formData = new FormData();
2024-08-28 00:18:19 +00:00
const file = new File([body.file], body.file.name.replace(/\s/g, "_"));
const nameImage = body.name.replace(/\s/g, "_");
2024-05-31 16:41:18 +00:00
const answers: Answer[] = [
{
question_id: questionId,
2024-08-28 00:18:19 +00:00
content: "file:" + nameImage,
2024-05-31 16:41:18 +00:00
},
];
formData.append("answers", JSON.stringify(answers));
2024-08-28 00:18:19 +00:00
formData.append(nameImage, file);
2024-05-31 16:41:18 +00:00
formData.append("qid", qid);
return publicationMakeRequest({
2024-06-02 09:55:23 +00:00
url: domain + `/answer/v1.0.0/answer`,
2024-05-31 16:41:18 +00:00
body: formData,
method: "POST",
});
}
//форма контактов
2024-04-17 16:08:40 +00:00
export type SendFCParams = {
2024-05-31 16:41:18 +00:00
questionId: string;
body: {
name?: string;
email?: string;
phone?: string;
address?: string;
customs?: Record<string, string>;
};
qid: string;
preview: boolean;
2024-05-01 08:12:06 +00:00
};
2024-04-17 16:08:40 +00:00
export function sendFC({ questionId, body, qid, preview }: SendFCParams) {
2024-05-31 16:41:18 +00:00
if (preview) return;
const formData = new FormData();
// const keysBody = Object.keys(body)
// const content:any = {}
// fields.forEach((key) => {
// if (keysBody.includes(key)) content[key] = body.key
// })
const answers = [
{
question_id: questionId,
content: JSON.stringify(body),
result: true,
qid,
},
];
formData.append("answers", JSON.stringify(answers));
formData.append("qid", qid);
return publicationMakeRequest({
2024-06-02 09:55:23 +00:00
url: domain + `/answer/v1.0.0/answer`,
2024-05-31 16:41:18 +00:00
body: formData,
method: "POST",
});
2024-01-29 11:16:21 +00:00
}
2024-10-23 19:48:26 +00:00
//форма контактов
export type SendResultParams = {
questionId: string;
pointsSum: number;
qid: string;
preview: boolean;
};
export function sendResult({ questionId, pointsSum, qid, preview }: SendResultParams) {
if (preview) return;
const formData = new FormData();
// const keysBody = Object.keys(body)
// const content:any = {}
// fields.forEach((key) => {
// if (keysBody.includes(key)) content[key] = body.key
// })
const answers = [
{
question_id: questionId,
content: pointsSum.toString(),
result: false,
qid,
},
];
formData.append("answers", JSON.stringify(answers));
formData.append("qid", qid);
return publicationMakeRequest({
url: domain + `/answer/v1.0.0/answer`,
body: formData,
method: "POST",
});
}