Created
February 13, 2026 14:57
-
-
Save Windowsfreak/0f4b0b727120d6a408a68a832e5cc7b6 to your computer and use it in GitHub Desktop.
Aurum-Partnerstatistik-Export
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (async function () { | |
| class AurumCryptor { | |
| #password; | |
| #iterations; | |
| #encoder; | |
| #decoder; | |
| constructor(password, iterations = 150000) { | |
| if (!password) { | |
| throw new Error("Password is required for key derivation"); | |
| } | |
| this.#password = password; | |
| this.#iterations = iterations; | |
| this.#encoder = new TextEncoder(); | |
| this.#decoder = new TextDecoder(); | |
| } | |
| async deriveKey(salt) { | |
| const baseKey = await window.crypto.subtle.importKey( | |
| "raw", | |
| this.#encoder.encode(this.#password), | |
| "PBKDF2", | |
| false, | |
| ["deriveKey"] | |
| ); | |
| return window.crypto.subtle.deriveKey( | |
| { | |
| name: "PBKDF2", | |
| salt: salt, | |
| iterations: this.#iterations, | |
| hash: "SHA-256" | |
| }, | |
| baseKey, | |
| { | |
| name: "AES-GCM", | |
| length: 256 | |
| }, | |
| false, | |
| ["encrypt", "decrypt"] | |
| ); | |
| } | |
| async decode(encryptedBase64) { | |
| const encryptedBytes = Uint8Array.from(atob(encryptedBase64), (char) => char.charCodeAt(0)); | |
| const salt = encryptedBytes.slice(0, 16); | |
| const iv = encryptedBytes.slice(16, 28); | |
| const ciphertext = encryptedBytes.slice(28); | |
| const aesKey = await this.deriveKey(salt); | |
| const decryptedBytes = await window.crypto.subtle.decrypt( | |
| { | |
| name: "AES-GCM", | |
| iv: iv | |
| }, | |
| aesKey, | |
| ciphertext | |
| ); | |
| return this.#decoder.decode(decryptedBytes); | |
| } | |
| } | |
| const cryptor = new AurumCryptor("default-password"); | |
| async function buildPartnerTree() { | |
| console.log("Starting data extraction..."); | |
| const token = localStorage.getItem("token"); | |
| if (!token) { | |
| console.error("No token found in localStorage. Please ensure you are logged in."); | |
| return; | |
| } | |
| const headers = { | |
| "Accept": "application/json", | |
| "Authorization": `Bearer ${token}` | |
| }; | |
| const delay = ms => new Promise(res => setTimeout(res, ms)); | |
| const backoffs = [10, 20, 40, 80, 120, 240, 360, 480, 600]; | |
| async function fetchAndDecrypt(url, pageInfo = "") { | |
| let attempt = 0; | |
| while (attempt <= backoffs.length) { | |
| const resp = await fetch(url, { headers }); | |
| if (resp.status === 429 && attempt < backoffs.length) { | |
| const waitSeconds = backoffs[attempt]; | |
| console.warn(`Rate limited (429). Waiting ${waitSeconds}s... (Attempt ${attempt + 1})`); | |
| await delay(waitSeconds * 1000); | |
| attempt++; | |
| continue; | |
| } | |
| if (!resp.ok) { | |
| throw new Error(`Fetch ${url} ${pageInfo} failed (status ${resp.status}) after ${attempt} retries`); | |
| } | |
| const raw = await resp.json(); | |
| if (raw.encrypted) { | |
| const decryptedStr = await cryptor.decode(raw.encrypted); | |
| return JSON.parse(decryptedStr); | |
| } | |
| return raw; | |
| } | |
| } | |
| function parseInvest(val) { | |
| if (!val) return 0; | |
| const cleaned = String(val).replace(/\s/g, ''); | |
| return parseFloat(cleaned) || 0; | |
| } | |
| async function getReferralsRecursive(prettyId) { | |
| const partners = []; | |
| const limit = 15; | |
| let page = 1; | |
| let total = 0; | |
| do { | |
| const url = `https://api.aurum.foundation/partners/statistics?limit=${limit}&page=${page}&prettyId=${prettyId}&search=`; | |
| const data = await fetchAndDecrypt(url, `page ${page}`); | |
| total = data.total || 0; | |
| if (data.referrals && Array.isArray(data.referrals)) { | |
| for (const p of data.referrals) { | |
| const node = { | |
| id: p.prettyId, | |
| name: p.name, | |
| rank: (p.rankId || 1) - 1, | |
| invest: parseInvest(p.investmentsAmount), | |
| partners: [] | |
| }; | |
| if (p.referralsCount > 0) { | |
| console.log(`Fetching referrals for ${p.name} (${p.prettyId})...`); | |
| node.partners = await getReferralsRecursive(p.prettyId); | |
| } | |
| partners.push(node); | |
| } | |
| } | |
| page++; | |
| } while (partners.length < total); | |
| return partners; | |
| } | |
| const rankNames = ["Nova", "Voyager", "Vanguard", "Vanguard Pro", "Nexus", "Oracle", "Prime", "Elite", "Magnat", "Mythos", "Legend"]; | |
| function getCsvTree(root) { | |
| const lines = ["id,name,rank,invest,parent,depth"]; | |
| function recurse(node, parentId = "", depth = 0) { | |
| const rankName = rankNames[node.rank] || rankNames[0]; | |
| lines.push(`${node.id},${node.name},${rankName},${node.invest},"${parentId}",${depth}`); | |
| if (node.partners && node.partners.length > 0) { | |
| for (const p of node.partners) { | |
| recurse(p, node.id, depth + 1); | |
| } | |
| } | |
| } | |
| recurse(root); | |
| return lines.join("\n"); | |
| } | |
| try { | |
| const rootData = await fetchAndDecrypt('https://api.aurum.foundation/'); | |
| const user = rootData.user; | |
| const affStats = rootData.affiliateStats || {}; | |
| const resultTree = { | |
| id: user.prettyId, | |
| name: `${user.personal.name} ${user.personal.surname}`.trim(), | |
| rank: (affStats.referralRankId || 1) - 1, | |
| invest: parseInvest(affStats.investAmount), | |
| partners: [] | |
| }; | |
| resultTree.partners = await getReferralsRecursive(""); | |
| console.log("Tree build complete!"); | |
| const section = document.getElementsByTagName("section")[0]; | |
| const jsonResult = JSON.stringify(resultTree, null, 2); | |
| const csvResult = getCsvTree(resultTree); | |
| if (section) { | |
| section.innerHTML = ` | |
| <div style="width: 100%; height: 100%; min-height: 90vh; display: flex; flex-direction: column; gap: 20px;"> | |
| <textarea id="result-json" style="flex: 1; width: 100%; height: 300px; font-family: 'Courier New', monospace; font-size: 14px; padding: 15px; border: 1px solid #ccc; box-sizing: border-box; background: #f9f9f9;">${jsonResult}</textarea> | |
| <textarea id="result-csv" style="flex: 1; width: 100%; height: 300px; font-family: 'Courier New', monospace; font-size: 14px; padding: 15px; border: 1px solid #ccc; box-sizing: border-box; background: #f9f9f9;">${csvResult}</textarea> | |
| </div>`; | |
| } else { | |
| console.log("JSON Result:", jsonResult); | |
| console.log("CSV Result:", csvResult); | |
| } | |
| } catch (error) { | |
| console.error("Error building tree:", error); | |
| } | |
| } | |
| buildPartnerTree(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment