Fanatical Bundle Regional Pricing

3/12/2025, 7:04:09 AM

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        Fanatical Bundle Regional Pricing
// @namespace   Violentmonkey Scripts
// @match       https://www.fanatical.com/en/bundle/*
// @match       https://www.fanatical.com/en/pick-and-mix/*
// @grant       none
// @version     1.1.1
// @author      Lex
// @description 3/12/2025, 7:04:09 AM
// ==/UserScript==

const btn = document.createElement("button")
const textArea = document.createElement("textarea")

function formatPrice(price) {
    price = price / 100
    if (price > 100 && (price - Math.floor(price) === 0))
        return price.toFixed(0)
    else
        return price.toFixed(2)
}

function convertPriceObjectToTable(priceObj) {
    const currencies = Object.keys(priceObj)
    let table = `  | ${currencies.join(" | ")}\n`
    table += `:- | ${currencies.map(() => ":-:").join(" | ")}\n`
    const row = `Tier 1 | ` + currencies.map(currency => formatPrice(priceObj[currency])).join(" | ")
    return table + row;
}

function convertTierListToTable(tiers) {
    if (tiers.length === 0) return "No data available";
    const currencies = Object.keys(tiers[0].price);
    let table = `Quantity | ${currencies.join(" | ")}\n`;
    table += `:-: | ${currencies.map(() => ":-:").join(" | ")}\n`;
    let rows = tiers.map(tier => {
        return `${tier.quantity} | ` + currencies.map(currency => formatPrice(tier.price[currency])).join(" | ");
    }).join("\n");
    return table + rows;
}

async function handleShowPricing() {
    console.log("Showing pricing")
    const slug = window.preloadedSlug.slice(1, -1)
    const isPickAndMix = Boolean(document.querySelector("div.PickAndMixProductPage__content__shortDesc"))
    const productType = isPickAndMix ? "pick-and-mix" : "products-group"
    const url = `https://www.fanatical.com/api/${productType}/${slug}/en`
    const response = await fetch(url)
    const json = await response.json()
    console.log(json)
    btn.style.display = "none"
    document.querySelector("section.container,div.PickAndMixProductPage__content__shortDesc").append(textArea)
    textArea.style.width = "600px"
    textArea.style.height = "150px"
    if (isPickAndMix)
        textArea.textContent = convertTierListToTable(json.tiers)
    else
        textArea.textContent = convertPriceObjectToTable(json.bundles[0].price)
}


function createButton() {
    btn.type = "button"
    btn.textContent = "Show Pricing"
    btn.addEventListener("click", handleShowPricing)
    const container = document.querySelector("section.container,div.PickAndMixProductPage__content__shortDesc")
    container.append(btn)
}


function main() {
    createButton()
}

function waitForLoad(query, callback) {
    if (document.querySelector(query)) {
        callback()
    } else {
        setTimeout(waitForLoad.bind(null, query, callback), 100)
    }
}

waitForLoad("section.container,div.PickAndMixProductPage__content__shortDesc", main)