메가스캔 에셋을 모두 추가하는 스크립트

사용 방법
- 아래 스크립트
run.js
를 복사합니다. - https://quixel.com 에 로그인합니다.
- https://quixel.com/megascans/collections 로 이동합니다.
- 개발자 도구(F12)를 열고 "Console" 탭으로 이동합니다.
- 복사한 스크립트를 붙여넣고
Enter
키를 누릅니다. - 실행을 확인하는 대화 상자가 나타나면 "OK"를 클릭합니다.
((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 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 }) => {
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))
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.`)
})())
자주 발생하는 문제
- "Forbidden" 오류가 발생하는 경우 (새로 고침 후에도 페이지가 계속 "Forbidden" 상태로 표시됨)
- API가 너무 빠르게 추가되어 API의 속도 제한에 걸릴 가능성이 있습니다.
(테스트 결과 약 10페이지 정도, 약 10,000개 항목 후 발생) - 약 10~20분 후에 다시 시도해보세요. https://quixel.com 페이지를 로드할 수 있게 되면,
Common Fixes -> Restart script
을 통해 실행을 계속할 수 있습니다.
- API가 너무 빠르게 추가되어 API의 속도 제한에 걸릴 가능성이 있습니다.
- 스크립트가 멈추는 경우
- 로그가 너무 많이 출력되어 문제가 발생할 수 있습니다.
스크립트를 모니터링하고 "END PAGE X"라는 메시지가 나타나면 페이지 번호를 기록한 후
개발자 도구 콘솔에서 "🚫" 아이콘을 클릭해 콘솔을 지우십시오. Common Fixes -> Restart script
을 통해 실행을 계속할 수 있습니다.
- 로그가 너무 많이 출력되어 문제가 발생할 수 있습니다.
**UNABLE TO ADD ITEM**
오류가 발생하는 경우( )
안에 오류 메시지가 표시됩니다.
오류 메시지가user already owns specified asset at a higher or equal resolution
인 경우,
해당 항목은 이미 계정에 추가된 것입니다.
cannot find authentication token. Please login again
오류가 발생하는 경우- 브라우저 쿠키를 삭제한 후 quixel에 다시 로그인합니다.
에셋 하나를 수동으로 추가해보세요.
성공하면Common Fixes -> Restart script
을 통해 실행을 계속할 수 있습니다.
- 브라우저 쿠키를 삭제한 후 quixel에 다시 로그인합니다.
일반적인 해결 방법
스크립트 재시작
- 스크립트가 실행 중이던 페이지를 기록합니다.
run.js
스크립트를 복사합니다.- 첫 번째 줄에 있는
startPage = 0
을startPage = 10
으로 업데이트합니다.
(예를 들어, 페이지 10에서 멈췄을 경우)
변경 사항
- 초기 스크립트 출시
- 로그를 지워 멈출 확률을 줄이는 업데이트
- 이미 획득한 항목을 건너뛰도록 수정. 로그를 줄임.
스크립트 실행 완료 후 구매된 항목 수를 표시하는 정보 추가.
이제 구매된 항목을 건너뛰므로startPage
를 지정할 필요가 없어짐.
참고 자료