From aa73254a8777bae18bb224a4a97411a91828b34c Mon Sep 17 00:00:00 2001 From: bootunloader Date: Sat, 25 Jan 2025 23:41:57 +0200 Subject: [PATCH] done with upgrades..... I believe --- package.json | 2 +- pnpm-lock.yaml | 50 +- src/lib/server/connectors/surreal.db.ts | 50 +- src/lib/server/db/apidata.db.ts | 419 ++++++---- src/lib/server/db/apidraw.db.ts | 143 ++-- src/lib/server/db/apipostdata.db.ts | 147 ++-- src/lib/server/db/apiuser.db.ts | 425 +++++----- src/lib/server/db/booking.db.ts | 4 - src/lib/server/db/finalsheet.db.ts | 63 +- src/lib/server/db/presetdata.db.ts | 87 +- src/lib/server/db/user.db.ts | 158 ++-- .../server/external/api.scraping.helpers.ts | 550 ++++++------ src/lib/server/postdata/post.handler.ts | 572 ++++++------- .../postdata/postdata.gen.controller.ts | 788 +++++++++--------- src/lib/trpc/routers/apiauth.router.ts | 196 ++--- src/lib/trpc/routers/apidata.router.ts | 341 ++++---- src/lib/trpc/routers/apiuser.router.ts | 54 +- src/lib/trpc/routers/booking.router.ts | 110 +-- src/lib/trpc/routers/draws.router.ts | 45 +- src/lib/utils/data.types.ts | 514 ++++++------ src/routes/admin/api-controls/+page.server.ts | 86 +- .../api-controls/fetch-latest-data.svelte | 2 + .../admin/post-data-config/+page.svelte | 4 +- 23 files changed, 2442 insertions(+), 2368 deletions(-) delete mode 100755 src/lib/server/db/booking.db.ts diff --git a/package.json b/package.json index e92d4d1..a155f29 100755 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "ioredis": "^5.3.2", "lucide-svelte": "^0.424.0", "node-fetch": "^3.3.2", - "surrealdb.js": "^0.8.2", + "surrealdb": "^1.1.0", "svelte-french-toast": "^1.1.0", "svelte-headlessui": "^0.0.20", "tailwind-merge": "^2.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c44873..b1b7fc4 100755 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,9 +65,9 @@ importers: node-fetch: specifier: ^3.3.2 version: 3.3.2 - surrealdb.js: - specifier: ^0.8.2 - version: 0.8.4 + surrealdb: + specifier: ^1.1.0 + version: 1.1.0(tslib@2.6.2)(typescript@5.2.2)(ws@8.14.2) svelte-french-toast: specifier: ^1.1.0 version: 1.2.0(svelte@4.2.1) @@ -1141,6 +1141,11 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isows@1.0.6: + resolution: {integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==} + peerDependencies: + ws: '*' + jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true @@ -1561,8 +1566,12 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - surrealdb.js@0.8.4: - resolution: {integrity: sha512-ToCyBHxpVPGXth31ZktQvv+s7fvZG6+sR3mXHNAlhq0/43yYiYx3+3cYvCDGZQNBNUI42KENv8/aBQ5mGQZEEA==} + surrealdb@1.1.0: + resolution: {integrity: sha512-EAopFKeIo1lVCR+XEE/oMuh8LCPAIa2xC9MyVs5nw+BJyHc0Fr6F/UWVF9399LRtTBCoqe5G1W0hgxqLqkWaYA==} + engines: {node: '>=18.0.0'} + peerDependencies: + tslib: ^2.6.3 + typescript: ^5.0.0 svelte-check@3.5.2: resolution: {integrity: sha512-5a/YWbiH4c+AqAUP+0VneiV5bP8YOk9JL3jwvN+k2PEPLgpu85bjQc5eE67+eIZBBwUEJzmO3I92OqKcqbp3fw==} @@ -1760,12 +1769,6 @@ packages: unplugin@1.5.0: resolution: {integrity: sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==} - unws@0.2.4: - resolution: {integrity: sha512-/N1ajiqrSp0A/26/LBg7r10fOcPtGXCqJRJ61sijUFoGZMr6ESWGYn7i0cwr7fR7eEECY5HsitqtjGHDZLAu2w==} - engines: {node: '>=16.14.0'} - peerDependencies: - ws: '*' - update-browserslist-db@1.1.0: resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} hasBin: true @@ -1779,6 +1782,10 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + uuidv7@1.0.2: + resolution: {integrity: sha512-8JQkH4ooXnm1JCIhqTMbtmdnYEn6oKukBxHn1Ic9878jMkL7daTI7anTExfY18VRCX7tcdn5quzvCb6EWrR8PA==} + hasBin: true + vite-node@0.33.0: resolution: {integrity: sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==} engines: {node: '>=v14.18.0'} @@ -2830,6 +2837,10 @@ snapshots: isexe@2.0.0: {} + isows@1.0.6(ws@8.14.2): + dependencies: + ws: 8.14.2 + jiti@1.21.6: {} jsonc-parser@3.2.0: {} @@ -3202,13 +3213,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - surrealdb.js@0.8.4: + surrealdb@1.1.0(tslib@2.6.2)(typescript@5.2.2)(ws@8.14.2): dependencies: - unws: 0.2.4(ws@8.14.2) - ws: 8.14.2 + isows: 1.0.6(ws@8.14.2) + tslib: 2.6.2 + typescript: 5.2.2 + uuidv7: 1.0.2 transitivePeerDependencies: - - bufferutil - - utf-8-validate + - ws svelte-check@3.5.2(postcss-load-config@4.0.1(postcss@8.4.40))(postcss@8.4.40)(svelte@4.2.1): dependencies: @@ -3426,10 +3438,6 @@ snapshots: webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 - unws@0.2.4(ws@8.14.2): - dependencies: - ws: 8.14.2 - update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: browserslist: 4.23.3 @@ -3440,6 +3448,8 @@ snapshots: uuid@9.0.1: {} + uuidv7@1.0.2: {} + vite-node@0.33.0(@types/node@20.6.4): dependencies: cac: 6.7.14 diff --git a/src/lib/server/connectors/surreal.db.ts b/src/lib/server/connectors/surreal.db.ts index edbcbc8..c09455c 100755 --- a/src/lib/server/connectors/surreal.db.ts +++ b/src/lib/server/connectors/surreal.db.ts @@ -1,36 +1,32 @@ -import Surreal from "surrealdb.js"; -export type { QueryResult } from "surrealdb.js/script/types"; +import Surreal, { RecordId, StringRecordId } from "surrealdb"; +export type { QueryResult } from "surrealdb"; try { - if (document || window) { - throw new Error("SurrealDB needs a NodeJS environment to run."); - } + if (document || window) { + throw new Error("SurrealDB needs a NodeJS environment to run."); + } } catch (err) {} const CONFIG = { - url: process.env.SURREAL_URL ?? "", - user: process.env.SURREAL_USER ?? "", - pass: process.env.SURREAL_PASS ?? "", - ns: process.env.SURREAL_NS ?? "", - db: process.env.SURREAL_DB ?? "", + url: process.env.SURREAL_URL ?? "", + user: process.env.SURREAL_USER ?? "", + pass: process.env.SURREAL_PASS ?? "", + ns: process.env.SURREAL_NS ?? "", + db: process.env.SURREAL_DB ?? "", } as const; -// for (let key in CONFIG) { -// if ( -// !CONFIG[key as keyof typeof CONFIG] || -// CONFIG[key as keyof typeof CONFIG] === "" -// ) { -// throw new Error(`Missing configuration for ${key}`); -// } -// } +const db = new Surreal(); -let _surreal = - CONFIG.url.length > 0 - ? new Surreal(`http://${CONFIG.url}/rpc`, { - auth: { user: CONFIG.user, pass: CONFIG.pass }, - ns: CONFIG.ns, - db: CONFIG.db, - }) - : undefined; +export function parseToRID(idStr: string) { + return new StringRecordId(idStr); + // const [a, b] = idStr.split(":"); + // return new RecordId(a, b); +} -export const surreal = _surreal as Surreal; +if (CONFIG.url.length > 0) { + await db.connect(`http://${CONFIG.url}/rpc`); + await db.use({ namespace: CONFIG.ns, database: CONFIG.db }); + await db.signin({ username: CONFIG.user, password: CONFIG.pass }); +} + +export const surreal = db as Surreal; diff --git a/src/lib/server/db/apidata.db.ts b/src/lib/server/db/apidata.db.ts index 8943a9f..7b21bc4 100755 --- a/src/lib/server/db/apidata.db.ts +++ b/src/lib/server/db/apidata.db.ts @@ -3,210 +3,279 @@ import { chunkArray } from "../array.chunk"; import { surreal } from "../connectors/surreal.db"; const getTableName = (date: string) => { - return `apidata${date.replaceAll("-", "")}`; + return `apidata${date.replaceAll("-", "")}`; }; const upsertData = async ( - data: BookingEntry[], - date: string, - tries: number = 0, + data: BookingEntry[], + date: string, + tries: number = 0, ): Promise => { - const tableName = getTableName(date); - console.log(`[...] Upserting ${data.length} entries into ${tableName}`); - const alreadyPresentIds = new Set(); - try { - const [alreadyPresent] = await surreal.query<[string[]]>( - `select value id from type::table($tableName) where bookDate = $bookDate`, - { tableName, bookDate: date }, - ); - for (let eId of alreadyPresent.result ?? []) { - alreadyPresentIds.add(eId); - } - } catch (err) { - console.log("Failed to fetch, seeing if can try again"); if (tries >= 3) { - console.log("Max tries exceeded for initial fetch for upserting data"); - return; + console.log("Max tries exceeded for processing data"); + return; } - return await upsertData(data, date, tries++); - } - const oldEntries = [] as any[]; - const newEntries = [] as BookingEntry[]; - for (let entry of data) { - if (alreadyPresentIds.has(`${tableName}:${entry.id}`)) { - oldEntries.push({ - distributorId: entry.distributorId, - dealerId: entry.dealerId, - drawId: entry.drawId, - bookDate: entry.bookDate.split(" ")[0], - number: entry.number, - first: entry.first, - second: entry.second, - changedBalance: entry.changedBalance, - sheetName: entry.sheetName, - sheetId: entry.sheetId, - requestId: entry.requestId, - updatedAt: new Date().toISOString(), - }); - continue; - } - newEntries.push({ - ...entry, - id: `${tableName}:${entry.id}`, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - bookDate: entry.bookDate.split(" ")[0], - requestId: entry.requestId ?? "", - }); - } - console.log( - `[+] Inserting ${newEntries.length} new entries into ${tableName}`, - ); - // 5 to 25% of the total data length - let chunkSize = Math.floor( - Math.random() * (data.length * 0.2 - data.length * 0.05) + - data.length * 0.05, - ); - if (chunkSize > 10_000) { - chunkSize = 10_000; - } + const tableName = getTableName(date); + const drawId = data[0].drawId; - console.log(`Chunk Size : ${chunkSize}`); + console.log(`[...] Processing ${data.length} entries for ${tableName}`); - console.log(`[+] Inserting new entries`); - console.time("insertion time"); - const chunks = chunkArray(newEntries, chunkSize).map(async (chunk) => { - await surreal.insert(tableName, chunk); - }); - for (let i = 0; i < chunks.length; i += 2) { - await Promise.all(chunks.slice(i, i + 2)); - } - console.timeEnd("insertion time"); + try { + // Delete existing entries for this date + console.log( + `[...] Deleting existing entries for ${date} in ${tableName}`, + ); + console.time("deletion time"); + await surreal.query( + `DELETE type::table($tableName) WHERE bookDate = $bookDate AND drawId = $drawId`, + { tableName, bookDate: date, drawId }, + ); + console.timeEnd("deletion time"); - console.log( - `[+] Updating ${oldEntries.length} old entries into ${tableName}`, - ); + // Prepare new entries + const entries = data.map((entry) => ({ + ...entry, + id: `${tableName}:${entry.id}`, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + bookDate: entry.bookDate.split(" ")[0], + requestId: entry.requestId ?? "", + })); - const chunks2 = chunkArray(oldEntries, chunkSize).map(async (chunk) => { - await Promise.all( - chunk.map(async (entry) => { - // @ts-ignore - await surreal.update(`${tableName}:${entry.id}`, { - distributorId: entry.distributorId, - dealerId: entry.dealerId, - drawId: entry.drawId, - bookDate: entry.bookDate.split(" ")[0], - number: entry.number, - first: entry.first, - second: entry.second, - changedBalance: entry.changedBalance, - sheetName: entry.sheetName, - sheetId: entry.sheetId, - requestId: entry.requestId, - updatedAt: new Date().toISOString(), + // Calculate chunk size (5 to 25% of total data length, max 10,000) + let chunkSize = Math.floor( + Math.random() * (data.length * 0.2 - data.length * 0.05) + + data.length * 0.05, + ); + if (chunkSize > 1_000) { + chunkSize = 1_000; + } + + console.log(`Chunk Size: ${chunkSize}`); + console.log( + `[+] Inserting ${entries.length} entries into ${tableName}`, + ); + + // Insert new entries in chunks + console.time("insertion time"); + const chunks = chunkArray(entries, chunkSize).map(async (chunk) => { + await surreal.insert(tableName, chunk); }); - }), + + for (let i = 0; i < chunks.length; i += 2) { + await Promise.all(chunks.slice(i, i + 2)); + } + console.timeEnd("insertion time"); + + console.log( + `[+] Successfully processed ${data.length} entries into ${tableName}`, + ); + } catch (err) { + console.log("Failed to process data, attempting retry"); + return await upsertData(data, date, tries + 1); + } +}; + +const upsertDataDED = async ( + data: BookingEntry[], + date: string, + tries: number = 0, +): Promise => { + const tableName = getTableName(date); + console.log(`[...] Upserting ${data.length} entries into ${tableName}`); + const alreadyPresentIds = new Set(); + try { + const [alreadyPresent] = await surreal.query<[string[]]>( + `select value id from type::table($tableName) where bookDate = $bookDate`, + { tableName, bookDate: date }, + ); + for (let eId of alreadyPresent ?? []) { + alreadyPresentIds.add(eId); + } + } catch (err) { + console.log("Failed to fetch, seeing if can try again"); + if (tries >= 3) { + console.log( + "Max tries exceeded for initial fetch for upserting data", + ); + return; + } + return await upsertData(data, date, tries++); + } + const oldEntries = [] as any[]; + const newEntries = [] as BookingEntry[]; + for (let entry of data) { + if (alreadyPresentIds.has(`${tableName}:${entry.id}`)) { + oldEntries.push({ + distributorId: entry.distributorId, + dealerId: entry.dealerId, + drawId: entry.drawId, + bookDate: entry.bookDate.split(" ")[0], + number: entry.number, + first: entry.first, + second: entry.second, + changedBalance: entry.changedBalance, + sheetName: entry.sheetName, + sheetId: entry.sheetId, + requestId: entry.requestId, + updatedAt: new Date().toISOString(), + }); + continue; + } + newEntries.push({ + ...entry, + id: `${tableName}:${entry.id}`, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + bookDate: entry.bookDate.split(" ")[0], + requestId: entry.requestId ?? "", + }); + } + console.log( + `[+] Inserting ${newEntries.length} new entries into ${tableName}`, ); - }); - console.time("update time"); - for (let i = 0; i < chunks2.length; i += 10) { - await Promise.all(chunks2.slice(i, i + 10)); - } - console.timeEnd("update time"); + // 5 to 25% of the total data length + let chunkSize = Math.floor( + Math.random() * (data.length * 0.2 - data.length * 0.05) + + data.length * 0.05, + ); + if (chunkSize > 10_000) { + chunkSize = 10_000; + } - console.log( - `[+] Successfully upserted ${data.length} entries into ${tableName}`, - ); + console.log(`Chunk Size : ${chunkSize}`); + + console.log(`[+] Inserting new entries`); + console.time("insertion time"); + const chunks = chunkArray(newEntries, chunkSize).map(async (chunk) => { + await surreal.insert(tableName, chunk); + }); + for (let i = 0; i < chunks.length; i += 2) { + await Promise.all(chunks.slice(i, i + 2)); + } + console.timeEnd("insertion time"); + + console.log( + `[+] Updating ${oldEntries.length} old entries into ${tableName}`, + ); + + const chunks2 = chunkArray(oldEntries, chunkSize).map(async (chunk) => { + await Promise.all( + chunk.map(async (entry) => { + // @ts-ignore + await surreal.update(`${tableName}:${entry.id}`, { + distributorId: entry.distributorId, + dealerId: entry.dealerId, + drawId: entry.drawId, + bookDate: entry.bookDate.split(" ")[0], + number: entry.number, + first: entry.first, + second: entry.second, + changedBalance: entry.changedBalance, + sheetName: entry.sheetName, + sheetId: entry.sheetId, + requestId: entry.requestId, + updatedAt: new Date().toISOString(), + }); + }), + ); + }); + + console.time("update time"); + for (let i = 0; i < chunks2.length; i += 10) { + await Promise.all(chunks2.slice(i, i + 10)); + } + console.timeEnd("update time"); + + console.log( + `[+] Successfully upserted ${data.length} entries into ${tableName}`, + ); }; const getBookingEntriesForDealer = async ( - date: string, - drawId: string, - userId: string, - sorted?: boolean, + date: string, + drawId: string, + userId: string, + sorted?: boolean, ) => { - const tableName = getTableName(date); - let query = `select * from type::table($tableName) where bookDate = $date and dealerId = $userId and drawId = $drawId`; - if (sorted) { - query += " order by requestId desc"; - } - const [data] = await surreal.query<[BookingEntry[]]>(query, { - tableName, - date: `${date}`, - userId: parseInt(userId), - drawId: parseInt(drawId), - }); - console.log( - `Found ${JSON.stringify( - data, - )} entries for ${userId}, filters are ${date}, ${drawId} for ${tableName}`, - ); - if (data.status === "OK") { - return data.result ?? []; - } - return []; + const tableName = getTableName(date); + let query = `select * from type::table($tableName) where bookDate = $date and dealerId = $userId and drawId = $drawId`; + if (sorted) { + query += " order by requestId desc"; + } + const [data] = await surreal.query<[BookingEntry[]]>(query, { + tableName, + date: `${date}`, + userId: parseInt(userId), + drawId: parseInt(drawId), + }); + console.log( + `Found ${JSON.stringify( + data, + )} entries for ${userId}, filters are ${date}, ${drawId} for ${tableName}`, + ); + return data ?? []; }; const getBookingEntriesByDraw = async (date: string, drawId: string) => { - const tableName = getTableName(date); - const [data] = await surreal.query<[BookingEntry[]]>( - `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { - tableName, - date: date, - drawId: parseInt(drawId.includes(":") ? drawId.split(":")[1] : drawId), - }, - ); - if (data.status === "OK") { - return data.result ?? []; - } - return []; + const tableName = getTableName(date); + const [data] = await surreal.query<[BookingEntry[]]>( + `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { + tableName, + date: date, + drawId: parseInt( + drawId.includes(":") ? drawId.split(":")[1] : drawId, + ), + }, + ); + return data ?? []; }; const deleteDataOlderThan2Weeks = async () => { - const [out] = await surreal.query("info for db"); - // @ts-ignore - const tableNames = Object.keys(out.result.tables); + const [out] = await surreal.query("info for db"); + // @ts-ignore + const tableNames = Object.keys(out.result.tables); - const twoWeeksAgo = new Date(); - twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14); + const twoWeeksAgo = new Date(); + twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14); - for (const tableName of tableNames) { - if (tableName.startsWith("apidata")) { - const datePart = tableName.slice(7); - const d = new Date( - parseInt(datePart.slice(0, 4), 10), - parseInt(datePart.slice(4, 6), 10) - 1, // Month is 0-based in JavaScript Date - parseInt(datePart.slice(6, 8), 10), - ); - if (d < twoWeeksAgo) { - console.log(`[...] Deleting ${tableName}`); - await surreal.query("remove table if exists " + tableName); - console.log(`[+] Deleted ${tableName}`); - } - } else if (tableName.startsWith("apipostdata_")) { - const datePart = tableName.slice(12); - const d = new Date( - parseInt(datePart.slice(0, 4), 10), - parseInt(datePart.slice(4, 6), 10) - 1, // Month is 0-based in JavaScript Date - parseInt(datePart.slice(6, 8), 10), - ); - if (d < twoWeeksAgo) { - console.log(`[...] Deleting ${tableName}`); - await surreal.query("remove table if exists " + tableName); - console.log(`[+] Deleted ${tableName}`); - } - } else { - console.log(`Skipping ${tableName}`); + for (const tableName of tableNames) { + if (tableName.startsWith("apidata")) { + const datePart = tableName.slice(7); + const d = new Date( + parseInt(datePart.slice(0, 4), 10), + parseInt(datePart.slice(4, 6), 10) - 1, // Month is 0-based in JavaScript Date + parseInt(datePart.slice(6, 8), 10), + ); + if (d < twoWeeksAgo) { + console.log(`[...] Deleting ${tableName}`); + await surreal.query("remove table if exists " + tableName); + console.log(`[+] Deleted ${tableName}`); + } + } else if (tableName.startsWith("apipostdata_")) { + const datePart = tableName.slice(12); + const d = new Date( + parseInt(datePart.slice(0, 4), 10), + parseInt(datePart.slice(4, 6), 10) - 1, // Month is 0-based in JavaScript Date + parseInt(datePart.slice(6, 8), 10), + ); + if (d < twoWeeksAgo) { + console.log(`[...] Deleting ${tableName}`); + await surreal.query("remove table if exists " + tableName); + console.log(`[+] Deleted ${tableName}`); + } + } else { + console.log(`Skipping ${tableName}`); + } } - } }; export const dbApiData = { - upsertData, - getBookingEntriesForDealer, - getBookingEntriesByDraw, - deleteDataOlderThan2Weeks, + upsertData, + getBookingEntriesForDealer, + getBookingEntriesByDraw, + deleteDataOlderThan2Weeks, }; diff --git a/src/lib/server/db/apidraw.db.ts b/src/lib/server/db/apidraw.db.ts index 0ae8c5e..89e1282 100755 --- a/src/lib/server/db/apidraw.db.ts +++ b/src/lib/server/db/apidraw.db.ts @@ -1,100 +1,101 @@ import { constants } from "$lib/utils/constants"; import type { Draw } from "$lib/utils/data.types"; import { getDraws } from "../external/api.scraping.helpers"; -import { surreal } from "../connectors/surreal.db"; +import { parseToRID, surreal } from "../connectors/surreal.db"; import { getSessionFromStore } from "../utils/session.service"; const tableName = "apidraw"; const _populateDrawsTable = async () => { - const session = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); - if (!session) { - return; - } - const draws = await getDraws(session?.sessionToken); - if (draws.data.length === 0 || !draws.ok) { - return; - } - await surreal.insert( - tableName, - draws.data.map((e) => { - return { - id: e.id, - drawType: e.drawType, - adminId: e.adminId, - title: e.title, - closeTime: e.closeTime, - filterDuplicatesWhilePosting: false, - abRateF: 0, - abcRateF: 0, - abRateS: 0, - abcRateS: 0, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - }), - ); + const session = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); + if (!session) { + return; + } + const draws = await getDraws(session?.sessionToken); + if (draws.data.length === 0 || !draws.ok) { + return; + } + await surreal.insert( + tableName, + draws.data.map((e) => { + return { + id: e.id, + drawType: e.drawType, + adminId: e.adminId, + title: e.title, + closeTime: e.closeTime, + filterDuplicatesWhilePosting: false, + abRateF: 0, + abcRateF: 0, + abRateS: 0, + abcRateS: 0, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + }), + ); }; const getAllDraws = async ( - skipOptional?: boolean, - retry: number = 0, + skipOptional?: boolean, + retry: number = 0, ): Promise => { - let query = `select * from apidraw order by closeTime`; - const [out] = await surreal.query<[Draw[]]>(query); - if (out.status === "OK") { - const draws = out.result ?? []; - if (draws.length > 0) { - return draws; + const [out] = await surreal.query<[Draw[]]>( + `select * from apidraw order by closeTime`, + ); + if (out.length > 0) { + return out; } await _populateDrawsTable(); if (retry < 3) { - return getAllDraws(skipOptional, retry + 1); + return getAllDraws(skipOptional, retry + 1); } - } - return []; + return []; }; async function setFilterDuplicatesFlag(drawId: string, flag: boolean) { - const [d] = await surreal.select(drawId); - if (!d || !d.id) { - return; - } - console.log("setFilterDuplicatesFlag :: ", drawId, flag); - await surreal.update(drawId, { - ...d, - filterDuplicatesWhilePosting: flag, - updatedAt: new Date().toISOString(), - } as Draw); + const rid = parseToRID(drawId); + const d = await surreal.select(rid); + if (!d || !d.id) { + return; + } + console.log("setFilterDuplicatesFlag :: ", rid, flag); + await surreal.update(rid, { + ...d, + filterDuplicatesWhilePosting: flag, + updatedAt: new Date().toISOString(), + } as Draw); } async function updateDrawPresetInfo(draw: Draw) { - const drawId = draw.id; - const [d] = await surreal.select(drawId); - if (!d || !d.id) { - return; - } - await surreal.update(drawId, { - ...d, - filterDuplicatesWhilePosting: draw.filterDuplicatesWhilePosting, - abRateF: draw.abRateF, - abcRateF: draw.abcRateF, - abRateS: draw.abRateS, - abcRateS: draw.abcRateS, - updatedAt: new Date().toISOString(), - } as Draw); + const drawId = parseToRID(draw.id); + const d = await surreal.select(drawId); + if (!d || !d.id) { + console.log(`Draw not present for ${drawId}`); + return; + } + console.log(`Updating draw info ${drawId}`); + const out = await surreal.update(drawId, { + ...d, + filterDuplicatesWhilePosting: draw.filterDuplicatesWhilePosting, + abRateF: draw.abRateF, + abcRateF: draw.abcRateF, + abRateS: draw.abRateS, + abcRateS: draw.abcRateS, + updatedAt: new Date().toISOString(), + } as Draw); } const getDraw = async (drawId: string): Promise => { - const draws = await surreal.select( - drawId.includes("apidraw") ? drawId : `apidraw:${drawId}`, - ); - return draws[0]; + const draws = await surreal.select( + parseToRID(drawId.includes("apidraw") ? drawId : `apidraw:${drawId}`), + ); + return draws; }; export const dbDraw = { - getAllDraws, - getDraw, - setFilterDuplicatesFlag, - updateDrawPresetInfo, + getAllDraws, + getDraw, + setFilterDuplicatesFlag, + updateDrawPresetInfo, }; diff --git a/src/lib/server/db/apipostdata.db.ts b/src/lib/server/db/apipostdata.db.ts index 8319deb..62496ae 100755 --- a/src/lib/server/db/apipostdata.db.ts +++ b/src/lib/server/db/apipostdata.db.ts @@ -2,95 +2,98 @@ import type { PostDataEntry, PostDataHistory } from "$lib/utils/data.types"; import { surreal } from "../connectors/surreal.db"; const getTableName = (date: string) => { - return `apipostdata_${date.replaceAll("-", "")}`; + return `apipostdata_${date.replaceAll("-", "")}`; }; const upsertData = async (data: PostDataHistory) => { - const tableName = getTableName(data.bookDate); - const [check] = await surreal.query<[PostDataHistory[]]>( - `select * from type::table($tableName) where bookDate = $bookDate and drawId = $drawId`, - { tableName, bookDate: data.bookDate, drawId: data.drawId }, - ); - console.log(check); - const firstOut = check.result ? check.result[0] : undefined; - if (check.status === "OK" && !!firstOut && !!firstOut.id) { - console.log( - `Adding ${data.data.length} entries to ${firstOut.data.length} existing array`, + const tableName = getTableName(data.bookDate); + const [check] = await surreal.query<[PostDataHistory[]]>( + `select * from type::table($tableName) where bookDate = $bookDate and drawId = $drawId`, + { tableName, bookDate: data.bookDate, drawId: data.drawId }, ); - firstOut.data.push(...data.data); - console.log(`Now have ${firstOut.data.length} entries in data list`); - console.log(`[...] Updating data row in db now`); - await surreal.update(firstOut.id, { - id: firstOut.id, - data: firstOut.data, - drawId: firstOut.drawId, - bookDate: firstOut.bookDate, - updatedAt: new Date().toISOString(), - }); + console.log(check); + const firstOut = check && check.length > 0 ? check[0] : undefined; + if (check.length > 0 && !!firstOut && !!firstOut.id) { + console.log( + `Adding ${data.data.length} entries to ${firstOut.data.length} existing array`, + ); + firstOut.data.push(...data.data); + console.log(`Now have ${firstOut.data.length} entries in data list`); + console.log(`[...] Updating data row in db now`); + await surreal.update(firstOut.id, { + id: firstOut.id, + data: firstOut.data, + drawId: firstOut.drawId, + bookDate: firstOut.bookDate, + updatedAt: new Date().toISOString(), + }); - return; - } - await surreal.insert(tableName, data); - console.log( - `[+] Inserted post data in ${tableName} for ${data.bookDate} - ${data.drawId}`, - ); + return; + } + await surreal.insert(tableName, data); + console.log( + `[+] Inserted post data in ${tableName} for ${data.bookDate} - ${data.drawId}`, + ); }; const getPostDataByDraw = async (date: string, drawId: string) => { - const tableName = getTableName(date); - const [data] = await surreal.query<[PostDataHistory[]]>( - `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { - tableName, - date: date, - drawId: parseInt(drawId.includes(":") ? drawId.split(":")[1] : drawId), - }, - ); - let out = [] as PostDataEntry[]; - if (data.status === "OK" && data.result.length > 0) { - out = data.result[0].data; - } - return out; + const tableName = getTableName(date); + const [data] = await surreal.query<[PostDataHistory[]]>( + `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { + tableName, + date, + drawId: parseInt( + drawId.includes(":") ? drawId.split(":")[1] : drawId, + ), + }, + ); + let out = [] as PostDataEntry[]; + if (data.length > 0) { + out = data[0].data; + } + return out; }; async function doesPostHistoryDataExist(date: string, drawId: string) { - const tableName = getTableName(date); - const [data] = await surreal.query<[PostDataHistory[]]>( - `select id from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { - tableName, - date: date, - drawId: parseInt(drawId.includes(":") ? drawId.split(":")[1] : drawId), - }, - ); + const tableName = getTableName(date); + const [data] = await surreal.query<[PostDataHistory[]]>( + `select id from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { + tableName, + date: date, + drawId: parseInt( + drawId.includes(":") ? drawId.split(":")[1] : drawId, + ), + }, + ); - if (data.status === "OK") { - return data.result[0]?.id.length > 0; - } - return false; + return data[0]?.id.length > 0; } async function deletePostDataByDraw(date: string, drawId: string) { - const tableName = getTableName(date); - const [data] = await surreal.query<[PostDataHistory[]]>( - `select id from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { - tableName, - date: date, - drawId: parseInt(drawId.includes(":") ? drawId.split(":")[1] : drawId), - }, - ); + const tableName = getTableName(date); + const [data] = await surreal.query<[PostDataHistory[]]>( + `select id from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { + tableName, + date: date, + drawId: parseInt( + drawId.includes(":") ? drawId.split(":")[1] : drawId, + ), + }, + ); - if (data.status === "OK") { - await surreal.delete(tableName); - return true; - } - return false; + if (data.length > 0) { + await surreal.delete(tableName); + return true; + } + return false; } export const dbApiPostData = { - upsertData, - getPostDataByDraw, - deletePostDataByDraw, - doesPostHistoryDataExist, + upsertData, + getPostDataByDraw, + deletePostDataByDraw, + doesPostHistoryDataExist, }; diff --git a/src/lib/server/db/apiuser.db.ts b/src/lib/server/db/apiuser.db.ts index 9f9fae3..1e59da7 100755 --- a/src/lib/server/db/apiuser.db.ts +++ b/src/lib/server/db/apiuser.db.ts @@ -1,281 +1,262 @@ import { - type ApiUser, - type LooseApiUser, - type ApiPostUser, - type ApiPostUserWithParent, - ApiUserTypes, - DEFAULT_RANDOM_DISTRIBUTOR, + type ApiUser, + type LooseApiUser, + type ApiPostUser, + type ApiPostUserWithParent, + ApiUserTypes, + DEFAULT_RANDOM_DISTRIBUTOR, + zApiPostUser, } from "$lib/utils/data.types"; -import { surreal } from "../connectors/surreal.db"; +import { parseToRID, surreal } from "../connectors/surreal.db"; const getUserById = async (userId: string) => { - const query = `select * from apiuser where id = $id`; - const [rizzult] = await surreal.query<[ApiUser[]]>(query, { id: userId }); - return rizzult.result?.[0]; + return await surreal.select(parseToRID(userId)); + // const [rizzult] = await surreal.query<[ApiUser[]]>(query, { id: userId }); + // return rizzult[0]; }; const getAllIdsByUserType = async (userType: number) => { - const query = `select value id from apiuser where userType = $userType`; - const rizzult = (await surreal.query<[string[]]>(query, { userType }))[0]; - return (rizzult.result ?? []).map((e) => { - return e.split(":")[1]; - }); + const query = `select value id from apiuser where userType = $userType`; + const [rizzult] = await surreal.query<[any[]]>(query, { userType }); + return (rizzult ?? []).map((e) => { + return e.id; + }); }; async function allUsersOfTypeLimitedInfo(userType: number) { - const rizzult = ( - await surreal.query<[ApiPostUser[]]>( - `select id,userName,userId,postData from apiuser where userType = $userType`, - { userType: userType }, - ) - )[0]; - if (rizzult.status == "OK") { - return rizzult.result ?? []; - } - return []; + const [rizzult] = await surreal.query<[ApiPostUser[]]>( + `select id,userName,userId,postData from apiuser where userType = $userType`, + { userType: userType }, + ); + return rizzult ?? []; } async function setPostDataFlagForUsers(users: ApiPostUser[]) { - for (const user of users) { - const [u] = await surreal.select(user.id); - if (!u || !u.id) { - continue; + for (const user of users) { + const uid = parseToRID(user.id); + const u = await surreal.select(uid); + if (!u || !u.id) { + continue; + } + console.log("Updating user :: ", uid); + await surreal.update(uid, { + ...u, + postData: user.postData ?? false, + }); } - await surreal.update(user.id, { - ...u, - postData: user.postData ?? false, - }); - } } const getUserTypeCount = async (userType: number) => { - const queryBase = `select count() from apiuser where userType = $userType`; - let query = `${queryBase} and disable = 0 group all`; - let disabledQuery = `${queryBase} and disable = 1 group all`; - const enabledRizzult = ( - await surreal.query<[{ count: number }[]]>(query, { userType: userType }) - )[0]; - const count = { enabled: 0, disabled: 0 }; - if (enabledRizzult.status == "OK") { - count.enabled = enabledRizzult.result[0]?.count ?? 0; - } - const disabledRizzult = ( - await surreal.query<[{ count: number }[]]>(disabledQuery, { - userType: userType, - }) - )[0]; - if (disabledRizzult.status == "OK") { - count.disabled = disabledRizzult.result[0]?.count ?? 0; - } - return count; + const queryBase = `select count() from apiuser where userType = $userType`; + let query = `${queryBase} and disable = 0 group all`; + let disabledQuery = `${queryBase} and disable = 1 group all`; + const enabledRizzult = ( + await surreal.query<[{ count: number }[]]>(query, { + userType: userType, + }) + )[0]; + const count = { enabled: 0, disabled: 0 }; + if (enabledRizzult.length > 0) { + count.enabled = enabledRizzult[0]?.count ?? 0; + } + const disabledRizzult = ( + await surreal.query<[{ count: number }[]]>(disabledQuery, { + userType: userType, + }) + )[0]; + if (disabledRizzult.length > 0) { + count.disabled = disabledRizzult[0]?.count ?? 0; + } + return count; }; const allUsersOfType = async (userType: number) => { - const rizzult = ( - await surreal.query<[ApiUser[]]>( - `select * from apiuser where userType = $userType`, - { userType: userType }, - ) - )[0]; - if (rizzult.status == "OK") { - return rizzult.result ?? []; - } - return []; + const rizzult = ( + await surreal.query<[ApiUser[]]>( + `select * from apiuser where userType = $userType`, + { userType: userType }, + ) + )[0]; + return rizzult ?? []; }; async function updatePostUsersBalances( - payload: { balance: number; id: string }[], + payload: { balance: number; id: string }[], ) { - console.log("Updating users balances"); - console.log(payload); - for (const each of payload) { - const [rizzult] = await surreal.query<[ApiUser[]]>( - `update $userId set balance = $balance`, - { userId: each.id, balance: each.balance }, - ); - if (rizzult.status !== "OK") { - console.error("updatePostUsersBalance :: ", rizzult); + console.log("Updating users balances"); + console.log(payload); + for (const each of payload) { + const [rizzult] = await surreal.query<[ApiUser[]]>( + `update type::table($tableName) set balance = $balance`, + { tableName: each.id, balance: each.balance }, + ); + if (rizzult.length < 1) { + console.error("updatePostUsersBalance :: ", rizzult); + } } - } - console.log("Users balances updated"); + console.log("Users balances updated"); } async function getAllPostUsers() { - const [rizzult] = await surreal.query<[ApiPostUser[]]>( - `select id,userName,userId,postData from apiuser where postData = true`, - ); - if (rizzult.status === "OK") { - return rizzult.result ?? []; - } - return []; + const [rizzult] = await surreal.query<[ApiPostUser[]]>( + `select id,userName,userId,postData from apiuser where postData = true`, + ); + return rizzult ?? []; } async function getAllPostUsersWithParentUsers() { - const [rizzult] = await surreal.query<[ApiPostUserWithParent[]]>( - `select id,userName,userId,postData,parentDistributor,parentAdmin from apiuser where postData = true`, - ); - if (rizzult.status === "OK") { - return rizzult.result ?? []; - } - return []; + const [rizzult] = await surreal.query<[ApiPostUserWithParent[]]>( + `select id,userName,userId,postData,parentDistributor,parentAdmin from apiuser where postData = true`, + ); + const out = []; + for (const each of rizzult) { + out.push({ ...each, id: each.id.toString() }); + } + return out; + // return rizzult ?? []; } -const getAllDistributorsWithTheirChildren = async () => { - const distributorIds = await getAllIdsByUserType(ApiUserTypes.DISTRIBUTOR); - const out = distributorIds.map(async (id) => { - const [rizzult] = await surreal.query<[ApiUser[]]>( - `select *, (select * from apiuser where parentDistributor = $id) as children from apiuser where id = $prefixedId`, - { id, prefixedId: `apiuser:${id}` }, - ); - if (rizzult.status == "OK") { - return rizzult.result[0]; - } - return undefined; - }); - const responses = await Promise.all(out); - return responses; -}; - const getRandomDistributor = async (): Promise => { - const ignoreList = ["001OP9"]; - const randomUser = await _getRandomUser(ApiUserTypes.DISTRIBUTOR, ignoreList); - if (!randomUser) { - console.log("getting random distributor...."); - return DEFAULT_RANDOM_DISTRIBUTOR; - } - return randomUser as any as ApiUser; + const ignoreList = ["001OP9"]; + const randomUser = await _getRandomUser( + ApiUserTypes.DISTRIBUTOR, + ignoreList, + ); + if (!randomUser) { + console.log("getting random distributor...."); + return DEFAULT_RANDOM_DISTRIBUTOR; + } + return randomUser as any as ApiUser; }; const getRandomDealer = async (): Promise => { - const ignoreList = ["rizgnore"]; - return _getRandomUser(ApiUserTypes.DEALER, ignoreList); + const ignoreList = ["rizgnore"]; + return _getRandomUser(ApiUserTypes.DEALER, ignoreList); }; const _getRandomUser = async ( - userType: number, - ignoreList: string[], + userType: number, + ignoreList: string[], ): Promise => { - console.log("_getRandomUser :: ", userType); - const rizzult = ( - await surreal.query<[ApiUser[]]>( - `select * from apiuser where disable = 0 and userType = $userType and userId notinside $ignoreList order by rand() limit 1`, - { userType: userType, ignoreList: ignoreList }, - ) - )[0]; - if (rizzult.status == "OK") { + console.log("_getRandomUser :: ", userType); + const [rizzult] = await surreal.query<[ApiUser[]]>( + `select * from apiuser where disable = 0 and userType = $userType and userId notinside $ignoreList order by rand() limit 1`, + { userType: userType, ignoreList: ignoreList }, + ); console.log("found random user"); - return rizzult.result[0]; - } + return rizzult[0]; }; const doesExist = async (userId?: string) => { - console.log("doesExist :: ", userId); - if (userId) { - const [rizzult] = await surreal.query<{ count: number }[]>( - "select count() from apiuser where userId = $userId group all", - { userId: userId }, - ); - if (rizzult.status == "OK") { - return rizzult.result?.count > 0; + console.log("doesExist :: ", userId); + if (userId) { + const [rizzult] = await surreal.query<{ count: number }[]>( + "select count() from apiuser where userId = $userId group all", + { userId: userId }, + ); + return rizzult?.count > 0; } - } - return false; + return false; }; const insertMany = async (data: LooseApiUser[], postUsers: ApiPostUser[]) => { - console.log("insertMany :: ", data.length); - await surreal.insert( - "apiuser", - data.map((e) => { - return { - ...e, - postData: !!postUsers.find((u) => u.userId === e.userId), - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - }), - ); + console.log("insertMany :: ", data.length); + await surreal.insert( + "apiuser", + data.map((e) => { + return { + ...e, + postData: !!postUsers.find((u) => u.userId === e.userId), + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + }), + ); }; async function upsertMany( - data: LooseApiUser[], - wipeTable: boolean, - deleteUserType: typeof ApiUserTypes.DISTRIBUTOR | typeof ApiUserTypes.DEALER, + data: LooseApiUser[], + wipeTable: boolean, + deleteUserType: + | typeof ApiUserTypes.DISTRIBUTOR + | typeof ApiUserTypes.DEALER, ) { - const postUsers = await getAllPostUsers(); - console.log(postUsers); - if (wipeTable) { - console.log("[wipeTable] :: deleting all previous users"); - await surreal.query("delete from apiuser where userType = $userType", { - userType: deleteUserType, - }); - } - console.log("upsertMany :: ", data.length); - const toCreate = [] as LooseApiUser[]; - const out = data.map(async (apiUser) => { - // INFO: if you do want to keep disabled users, remove this check - if (apiUser.disable === 1) { - return; + const postUsers = await getAllPostUsers(); + console.log(postUsers); + if (wipeTable) { + console.log("[wipeTable] :: deleting all previous users"); + await surreal.query("delete from apiuser where userType = $userType", { + userType: deleteUserType, + }); } - const [u] = await surreal.select(`apiuser:${apiUser.id}`); - if (!u || !u.id) { - toCreate.push(apiUser); - return; - } - let postData = - u.postData ?? !!postUsers.find((pu) => pu.userId === u.userId) ?? false; - const qId = u.id; - await surreal.update(qId, { - id: u.id, - userId: apiUser.userId, - userType: apiUser.userType, - disableBooking: apiUser.disableBooking, - sendVoucher: apiUser.sendVoucher, - voucherGenerated: apiUser.voucherGenerated, - parentAdmin: apiUser.parentAdmin, - parentDistributor: apiUser.parentDistributor, - userName: apiUser.userName, - userCity: apiUser.userCity, - password: apiUser.password, - accessDenied: apiUser.accessDenied, - phoneNumber: apiUser.phoneNumber, - emailAddress: apiUser.emailAddress, - disable: apiUser.disable, - commission: apiUser.commission, - commissionPangora: apiUser.commissionPangora, - allowTitles: apiUser.allowTitles, - specialDealer: apiUser.specialDealer, - allowBalance: apiUser.allowBalance, - balance: apiUser.balance, - profitlossShare: apiUser.profitlossShare, - shareProfitonly: apiUser.shareProfitonly, - allowRemoveold: apiUser.allowRemoveold, - removeDays: apiUser.removeDays, - language: apiUser.language, - postData, - createdAt: u.createdAt, - updatedAt: new Date().toISOString(), + console.log("upsertMany :: ", data.length); + const toCreate = [] as LooseApiUser[]; + const out = data.map(async (apiUser) => { + // INFO: if you do want to keep disabled users, remove this check + if (apiUser.disable === 1) { + return; + } + const uid = parseToRID(`apiuser:${apiUser.id}`); + const u = await surreal.select(uid); + if (!u || !u.id) { + toCreate.push(apiUser); + return; + } + let postData = + u.postData ?? + !!postUsers.find((pu) => pu.userId === u.userId) ?? + false; + const qId = parseToRID(u.id); + await surreal.update(qId, { + id: u.id, + userId: apiUser.userId, + userType: apiUser.userType, + disableBooking: apiUser.disableBooking, + sendVoucher: apiUser.sendVoucher, + voucherGenerated: apiUser.voucherGenerated, + parentAdmin: apiUser.parentAdmin, + parentDistributor: apiUser.parentDistributor, + userName: apiUser.userName, + userCity: apiUser.userCity, + password: apiUser.password, + accessDenied: apiUser.accessDenied, + phoneNumber: apiUser.phoneNumber, + emailAddress: apiUser.emailAddress, + disable: apiUser.disable, + commission: apiUser.commission, + commissionPangora: apiUser.commissionPangora, + allowTitles: apiUser.allowTitles, + specialDealer: apiUser.specialDealer, + allowBalance: apiUser.allowBalance, + balance: apiUser.balance, + profitlossShare: apiUser.profitlossShare, + shareProfitonly: apiUser.shareProfitonly, + allowRemoveold: apiUser.allowRemoveold, + removeDays: apiUser.removeDays, + language: apiUser.language, + postData, + createdAt: u.createdAt, + updatedAt: new Date().toISOString(), + }); }); - }); - await Promise.allSettled(out); - if (toCreate.length > 0) { - await insertMany(toCreate, postUsers); - } + await Promise.allSettled(out); + if (toCreate.length > 0) { + await insertMany(toCreate, postUsers); + } } export const dbApiUser = { - allUsersOfType, - allUsersOfTypeLimitedInfo, - getUserById, - getAllDistributorsWithTheirChildren, - getUserTypeCount, - getAllIdsByUserType, - getAllPostUsers, - getAllPostUsersWithParentUsers, - getRandomDistributor, - getRandomDealer, - doesExist, - upsertMany, - setPostDataFlagForUsers, - updatePostUsersBalances, + allUsersOfType, + allUsersOfTypeLimitedInfo, + getUserById, + getUserTypeCount, + getAllIdsByUserType, + getAllPostUsers, + getAllPostUsersWithParentUsers, + getRandomDistributor, + getRandomDealer, + doesExist, + upsertMany, + setPostDataFlagForUsers, + updatePostUsersBalances, }; diff --git a/src/lib/server/db/booking.db.ts b/src/lib/server/db/booking.db.ts deleted file mode 100755 index b5ea1fe..0000000 --- a/src/lib/server/db/booking.db.ts +++ /dev/null @@ -1,4 +0,0 @@ - - -export const dbBooking = { -}; diff --git a/src/lib/server/db/finalsheet.db.ts b/src/lib/server/db/finalsheet.db.ts index 0470432..d3c9579 100755 --- a/src/lib/server/db/finalsheet.db.ts +++ b/src/lib/server/db/finalsheet.db.ts @@ -1,40 +1,39 @@ import type { FinalSheetData } from "$lib/utils/data.types"; -import { surreal } from "../connectors/surreal.db"; +import { parseToRID, surreal } from "../connectors/surreal.db"; const getTableName = (date: string) => { - return `finalsheet${date.replaceAll("-", "")}`; + return `finalsheet${date.replaceAll("-", "")}`; }; const upsertData = async (data: FinalSheetData, date: string) => { - const tableName = getTableName(date); - const [present] = await surreal.query<[FinalSheetData[]]>( - `select id from type::table($tableName) where date = $date and drawId = $drawId`, - { tableName, date: `${date}`, drawId: data.drawId } - ); - if (present) { - // @ts-ignore - await surreal.update(`${tableName}:${data.id}`, { - date: data.date, - drawId: data.drawId, - data: data.data, - totals: data.totals, - // @ts-ignore - createdAt: present?.result[0]?.createdAt ?? new Date().toISOString(), - updatedAt: new Date().toISOString(), - }); - } else { - // @ts-ignore - await surreal.create(`${tableName}:${data.id}`, { - date: data.date, - drawId: data.drawId, - data: data.data, - totals: data.totals, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }); - } + const tableName = getTableName(date); + const [present] = await surreal.query<[FinalSheetData[]]>( + `select id from type::table($tableName) where date = $date and drawId = $drawId`, + { tableName, date: `${date}`, drawId: data.drawId }, + ); + const id = parseToRID(`${tableName}:${data.id}`); + if (present) { + // @ts-ignore + await surreal.update(id, { + date: data.date, + drawId: data.drawId, + data: data.data, + totals: data.totals, + // @ts-ignore + createdAt: present[0]?.createdAt ?? new Date().toISOString(), + updatedAt: new Date().toISOString(), + }); + } else { + // @ts-ignore + await surreal.create(id, { + date: data.date, + drawId: data.drawId, + data: data.data, + totals: data.totals, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }); + } }; -export const dbFinalSheet = { - upsertData, -}; +export const dbFinalSheet = { upsertData }; diff --git a/src/lib/server/db/presetdata.db.ts b/src/lib/server/db/presetdata.db.ts index 47dde5e..aa5ad5e 100755 --- a/src/lib/server/db/presetdata.db.ts +++ b/src/lib/server/db/presetdata.db.ts @@ -1,65 +1,62 @@ -import type { - ApiPostUser, - PostDataEntry, - PresetDataEntry, -} from "$lib/utils/data.types"; +import type { PresetDataEntry } from "$lib/utils/data.types"; import { surreal } from "../connectors/surreal.db"; const getTableName = (date: string) => { - return `presetdata_${date.replaceAll("-", "")}`; + return `presetdata_${date.replaceAll("-", "")}`; }; const insertData = async (data: PresetDataEntry[]) => { - if (data.length < 1) return; - const tableName = getTableName(data[0].bookDate); - const out = await surreal.insert(tableName, data); - console.log( - `[+] Inserted post data in ${tableName} for ${data[0].bookDate} - ${data[0].drawId}`, - ); - return out; + if (data.length < 1) return; + const tableName = getTableName(data[0].bookDate); + console.log(`Inserting ${data.length} rows in ${tableName}`); + const out = await surreal.insert(tableName, data); + console.log( + `[+] Inserted post data in ${tableName} for ${data[0].bookDate} - ${data[0].drawId}`, + ); + return out; }; const getDataByDraw = async (date: string, drawId: number) => { - const tableName = getTableName(date); - const [data] = await surreal.query<[PresetDataEntry[]]>( - `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { tableName, date, drawId }, - ); - return data.result || ([] as PresetDataEntry[]); + const tableName = getTableName(date); + const [data] = await surreal.query<[PresetDataEntry[]]>( + `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { tableName, date, drawId }, + ); + return data || ([] as PresetDataEntry[]); }; const getDataGroupedBySheetByDraw = async (date: string, drawId: number) => { - const tableName = getTableName(date); - const [data] = await surreal.query<[PresetDataEntry[]]>( - `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, - { tableName, date, drawId }, - ); - const out = { - abData: [] as PresetDataEntry[], - abcData: [] as PresetDataEntry[], - all: data.result || ([] as PresetDataEntry[]), - }; - for (const row of data.result ?? []) { - if (row.number.length === 2) { - out.abData.push(row); - } else if (row.number.length === 3) { - out.abcData.push(row); + const tableName = getTableName(date); + const [data] = await surreal.query<[PresetDataEntry[]]>( + `select * from type::table($tableName) where bookDate = $date and drawId = $drawId`, + { tableName, date, drawId }, + ); + const out = { + abData: [] as PresetDataEntry[], + abcData: [] as PresetDataEntry[], + all: data || ([] as PresetDataEntry[]), + }; + for (const row of data ?? []) { + if (row.number.length === 2) { + out.abData.push(row); + } else if (row.number.length === 3) { + out.abcData.push(row); + } } - } - return out; + return out; }; async function deleteDataByIds(date: string, ids: string[]) { - const tableName = getTableName(date); - await surreal.query<[PresetDataEntry[]]>( - `delete from type::table($tableName) where id in $ids`, - { tableName, ids }, - ); + const tableName = getTableName(date); + await surreal.query<[PresetDataEntry[]]>( + `delete from type::table($tableName) where id in $ids`, + { tableName, ids }, + ); } export const dbPresetData = { - insertData, - getDataGroupedBySheetByDraw, - getDataByDraw, - deleteDataByIds, + insertData, + getDataGroupedBySheetByDraw, + getDataByDraw, + deleteDataByIds, }; diff --git a/src/lib/server/db/user.db.ts b/src/lib/server/db/user.db.ts index 8ea842a..7f10abd 100755 --- a/src/lib/server/db/user.db.ts +++ b/src/lib/server/db/user.db.ts @@ -1,90 +1,76 @@ import type { User } from "$lib/utils/data.types"; -import { surreal, type QueryResult } from "../connectors/surreal.db"; +import { surreal } from "../connectors/surreal.db"; export const dbUser = { - doesExist: async (username?: string) => { - if (username) { - const [rizzult] = await surreal.query<{ count: number }[]>( - "select count() from user where username = $username group all", - { username: username } - ); - if (rizzult.status == "OK") { - return rizzult.result?.count > 0; - } - } - return false; - }, - create: async (data: { - username: string; - password: string; - userType: string; - association: string; - }) => { - const doesUserAlreadyExist = await dbUser.doesExist(data.username); - console.log("doesUserAlreadyExist :: ", doesUserAlreadyExist); - if (doesUserAlreadyExist) { - return [{ message: "User already exists." }]; - } - const { username, password, association, userType } = data; - const out = await surreal.create(`user:ulid()`, { - createdAt: Date.now().toString(), - updatedAt: Date.now().toString(), - username, - password, - userType, - association, - }); - return out as User[]; - }, - all: async () => { - return await surreal.select("user"); - }, - get: async (d: { - username?: string; - id?: string; - }): Promise => { - if (d.id) { - return (await surreal.select(`user:${d.id}`))[0]; - } - if (d.username) { - const rizzult = ( - await surreal.query<[User[]]>( - `select * from user where username = $username`, - { username: d.username } - ) - )[0]; - if (rizzult.status == "OK") { - return rizzult.result[0]; - } - } - return undefined; - }, - getChildren: async (username?: string) => { - const rizzult = await surreal.query( - `select * from user where association = $username`, - { username: username } - ); - return getParsedUsers(rizzult); - }, - update: async (id: string, data: { association: string }) => { - const [rizzult] = await surreal.update(`user:${id}`, { - updatedAt: Date.now().toString(), - association: data.association, - } as User); - return rizzult; - }, - delete: async (id: string) => { - const out = await surreal.delete(`user:${id}`); - return out[0].id; - }, -}; - -const getParsedUsers = (data: QueryResult[]) => { - const users = [] as User[]; - for (const each of data) { - if (each.status == "OK") { - users.push(each.result); - } - } - return users; + doesExist: async (username?: string) => { + if (username) { + const [rizzult] = await surreal.query<{ count: number }[]>( + "select count() from user where username = $username group all", + { username }, + ); + return rizzult?.count > 0; + } + return false; + }, + create: async (data: { + username: string; + password: string; + userType: string; + association: string; + }) => { + const doesUserAlreadyExist = await dbUser.doesExist(data.username); + console.log("doesUserAlreadyExist :: ", doesUserAlreadyExist); + if (doesUserAlreadyExist) { + return [{ message: "User already exists." }]; + } + const { username, password, association, userType } = data; + const out = await surreal.create(`user`, { + createdAt: Date.now().toString(), + updatedAt: Date.now().toString(), + username, + password, + userType, + association, + }); + return out as User[]; + }, + all: async () => { + return await surreal.select("user"); + }, + get: async (d: { + username?: string; + id?: string; + }): Promise => { + if (d.id) { + return (await surreal.select(`user:${d.id}`))[0]; + } + if (d.username) { + const rizzult = ( + await surreal.query<[User[]]>( + `select * from user where username = $username`, + { username: d.username }, + ) + )[0]; + return rizzult[0]; + } + return undefined; + }, + getChildren: async (username?: string) => { + const [rizzult] = await surreal.query( + `select * from user where association = $username`, + { username: username }, + ); + return rizzult; + }, + update: async (id: string, data: { association: string }) => { + const [rizzult] = await surreal.update(`user:${id}`, { + updatedAt: Date.now().toString(), + association: data.association, + } as User); + return rizzult; + }, + delete: async (id: string) => { + const out = await surreal.delete(`user:${id}`); + return out[0].id; + }, }; diff --git a/src/lib/server/external/api.scraping.helpers.ts b/src/lib/server/external/api.scraping.helpers.ts index b7d601f..24ad727 100755 --- a/src/lib/server/external/api.scraping.helpers.ts +++ b/src/lib/server/external/api.scraping.helpers.ts @@ -13,317 +13,317 @@ 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; + 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; } - 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.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 }; }; 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; + 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; } - 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) { + 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: [], - ok: false, - code: data.code, - message: data.message, + dealers: [], + errors: [{ message: "An error occured during fetching dealers" }], }; - } - 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.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[] }; + }; - 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.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), + }; }; 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.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) }; }; 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 8531812..8ed56f5 100644 --- a/src/lib/server/postdata/post.handler.ts +++ b/src/lib/server/postdata/post.handler.ts @@ -1,320 +1,334 @@ import { getRandomUserAgent, 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 APIRespnose = { - 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; + 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};`; } - 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 }; + 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 APIRespnose<[]>[]; - const responsesIds = [] as { requestId: number; bookId: string }[]; - let failedResponses = 0; - let successResponses = 0; + const responses = [] as APIRespnose<[]>[]; + 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, - }; + 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); } - 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]; + + 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 mockSendBatchRequest( + session, + dealerId, + payload.draw, + total, + message, + ); + let rj: + | APIRespnose<{ + 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, + }; } - 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 }[]; - - 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: - | APIRespnose<{ - 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, - }; + 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", + }; } - - 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.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, + }), + }); } 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], - }; + 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(), }), - }, - time: new Date().toISOString(), - }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - statusText: "OK", - }, - ); + { + 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.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, + }), + }); } // export async function postDataToApi(payload: { diff --git a/src/lib/server/postdata/postdata.gen.controller.ts b/src/lib/server/postdata/postdata.gen.controller.ts index 1a8fcbd..0da11b3 100644 --- a/src/lib/server/postdata/postdata.gen.controller.ts +++ b/src/lib/server/postdata/postdata.gen.controller.ts @@ -2,446 +2,462 @@ import { dbApiPostData } from "$lib/server/db/apipostdata.db"; import { dbApiUser } from "$lib/server/db/apiuser.db"; import { getReducedFinalSheet } from "$lib/server/finalsheet.helpers"; import { - adjustRatesIfDuplicatesFound, - pairRatesWithNumbers, - removeNumbersWithRepeatingDigits, - splitRatesIntoSmallerForRowsWithLargerRates, - spreadRatesForNumbersBetweenUsers, + adjustRatesIfDuplicatesFound, + pairRatesWithNumbers, + removeNumbersWithRepeatingDigits, + splitRatesIntoSmallerForRowsWithLargerRates, + spreadRatesForNumbersBetweenUsers, } from "$lib/server/postdata/postdata.gen.helpers"; import { getAllSessions } from "$lib/server/utils/session.service"; import { getDefaultTotals, getULID } from "$lib/utils"; import type { - ApiPostUser, - ApiPostUserWithParent, - PresetDataEntry, - PostDataEntry, - PostDataFilters, - PostDataHistoryFilters, - ReducedFinalSheetData, - ReducedFinalSheetRow, - ServerError, + ApiPostUser, + ApiPostUserWithParent, + PresetDataEntry, + PostDataEntry, + PostDataFilters, + PostDataHistoryFilters, + ReducedFinalSheetData, + ReducedFinalSheetRow, + ServerError, } from "$lib/utils/data.types"; import { dbPresetData } from "$lib/server/db/presetdata.db"; import { getUsersBalance } from "$lib/server/external/api.scraping.helpers"; function filterMatching( - data: ReducedFinalSheetRow[], - min: number, - max: number, - sheetType: "first" | "second", + data: ReducedFinalSheetRow[], + min: number, + max: number, + sheetType: "first" | "second", ) { - let abNums = new Set(); - let abcNums = new Set(); + let abNums = new Set(); + let abcNums = new Set(); - for (const row of data) { - if (row.prize[sheetType] >= min && row.prize[sheetType] <= max) { - abNums.add(`${row.number[0]}${row.number[1]}`); - abcNums.add(`${row.number[0]}${row.number[1]}${row.number[2]}`); + for (const row of data) { + if (row.prize[sheetType] >= min && row.prize[sheetType] <= max) { + abNums.add(`${row.number[0]}${row.number[1]}`); + abcNums.add(`${row.number[0]}${row.number[1]}${row.number[2]}`); + } } - } - return { abNums, abcNums }; + return { abNums, abcNums }; } export async function updateBalanceOfPostUsers(users: ApiPostUserWithParent[]) { - const sessions = await getAllSessions(); - const balances = [] as { id: string; balance: number }[]; - for (const user of users) { - const session = sessions.find((e) => e.value.userId === user.id); - const jwt = session?.value.sessionToken; - if (!jwt) { - return { - ok: false, - detail: `Session not found for user ${user.userId}`, - }; + const sessions = await getAllSessions(); + console.log(sessions); + console.log(`Fetching balances`); + const balances = [] as { id: string; balance: number }[]; + for (const user of users) { + console.log(`Finding ${user.id} in sessions`); + const session = sessions.find((e) => e.value.userId.includes(user.id)); + const jwt = session?.value.sessionToken; + if (!jwt) { + return { + ok: false, + detail: `Session not found for user ${user.userId}`, + }; + } + const uid = session.value.userId.toString(); + console.log(`Found ${uid} in session`); + const out = await getUsersBalance(+uid.split(":")[1], jwt); + if (!out) { + return { + ok: false, + detail: `Error fetching balance for user ${user.userName}`, + }; + } + balances.push({ id: uid, balance: out }); } - const out = await getUsersBalance(+user.id.split(":")[1], jwt); - if (!out) { - return { - ok: false, - detail: `Error fetching balance for user ${user.userName}`, - }; - } - balances.push({ id: user.id, balance: out }); - } - await dbApiUser.updatePostUsersBalances(balances); - return { - ok: true, - detail: "", - data: users.map((u) => { - const bal = balances.find((b) => b.id === u.id); - if (!bal) { - console.log(`ERROR: Balance not found for user ${u.userName}`); - } - return { ...u, balance: bal?.balance ?? 0 }; - }), - }; + console.log(`Updating balances`); + console.log(balances); + await dbApiUser.updatePostUsersBalances(balances); + return { + ok: true, + detail: "", + data: users.map((u) => { + const bal = balances.find((b) => b.id === u.id); + if (!bal) { + console.log(`ERROR: Balance not found for user ${u.userName}`); + } + return { ...u, balance: bal?.balance ?? 0 }; + }), + }; } export async function fetchDataForPosting( - date: string, - input: PostDataFilters, - users: ApiPostUser[], + date: string, + input: PostDataFilters, + users: ApiPostUser[], ) { - console.log(`The input ${JSON.stringify(input, null, 2)}`); - const { minPrize, maxPrize } = input; - const draw = input.draw!; - const fsData = { - id: getULID(), - date, - drawId: draw.id, - data: [], - totals: getDefaultTotals(), - } as ReducedFinalSheetData; - if (!draw) { - return { - ok: false, - detail: `Draw for the passed draw ID not found`, - data: [], - users: [], - errors: [ - { message: `Draw for the passed draw ID not found` }, - ] as ServerError, - }; - } - const data = await getReducedFinalSheet(fsData); - if (!data.ok) { - return { - ok: false, - detail: `Error compiling final sheet`, - data: [], - users: [], - errors: data.errors, - }; - } - - console.log("[+] Filtering the fs data to get the numbers"); - const filteredF = filterMatching(fsData.data, minPrize, maxPrize, "first"); - console.log( - `Filtered data: ${filteredF.abNums.size}; ${filteredF.abcNums.size}`, - ); - - // ------------------------------------------ - - let _abNums = new Set(), - _abcNums = new Set(); - for (const each of filteredF.abNums) _abNums.add(each); - for (const each of filteredF.abcNums) _abcNums.add(each); - let abNums = Array.from(_abNums), - abcNums = Array.from(_abcNums); - - if (draw.filterDuplicatesWhilePosting === true) { - console.log(`[+] Removing numbers that have repeating digits`); - console.log(`[=] Original : AB: ${abNums.length}, ABC: ${abcNums.length}`); - abNums = removeNumbersWithRepeatingDigits(abNums); - abcNums = removeNumbersWithRepeatingDigits(abcNums); - } - console.log(`[=] AB: ${abNums.length}, ABC: ${abcNums.length}`); - - console.log(`Fetching preset data`); - const presetData = await dbPresetData.getDataGroupedBySheetByDraw( - date, - +draw.id.split(":")[1], - ); - console.log(`${presetData.all.length} preset entries found`); - - for (let tries = 0; tries < 3; tries++) { - console.log(`[✍️] Try ${tries + 1} of generating the result`); - const out = await generatePostDataArrayFromBaseInfo( - input, - users, - abNums, - abcNums, - presetData, - ); - if (out.ok) { - return out; - } - if (out.detail.includes("Not enough balance")) { - return { - ok: false, - detail: `Users don't have enough balance to post the data, try reducing the rates`, + console.log(`The input ${JSON.stringify(input, null, 2)}`); + const { minPrize, maxPrize } = input; + const draw = input.draw!; + const fsData = { + id: getULID(), + date, + drawId: draw.id, data: [], - users: [], - }; + totals: getDefaultTotals(), + } as ReducedFinalSheetData; + if (!draw) { + return { + ok: false, + detail: `Draw for the passed draw ID not found`, + data: [], + users: [], + errors: [ + { message: `Draw for the passed draw ID not found` }, + ] as ServerError, + }; + } + const data = await getReducedFinalSheet(fsData); + if (!data.ok) { + return { + ok: false, + detail: `Error compiling final sheet`, + data: [], + users: [], + errors: data.errors, + }; } - } - return { - ok: false, - detail: `Could not generate data, please try adjusting the filters`, - data: [], - }; + console.log("[+] Filtering the fs data to get the numbers"); + const filteredF = filterMatching(fsData.data, minPrize, maxPrize, "first"); + console.log( + `Filtered data: ${filteredF.abNums.size}; ${filteredF.abcNums.size}`, + ); + + // ------------------------------------------ + + let _abNums = new Set(), + _abcNums = new Set(); + for (const each of filteredF.abNums) _abNums.add(each); + for (const each of filteredF.abcNums) _abcNums.add(each); + let abNums = Array.from(_abNums), + abcNums = Array.from(_abcNums); + + if (draw.filterDuplicatesWhilePosting === true) { + console.log(`[+] Removing numbers that have repeating digits`); + console.log( + `[=] Original : AB: ${abNums.length}, ABC: ${abcNums.length}`, + ); + abNums = removeNumbersWithRepeatingDigits(abNums); + abcNums = removeNumbersWithRepeatingDigits(abcNums); + } + console.log(`[=] AB: ${abNums.length}, ABC: ${abcNums.length}`); + + console.log(`Fetching preset data`); + const presetData = await dbPresetData.getDataGroupedBySheetByDraw( + date, + +draw.id.split(":")[1], + ); + console.log(`${presetData.all.length} preset entries found`); + + for (let tries = 0; tries < 3; tries++) { + console.log(`[✍️] Try ${tries + 1} of generating the result`); + const out = await generatePostDataArrayFromBaseInfo( + input, + users, + abNums, + abcNums, + presetData, + ); + if (out.ok) { + return out; + } + if (out.detail.includes("Not enough balance")) { + return { + ok: false, + detail: `Users don't have enough balance to post the data, try reducing the rates`, + data: [], + users: [], + }; + } + } + + return { + ok: false, + detail: `Could not generate data, please try adjusting the filters`, + data: [], + }; } export async function generatePostDataArrayFromBaseInfo( - input: PostDataFilters, - users: ApiPostUser[], - abNums: string[], - abcNums: string[], - presetData: { - all: PostDataEntry[]; - abData: PresetDataEntry[]; - abcData: PresetDataEntry[]; - }, + input: PostDataFilters, + users: ApiPostUser[], + abNums: string[], + abcNums: string[], + presetData: { + all: PostDataEntry[]; + abData: PresetDataEntry[]; + abcData: PresetDataEntry[]; + }, ) { - console.log("[+] Spreading the rates for the numbers for all post user"); - const abData = splitRatesIntoSmallerForRowsWithLargerRates( - spreadRatesForNumbersBetweenUsers( - adjustRatesIfDuplicatesFound( - pairRatesWithNumbers(abNums, input.twoDigitRates), - presetData.abData, - ), - users.map((u) => u.userId), - ), - ); - const abcData = splitRatesIntoSmallerForRowsWithLargerRates( - spreadRatesForNumbersBetweenUsers( - adjustRatesIfDuplicatesFound( - pairRatesWithNumbers(abcNums, input.threeDigitRates), - presetData.abcData, - ), - users.map((u) => u.userId), - ), - ); - - // ------------------------------------------ - - console.log(`[+] Adding ${abData.length} ab entries to final list`); - console.log(`[+] Adding ${abcData.length} abc entries to final list`); - - const result = [] as PostDataEntry[]; - const alreadyPresent = new Set(); - for (const each of abData) { - alreadyPresent.add(each.number); - result.push(each); - } - for (const each of abcData) { - alreadyPresent.add(each.number); - result.push(each); - } - - // ------------------------------------------ - - const balanceCounts = {} as Record; - for (const each of result) { - const uid = each.userId ?? ""; - if (balanceCounts[uid] === undefined) { - balanceCounts[uid] = 0; - } - balanceCounts[uid] += each.first + each.second; - } - - // ------------------------------------------ - - console.log( - `[+] Appending up to ${presetData.all.length} entries that are not ab, abc`, - ); - for (const entry of presetData.all) { - if ( - alreadyPresent.has(entry.number) || - (entry.first < 5 && entry.second < 5) - ) { - continue; - } - const randomUserId = users[Math.floor(Math.random() * users.length)].userId; - if (balanceCounts[randomUserId] === undefined) { - balanceCounts[randomUserId] = 0; - } - balanceCounts[randomUserId] += entry.first + entry.second; - result.push({ ...entry, userId: randomUserId }); - } - - // ------------------------------------------ - - const usersTotalbalance = users.reduce((a, b) => a + (b.balance ?? 0), 0); - let totalAmtForPostingData = Object.values(balanceCounts).reduce( - (acc, curr) => acc + curr, - 0, - ); - if (usersTotalbalance < totalAmtForPostingData) { - return { - ok: false, - detail: `Not enough balance to book overall with ${usersTotalbalance} < ${totalAmtForPostingData}`, - data: [], - users: [], - errors: [ - { message: `Not enough balance to book overall` }, - ] as ServerError, - }; - } - - function isDistributionUnbalanced() { - let out = false; - for (const key in balanceCounts) { - if ( - balanceCounts[key] > (users.find((u) => u.userId === key)?.balance ?? 0) - ) { - out = true; - break; - } - } - return out; - } - - for (let tries = 0; tries < 5; tries++) { - console.log( - `Balance counts start : ${JSON.stringify(balanceCounts, null, 2)}`, + console.log("[+] Spreading the rates for the numbers for all post user"); + const abData = splitRatesIntoSmallerForRowsWithLargerRates( + spreadRatesForNumbersBetweenUsers( + adjustRatesIfDuplicatesFound( + pairRatesWithNumbers(abNums, input.twoDigitRates), + presetData.abData, + ), + users.map((u) => u.userId), + ), + ); + const abcData = splitRatesIntoSmallerForRowsWithLargerRates( + spreadRatesForNumbersBetweenUsers( + adjustRatesIfDuplicatesFound( + pairRatesWithNumbers(abcNums, input.threeDigitRates), + presetData.abcData, + ), + users.map((u) => u.userId), + ), ); - rebalancePostDataListByBalanceOfUsers(balanceCounts, users, result); + // ------------------------------------------ - console.log(`Balance counts final : ${JSON.stringify(balanceCounts)}`); + console.log(`[+] Adding ${abData.length} ab entries to final list`); + console.log(`[+] Adding ${abcData.length} abc entries to final list`); - let totalAmtForPostingDataAfterRebalance = Object.values( - balanceCounts, - ).reduce((acc, curr) => acc + curr, 0); + const result = [] as PostDataEntry[]; + const alreadyPresent = new Set(); + for (const each of abData) { + alreadyPresent.add(each.number); + result.push(each); + } + for (const each of abcData) { + alreadyPresent.add(each.number); + result.push(each); + } + + // ------------------------------------------ + + const balanceCounts = {} as Record; + for (const each of result) { + const uid = each.userId ?? ""; + if (balanceCounts[uid] === undefined) { + balanceCounts[uid] = 0; + } + balanceCounts[uid] += each.first + each.second; + } + + // ------------------------------------------ console.log( - `Total amount for posting data after rebalance: ${totalAmtForPostingDataAfterRebalance}`, - `Total balance of users: ${JSON.stringify(users.map((u) => ({ un: u.userName, b: u.balance })))}`, + `[+] Appending up to ${presetData.all.length} entries that are not ab, abc`, ); - - if (!isDistributionUnbalanced()) { - console.log(`[+] Distribution is balanced`); - break; + for (const entry of presetData.all) { + if ( + alreadyPresent.has(entry.number) || + (entry.first < 5 && entry.second < 5) + ) { + continue; + } + const randomUserId = + users[Math.floor(Math.random() * users.length)].userId; + if (balanceCounts[randomUserId] === undefined) { + balanceCounts[randomUserId] = 0; + } + balanceCounts[randomUserId] += entry.first + entry.second; + result.push({ ...entry, userId: randomUserId }); } - console.log(`[!] Rebalancing again`); - } - if (isDistributionUnbalanced()) { + // ------------------------------------------ + + const usersTotalbalance = users.reduce((a, b) => a + (b.balance ?? 0), 0); + let totalAmtForPostingData = Object.values(balanceCounts).reduce( + (acc, curr) => acc + curr, + 0, + ); + if (usersTotalbalance < totalAmtForPostingData) { + return { + ok: false, + detail: `Not enough balance to book overall with ${usersTotalbalance} < ${totalAmtForPostingData}`, + data: [], + users: [], + errors: [ + { message: `Not enough balance to book overall` }, + ] as ServerError, + }; + } + + function isDistributionUnbalanced() { + let out = false; + for (const key in balanceCounts) { + if ( + balanceCounts[key] > + (users.find((u) => u.userId === key)?.balance ?? 0) + ) { + out = true; + break; + } + } + return out; + } + + for (let tries = 0; tries < 5; tries++) { + console.log( + `Balance counts start : ${JSON.stringify(balanceCounts, null, 2)}`, + ); + + rebalancePostDataListByBalanceOfUsers(balanceCounts, users, result); + + console.log(`Balance counts final : ${JSON.stringify(balanceCounts)}`); + + let totalAmtForPostingDataAfterRebalance = Object.values( + balanceCounts, + ).reduce((acc, curr) => acc + curr, 0); + + console.log( + `Total amount for posting data after rebalance: ${totalAmtForPostingDataAfterRebalance}`, + `Total balance of users: ${JSON.stringify(users.map((u) => ({ un: u.userName, b: u.balance })))}`, + ); + + if (!isDistributionUnbalanced()) { + console.log(`[+] Distribution is balanced`); + break; + } + console.log(`[!] Rebalancing again`); + } + + if (isDistributionUnbalanced()) { + return { + ok: false, + detail: `Please regenerate dataset as the some users have not enough balance to book their entries`, + data: [], + users: [], + }; + } + + // ------------------------------------------ + + console.log(`[+] Shuffling ${result.length} entries for posting`); + shuffleArray(result); + return { - ok: false, - detail: `Please regenerate dataset as the some users have not enough balance to book their entries`, - data: [], - users: [], + ok: true, + detail: `Fetched the data successfully`, + data: result, + users, + errors: undefined, }; - } - - // ------------------------------------------ - - console.log(`[+] Shuffling ${result.length} entries for posting`); - shuffleArray(result); - - return { - ok: true, - detail: `Fetched the data successfully`, - data: result, - users, - errors: undefined, - }; } function shuffleArray(array: T[]): T[] { - for (let i = array.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [array[i], array[j]] = [array[j], array[i]]; - } - return array; + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; } export function rebalancePostDataListByBalanceOfUsers( - balanceCounts: Record, - users: ApiPostUser[], - result: PostDataEntry[], + balanceCounts: Record, + users: ApiPostUser[], + result: PostDataEntry[], ) { - console.log( - `[+] Checking if the users have enough balance to book their assigned data`, - ); - - for (const user of users) { - const usersBalance = user.balance ?? 0; - const dueForUser = balanceCounts[user.userId] ?? 0; - if (usersBalance === 0) { - console.log(`\n[!] ${user.userName} has no balance\n`); - continue; - } - if (usersBalance >= dueForUser) { - console.log( - `[✅] ${user.userName} can book the data of ${usersBalance} > ${dueForUser} `, - ); - continue; - } console.log( - `[!❎!] ${user.userName} can't book it all ${usersBalance} < ${dueForUser}`, + `[+] Checking if the users have enough balance to book their assigned data`, ); - const difference = dueForUser - usersBalance; - let differenceLeft = Number(difference); // make a copy - const entriesToMove = result - .filter((r) => { - if (r.userId === user.userId && differenceLeft > 0) { - differenceLeft -= r.first + r.second; - return true; + for (const user of users) { + const usersBalance = user.balance ?? 0; + const dueForUser = balanceCounts[user.userId] ?? 0; + if (usersBalance === 0) { + console.log(`\n[!] ${user.userName} has no balance\n`); + continue; } - }) - .map((r) => r.id); - console.log(`Have to move ${entriesToMove.length} entries to other users`); + if (usersBalance >= dueForUser) { + console.log( + `[✅] ${user.userName} can book the data of ${usersBalance} > ${dueForUser} `, + ); + continue; + } + console.log( + `[!❎!] ${user.userName} can't book it all ${usersBalance} < ${dueForUser}`, + ); - // find a user who has enough balance + const difference = dueForUser - usersBalance; + let differenceLeft = Number(difference); // make a copy + const entriesToMove = result + .filter((r) => { + if (r.userId === user.userId && differenceLeft > 0) { + differenceLeft -= r.first + r.second; + return true; + } + }) + .map((r) => r.id); + console.log( + `Have to move ${entriesToMove.length} entries to other users`, + ); - const userWithEnoughBalance = users.find((u) => { - return ( - (u.balance ?? 0) - balanceCounts[u.userId] >= difference && - u.userId !== user.userId - ); - }); - if (!userWithEnoughBalance) { - return { - ok: false, - detail: `No user found with enough balance to cover balance shortage of ${difference} for ${user.userName}`, - data: [], - }; + // find a user who has enough balance + + const userWithEnoughBalance = users.find((u) => { + return ( + (u.balance ?? 0) - balanceCounts[u.userId] >= difference && + u.userId !== user.userId + ); + }); + if (!userWithEnoughBalance) { + return { + ok: false, + detail: `No user found with enough balance to cover balance shortage of ${difference} for ${user.userName}`, + data: [], + }; + } + console.log( + `Dude has enough balance to take on this other user's expenses ': ${JSON.stringify(userWithEnoughBalance)}`, + ); + + for (let i = 0; i < result.length; i++) { + if (!entriesToMove.includes(result[i].id)) { + continue; + } + const entry = result[i]; + let amountMoved = 0; + if (entry.userId !== user.userId) { + continue; + } + entry.userId = userWithEnoughBalance.userId; + balanceCounts[userWithEnoughBalance.userId] += + entry.first + entry.second; + balanceCounts[user.userId] -= entry.first + entry.second; + amountMoved += entry.first + entry.second; + if (amountMoved >= difference) { + // don't move more than the difference' + break; + } + } + console.log( + `[+] Moved ${entriesToMove.length} entries to ${userWithEnoughBalance.userName}`, + ); } - console.log( - `Dude has enough balance to take on this other user's expenses ': ${JSON.stringify(userWithEnoughBalance)}`, - ); - - for (let i = 0; i < result.length; i++) { - if (!entriesToMove.includes(result[i].id)) { - continue; - } - const entry = result[i]; - let amountMoved = 0; - if (entry.userId !== user.userId) { - continue; - } - entry.userId = userWithEnoughBalance.userId; - balanceCounts[userWithEnoughBalance.userId] += entry.first + entry.second; - balanceCounts[user.userId] -= entry.first + entry.second; - amountMoved += entry.first + entry.second; - if (amountMoved >= difference) { - // don't move more than the difference' - break; - } - } - console.log( - `[+] Moved ${entriesToMove.length} entries to ${userWithEnoughBalance.userName}`, - ); - } } export async function fetchPostDataHistory(input: PostDataHistoryFilters) { - const { draw, date } = input; - console.log(`Fetching post data from HISTORY for draw: ${date} - ${draw.id}`); - const found = await dbApiPostData.getPostDataByDraw(date, draw.id); - if (!found) { - return { data: [], users: [], ok: false, detail: "Data not found" }; - } - console.log( - `Data found for the passed draw: ${date} - ${draw.id}, returning that`, - ); - const users = await dbApiUser.getAllPostUsers(); - const uniqueUserIds = [] as string[]; - for (const each of found) { - if (!each.userId || uniqueUserIds.includes(each.userId)) { - continue; + const { draw, date } = input; + console.log( + `Fetching post data from HISTORY for draw: ${date} - ${draw.id}`, + ); + const found = await dbApiPostData.getPostDataByDraw(date, draw.id); + if (!found) { + return { data: [], users: [], ok: false, detail: "Data not found" }; } - uniqueUserIds.push(each.userId); - } - return { - data: found, - users: users.filter((u) => uniqueUserIds.includes(u.userId)), - ok: true, - detail: "Data found", - }; + console.log( + `Data found for the passed draw: ${date} - ${draw.id}, returning that`, + ); + const users = await dbApiUser.getAllPostUsers(); + const uniqueUserIds = [] as string[]; + for (const each of found) { + if (!each.userId || uniqueUserIds.includes(each.userId)) { + continue; + } + uniqueUserIds.push(each.userId); + } + return { + data: found, + users: users.filter((u) => uniqueUserIds.includes(u.userId)), + ok: true, + detail: "Data found", + }; } diff --git a/src/lib/trpc/routers/apiauth.router.ts b/src/lib/trpc/routers/apiauth.router.ts index a8ba903..109ac18 100755 --- a/src/lib/trpc/routers/apiauth.router.ts +++ b/src/lib/trpc/routers/apiauth.router.ts @@ -7,108 +7,110 @@ import { z } from "zod"; import { dbApiUser } from "$lib/server/db/apiuser.db"; import type { ServerError } from "$lib/utils/data.types"; import { - isSessionValidInStore, - removeSessionFromStore, - setSessionToRedis, + isSessionValidInStore, + removeSessionFromStore, + setSessionToRedis, } from "$lib/server/utils/session.service"; 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.", - }); - } - }), - - 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; + 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.", + }); } - 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) }; - }), + 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(); - logoutUser: protectedProcedure - .input(z.object({ userId: z.string().optional() })) - .mutation(async ({ input }) => { - const { userId } = input; - await removeSessionFromStore(userId); - return { success: true, errors: [] as ServerError }; - }), + 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 }; + }), }); diff --git a/src/lib/trpc/routers/apidata.router.ts b/src/lib/trpc/routers/apidata.router.ts index cc9a5f7..6dad11b 100755 --- a/src/lib/trpc/routers/apidata.router.ts +++ b/src/lib/trpc/routers/apidata.router.ts @@ -7,181 +7,192 @@ import { getReducedFinalSheet } from "$lib/server/finalsheet.helpers"; import { getDefaultTotals, getULID } from "$lib/utils"; import { constants } from "$lib/utils/constants"; import { - ApiUserTypes, - type APISession, - type ReducedFinalSheetData, - type ServerError, + ApiUserTypes, + type APISession, + type ReducedFinalSheetData, + type ServerError, } from "$lib/utils/data.types"; import { z } from "zod"; import { createTRPCRouter, protectedProcedure } from "../t"; const lastFetched = { - get: async () => { - const out = await redis.get(constants.LAST_FETCHED_KEY); - if (out === null) { - return "Not fetched yet"; - } - return out; - }, - set: async () => { - await redis.set(constants.LAST_FETCHED_KEY, new Date().toISOString()); - }, + get: async () => { + const out = await redis.get(constants.LAST_FETCHED_KEY); + if (out === null) { + return "Not fetched yet"; + } + return out; + }, + set: async () => { + await redis.set(constants.LAST_FETCHED_KEY, new Date().toISOString()); + }, }; export const apiDataRouter = createTRPCRouter({ - getDealersAndDraws: protectedProcedure.query(async () => { - const draws = await dbDraw.getAllDraws(true); - const dealers = await dbApiUser.allUsersOfType(ApiUserTypes.DEALER); - const lf = await lastFetched.get(); - return { users: dealers, draws, lastFetched: lf }; - }), - - refetchData: protectedProcedure - .input( - z.object({ - userIds: z.array(z.string()), - drawId: z.string(), - targetDate: z.string(), - }), - ) - .mutation(async ({ input }) => { - const { userIds, targetDate, drawId } = input; - if (userIds.length < 1) { - return { - detail: "No users selected", - success: false, - errors: [ - { message: "No users selected to refetch data for" }, - ] as ServerError, - }; - } - const sess = JSON.parse( - (await redis.get(constants.SCRAP_API_SESSION_KEY)) ?? "", - ) as APISession; - if (sess === null) { - return { - detail: "API Session expired", - success: false, - errors: [ - { - message: - "API Session expired, get a new api session and try again", - }, - ] as ServerError, - }; - } - const userIdsInt = userIds.map((x) => parseInt(x.split(":")[1])); - const out = await getData( - sess.sessionToken, - userIdsInt, - parseInt(drawId.split(":")[1]), - targetDate, - ); - if (!out.ok) { - return { - success: false, - detail: "Error fetching data", - errors: [{ message: out.message }] as ServerError, - }; - } - const dataCount = out.data.length; - await dbApiData.upsertData(out.data, targetDate); - return { - detail: `Scraped ${dataCount} entries for ${userIds.length} users`, - success: true, - errors: [] as ServerError, - }; + getDealersAndDraws: protectedProcedure.query(async () => { + const draws = await dbDraw.getAllDraws(true); + const dealers = await dbApiUser.allUsersOfType(ApiUserTypes.DEALER); + const lf = await lastFetched.get(); + return { users: dealers, draws, lastFetched: lf }; }), - getDataByFilters: protectedProcedure - .input( - z.object({ date: z.string(), drawId: z.string(), userId: z.string() }), - ) - .mutation(async ({ input }) => { - const { date, drawId, userId } = input; - const data = await dbApiData.getBookingEntriesForDealer( - date, - drawId.split(":")[1], - userId.split(":")[1], - true, - ); - return { data }; + refetchData: protectedProcedure + .input( + z.object({ + userIds: z.array(z.string()), + drawId: z.string(), + targetDate: z.string(), + }), + ) + .mutation(async ({ input }) => { + const { userIds, targetDate, drawId } = input; + if (userIds.length < 1) { + return { + detail: "No users selected", + success: false, + errors: [ + { message: "No users selected to refetch data for" }, + ] as ServerError, + }; + } + const sess = JSON.parse( + (await redis.get(constants.SCRAP_API_SESSION_KEY)) ?? "", + ) as APISession; + if (sess === null) { + return { + detail: "API Session expired", + success: false, + errors: [ + { + message: + "API Session expired, get a new api session and try again", + }, + ] as ServerError, + }; + } + console.log( + `Fetching data for ${userIds.length} users for draw ${drawId}`, + ); + const userIdsInt = userIds.map((x) => parseInt(x.split(":")[1])); + const out = await getData( + sess.sessionToken, + userIdsInt, + parseInt(drawId.split(":")[1]), + targetDate, + ); + if (!out.ok) { + return { + success: false, + detail: "Error fetching data", + errors: [{ message: out.message }] as ServerError, + }; + } + const dataCount = out.data.length; + await dbApiData.upsertData(out.data, targetDate); + return { + detail: `Scraped ${dataCount} entries for ${userIds.length} users`, + success: true, + errors: [] as ServerError, + }; + }), + + getDataByFilters: protectedProcedure + .input( + z.object({ + date: z.string(), + drawId: z.string(), + userId: z.string(), + }), + ) + .mutation(async ({ input }) => { + const { date, drawId, userId } = input; + const data = await dbApiData.getBookingEntriesForDealer( + date, + drawId.split(":")[1], + userId.split(":")[1], + true, + ); + return { data }; + }), + + getReducedFinalSheet: protectedProcedure + .input(z.object({ date: z.string(), drawId: z.string() })) + .mutation(async ({ input }) => { + const { date, drawId } = input; + const draw = await dbDraw.getDraw(drawId); + const fsData = { + id: getULID(), + date, + drawId, + data: [], + totals: getDefaultTotals(), + } as ReducedFinalSheetData; + if (!draw) { + return { + ok: false, + detail: `Draw for the passed draw ID not found`, + data: fsData, + errors: [ + { message: `Draw for the passed draw ID not found` }, + ] as ServerError, + }; + } + console.log("Fetching data"); + const data = await getReducedFinalSheet(fsData); + console.log(data); + if (!data.ok) { + return { + ok: false, + detail: `Error compiling final sheet`, + data: fsData, + errors: data.errors, + }; + } + return { + ok: true, + detail: `Final sheet for ${date}, draw ${draw.title} has been compiled`, + data: fsData, + errors: [] as ServerError, + }; + }), + + getFinalSheetRow: protectedProcedure + .input( + z.object({ + date: z.string(), + drawId: z.string(), + number: z.string(), + }), + ) + .mutation(async ({ input }) => { + return { + ok: true, + data: {}, + errors: [] as ServerError, + }; + }), + + delDataOlderThan2Weeks: protectedProcedure.mutation(async () => { + await dbApiData.deleteDataOlderThan2Weeks(); + return { ok: true, detail: "Data older than 2 weeks has been deleted" }; }), - getReducedFinalSheet: protectedProcedure - .input(z.object({ date: z.string(), drawId: z.string() })) - .mutation(async ({ input }) => { - const { date, drawId } = input; - const draw = await dbDraw.getDraw(drawId); - const fsData = { - id: getULID(), - date, - drawId, - data: [], - totals: getDefaultTotals(), - } as ReducedFinalSheetData; - if (!draw) { - return { - ok: false, - detail: `Draw for the passed draw ID not found`, - data: fsData, - errors: [ - { message: `Draw for the passed draw ID not found` }, - ] as ServerError, - }; - } - console.log("Fetching data"); - const data = await getReducedFinalSheet(fsData); - console.log(data); - if (!data.ok) { - return { - ok: false, - detail: `Error compiling final sheet`, - data: fsData, - errors: data.errors, - }; - } - return { - ok: true, - detail: `Final sheet for ${date}, draw ${draw.title} has been compiled`, - data: fsData, - errors: [] as ServerError, - }; - }), - - getFinalSheetRow: protectedProcedure - .input( - z.object({ date: z.string(), drawId: z.string(), number: z.string() }), - ) - .mutation(async ({ input }) => { - return { - ok: true, - data: {}, - errors: [] as ServerError, - }; - }), - - delDataOlderThan2Weeks: protectedProcedure.mutation(async () => { - await dbApiData.deleteDataOlderThan2Weeks(); - return { ok: true, detail: "Data older than 2 weeks has been deleted" }; - }), - - postTestBooking: protectedProcedure - .input(z.object({ drawId: z.string(), date: z.string() })) - .mutation(async () => { - return { - ok: true, - detail: "API not live", - errors: [] as ServerError, - }; - // console.log("GENERATING TEST DATA :: ", drawId, date); - // const testData = await getTestBookingData(drawId, date); - // // console.log(testData); - // await dbApiData.upsertData(testData, date); - // return { - // ok: true, - // detail: "Test booking committed", - // errors: [] as ServerError, - // }; - }), + postTestBooking: protectedProcedure + .input(z.object({ drawId: z.string(), date: z.string() })) + .mutation(async () => { + return { + ok: true, + detail: "API not live", + errors: [] as ServerError, + }; + // console.log("GENERATING TEST DATA :: ", drawId, date); + // const testData = await getTestBookingData(drawId, date); + // // console.log(testData); + // await dbApiData.upsertData(testData, date); + // return { + // ok: true, + // detail: "Test booking committed", + // errors: [] as ServerError, + // }; + }), }); diff --git a/src/lib/trpc/routers/apiuser.router.ts b/src/lib/trpc/routers/apiuser.router.ts index a6622ab..178b84b 100644 --- a/src/lib/trpc/routers/apiuser.router.ts +++ b/src/lib/trpc/routers/apiuser.router.ts @@ -4,34 +4,30 @@ import { dbApiUser } from "$lib/server/db/apiuser.db"; import { z } from "zod"; export const apiUserRouter = createTRPCRouter({ - getAllDistributors: protectedProcedure.query(async () => { - return await dbApiUser.allUsersOfType(ApiUserTypes.DISTRIBUTOR); - }), - getAllDealers: protectedProcedure.query(async () => { - return await dbApiUser.allUsersOfType(ApiUserTypes.DEALER); - }), - getAllDistributorsCount: protectedProcedure.query(async () => { - return await dbApiUser.getUserTypeCount(ApiUserTypes.DISTRIBUTOR); - }), - getAllDealersCount: protectedProcedure.query(async () => { - return await dbApiUser.getUserTypeCount(ApiUserTypes.DEALER); - }), - getDistributorsWithTheirChildren: protectedProcedure.query(async () => { - const users = await dbApiUser.getAllDistributorsWithTheirChildren(); - return { users }; - }), - - getAllDealersPostUserFormat: protectedProcedure.query(async () => { - return await dbApiUser.allUsersOfTypeLimitedInfo(ApiUserTypes.DEALER); - }), - - getAllPostUsers: protectedProcedure.query(async () => { - return await dbApiUser.getAllPostUsers(); - }), - - setPostDataFlagForUser: protectedProcedure - .input(z.object({ users: z.array(zApiPostUser) })) - .mutation(async ({ input }) => { - await dbApiUser.setPostDataFlagForUsers(input.users); + getAllDistributors: protectedProcedure.query(async () => { + return await dbApiUser.allUsersOfType(ApiUserTypes.DISTRIBUTOR); }), + getAllDealers: protectedProcedure.query(async () => { + return await dbApiUser.allUsersOfType(ApiUserTypes.DEALER); + }), + getAllDistributorsCount: protectedProcedure.query(async () => { + return await dbApiUser.getUserTypeCount(ApiUserTypes.DISTRIBUTOR); + }), + getAllDealersCount: protectedProcedure.query(async () => { + return await dbApiUser.getUserTypeCount(ApiUserTypes.DEALER); + }), + + getAllDealersPostUserFormat: protectedProcedure.query(async () => { + return await dbApiUser.allUsersOfTypeLimitedInfo(ApiUserTypes.DEALER); + }), + + getAllPostUsers: protectedProcedure.query(async () => { + return await dbApiUser.getAllPostUsers(); + }), + + setPostDataFlagForUser: protectedProcedure + .input(z.object({ users: z.array(zApiPostUser) })) + .mutation(async ({ input }) => { + await dbApiUser.setPostDataFlagForUsers(input.users); + }), }); diff --git a/src/lib/trpc/routers/booking.router.ts b/src/lib/trpc/routers/booking.router.ts index f4844e7..88c03e8 100755 --- a/src/lib/trpc/routers/booking.router.ts +++ b/src/lib/trpc/routers/booking.router.ts @@ -3,70 +3,70 @@ import { createTRPCRouter, protectedProcedure } from "../t"; import { dbDraw } from "$lib/server/db/apidraw.db"; import { DEFAULT_TZ } from "$lib/utils/constants"; import { - zBookingEntry, - type BookingEntry, - type ServerError, + zBookingEntry, + type BookingEntry, + type ServerError, } from "$lib/utils/data.types"; import { surreal } from "$lib/server/connectors/surreal.db"; import { parseToDateString } from "$lib/utils/datetime.helper.utils"; function getTodaysTableName() { - const today = parseToDateString(new Date()); - return `booking${today.replaceAll("-", "")}`; + const today = parseToDateString(new Date()); + return `booking${today.replaceAll("-", "")}`; } export const bookingRouter = createTRPCRouter({ - getPanelData: protectedProcedure.query(async () => { - const draws = await dbDraw.getAllDraws(true); - const timeInDrawsTz = new Date().toLocaleString("en-US", { - timeZone: DEFAULT_TZ, - }); - return { draws, timeInDrawsTz: timeInDrawsTz }; - }), - - getBookingData: protectedProcedure - .input(z.object({ drawId: z.string() })) - .mutation(async ({ input }) => { - const { drawId } = input; - const date = parseToDateString(new Date()); - const tn = getTodaysTableName(); - const did = parseInt(drawId.split(":")[1]); - const [out] = await surreal.query<[BookingEntry[]]>( - `select * from type::table($table) where drawId = $drawId and bookDate = $bookDate order by requestId desc`, - { table: tn, drawId: did, bookDate: date } - ); - return { data: out.result ?? [], errors: [] as ServerError }; + getPanelData: protectedProcedure.query(async () => { + const draws = await dbDraw.getAllDraws(true); + const timeInDrawsTz = new Date().toLocaleString("en-US", { + timeZone: DEFAULT_TZ, + }); + return { draws, timeInDrawsTz: timeInDrawsTz }; }), - syncBooking: protectedProcedure - .input(z.object({ data: z.array(zBookingEntry) })) - .mutation(async ({ input }) => { - const tableName = getTodaysTableName(); - const syncedEntriesIds = [] as string[]; - if (input.data.length > 0) { - await surreal.insert( - tableName, - input.data.map((e) => { - syncedEntriesIds.push(`${e.id}`); - return { - ...e, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - }) - ); - } - return { detail: "Add Booking api donezo", syncedEntriesIds }; - }), + getBookingData: protectedProcedure + .input(z.object({ drawId: z.string() })) + .mutation(async ({ input }) => { + const { drawId } = input; + const date = parseToDateString(new Date()); + const tn = getTodaysTableName(); + const did = parseInt(drawId.split(":")[1]); + const [out] = await surreal.query<[BookingEntry[]]>( + `select * from type::table($table) where drawId = $drawId and bookDate = $bookDate order by requestId desc`, + { table: tn, drawId: did, bookDate: date }, + ); + return { data: out ?? [], errors: [] as ServerError }; + }), - deleteBooking: protectedProcedure - .input(z.object({ bookingIds: z.array(z.string()) })) - .mutation(async ({ input }) => { - await Promise.all( - input.bookingIds.map(async (id) => { - await surreal.delete(id); - }) - ); - return { detail: `Deleted ${input.bookingIds.length} Entries` }; - }), + syncBooking: protectedProcedure + .input(z.object({ data: z.array(zBookingEntry) })) + .mutation(async ({ input }) => { + const tableName = getTodaysTableName(); + const syncedEntriesIds = [] as string[]; + if (input.data.length > 0) { + await surreal.insert( + tableName, + input.data.map((e) => { + syncedEntriesIds.push(`${e.id}`); + return { + ...e, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + }), + ); + } + return { detail: "Add Booking api donezo", syncedEntriesIds }; + }), + + deleteBooking: protectedProcedure + .input(z.object({ bookingIds: z.array(z.string()) })) + .mutation(async ({ input }) => { + await Promise.all( + input.bookingIds.map(async (id) => { + await surreal.delete(id); + }), + ); + return { detail: `Deleted ${input.bookingIds.length} Entries` }; + }), }); diff --git a/src/lib/trpc/routers/draws.router.ts b/src/lib/trpc/routers/draws.router.ts index 955c364..4b0f745 100755 --- a/src/lib/trpc/routers/draws.router.ts +++ b/src/lib/trpc/routers/draws.router.ts @@ -4,27 +4,28 @@ import { z } from "zod"; import { zDraw } from "$lib/utils/data.types"; export const drawRouter = createTRPCRouter({ - getAllDraws: protectedProcedure.query(async () => { - return await dbDraw.getAllDraws(true); - }), - - getCurrentTime: protectedProcedure.query(async () => { - const now = new Date(); - const timezone = "Asia/Karachi"; - const nowKarachi = new Date( - now.toLocaleString("en-US", { timeZone: timezone }), - ); - // console.log(nowKarachi.toLocaleString()); - return { now: nowKarachi }; - }), - - savePresetInfoForDraws: protectedProcedure - .input(z.object({ draws: z.array(zDraw) })) - .mutation(async ({ input }) => { - // console.log("savePresetInfoForDraws", input); - for (const draw of input.draws) { - await dbDraw.updateDrawPresetInfo(draw); - } - return { success: true }; + getAllDraws: protectedProcedure.query(async () => { + return await dbDraw.getAllDraws(true); }), + + getCurrentTime: protectedProcedure.query(async () => { + const now = new Date(); + const timezone = "Asia/Karachi"; + const nowKarachi = new Date( + now.toLocaleString("en-US", { timeZone: timezone }), + ); + // console.log(nowKarachi.toLocaleString()); + return { now: nowKarachi }; + }), + + savePresetInfoForDraws: protectedProcedure + .input(z.object({ draws: z.array(zDraw) })) + .mutation(async ({ input }) => { + console.log("Saving preset info for draws"); + for (const draw of input.draws) { + await dbDraw.updateDrawPresetInfo(draw); + } + console.log("Done saving preset info for draws"); + return { success: true }; + }), }); diff --git a/src/lib/utils/data.types.ts b/src/lib/utils/data.types.ts index 0838e7f..224fbda 100755 --- a/src/lib/utils/data.types.ts +++ b/src/lib/utils/data.types.ts @@ -1,265 +1,259 @@ import { z } from "zod"; export type Session = { - sId: string; - ip: string; - userAgent: string; - username: string; - userType: string; + sId: string; + ip: string; + userAgent: string; + username: string; + userType: string; }; export type APISession = { - ip: string; - sessionToken: string; - userId: string; + ip: string; + sessionToken: string; + userId: string; }; export const zAuthPayload = z.object({ - username: z.string().min(4).max(64), - password: z.string().min(8).max(64), + username: z.string().min(4).max(64), + password: z.string().min(8).max(64), }); export const zUser = z.object({ - id: z.string().length(16), - createdAt: z.string(), - updatedAt: z.string(), - username: z.string().min(4).max(64), - password: z.string().min(8).max(64), - userType: z.string().min(4).max(5), - association: z.string(), + id: z.string().length(16), + createdAt: z.string(), + updatedAt: z.string(), + username: z.string().min(4).max(64), + password: z.string().min(8).max(64), + userType: z.string().min(4).max(5), + association: z.string(), }); +export type User = z.infer; export const zLooseUser = z.object({ - id: z.string().length(16).optional(), - createdAt: z.string().optional(), - updatedAt: z.string().optional(), - username: z.string().min(4).max(64), - password: z.string().min(8).max(64), - userType: z.string().min(4).max(5), - association: z.string(), + id: z.string().length(16).optional(), + createdAt: z.string().optional(), + updatedAt: z.string().optional(), + username: z.string().min(4).max(64), + password: z.string().min(8).max(64), + userType: z.string().min(4).max(5), + association: z.string(), }); +export type LooseUser = z.infer; export const zApiUser = z.object({ - id: z.string().length(16), - userType: z.number(), - disableBooking: z.string().nullable().optional(), - sendVoucher: z.string().nullable().optional(), - voucherGenerated: z.string().nullable().optional(), - parentAdmin: z.number(), - parentDistributor: z.number(), - userName: z.string(), - userCity: z.string().nullable().optional(), - userId: z.string(), - password: z.string(), - accessDenied: z.number(), - phoneNumber: z.string(), - emailAddress: z.string(), - disable: z.number(), - commission: z.number(), - commissionPangora: z.number(), - allowTitles: z.string(), - specialDealer: z.number(), - allowBalance: z.number(), - balance: z.number(), - profitlossShare: z.number(), - shareProfitonly: z.number(), - allowRemoveold: z.number(), - removeDays: z.number().nullable().optional(), - language: z.number(), - postData: z.boolean().nullable().optional(), - createdAt: z.string().nullable(), - updatedAt: z.string().nullable(), + id: z.string().length(16), + userType: z.number(), + disableBooking: z.string().nullable().optional(), + sendVoucher: z.string().nullable().optional(), + voucherGenerated: z.string().nullable().optional(), + parentAdmin: z.number(), + parentDistributor: z.number(), + userName: z.string(), + userCity: z.string().nullable().optional(), + userId: z.string(), + password: z.string(), + accessDenied: z.number(), + phoneNumber: z.string(), + emailAddress: z.string(), + disable: z.number(), + commission: z.number(), + commissionPangora: z.number(), + allowTitles: z.string(), + specialDealer: z.number(), + allowBalance: z.number(), + balance: z.number(), + profitlossShare: z.number(), + shareProfitonly: z.number(), + allowRemoveold: z.number(), + removeDays: z.number().nullable().optional(), + language: z.number(), + postData: z.boolean().nullable().optional(), + createdAt: z.string().nullable(), + updatedAt: z.string().nullable(), }); +export type ApiUser = z.infer; export const zApiPostUser = z.object({ - id: z.string(), - userName: z.string(), - userId: z.string(), - postData: z.boolean(), - balance: z.number().optional(), + id: z.string(), + userName: z.string(), + userId: z.string(), + postData: z.boolean(), + balance: z.number().optional(), }); +export type ApiPostUser = z.infer; export const zLooseApiUser = z.object({ - id: z.string().length(16).optional(), - userType: z.number().optional(), - disableBooking: z.string().nullable().optional(), - sendVoucher: z.string().nullable().optional(), - voucherGenerated: z.string().nullable().optional(), - parentAdmin: z.number(), - parentDistributor: z.number(), - userName: z.string(), - userCity: z.string().nullable().optional(), - userId: z.string().optional(), - password: z.string(), - accessDenied: z.number(), - phoneNumber: z.string(), - emailAddress: z.string(), - disable: z.number(), - commission: z.number(), - commissionPangora: z.number(), - allowTitles: z.string(), - specialDealer: z.number(), - allowBalance: z.number(), - balance: z.number(), - profitlossShare: z.number(), - shareProfitonly: z.number(), - allowRemoveold: z.number(), - removeDays: z.number().nullable().optional(), - language: z.number().optional(), - postData: z.boolean().nullable().optional(), - createdAt: z.string().nullable().optional(), - updatedAt: z.string().nullable().optional(), + id: z.string().length(16).optional(), + userType: z.number().optional(), + disableBooking: z.string().nullable().optional(), + sendVoucher: z.string().nullable().optional(), + voucherGenerated: z.string().nullable().optional(), + parentAdmin: z.number(), + parentDistributor: z.number(), + userName: z.string(), + userCity: z.string().nullable().optional(), + userId: z.string().optional(), + password: z.string(), + accessDenied: z.number(), + phoneNumber: z.string(), + emailAddress: z.string(), + disable: z.number(), + commission: z.number(), + commissionPangora: z.number(), + allowTitles: z.string(), + specialDealer: z.number(), + allowBalance: z.number(), + balance: z.number(), + profitlossShare: z.number(), + shareProfitonly: z.number(), + allowRemoveold: z.number(), + removeDays: z.number().nullable().optional(), + language: z.number().optional(), + postData: z.boolean().nullable().optional(), + createdAt: z.string().nullable().optional(), + updatedAt: z.string().nullable().optional(), }); +export type LooseApiUser = z.infer; export const zDraw = z.object({ - id: z.string(), - title: z.string(), - closeTime: z.string(), - filterDuplicatesWhilePosting: z.boolean(), - drawType: z.number(), - adminId: z.number(), - abRateF: z.coerce.number(), - abRateS: z.coerce.number(), - abcRateF: z.coerce.number(), - abcRateS: z.coerce.number(), - createdAt: z.string().nullable().optional(), - updatedAt: z.string().nullable().optional(), + id: z.string(), + title: z.string(), + closeTime: z.string(), + filterDuplicatesWhilePosting: z.boolean(), + drawType: z.number(), + adminId: z.number(), + abRateF: z.coerce.number(), + abRateS: z.coerce.number(), + abcRateF: z.coerce.number(), + abcRateS: z.coerce.number(), + createdAt: z.string().nullable().optional(), + updatedAt: z.string().nullable().optional(), }); - export type Draw = z.infer; export const zBookingEntry = z.object({ - id: z.string(), - distributorId: z.number(), - dealerId: z.number(), - drawId: z.number(), - bookDate: z.string(), - number: z.string(), - first: z.number(), - second: z.number(), - changedBalance: z.number(), - sheetName: z.string().nullable().optional(), - sheetId: z.string().nullable().optional(), - requestId: z.string(), - createdAt: z.string().nullable().optional(), - updatedAt: z.string().nullable().optional(), + id: z.string(), + distributorId: z.number(), + dealerId: z.number(), + drawId: z.number(), + bookDate: z.string(), + number: z.string(), + first: z.number(), + second: z.number(), + changedBalance: z.number(), + sheetName: z.string().nullable().optional(), + sheetId: z.string().nullable().optional(), + requestId: z.string(), + createdAt: z.string().nullable().optional(), + updatedAt: z.string().nullable().optional(), }); export type BookingEntry = z.infer; export const zPostDataEntry = z.object({ - id: z.string(), - requestId: z.string().nullable().optional(), - number: z.string(), - first: z.number(), - second: z.number(), - userId: z.string().nullable().optional(), - createdAt: z.string().nullable().optional(), - updatedAt: z.string().nullable().optional(), + id: z.string(), + requestId: z.string().nullable().optional(), + number: z.string(), + first: z.number(), + second: z.number(), + userId: z.string().nullable().optional(), + createdAt: z.string().nullable().optional(), + updatedAt: z.string().nullable().optional(), }); export type PostDataEntry = z.infer; const zPostDataHistory = z.object({ - id: z.string(), - data: z.array(zPostDataEntry), - drawId: z.number(), - bookDate: z.string(), - createdAt: z.string().nullable().optional(), - updatedAt: z.string().nullable().optional(), + id: z.string(), + data: z.array(zPostDataEntry), + drawId: z.number(), + bookDate: z.string(), + createdAt: z.string().nullable().optional(), + updatedAt: z.string().nullable().optional(), }); export type PostDataHistory = z.infer; export const zPresetDataEntry = z.object({ - id: z.string(), - drawId: z.number(), - bookDate: z.string(), - number: z.string(), - first: z.number(), - second: z.number(), - createdAt: z.string().nullable().optional(), - dealerId: z.number().optional().nullable(), + id: z.string(), + drawId: z.number(), + bookDate: z.string(), + number: z.string(), + first: z.number(), + second: z.number(), + createdAt: z.string().nullable().optional(), + dealerId: z.number().optional().nullable(), }); export type PresetDataEntry = z.infer; export const fsPair = z.object({ - first: z.number(), - second: z.number(), + first: z.number(), + second: z.number(), }); export const zLexiCodeCacheObject = z.object({ - number: z.string(), - rate: fsPair, - prize: fsPair, - frequency: fsPair, + number: z.string(), + rate: fsPair, + prize: fsPair, + frequency: fsPair, }); export const reducedFinalSheetRow = z.object({ - id: z.string(), - number: z.string(), - frequency: fsPair, - frequencies: z.object({ - // a: fsPair, - // ab: fsPair, - // abc: fsPair, - // "+abc": fsPair, - // "a+bc": fsPair, - // "ab+c": fsPair, - abcd: fsPair, - }), - rate: fsPair, - prize: fsPair, - profit: fsPair, + id: z.string(), + number: z.string(), + frequency: fsPair, + frequencies: z.object({ + // a: fsPair, + // ab: fsPair, + // abc: fsPair, + // "+abc": fsPair, + // "a+bc": fsPair, + // "ab+c": fsPair, + abcd: fsPair, + }), + rate: fsPair, + prize: fsPair, + profit: fsPair, }); export const zfinalSheetRow = z.object({ - id: z.string(), - number: z.string(), - frequency: fsPair, - rate: fsPair, - prize: fsPair, - profit: fsPair, + id: z.string(), + number: z.string(), + frequency: fsPair, + rate: fsPair, + prize: fsPair, + profit: fsPair, - a: zLexiCodeCacheObject, - xa: zLexiCodeCacheObject, - xxa: zLexiCodeCacheObject, - xxxa: zLexiCodeCacheObject, - ab: zLexiCodeCacheObject, - xab: zLexiCodeCacheObject, - axb: zLexiCodeCacheObject, - xaxb: zLexiCodeCacheObject, - xxab: zLexiCodeCacheObject, - axxb: zLexiCodeCacheObject, - abc: zLexiCodeCacheObject, - xabc: zLexiCodeCacheObject, - axbc: zLexiCodeCacheObject, - abxc: zLexiCodeCacheObject, - abcd: zLexiCodeCacheObject, + a: zLexiCodeCacheObject, + xa: zLexiCodeCacheObject, + xxa: zLexiCodeCacheObject, + xxxa: zLexiCodeCacheObject, + ab: zLexiCodeCacheObject, + xab: zLexiCodeCacheObject, + axb: zLexiCodeCacheObject, + xaxb: zLexiCodeCacheObject, + xxab: zLexiCodeCacheObject, + axxb: zLexiCodeCacheObject, + abc: zLexiCodeCacheObject, + xabc: zLexiCodeCacheObject, + axbc: zLexiCodeCacheObject, + abxc: zLexiCodeCacheObject, + abcd: zLexiCodeCacheObject, }); export type ServerError = Array<{ - message: string; - value?: string; - meta?: any; + message: string; + value?: string; + meta?: any; }>; export const UserTypes = { ADMIN: "ADMIN", USER: "USER" }; export const ApiUserTypes = { ADMIN: 1, DISTRIBUTOR: 2, DEALER: 3 }; -export type User = z.infer; - -export type LooseUser = z.infer; - -export type ApiUser = z.infer; - -export type ApiPostUser = z.infer; - export type ApiPostUserWithParent = ApiPostUser & { - parentAdmin: number; - parentDistributor: number; + parentAdmin: number; + parentDistributor: number; }; -export type LooseApiUser = z.infer; - export type LexiCodeCacheObject = z.infer; export type SimpleLexiCodeObject = { number: string; lexiCode: string }; @@ -271,108 +265,108 @@ export type ReducedFinalSheetRow = z.infer; export type FSPair = z.infer; export type FSTotals = { - rate: FSPair; - prize: FSPair; - commission: FSPair; - netRate: FSPair; - frequency: FSPair; + rate: FSPair; + prize: FSPair; + commission: FSPair; + netRate: FSPair; + frequency: FSPair; }; export type ReducedFinalSheetData = { - id: string; - date: string; - drawId: string; - data: Array; - totals: FSTotals; - createdAt?: string; - updatedAt?: string; + id: string; + date: string; + drawId: string; + data: Array; + totals: FSTotals; + createdAt?: string; + updatedAt?: string; }; export type FinalSheetData = { - id: string; - date: string; - drawId: string; - data: Array; - totals: FSTotals; - createdAt?: string; - updatedAt?: string; + id: string; + date: string; + drawId: string; + data: Array; + totals: FSTotals; + createdAt?: string; + updatedAt?: string; }; export type AuthPayload = z.infer; export type SessionData = { - username: string; - userType: string; + username: string; + userType: string; }; export type BookingInputValues = { - number: string; - default: { first: string; second: string }; - first: Record; - second: Record; + number: string; + default: { first: string; second: string }; + first: Record; + second: Record; }; export const zPostDataHistoryFilters = z.object({ - date: z.string(), - draw: zDraw, + date: z.string(), + draw: zDraw, }); export type PostDataHistoryFilters = z.infer; export const zDDFilters = z.object({ - date: z.string(), - draw: zDraw.optional(), + date: z.string(), + draw: zDraw.optional(), }); export type DDFilters = z.infer; export const zDDUserFilters = z.object({ - date: z.string(), - draw: zDraw.optional(), - user: zApiUser.optional(), + date: z.string(), + draw: zDraw.optional(), + user: zApiUser.optional(), }); export type DDUserFilters = z.infer; export const zPostDataFilters = z.object({ - date: z.string(), - draw: zDraw.optional().nullable(), - minPrize: z.coerce.number(), - maxPrize: z.coerce.number(), - twoDigitRates: fsPair, - threeDigitRates: fsPair, - customData: z.string(), + date: z.string(), + draw: zDraw.optional().nullable(), + minPrize: z.coerce.number(), + maxPrize: z.coerce.number(), + twoDigitRates: fsPair, + threeDigitRates: fsPair, + customData: z.string(), }); export type PostDataFilters = z.infer; export const DEFAULT_RANDOM_DISTRIBUTOR = { - id: "apiuser:6339", - userType: 2, - disableBooking: null, - sendVoucher: null, - voucherGenerated: null, - parentAdmin: 15, - parentDistributor: 0, - userName: "Baba Sagar", - userCity: "Shikar pur", - userId: "317XY3", - password: "405613", - accessDenied: 0, - phoneNumber: "", - emailAddress: "", - disable: 0, - commission: 20.0, - commissionPangora: 20.0, - allowTitles: ",7,8,9,10,11,12,13,14,15,16,30,31,32,", - specialDealer: 0, - allowBalance: 1, - balance: 30094.905, - profitlossShare: 50.0, - shareProfitonly: 0, - allowRemoveold: 0, - removeDays: 30, - language: 0, - createdAt: new Date().toString(), - updatedAt: new Date().toString(), + id: "apiuser:6339", + userType: 2, + disableBooking: null, + sendVoucher: null, + voucherGenerated: null, + parentAdmin: 15, + parentDistributor: 0, + userName: "Baba Sagar", + userCity: "Shikar pur", + userId: "317XY3", + password: "405613", + accessDenied: 0, + phoneNumber: "", + emailAddress: "", + disable: 0, + commission: 20.0, + commissionPangora: 20.0, + allowTitles: ",7,8,9,10,11,12,13,14,15,16,30,31,32,", + specialDealer: 0, + allowBalance: 1, + balance: 30094.905, + profitlossShare: 50.0, + shareProfitonly: 0, + allowRemoveold: 0, + removeDays: 30, + language: 0, + createdAt: new Date().toString(), + updatedAt: new Date().toString(), } as unknown as ApiUser; diff --git a/src/routes/admin/api-controls/+page.server.ts b/src/routes/admin/api-controls/+page.server.ts index 5318572..4119e11 100755 --- a/src/routes/admin/api-controls/+page.server.ts +++ b/src/routes/admin/api-controls/+page.server.ts @@ -2,54 +2,54 @@ import { fail } from "@sveltejs/kit"; import type { Actions } from "../../$types"; import { ApiUserTypes, type ServerError } from "$lib/utils/data.types"; import { - getDealers, - getDistributors, + getDealers, + getDistributors, } from "$lib/server/external/api.scraping.helpers"; import { dbApiUser } from "$lib/server/db/apiuser.db"; import { constants } from "$lib/utils/constants"; -import fs from "fs"; import { getSessionFromStore } from "$lib/server/utils/session.service"; export const actions = { - refetchDistributors: async () => { - const sess = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); - if (!sess) { - return fail(400, { - success: false, - errors: [{ message: "No api session found" }], - }); - } - const done = await getDistributors(sess.sessionToken); - console.log(`[+] ${done.data.length} distributors found`); - // fs.writeFileSync("distributors.json", JSON.stringify(done.data, null, 2)); - if (!done.ok) { - return fail(400, { - success: false, - errors: [{ message: done.message }], - }); - } - await dbApiUser.upsertMany(done.data, true, ApiUserTypes.DISTRIBUTOR); - return { success: true, errors: [] as ServerError }; - }, + refetchDistributors: async () => { + const sess = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); + if (!sess) { + return fail(400, { + success: false, + errors: [{ message: "No api session found" }], + }); + } + const done = await getDistributors(sess.sessionToken); + console.log(`[+] ${done.data.length} distributors found`); + // fs.writeFileSync("distributors.json", JSON.stringify(done.data, null, 2)); + if (!done.ok) { + return fail(400, { + success: false, + errors: [{ message: done.message }], + }); + } + await dbApiUser.upsertMany(done.data, true, ApiUserTypes.DISTRIBUTOR); + return { success: true, errors: [] as ServerError }; + }, - refetchDealers: async () => { - const sess = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); - if (!sess) { - return fail(400, { - success: false, - errors: [{ message: "No api session found" }], - }); - } - const distributor_ids = await dbApiUser.getAllIdsByUserType( - ApiUserTypes.DISTRIBUTOR, - ); - const done = await getDealers(sess.sessionToken, distributor_ids); - console.log(`[+] ${done.dealers.length} dealers found`); - // fs.writeFileSync("dealers.json", JSON.stringify(done.dealers, null, 2)); - if (done.errors.length > 0) { - return fail(400, { success: false, errors: done.errors }); - } - await dbApiUser.upsertMany(done.dealers, true, ApiUserTypes.DEALER); - return { success: true, errors: [] as ServerError }; - }, + refetchDealers: async () => { + const sess = await getSessionFromStore(constants.SCRAP_API_SESSION_KEY); + if (!sess) { + return fail(400, { + success: false, + errors: [{ message: "No api session found" }], + }); + } + const distributor_ids = await dbApiUser.getAllIdsByUserType( + ApiUserTypes.DISTRIBUTOR, + ); + console.log(distributor_ids); + const done = await getDealers(sess.sessionToken, distributor_ids); + console.log(`[+] ${done.dealers.length} dealers found`); + // fs.writeFileSync("dealers.json", JSON.stringify(done.dealers, null, 2)); + if (done.errors.length > 0) { + return fail(400, { success: false, errors: done.errors }); + } + await dbApiUser.upsertMany(done.dealers, true, ApiUserTypes.DEALER); + return { success: true, errors: [] as ServerError }; + }, } satisfies Actions; diff --git a/src/routes/admin/api-controls/fetch-latest-data.svelte b/src/routes/admin/api-controls/fetch-latest-data.svelte index b99812a..0ee8952 100755 --- a/src/routes/admin/api-controls/fetch-latest-data.svelte +++ b/src/routes/admin/api-controls/fetch-latest-data.svelte @@ -40,6 +40,7 @@ let refetchDataM = api.apiData.refetchData.createMutation({ onSuccess: (o) => { + console.log(o); if (!o.success) { for (const each of o.errors) { toast.error(each.message); @@ -49,6 +50,7 @@ } }, onError: (e) => { + console.log(e); toast.error(e.message); }, }); diff --git a/src/routes/admin/post-data-config/+page.svelte b/src/routes/admin/post-data-config/+page.svelte index 0eaf32b..ff00663 100644 --- a/src/routes/admin/post-data-config/+page.svelte +++ b/src/routes/admin/post-data-config/+page.svelte @@ -19,12 +19,12 @@ let updateDrawFilterM = api.draw.savePresetInfoForDraws.createMutation({ onSuccess: (d) => { console.log(d); - toast("Saved successfully."); + toast("Saved successfully"); }, onError: (e) => { console.error(e); toast( - "An error occurred while fetching data. Try again after a page refresh.", + "An error occurred while fetching data. Try again after a page refresh", ); }, });