Steam 轻便管理购物车

轻便管理购物车

目前為 2020-07-24 提交的版本,檢視 最新版本

  // ==UserScript==
  // @name         Steam 轻便管理购物车
  // @namespace    http://tampermonkey.net/
  // @version      0.3
  // @description  轻便管理购物车
  // @author       ku mi
  // @include      /https:\/\/store\.steampowered\.com\/(?:wishlist\/(?:profiles|id)|app|bundle|sub)\/*/
  // @grant        GM_addStyle
  // ==/UserScript==

  (function () {
    'use strict'
    const sessionID = g_sessionID
    // 初始化商店页面
    const storeFun = () => {
      const bundleReg = /addBundleToCart\(\s?(\d+)\)/
      const cartReg = /addToCart\(\s?(\d+)\)/
      let cartButton = query('.btn_green_steamui.btn_medium', true)
      if (!cartButton.length) {
        cartButton = query('.btnv6_green_white_innerfade.btn_medium', true)
      }
      cartButton.forEach(item => {
        const subMatch = cartReg.exec(item.href)
        if (!subMatch) {
          if(item.href === 'javascript:addAllDlcToCart();') {
            item.dataset.c_dlcid = query(('[name="subid[]"]'), true).map(it => 'subid[]=' + it.value).join('&')
          } else {
            const bundleidMatch = bundleReg.exec(item.href)
            if(!bundleidMatch) return
            item.dataset.c_bundleid = bundleidMatch[1]
          }
        } else {
          item.dataset.c_subid = subMatch[1]
        }
        item.href = 'javascript:void(0);'
        item.addEventListener('click', async e => {
          let target = e.target
          let res
          if (target.nodeName === 'SPAN') target = target.parentElement
          const sub = target.dataset.c_subid
          const bundleid = target.dataset.c_bundleid
          const dlcid = target.dataset.c_dlcid
          if(dlcid) {
              res = await request({ url: 'https://store.steampowered.com/cart/', method: 'POST', body: `action=add_to_cart&${dlcid}&sessionid=${sessionID}` })
          } else {
              res = await request({ url: 'https://store.steampowered.com/cart/', method: 'POST', body: `action=add_to_cart&${sub ? `subid=${sub}` : `bundleid=${bundleid}`}&sessionid=${sessionID}` })
          }
          getCartItem(res)
        })
      })
    }
    // 初始化愿望单页面
    const wishFun = () => {
      let time = setInterval(() => {
        const wishContent = query('#wishlist_ctn')
        const wishList = wishContent.children
        const changeItem = (wishContent) => {
          ;[...wishContent.children].forEach(item => {
            let cart = query('.btn_medium:not(.already_change)', false, item)
            if (!cart) return
            const { appId } = item.dataset
            const { subs } = g_rgAppInfo[appId]
            const subId = subs.length ? `${subs[0].id}` : ''
            Object.assign(cart.dataset, {c_appid: appId, c_subid: subId})
            cart.href = 'javascript:void(0);'
            cart.classList.add('already_change')
          })
        }
        if (wishList.length) {
          clearInterval(time)
          wishContent.addEventListener('click', async (e) => {
            let target = e.target
            if (target.nodeName === 'IMG' && target.classList.contains('ico_cart')) target = target.parentElement
            if (target.nodeName === 'SPAN') target = target.parentElement
            if (target.classList.contains('already_change')) {
              const sub = target.dataset.c_subid
              if(!sub) return
              const res = await request({ url: 'https://store.steampowered.com/cart/', method: 'POST', body: `action=add_to_cart&subid=${sub}&sessionid=${sessionID}` })
              getCartItem(res)
            }
          })
          function debounce(cb, wishContent) {
            let time = true
            cb(wishContent)
            return () => {
              clearTimeout(time)
              time = setTimeout(() => {
                time = null
                cb(wishContent)
              }, 1000)
            }
          }
          document.onscroll = debounce(changeItem, wishContent)
        }
      }, 2000)
    }
    const cartItemReg = /(?:<input type="hidden" name="cart" value="(\d+)">[\s\S]+?)?(<div class="cart_item">[\s\S]+?<div style="clear: left"><\/div>\s+<\/div>)/igm
    const query = (el, flag, pel = document) => flag ? [...pel.querySelectorAll(el)] : pel.querySelector(el)
    const create = (el, pel) => {
      const ele = document.createElement(el)
      pel.appendChild(ele)
      return ele
    }
    const getCartItem = (htmlStr) => {
      let matchItem = null
      let cart = ''
      let cartHtml = ''
      while (matchItem = cartItemReg.exec(htmlStr)) {
        if (matchItem[1]) cart = matchItem[1]
        cartHtml += matchItem[2]
      }
      cartWrapper.innerHTML = cartHtml
      if(!cartHtml.length) return
      const cartItemList = query('.cart_item', true, _scart)
      cartItemList.forEach(item => item.classList.add('cart_item_add'))
      const aList = query('a:not([href^=javascript])', true, _scart)
      const removeList = query('.remove_link', true, _scart)
      aList.forEach(item => (item.target = '_blank'))
      removeList.forEach(item => {
        const lineitem_gid = item.href.match(/javascript:removeFromCart\('(\d+)'\)/)
        item.href = 'javascript:void(0);'
        item.dataset.lineitem_gid = lineitem_gid[1]
      })
      _scart.onclick = async e => {
        const reamoveA = e.target
        const lineitem_gid = reamoveA.dataset.lineitem_gid
        if (reamoveA.classList.contains('remove_link') && lineitem_gid) {
            const res = await request({ url: 'https://store.steampowered.com/cart/', method: 'POST', body: `action=remove_line_item&sessionid=${sessionID}&lineitem_gid=${lineitem_gid}&cart=${cart}` })
            const cartItem = reamoveA.parentElement.parentElement.parentElement
            cartItem.className = 'cart_item cart_item_remove'
            let time = setTimeout(() => {
                clearTimeout(time)
                cartItem.remove()
            }, 300)
        }
      }
    }
    const request = async ({ url, method, body }) => {
        loading.style.display = 'block'
        const res = await fetch(url, {
            method,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: body || null
        })
        const text = await res.text()
        loading.style.display = 'none'
        return text
      }
    const _scart = create('div', document.body)
    _scart.id = 'mini_cart'
    _scart.innerHTML = `<div class="mini_ul"><div class="button_option"><button class="to_hide">显示</button><button class="to_cart">去购物车</button><button class="to_removeAll">移除所有</button></div><div class="mini_loading"></div><div class="cart_wrapper"></div></div>`
    const cartWrapper = query('.cart_wrapper', false, _scart)
    const toCart = query('.to_cart', false, _scart)
    const toRemoveAll = query('.to_removeAll', false, _scart)
    const toHide = query('.to_hide', false, _scart)
    const loading = query('.mini_loading', false, _scart)
    toHide.onclick = e => {
      const flag = e.target.innerText === '隐藏'
      _scart.classList.add(flag ? 'to_transform_hiden' : 'to_transform_show')
      _scart.classList.remove(flag ? 'to_transform_show' : 'to_transform_hiden')
      e.target.innerText = flag ? '显示' : '隐藏'
    }
    toRemoveAll.onclick = () => {
        ShowConfirmDialog( '', '您确定要移除所有您购物车中的物品吗?', '是', '否').done( () => {
            const date = new Date();
            date.setTime(date.getTime() - 10 * 24 * 60 * 60 * 1000)
            const expires = "expires=" + date.toUTCString()
            document.cookie = 'shoppingCartGID=-1; ' + expires + '; path=/'
            query('.cart_item', true, _scart).forEach(item => {
                item.className = 'cart_item cart_item_remove'
            })
            let time = setTimeout(() => {
                clearTimeout(time)
                getCartItem('')
            }, 300)
            } );
    }
    toCart.onclick = () => window.open('https://store.steampowered.com/cart/')
    // 初始化第一次购物车
    request({ url: 'https://store.steampowered.com/cart/', method: 'GET' }).then(res => getCartItem(res))
    if (location.pathname.startsWith('/wishlist/')) {
      wishFun()
    } else {
      storeFun()
    }
      GM_addStyle(`.cart_item_remove{animation:removeitem .3s forwards;transform-origin:center;}.cart_item_add{animation:additem .3s forwards;transform-origin:center;}@keyframes additem{from{transform:scale(0);}to{transform:scale(1);}}@keyframes removeitem{to{transform:scale(0);}}.mini_ul .mini_loading{background-image:url(https://steamcommunity-a.akamaihd.net/public/images/login/throbber.gif);width:32px;height:32px;margin:0 auto 10px;display:none;}#mini_cart{border-radius:10px;position:fixed;width:300px;z-index:999;height:550px;right:0;bottom:0;background-color:rgba(0,0,0,.3);padding:0 15px 0 15px;box-sizing:border-box;transform:translateY(500px);}.mini_ul .cart_item{display:flex;margin-bottom:20px;}.mini_ul .cart_item_price_container{order:1;flex:1;}.mini_ul .original_price.price{text-decoration:line-through;}.mini_ul .cart_item_desc{margin:0 15px;flex:2;display:flex;width:70px;flex-direction:column;}.mini_ul .cart_item_desc a{width:100%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;}.mini_ul .cart_item_desc br{display:none;}.mini_ul .cart_item_desc_ext{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;color:#ffcc6a;}.mini_ul .cart_item_img{flex-basis:120px;}.mini_ul .cart_wrapper{height:500px;overflow-y:auto;}.mini_ul .button_option{display:flex;justify-content:space-around;margin:10px 0;}.mini_ul .button_option > button{border:none;outline:none;background-image:linear-gradient( to right,#47bfff 5%,#1a44c2 60%);color:#A4D7F5;margin-bottom:10px;font-size:12px;border-radius:7px;padding:5px 8px;width:70px;cursor:pointer;}.to_transform_hiden{animation:hidenAn .5s forwards;}.to_transform_show{animation:showAn .5s forwards;}@keyframes hidenAn{from{transform:translateY(0);}to{transform:translateY(500px);}}@keyframes showAn{from{transform:translateY(500px);}to{transform:translateY(0px);}}}`)
  })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址