diff --git a/lib/api/quizRelase.ts b/lib/api/quizRelase.ts index 92ce9dd..62c47e2 100644 --- a/lib/api/quizRelase.ts +++ b/lib/api/quizRelase.ts @@ -79,16 +79,28 @@ export const publicationMakeRequest = ({ url, body }: PublicationMakeRequestPara let globalStatus: string | null = null; let isFirstRequest = true; -export async function getData({ quizId }: { quizId: string }): Promise<{ +/* +если запросить 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; }> { const body = { quiz_id: quizId, - limit: 100, - page: 0, - need_config: true, + limit, + page, + need_config: needConfig, } as any; if (paudParam) body.auditory = Number(paudParam); @@ -111,7 +123,12 @@ export async function getData({ quizId }: { quizId: string }): Promise<{ const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); //Тут ещё проверка на антифрод без парса конфига. Нам не интересно время если не нужно запрещать проходить чаще чем в сутки - if (typeof sessions[quizId] === "number" && data.settings.cfg.includes('antifraud":true')) { + 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 }; @@ -128,113 +145,10 @@ export async function getData({ quizId }: { quizId: string }): Promise<{ } } -export async function getDataSingle({ quizId, page }: { quizId: string; page?: number }): Promise<{ - data: GetQuizDataResponse | null; - isRecentlyCompleted: boolean; - error?: AxiosError; -}> { - try { - // Первый запрос: 1 вопрос + конфиг - if (isFirstRequest) { - const { data, headers } = await axios( - 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: { - quiz_id: quizId, - limit: 1, - page: 0, - need_config: true, - }, - } - ); +export async function getAndParceData(props: GetDataProps) { + if (!props.quizId) throw new Error("No quiz id"); - globalStatus = data.settings.status; - isFirstRequest = false; - SESSIONS = headers["x-sessionkey"] || SESSIONS; - - // Проверка антифрода - const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); - if (typeof sessions[quizId] === "number" && data.settings.cfg.includes('antifraud":true')) { - if (Date.now() - sessions[quizId] < 86400000) { - return { data, isRecentlyCompleted: true }; - } - } - - // Если статус не AI - сразу делаем запрос за всеми вопросами - if (globalStatus !== "ai") { - const secondResponse = await axios( - 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: { - quiz_id: quizId, - limit: 100, - page: 0, - need_config: false, - }, - } - ); - return { - data: { ...data, items: secondResponse.data.items }, - isRecentlyCompleted: false, - }; - } - - return { data, isRecentlyCompleted: false }; - } - - // Последующие запросы - const response = await axios(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: { - quiz_id: quizId, - limit: 1, - page: page, - need_config: false, - }, - }); - - return { - data: response.data, - isRecentlyCompleted: false, - }; - } catch (error) { - return { - data: null, - isRecentlyCompleted: false, - error: error as AxiosError, - }; - } -} -export async function getQuizData({ quizId, status = "" }: { quizId: string; status?: string }) { - if (!quizId) throw new Error("No quiz id"); - - const response = await getData({ quizId }); + const response = await getData(props); const quizDataResponse = response.data; if (response.error) { @@ -252,8 +166,10 @@ export async function getQuizData({ quizId, status = "" }: { quizId: string; sta throw new Error("Quiz not found"); } + //Парсим строки в строках const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse)); + //Единоразово стрингифаим ВСЁ распаршенное и удаляем лишние пробелы const res = JSON.parse( JSON.stringify({ data: quizSettings }) .replaceAll(/\\" \\"/g, '""') @@ -263,124 +179,6 @@ export async function getQuizData({ quizId, status = "" }: { quizId: string; sta return res; } -let page = 1; - -export async function getQuizDataAI(quizId: string) { - console.log("[getQuizDataAI] Starting with quizId:", quizId); // Добавлено - let maxRetries = 50; - - if (!quizId) { - console.error("[getQuizDataAI] Error: No quiz id provided"); - throw new Error("No quiz id"); - } - - let lastError: Error | null = null; - let responseData: any = null; - - // Первый цикл - обработка result вопросов - console.log("[getQuizDataAI] Starting result retries loop"); // Добавлено - let resultRetryCount = 0; - while (resultRetryCount < maxRetries) { - try { - console.log(`[getQuizDataAI] Attempt ${resultRetryCount + 1} for result questions, page: ${page}`); - const response = await getData({ quizId }); - console.log("[getQuizDataAI] Response from getData:", response); - - if (response.error) { - console.error("[getQuizDataAI] Error in response:", response.error); - throw response.error; - } - if (!response.data) { - console.error("[getQuizDataAI] Error: Quiz not found"); - throw new Error("Quiz not found"); - } - - const hasAiResult = response.data.items.some((item) => item.typ === "result"); - console.log("[getQuizDataAI] Has AI result:", hasAiResult); - - if (hasAiResult) { - page++; - resultRetryCount++; - console.log(`[getQuizDataAI] Found result question, incrementing page to ${page}`); - continue; - } - - responseData = response; - console.log("[getQuizDataAI] Found non-result questions, breaking loop"); - break; - } catch (error) { - lastError = error as Error; - resultRetryCount++; - console.error(`[getQuizDataAI] Error in attempt ${resultRetryCount}:`, error); - - if (resultRetryCount >= maxRetries) { - console.error("[getQuizDataAI] Max retries reached for result questions"); - break; - } - - const delay = 1500 * resultRetryCount; - console.log(`[getQuizDataAI] Waiting ${delay}ms before next retry`); - await new Promise((resolve) => setTimeout(resolve, delay)); - } - } - - if (!responseData) { - console.error("[getQuizDataAI] Failed after result retries, throwing error"); - throw lastError || new Error("Failed to get quiz data after result retries"); - } - - // Второй цикл - обработка пустого массива - console.log("[getQuizDataAI] Starting empty items retry loop"); // Добавлено - let isEmpty = !responseData.data?.items.length; - let emptyRetryCount = 0; - - while (isEmpty && emptyRetryCount < maxRetries) { - try { - console.log(`[getQuizDataAI] Empty items retry ${emptyRetryCount + 1}`); - await new Promise((resolve) => setTimeout(resolve, 1000)); - const response = await getData({ quizId }); - - if (response.error) { - console.error("[getQuizDataAI] Error in empty items check:", response.error); - throw response.error; - } - if (!response.data) { - console.error("[getQuizDataAI] Error: Quiz not found in empty check"); - throw new Error("Quiz not found"); - } - - isEmpty = !response.data.items.length; - console.log("[getQuizDataAI] Is items empty:", isEmpty); - - if (!isEmpty) { - responseData = response; - console.log("[getQuizDataAI] Found non-empty items, updating responseData"); - } - emptyRetryCount++; - } catch (error) { - lastError = error as Error; - emptyRetryCount++; - console.error(`[getQuizDataAI] Error in empty check attempt ${emptyRetryCount}:`, error); - - if (emptyRetryCount >= maxRetries) { - console.error("[getQuizDataAI] Max empty retries reached"); - break; - } - } - } - - if (isEmpty) { - console.error("[getQuizDataAI] Items still empty after retries"); - throw new Error("Items array is empty after maximum retries"); - } - - // Финальная обработка - console.log("[getQuizDataAI] Processing final response data"); - - console.log("[getQuizDataAI] Final response before return:", responseData); - return responseData.data.items; -} - type SendAnswerProps = { questionId: string; body: string | string[]; @@ -389,8 +187,6 @@ type SendAnswerProps = { }; export function sendAnswer({ questionId, body, qid, preview = false }: SendAnswerProps) { - console.log("qid"); - console.log(qid); if (preview) return; const formData = new FormData(); diff --git a/lib/model/api/getQuizData.ts b/lib/model/api/getQuizData.ts index 384ef1b..c701641 100644 --- a/lib/model/api/getQuizData.ts +++ b/lib/model/api/getQuizData.ts @@ -3,7 +3,7 @@ import { QuizSettings } from "@model/settingsData"; export interface GetQuizDataResponse { cnt: number; - settings: { + settings?: { fp: boolean; rep: boolean; name: string; @@ -27,6 +27,13 @@ export interface GetQuizDataResponse { } export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit { + const readyData = { + cnt: quizDataResponse.cnt, + show_badge: quizDataResponse.show_badge, + settings: {} as QuizSettings["settings"], + questions: [] as QuizSettings["questions"], + } as QuizSettings; + const items: QuizSettings["questions"] = quizDataResponse.items.map((item) => { const content = JSON.parse(item.c); @@ -41,17 +48,21 @@ export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit