Greasy Fork

来自缓存

Greasy Fork is available in English.

Steam 轻便管理购物车

轻便管理购物车

当前为 2020-07-23 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

  // ==UserScript==
  // @name         Steam 轻便管理购物车
  // @namespace    http://tampermonkey.net/
  // @version      0.2
  // @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) {
          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
          if (target.nodeName === 'SPAN') target = target.parentElement
          const sub = target.dataset.c_subid
          const bundleid = target.dataset.c_bundleid
          const 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}` : ''
            cart.dataset.c_appid = appId
            cart.dataset.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
              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 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: `snr=1_8_4__cart-remove&action=remove_line_item&sessionid=${sessionID}&lineitem_gid=${lineitem_gid}&cart=${cart}` })
            reamoveA.parentElement.parentElement.parentElement.remove()
        }
      }
    }
    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 = () => {
      const date = new Date();
      date.setTime(date.getTime() + (- 10 * 24 * 60 * 60 * 1000))
      const expires = "expires=" + date.toUTCString()
      document.cookie = 'shoppingCartGID=-1; ' + expires + '; path=/'
      getCartItem('')
    }
    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(`.mini_loading{background-image:url(https://steamcommunity-a.akamaihd.net/public/images/login/throbber.gif);width:32px;height:32px;margin:10px auto; display: none;}#mini_cart{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;overflow-y:auto;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;}.button_option{display:flex;justify-content:space-around;margin:10px 0;}.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);}}}`)
  })();