convertified

This commit is contained in:
bootunloader
2025-12-31 08:08:55 +02:00
parent 2a122e1551
commit 9fa4a0c113
5 changed files with 637 additions and 676 deletions

7
pyapi/start.sh Executable file
View File

@@ -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

View File

@@ -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 };
};

View File

@@ -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<T> = {
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<string, APISession>;
draw: Draw;
data: PostDataEntry[];
users: ApiPostUserWithParent[];
sessions: Record<string, APISession>;
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<string, PostDataEntry[]>;
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<string, PostDataEntry[]>;
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: {

View File

@@ -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 };
}),
});

View File

@@ -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",