Script to add all items from quixel with a 5 seconds delay after every 10 items to avoid rate limiting
Please refer to this script to see how to use. I've only added a 5 second wait every 10 items being purchased.
Please refer to this script to see how to use. I've only added a 5 second wait every 10 items being purchased.
| (async (startPage = 0, autoClearConsole = true) => { | |
| const getCookie = (name) => { | |
| const value = `; ${document.cookie}`; | |
| const parts = value.split(`; ${name}=`); | |
| if (parts.length === 2) return parts.pop().split(';').shift(); | |
| }; | |
| const waitSeconds = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000)); | |
| const callCacheApi = async (params = {}) => { | |
| const defaultParams = { | |
| page: 0, | |
| maxValuesPerFacet: 1000, | |
| hitsPerPage: 1000, | |
| attributesToRetrieve: ['id', 'name'].join(','), | |
| }; | |
| const response = await fetch('https://proxy-algolia-prod.quixel.com/algolia/cache', { | |
| headers: { | |
| 'x-api-key': '2Zg8!d2WAHIUW?pCO28cVjfOt9seOWPx@2j', | |
| }, | |
| body: JSON.stringify({ | |
| url: 'https://6UJ1I5A072-2.algolianet.com/1/indexes/assets/query?x-algolia-application-id=6UJ1I5A072&x-algolia-api-key=e93907f4f65fb1d9f813957bdc344892', | |
| params: new URLSearchParams({ ...defaultParams, ...params }).toString(), | |
| }), | |
| method: 'POST', | |
| }); | |
| return await response.json(); | |
| }; | |
| const callAcl = async ({ id, name }, index) => { | |
| if (index % 10 === 0) { | |
| console.log(' --> Current index:', index, 'Waiting 5 seconds to avoid rate limit...'); | |
| await waitSeconds(5); | |
| } | |
| const response = await fetch('https://quixel.com/v1/acl', { | |
| headers: { | |
| authorization: 'Bearer ' + authToken, | |
| 'content-type': 'application/json;charset=UTF-8', | |
| }, | |
| body: JSON.stringify({ assetID: id }), | |
| method: 'POST', | |
| }); | |
| const json = await response.json(); | |
| if (json?.isError) { | |
| console.error(` --> **UNABLE TO ADD ITEM** Item ${id} | ${name} (${json?.msg})`); | |
| } else { | |
| console.log(` --> ADDED ITEM Item ${id} | ${name}`); | |
| } | |
| }; | |
| const callAcquired = async () => { | |
| const response = await fetch('https://quixel.com/v1/assets/acquired', { | |
| headers: { | |
| authorization: 'Bearer ' + authToken, | |
| 'content-type': 'application/json;charset=UTF-8', | |
| }, | |
| method: 'GET', | |
| }); | |
| return await response.json(); | |
| }; | |
| // 1. Check token exist, quixel API needs it | |
| console.log('-> Checking Auth API Token...'); | |
| let authToken = ''; | |
| try { | |
| const authCookie = getCookie('auth') ?? '{}'; | |
| authToken = JSON.parse(decodeURIComponent(authCookie))?.token; | |
| if (!authToken) { | |
| return console.error('-> Error: cannot find authentication token. Please login again.'); | |
| } | |
| } catch (_) { | |
| return console.error('-> Error: cannot find authentication token. Please login again.'); | |
| } | |
| // 2. Get all currently acquired items | |
| console.log('-> Get Acquired Items...'); | |
| const acquiredItems = (await callAcquired()).map((a) => a.assetID); | |
| // 3. Get total count of items | |
| console.log('-> Getting Total Number of Pages....'); | |
| const { nbPages: totalPages, hitsPerPage: itemsPerPage, nbHits: totalItems } = await callCacheApi(); | |
| console.log('-> =============================================='); | |
| console.log(`-> Total # of items: ${totalItems}`); | |
| console.log(`-> ${totalPages} total pages with ${itemsPerPage} per page`); | |
| console.log(`-> Total Items to add: ${totalItems - acquiredItems.length}.`); | |
| console.log('-> =============================================='); | |
| if (!confirm(`Click OK to start adding ${totalItems - acquiredItems.length} items in your account.`)) return; | |
| // Loop | |
| for (let pageIdx = startPage || 0; pageIdx < totalPages; pageIdx++) { | |
| console.log(`-> ======================= PAGE ${pageIdx + 1}/${totalPages} START =======================`); | |
| console.log('-> Getting Items from page ' + (pageIdx + 1) + ' ...'); | |
| const { hits: items } = await callCacheApi({ page: pageIdx }); | |
| console.log('-> Adding non-acquired items...'); | |
| // Filter out owned items | |
| const unownedItems = items.filter((i) => !acquiredItems.includes(i.id)); | |
| for (const item of unownedItems) { | |
| await callAcl(item); | |
| } | |
| // const aclPromises = unownedItems.map(callAcl); | |
| // await Promise.all(aclPromises); | |
| console.log(`-> ======================= PAGE ${pageIdx + 1}/${totalPages} COMPLETED =======================`); | |
| if (autoClearConsole) console.clear(); // Fix the issue that too much log hangs the console. Set autoClearConsole = false to keep the logs | |
| } | |
| console.log('-> Getting new acquired info...'); | |
| // Get acquired items again | |
| const newItemsAcquired = (await callAcquired()).length; | |
| const newTotalCount = (await callCacheApi()).nbHits; | |
| console.log(`-> Completed. Your account now have a total of ${newItemsAcquired} out of ${newTotalCount} items.`); | |
| alert(`-> Your account now have a total of ${newItemsAcquired} out of ${newTotalCount} items.\n\nIf you find some items missing, try refresh the page and run the script again.`); | |
| })(); |