From 9fa4a0c113ffcfdedc4292cb2fa70871ca81a71f Mon Sep 17 00:00:00 2001 From: bootunloader Date: Wed, 31 Dec 2025 08:08:55 +0200 Subject: [PATCH] convertified --- pyapi/start.sh | 7 + .../server/external/api.scraping.helpers.ts | 537 ++++++++--------- src/lib/server/postdata/post.handler.ts | 564 +++++++++--------- src/lib/trpc/routers/apiauth.router.ts | 204 +++---- src/lib/utils/constants.ts | 1 + 5 files changed, 637 insertions(+), 676 deletions(-) create mode 100755 pyapi/start.sh diff --git a/pyapi/start.sh b/pyapi/start.sh new file mode 100755 index 0000000..3ac5744 --- /dev/null +++ b/pyapi/start.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# FastAPI Proxy Server Startup Script +# This script starts the FastAPI proxy server that bypasses Cloudflare + +echo "Starting FastAPI Proxy Server on port 3070..." +uv run python -m fastapi dev --port=3070 main.py diff --git a/src/lib/server/external/api.scraping.helpers.ts b/src/lib/server/external/api.scraping.helpers.ts index 24ad727..fb9d91b 100755 --- a/src/lib/server/external/api.scraping.helpers.ts +++ b/src/lib/server/external/api.scraping.helpers.ts @@ -1,4 +1,4 @@ -import { getRandomUserAgent, getULID, sleep } from "$lib/utils"; +import { getULID, sleep } from "$lib/utils"; import { constants } from "$lib/utils/constants"; import type { BookingEntry, Draw, LooseApiUser } from "$lib/utils/data.types"; import { rng } from "$lib/utils/rng"; @@ -13,317 +13,300 @@ import { rng } from "$lib/utils/rng"; // } export const testIfSessionIsValid = async (jwt: string) => { - try { - const res = await fetch( - `${constants.SCRAP_API_URL}/v1/user/get-balance?userId=6339`, - { - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Authorization: jwt, - "User-Agent": getRandomUserAgent(), - }, - }, - ); - if (res.status !== 200) { - return false; - } - const rj = (await res.json()) as { - code: number; - success: boolean; - message: string; - data: any; - time: string; - }; - return rj.code == 200 && rj.success; - } catch (err) { - console.log(err); - return false; + try { + const res = await fetch( + `${constants.PROXY_API_URL}/v1/user/get-balance?userId=6339&authorization=${encodeURIComponent(jwt)}`, + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + if (res.status !== 200) { + return false; } + const rj = (await res.json()) as { + code: number; + success: boolean; + message: string; + data: any; + time: string; + }; + return rj.code == 200 && rj.success; + } catch (err) { + console.log(err); + return false; + } }; export const getSessionToken = async (payload: { - userId: string; - password: string; - verifyToken: string; - code: string; - userType: number; + userId: string; + password: string; + verifyToken: string; + code: string; + userType: number; }): Promise<{ ok: boolean; message: string }> => { - console.log("Requesting..."); - const res = await fetch(`${constants.SCRAP_API_URL}/v1/auth/login`, { - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - "User-Agent": getRandomUserAgent(), - "Content-Type": "application/json", - }, - body: JSON.stringify(payload), - }); - const out = await res.json(); - if (out.code !== 200) { - return { ok: false, message: out.message }; - } - return { ok: true, message: out.data.token }; + console.log("Requesting..."); + const res = await fetch(`${constants.PROXY_API_URL}/v1/auth/login`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); + const out = await res.json(); + if (out.code !== 200) { + return { ok: false, message: out.message }; + } + return { ok: true, message: out.data.token }; }; export async function getUsersBalance(userId: number, jwt: string) { - try { - const res = await fetch( - `${constants.SCRAP_API_URL}/v1/user/get-balance?userId=${userId}`, - { - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Authorization: jwt, - "User-Agent": getRandomUserAgent(), - }, - }, - ); - const rj = (await res.json()) as { - code: number; - success: boolean; - message: string; - data: { allowedBalance: number; balance: number }; - time: string; - }; - if (res.status !== 200 || rj.code !== 200 || !rj.success) { - console.log( - `[!] Error getting balance for ${userId} :: ${JSON.stringify(rj)}`, - ); - return false; - } - return rj.data.balance; - } catch (err) { - console.log(err); - return false; + try { + const res = await fetch( + `${constants.PROXY_API_URL}/v1/user/get-balance?userId=${userId}&authorization=${encodeURIComponent(jwt)}`, + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + const rj = (await res.json()) as { + code: number; + success: boolean; + message: string; + data: { allowedBalance: number; balance: number }; + time: string; + }; + if (res.status !== 200 || rj.code !== 200 || !rj.success) { + console.log(`[!] Error getting balance for ${userId} :: ${JSON.stringify(rj)}`); + return false; } + return rj.data.balance; + } catch (err) { + console.log(err); + return false; + } } export const getDealers = async (jwt: string, distributor_ids: string[]) => { - try { - // // Create an array of promises for each fetch request - const requests = distributor_ids.map(async (did) => { - await sleep(rng(100, 10000)); - const res = await fetch( - `${constants.SCRAP_API_URL}/v1/user/dealer-list`, - { - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - "Content-Type": "application/json", - "User-Agent": getRandomUserAgent(), - Authorization: jwt, - }, - body: JSON.stringify({ - page: 1, - pageSize: 999999, - parentDistributor: parseInt(did), - }), - }, - ); - const data = (await res.json()) as { - code: number; - success: boolean; - message: string; - data: { - items: any[]; - total: number; - }; - }; - if (data.code !== 200 || !data.success) { - return { - dealers: [], - ok: false, - code: data.code, - message: data.message, - }; - } - const dealers = data.data.items.map((item) => item.dealer); - - // dumpDealers(dealers); - - return { - dealers, - ok: res.status === 200 && data.success, - code: data.code, - message: data.message, - }; - }); - // // Wait for all promises to resolve - const responses = await Promise.all(requests); - const dealers: LooseApiUser[] = []; - const errors: { message: string }[] = []; - for (const res of responses) { - if (res.code !== 200 || !res.ok) { - errors.push({ message: res.message }); - continue; - } - for (const dealer of res.dealers) { - dealers.push(dealer); - } - } - - // fs.writeFileSync("dealers.json", JSON.stringify(dealers, null, 2)); - - return { dealers, errors }; - } catch (err) { - console.error(err); - return { - dealers: [], - errors: [{ message: "An error occured during fetching dealers" }], + try { + // // Create an array of promises for each fetch request + const requests = distributor_ids.map(async (did) => { + await sleep(rng(100, 10000)); + const res = await fetch( + `${constants.PROXY_API_URL}/v1/user/dealer-list?authorization=${encodeURIComponent(jwt)}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + page: 1, + pageSize: 999999, + parentDistributor: parseInt(did), + }), + }, + ); + const data = (await res.json()) as { + code: number; + success: boolean; + message: string; + data: { + items: any[]; + total: number; }; + }; + if (data.code !== 200 || !data.success) { + return { + dealers: [], + ok: false, + code: data.code, + message: data.message, + }; + } + const dealers = data.data.items.map((item) => item.dealer); + + // dumpDealers(dealers); + + return { + dealers, + ok: res.status === 200 && data.success, + code: data.code, + message: data.message, + }; + }); + // // Wait for all promises to resolve + const responses = await Promise.all(requests); + const dealers: LooseApiUser[] = []; + const errors: { message: string }[] = []; + for (const res of responses) { + if (res.code !== 200 || !res.ok) { + errors.push({ message: res.message }); + continue; + } + for (const dealer of res.dealers) { + dealers.push(dealer); + } } + + // fs.writeFileSync("dealers.json", JSON.stringify(dealers, null, 2)); + + return { dealers, errors }; + } catch (err) { + console.error(err); + return { + dealers: [], + errors: [{ message: "An error occured during fetching dealers" }], + }; + } }; export const getDistributors = async (jwt: string) => { - const res = await fetch( - `${constants.SCRAP_API_URL}/v1/user/distributor-list`, - { - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Authorization: jwt, - "Content-Type": "application/json", - "User-Agent": getRandomUserAgent(), - }, - body: JSON.stringify({ - page: 1, - pageSize: 999999, - parentDistributor: 15, - }), - }, - ); - const json = (await res.json()) as { - code: number; - success: boolean; - message: string; - data: { total: number; items: any[] }; - }; + const res = await fetch( + `${constants.PROXY_API_URL}/v1/user/distributor-list?authorization=${encodeURIComponent(jwt)}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + page: 1, + pageSize: 999999, + parentDistributor: 15, + }), + }, + ); + const json = (await res.json()) as { + code: number; + success: boolean; + message: string; + data: { total: number; items: any[] }; + }; - if (!json.data.items || json.code !== 200 || !json.success) { - return { ok: false, message: json.message, data: [] }; - } + if (!json.data.items || json.code !== 200 || !json.success) { + return { ok: false, message: json.message, data: [] }; + } - // fs.writeFileSync( - // "distributors.json", - // JSON.stringify(json.data.items, null, 2), - // ); + // fs.writeFileSync( + // "distributors.json", + // JSON.stringify(json.data.items, null, 2), + // ); - // dumpDistributors(json.data.items.map((item) => item.distributor)); + // dumpDistributors(json.data.items.map((item) => item.distributor)); - return { - ok: true, - message: "", - data: json.data.items.map((item) => item.distributor), - }; + return { + ok: true, + message: "", + data: json.data.items.map((item) => item.distributor), + }; }; export const getDraws = async (jwt: string) => { - const res = await fetch( - `${constants.SCRAP_API_URL}/v1/draw/list-my?userId=15`, - { - method: "GET", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Authorization: jwt, - "Content-Type": "application/json", - "User-Agent": getRandomUserAgent(), - }, - }, - ); - type J = { - code: number; - success: boolean; - message: string; - data: { draw: Draw }[]; - }; - let decoded = (await res.json()) as { data: J }; - const json = (decoded.data.success ? decoded.data : decoded) as any as J; - if (json.code !== 200 || !json.success || !json.data) { - return { ok: false, message: json.message, data: [] }; - } - return { - ok: true, - message: "", - data: json.data.map((item) => item.draw), - }; + const res = await fetch( + `${constants.PROXY_API_URL}/v1/draw/list-my?userId=15&authorization=${encodeURIComponent(jwt)}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ); + type J = { + code: number; + success: boolean; + message: string; + data: { draw: Draw }[]; + }; + let decoded = (await res.json()) as { data: J }; + const json = (decoded.data.success ? decoded.data : decoded) as any as J; + if (json.code !== 200 || !json.success || !json.data) { + return { ok: false, message: json.message, data: [] }; + } + return { + ok: true, + message: "", + data: json.data.map((item) => item.draw), + }; }; export const getData = async ( - jwt: string, - userIds: number[], - drawId: number, - chosenDate: string, + jwt: string, + userIds: number[], + drawId: number, + chosenDate: string, ) => { - const res = await fetch(`${constants.SCRAP_API_URL}/v1/book/list2`, { - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Authorization: jwt, - "Content-Type": "application/json", - "User-Agent": getRandomUserAgent(), - }, - body: JSON.stringify({ - userType: 3, - userIds, - drawId: drawId, - startDate: chosenDate, - endDate: chosenDate, - beAdmin: false, - containImported: false, - keyword: "", - }), - }); - type J = { - code: number; - success: boolean; - message: string; - data: { book: BookingEntry; user: any }[]; - }; - let decoded = (await res.json()) as { data: J }; - const json = (decoded.data.success ? decoded.data : decoded) as any as J; - if (json.code !== 200 || !json.success || !json.data) { - return { ok: false, message: json.message, data: [] }; - } - return { ok: true, message: "", data: json.data.map((e) => e.book) }; + const res = await fetch( + `${constants.PROXY_API_URL}/v1/book/list2?authorization=${encodeURIComponent(jwt)}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userType: 3, + userIds, + drawId: drawId, + startDate: chosenDate, + endDate: chosenDate, + beAdmin: false, + containImported: false, + keyword: "", + }), + }, + ); + type J = { + code: number; + success: boolean; + message: string; + data: { book: BookingEntry; user: any }[]; + }; + let decoded = (await res.json()) as { data: J }; + const json = (decoded.data.success ? decoded.data : decoded) as any as J; + if (json.code !== 200 || !json.success || !json.data) { + return { ok: false, message: json.message, data: [] }; + } + return { ok: true, message: "", data: json.data.map((e) => e.book) }; }; export const mockGetUserData = async ( - jwt: string, - userIds: number[], - drawId: number, - chosenDate: string, + jwt: string, + userIds: number[], + drawId: number, + chosenDate: string, ) => { - const entries = [] as BookingEntry[]; + const entries = [] as BookingEntry[]; - const rng = (min: number, max: number) => { - return Math.floor(Math.random() * (max - min + 1)) + min; - }; - const randomCeil = rng(10_000, 200_000); + const rng = (min: number, max: number) => { + return Math.floor(Math.random() * (max - min + 1)) + min; + }; + const randomCeil = rng(10_000, 200_000); - await sleep(rng(100, 1000)); + await sleep(rng(100, 1000)); - for (let i = 0; i < randomCeil; i++) { - const _f = rng(5, 50); - const _s = rng(5, 50); - const f = _f - (_f % 5); - const s = _s - (_s % 5); + for (let i = 0; i < randomCeil; i++) { + const _f = rng(5, 50); + const _s = rng(5, 50); + const f = _f - (_f % 5); + const s = _s - (_s % 5); - entries.push({ - id: getULID(), - bookDate: chosenDate, - changedBalance: f + s, - first: f, - second: s, - dealerId: userIds[rng(0, userIds.length - 1)], - distributorId: 6339, - drawId: drawId, - number: rng(0, 9999).toString(), - requestId: new Date().getTime().toString(), - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - sheetId: "0", - sheetName: "", - }); - } + entries.push({ + id: getULID(), + bookDate: chosenDate, + changedBalance: f + s, + first: f, + second: s, + dealerId: userIds[rng(0, userIds.length - 1)], + distributorId: 6339, + drawId: drawId, + number: rng(0, 9999).toString(), + requestId: new Date().getTime().toString(), + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + sheetId: "0", + sheetName: "", + }); + } - return { ok: true, message: "", data: entries }; + return { ok: true, message: "", data: entries }; }; diff --git a/src/lib/server/postdata/post.handler.ts b/src/lib/server/postdata/post.handler.ts index e235aed..3e6d32b 100644 --- a/src/lib/server/postdata/post.handler.ts +++ b/src/lib/server/postdata/post.handler.ts @@ -1,334 +1,312 @@ -import { getRandomUserAgent, getULID, sleep } from "$lib/utils"; +import { getULID, sleep } from "$lib/utils"; import { constants } from "$lib/utils/constants"; import type { - ApiPostUserWithParent, - APISession, - Draw, - PostDataEntry, - ServerError, + ApiPostUserWithParent, + APISession, + Draw, + PostDataEntry, + ServerError, } from "$lib/utils/data.types"; -import Fetch from "node-fetch"; -import { HttpsProxyAgent } from "https-proxy-agent"; export type APIResponse = { - code: number; - success: boolean; - message: string; - data: T; - time: string; + code: number; + success: boolean; + message: string; + data: T; + time: string; }; export function buildMessageString( - ptr: number, - rows: PostDataEntry[], - distributorId: number, - dealerId: number, - drawId: number, - date: string, + ptr: number, + rows: PostDataEntry[], + distributorId: number, + dealerId: number, + drawId: number, + date: string, ) { - let message = ""; - let jumpSize = Math.floor(Math.random() * 490) + 10; - let total = 0; - let startReqId = new Date().getTime(); - let x = 0; - for (let j = ptr; j < ptr + jumpSize; j++) { - if (j >= rows.length) { - break; - } - const row = rows[j]; - const reqId = startReqId + x++; - const no = row.number.trim(); - const f = row.first; - const s = row.second; - const mTotal = f + s; - if (mTotal <= 0) { - continue; - } - total += mTotal; - message += `${reqId},${distributorId},${dealerId},${drawId},${date},${no},${f},${s},${mTotal};`; + let message = ""; + let jumpSize = Math.floor(Math.random() * 490) + 10; + let total = 0; + let startReqId = new Date().getTime(); + let x = 0; + for (let j = ptr; j < ptr + jumpSize; j++) { + if (j >= rows.length) { + break; } - message = message.slice(0, -1); - return { message, total, jumped: ptr + jumpSize }; + const row = rows[j]; + const reqId = startReqId + x++; + const no = row.number.trim(); + const f = row.first; + const s = row.second; + const mTotal = f + s; + if (mTotal <= 0) { + continue; + } + total += mTotal; + message += `${reqId},${distributorId},${dealerId},${drawId},${date},${no},${f},${s},${mTotal};`; + } + message = message.slice(0, -1); + return { message, total, jumped: ptr + jumpSize }; } export async function postDataToApi(payload: { - sessions: Record; - draw: Draw; - data: PostDataEntry[]; - users: ApiPostUserWithParent[]; + sessions: Record; + draw: Draw; + data: PostDataEntry[]; + users: ApiPostUserWithParent[]; }) { - const responses = [] as APIResponse<[]>[]; - const responsesIds = [] as { requestId: number; bookId: string }[]; - let failedResponses = 0; - let successResponses = 0; + const responses = [] as APIResponse<[]>[]; + const responsesIds = [] as { requestId: number; bookId: string }[]; + let failedResponses = 0; + let successResponses = 0; - console.log(`[+] Sending ${payload.data.length} requests...`); + console.log(`[+] Sending ${payload.data.length} requests...`); - const dataByUser = {} as Record; - for (const row of payload.data) { - const userId = row.userId ?? ""; - if (userId.length < 1) { - console.log(`[!] User not found for request ${row.userId}`); - return { - ok: false, - detail: "User not found to post data with", - errors: [ - { message: "User not found for request" }, - ] as ServerError, - }; - } - if (!dataByUser[userId]) { - dataByUser[userId] = []; - } - dataByUser[userId].push(row); + const dataByUser = {} as Record; + for (const row of payload.data) { + const userId = row.userId ?? ""; + if (userId.length < 1) { + console.log(`[!] User not found for request ${row.userId}`); + return { + ok: false, + detail: "User not found to post data with", + errors: [{ message: "User not found for request" }] as ServerError, + }; } + if (!dataByUser[userId]) { + dataByUser[userId] = []; + } + dataByUser[userId].push(row); + } - try { - const userPromises = Object.entries(dataByUser).map( - async ([userId, userData]) => { - const session = payload.sessions[userId]; - const usr = payload.users.find((u) => u.userId === userId); - if (!usr) { - throw new Error( - `User ${userId} not found for posting to api`, - ); - } + try { + const userPromises = Object.entries(dataByUser).map(async ([userId, userData]) => { + const session = payload.sessions[userId]; + const usr = payload.users.find((u) => u.userId === userId); + if (!usr) { + throw new Error(`User ${userId} not found for posting to api`); + } - const distId = usr.parentDistributor ?? 0; - const dealerId = Number(session.userId.split(":")[1]); - const drawId = Number(payload.draw.id.split(":")[1]); - const date = new Date().toISOString().split("T")[0]; + const distId = usr.parentDistributor ?? 0; + const dealerId = Number(session.userId.split(":")[1]); + const drawId = Number(payload.draw.id.split(":")[1]); + const date = new Date().toISOString().split("T")[0]; - let ptr = 0; - const userResponseIds = [] as { - requestId: number; - bookId: string; + let ptr = 0; + const userResponseIds = [] as { + requestId: number; + bookId: string; + }[]; + + while (ptr < userData.length) { + let tries = 0; + while (tries < 3) { + let { message, total, jumped } = buildMessageString( + ptr, + userData, + distId, + dealerId, + drawId, + date, + ); + const res = await sendBatchRequest(session, dealerId, payload.draw, total, message); + let rj: + | APIResponse<{ + bookDtos: { + bookId: string; + requestId: number; }[]; - - while (ptr < userData.length) { - let tries = 0; - while (tries < 3) { - let { message, total, jumped } = buildMessageString( - ptr, - userData, - distId, - dealerId, - drawId, - date, - ); - const res = await sendBatchRequest( - session, - dealerId, - payload.draw, - total, - message, - ); - let rj: - | APIResponse<{ - bookDtos: { - bookId: string; - requestId: number; - }[]; - }> - | undefined = undefined; - try { - rj = (await res.json()) as any; - } catch (err) { - console.log( - "Encountered error while parsing post response", - ); - console.log(res.status, err); - } - if (rj && rj.code === 200 && res.status === 200) { - ptr = jumped; - userResponseIds.push( - ...rj.data.bookDtos.map((b) => ({ - requestId: b.requestId as number, - bookId: b.bookId as string, - })), - ); - successResponses++; - break; - } - console.log("Failed to send send post request"); - console.log(res.status, rj); - failedResponses++; - tries++; - } - - if (tries >= 3) { - if (userResponseIds.length > 0) { - const out = await deleteAllBookedEntries({ - data: userResponseIds, - closeTime: payload.draw.closeTime, - dealerId, - drawId, - session, - }); - console.log(await out.text()); - } - throw new Error( - `Failed to send data to api for user ${userId}`, - ); - } - } - return userResponseIds; - }, - ); - - // Wait for all user processes to complete - const results = await Promise.allSettled(userPromises); - - // Process results - let hasErrors = false; - results.forEach((result) => { - if (result.status === "fulfilled") { - responsesIds.push(...result.value); - } else { - hasErrors = true; - console.log(`[!] Error processing user`); - console.log(result.reason); - } - }); - - if (hasErrors) { - return { - ok: false, - detail: "Failed to post data to API for some users", - errors: [ - { message: "Failed to post data to API for some users" }, - ] as ServerError, - }; + }> + | undefined = undefined; + try { + rj = (await res.json()) as any; + } catch (err) { + console.log("Encountered error while parsing post response"); + console.log(res.status, err); + } + if (rj && rj.code === 200 && res.status === 200) { + ptr = jumped; + userResponseIds.push( + ...rj.data.bookDtos.map((b) => ({ + requestId: b.requestId as number, + bookId: b.bookId as string, + })), + ); + successResponses++; + break; + } + console.log("Failed to send send post request"); + console.log(res.status, rj); + failedResponses++; + tries++; } - console.log(`[+] Finished sending ${payload.data.length} requests`); - console.log(`[?] Failed responses: ${failedResponses}`); - console.log(`[?] Success responses: ${successResponses}`); - return { - ok: true, - detail: "Successfully sent data to api", - data: responses, - }; - } catch (err) { - console.log(err); - return { - ok: false, - detail: "Failed to send data to api", - }; + if (tries >= 3) { + if (userResponseIds.length > 0) { + const out = await deleteAllBookedEntries({ + data: userResponseIds, + closeTime: payload.draw.closeTime, + dealerId, + drawId, + session, + }); + console.log(await out.text()); + } + throw new Error(`Failed to send data to api for user ${userId}`); + } + } + return userResponseIds; + }); + + // Wait for all user processes to complete + const results = await Promise.allSettled(userPromises); + + // Process results + let hasErrors = false; + results.forEach((result) => { + if (result.status === "fulfilled") { + responsesIds.push(...result.value); + } else { + hasErrors = true; + console.log(`[!] Error processing user`); + console.log(result.reason); + } + }); + + if (hasErrors) { + return { + ok: false, + detail: "Failed to post data to API for some users", + errors: [{ message: "Failed to post data to API for some users" }] as ServerError, + }; } + + console.log(`[+] Finished sending ${payload.data.length} requests`); + console.log(`[?] Failed responses: ${failedResponses}`); + console.log(`[?] Success responses: ${successResponses}`); + return { + ok: true, + detail: "Successfully sent data to api", + data: responses, + }; + } catch (err) { + console.log(err); + return { + ok: false, + detail: "Failed to send data to api", + }; + } } async function sendBatchRequest( - session: APISession, - dealerId: number, - draw: Draw, - changedBalance: number, - body: string, + session: APISession, + dealerId: number, + draw: Draw, + changedBalance: number, + body: string, ) { - return Fetch(`${constants.SCRAP_API_URL}/v1/book/add-multiple`, { - agent: new HttpsProxyAgent(`http://${session.ip}`), - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - "Content-Type": "application/json;charset=UTF-8", - Authorization: session.sessionToken, - "User-Agent": getRandomUserAgent(), - }, - body: JSON.stringify({ - dealerId, - drawId: Number(draw.id.split(":")[1]), - closeTime: draw.closeTime, - date: new Date().toISOString().split("T")[0], - changedBalance, - insertData: body, - }), - }); + return fetch( + `${constants.PROXY_API_URL}/v1/book/add-multiple?authorization=${encodeURIComponent(session.sessionToken)}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + dealerId, + drawId: Number(draw.id.split(":")[1]), + closeTime: draw.closeTime, + date: new Date().toISOString().split("T")[0], + changedBalance, + insertData: body, + }), + }, + ); } async function mockSendBatchRequest( - session: APISession, - dealerId: number, - draw: Draw, - changedBalance: number, - body: string, + session: APISession, + dealerId: number, + draw: Draw, + changedBalance: number, + body: string, ) { - console.log("----- Sending batch request ------"); - console.log(session); - console.log(dealerId); - console.log(draw); - console.log(changedBalance); - console.log(body); - console.log("----------------------------------"); - // between 5 to 20 ms - await sleep(Math.floor(Math.random() * 1000) + 50); - // if (Math.random() < 0.005) { - // return new Response( - // JSON.stringify({ - // code: 500, - // success: false, - // message: "Failed", - // data: {}, - // time: new Date().toISOString(), - // }), - // { - // status: 500, - // headers: { "Content-Type": "application/json" }, - // statusText: "Failed", - // }, - // ); - // } - return new Response( - JSON.stringify({ - code: 200, - success: true, - message: "Success", - data: { - bookDtos: body.split(";").map((e) => { - return { - bookId: getULID(), - requestId: +e.split(",")[0], - }; - }), - }, - time: new Date().toISOString(), + console.log("----- Sending batch request ------"); + console.log(session); + console.log(dealerId); + console.log(draw); + console.log(changedBalance); + console.log(body); + console.log("----------------------------------"); + // between 5 to 20 ms + await sleep(Math.floor(Math.random() * 1000) + 50); + // if (Math.random() < 0.005) { + // return new Response( + // JSON.stringify({ + // code: 500, + // success: false, + // message: "Failed", + // data: {}, + // time: new Date().toISOString(), + // }), + // { + // status: 500, + // headers: { "Content-Type": "application/json" }, + // statusText: "Failed", + // }, + // ); + // } + return new Response( + JSON.stringify({ + code: 200, + success: true, + message: "Success", + data: { + bookDtos: body.split(";").map((e) => { + return { + bookId: getULID(), + requestId: +e.split(",")[0], + }; }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - statusText: "OK", - }, - ); + }, + time: new Date().toISOString(), + }), + { + status: 200, + headers: { "Content-Type": "application/json" }, + statusText: "OK", + }, + ); } async function deleteAllBookedEntries({ - session, - data, - dealerId, - drawId, - closeTime, + session, + data, + dealerId, + drawId, + closeTime, }: { - session: APISession; - data: { bookId: string; requestId: number }[]; - dealerId: number; - drawId: number; - closeTime: string; + session: APISession; + data: { bookId: string; requestId: number }[]; + dealerId: number; + drawId: number; + closeTime: string; }) { - return Fetch(`${constants.SCRAP_API_URL}/v1/book/delete-multiple`, { - agent: new HttpsProxyAgent(`http://${session.ip}`), - method: "POST", - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - "Content-Type": "application/json;charset=UTF-8", - Authorization: session.sessionToken, - "User-Agent": getRandomUserAgent(), - }, - body: JSON.stringify({ - bookIds: data.map((e) => e.bookId), - closeTime, - dealerId, - drawId, - }), - }); + return fetch( + `${constants.PROXY_API_URL}/v1/book/delete-multiple?authorization=${encodeURIComponent(session.sessionToken)}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + bookIds: data.map((e) => e.bookId), + closeTime, + dealerId, + drawId, + }), + }, + ); } // export async function postDataToApi(payload: { diff --git a/src/lib/trpc/routers/apiauth.router.ts b/src/lib/trpc/routers/apiauth.router.ts index 109ac18..24e4a44 100755 --- a/src/lib/trpc/routers/apiauth.router.ts +++ b/src/lib/trpc/routers/apiauth.router.ts @@ -1,116 +1,108 @@ -import { getSessionToken } from "$lib/server/external/api.scraping.helpers"; -import { TRPCError } from "@trpc/server"; -import { createTRPCRouter, protectedProcedure } from "../t"; -import { constants } from "$lib/utils/constants"; -import { getUUID } from "$lib/utils"; -import { z } from "zod"; import { dbApiUser } from "$lib/server/db/apiuser.db"; -import type { ServerError } from "$lib/utils/data.types"; +import { getSessionToken } from "$lib/server/external/api.scraping.helpers"; import { - isSessionValidInStore, - removeSessionFromStore, - setSessionToRedis, + isSessionValidInStore, + removeSessionFromStore, + setSessionToRedis, } from "$lib/server/utils/session.service"; +import { getUUID } from "$lib/utils"; +import { constants } from "$lib/utils/constants"; +import type { ServerError } from "$lib/utils/data.types"; +import { TRPCError } from "@trpc/server"; +import { z } from "zod"; +import { createTRPCRouter, protectedProcedure } from "../t"; export const apiAuthRouter = createTRPCRouter({ - getCaptcha: protectedProcedure.mutation(async () => { - try { - const uuid = getUUID(); - const res = await fetch( - `${constants.SCRAP_API_URL}/verify/image?uuid=${uuid}`, - { - headers: { - ...constants.SCRAP_API_BASE_HEADERS, - Accept: "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", - }, - }, - ); - const bloob = await res.blob(); - const imageBuffer = Buffer.from(await bloob.arrayBuffer()); - const base64String = imageBuffer.toString("base64"); - return { id: uuid, image: base64String }; - } catch (err) { - console.log(err); - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "Error getting captcha image.", - }); + getCaptcha: protectedProcedure.mutation(async () => { + try { + const uuid = getUUID(); + const res = await fetch(`${constants.PROXY_API_URL}/verify/image?uuid=${uuid}`, { + headers: { + "Content-Type": "application/json", + }, + }); + const bloob = await res.blob(); + const imageBuffer = Buffer.from(await bloob.arrayBuffer()); + const base64String = imageBuffer.toString("base64"); + return { id: uuid, image: base64String }; + } catch (err) { + console.log(err); + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Error getting captcha image.", + }); + } + }), + + getNewSession: protectedProcedure + .input( + z.object({ + captchaId: z.string().min(1), + captchaAnswer: z.string().min(1), + userId: z.string().optional(), + }), + ) + .mutation(async ({ input }) => { + console.log("[=] Getting new session... ", input); + try { + const { captchaId, captchaAnswer } = input; + let { userId, userType, password } = await dbApiUser.getRandomDistributor(); + + if (input.userId) { + let _user = await dbApiUser.getUserById(input.userId); + console.log("[=] User :: ", _user?.userId); + if (!_user) { + return { + success: false, + errors: [{ message: "User not found." }], + }; + } + userId = _user.userId; + userType = _user.userType; + password = _user.password; } + console.log(`[=] Getting session token for user ${userId}...`); + const token = await getSessionToken({ + code: captchaAnswer, + verifyToken: captchaId, + userId: userId, + userType: userType, + password: password, + }); + console.log("[=] Token Response :: ", JSON.stringify(token, null, 2)); + if (!token.ok) { + return { + success: false, + errors: [{ message: token.message }], + }; + } + await setSessionToRedis(token.message, input.userId ?? ""); + return { success: true, errors: [] as ServerError }; + } catch (err) { + console.log(err); + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Error getting new session.", + }); + } }), - getNewSession: protectedProcedure - .input( - z.object({ - captchaId: z.string().min(1), - captchaAnswer: z.string().min(1), - userId: z.string().optional(), - }), - ) - .mutation(async ({ input }) => { - console.log("[=] Getting new session... ", input); - try { - const { captchaId, captchaAnswer } = input; - let { userId, userType, password } = - await dbApiUser.getRandomDistributor(); + isApiSessionValid: protectedProcedure + .input( + z.object({ + checkingUserSession: z.boolean(), + userId: z.string().optional(), + }), + ) + .query(async ({ input }) => { + return { valid: await isSessionValidInStore(input.userId) }; + }), - if (input.userId) { - let _user = await dbApiUser.getUserById(input.userId); - console.log("[=] User :: ", _user?.userId); - if (!_user) { - return { - success: false, - errors: [{ message: "User not found." }], - }; - } - userId = _user.userId; - userType = _user.userType; - password = _user.password; - } - console.log(`[=] Getting session token for user ${userId}...`); - const token = await getSessionToken({ - code: captchaAnswer, - verifyToken: captchaId, - userId: userId, - userType: userType, - password: password, - }); - console.log( - "[=] Token Response :: ", - JSON.stringify(token, null, 2), - ); - if (!token.ok) { - return { - success: false, - errors: [{ message: token.message }], - }; - } - await setSessionToRedis(token.message, input.userId ?? ""); - return { success: true, errors: [] as ServerError }; - } catch (err) { - console.log(err); - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "Error getting new session.", - }); - } - }), - - isApiSessionValid: protectedProcedure - .input( - z.object({ - checkingUserSession: z.boolean(), - userId: z.string().optional(), - }), - ) - .query(async ({ input }) => { - return { valid: await isSessionValidInStore(input.userId) }; - }), - - logoutUser: protectedProcedure - .input(z.object({ userId: z.string().optional() })) - .mutation(async ({ input }) => { - const { userId } = input; - await removeSessionFromStore(userId); - return { success: true, errors: [] as ServerError }; - }), + logoutUser: protectedProcedure + .input(z.object({ userId: z.string().optional() })) + .mutation(async ({ input }) => { + const { userId } = input; + await removeSessionFromStore(userId); + return { success: true, errors: [] as ServerError }; + }), }); diff --git a/src/lib/utils/constants.ts b/src/lib/utils/constants.ts index 436f4f0..546c2ef 100755 --- a/src/lib/utils/constants.ts +++ b/src/lib/utils/constants.ts @@ -4,6 +4,7 @@ export const constants = { POST_SESSION_KEY: "postsession", LAST_FETCHED_KEY: "LAST_FETCHED", SCRAP_API_URL: "https://gamebooking24.com/lottery-api", + PROXY_API_URL: "http://localhost:3070", SCRAP_API_SESSION_KEY: "SRAJWT", SCRAP_API_BASE_HEADERS: { Host: "gamebooking24.com",