Greasy Fork

来自缓存

Greasy Fork is available in English.

CSGO开箱历史统计

CSGO开箱历统计,清算数量和出金次数。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         CSGO开箱历史统计
// @namespace    csgo_openBoxHistory
// @version      0.1.7
// @description  CSGO开箱历统计,清算数量和出金次数。
// @author       lock
// @match        https://steamcommunity.com/*
// @icon         https://www.google.com/s2/favicons?domain=steamcommunity.com
// @grant        unsafeWindow
// @grant        GM.getValue
// @grant        GM.setValue
// @license      MIT
// ==/UserScript==

const LOG_PREFIX = '[CSGO开箱历史统计]'

const IMSORR = `
<p>尊敬的!#{userName}:</p>
<p style="padding-left: 2em;">我们非常抱歉听到您在开箱子时没有获得您期望的物品。我们理解这可能会令您感到失望。</p>
<p style="padding-left: 2em;">请注意,CSGO的箱子开启是基于随机概率的,每个物品都有一定的概率被获得。我们无法保证每个玩家都能获得他们想要的物品。</p>
<p style="padding-left: 2em;">我们希望您能理解这一点,并继续享受游戏的乐趣和挑战。为了表示感谢您对CSGO的支持,我们决定赠送您一份特别的礼物,一个包含了一些稀有物品的神秘箱子。</p>
<p style="padding-left: 2em;">您可以在游戏内找到它,并用您的钥匙打开它。我们希望您能喜欢这份礼物,并祝您好运!</p>
<p style="padding-left: 2em;">我们感谢您对CSGO的支持,并希望您能继续享受游戏。</p>
<p style="text-align: right;">此致, CSGO团队</p>
`

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

// 定时请求
const RAF = {
  intervalTimer: null,
  timeoutTimer: null,

  setTimeout(cb, interval) {
    // 实现setTimeout功能
    let now = Date.now
    let stime = now()
    let etime = stime
    let loop = () => {
      this.timeoutTimer = requestAnimationFrame(loop)
      etime = now()
      if (etime - stime >= interval) {
        cb()
        cancelAnimationFrame(this.timeoutTimer)
      }
    }
    this.timeoutTimer = requestAnimationFrame(loop)
    return this.timeoutTimer
  },
  clearTimeout() {
    cancelAnimationFrame(this.timeoutTimer)
  },
  setInterval(cb, interval) {
    // 实现setInterval功能
    let now = Date.now
    let stime = now()
    let etime = stime
    let loop = () => {
      this.intervalTimer = requestAnimationFrame(loop)
      etime = now()
      if (etime - stime >= interval) {
        stime = now()
        etime = stime
        cb()
      }
    }
    this.intervalTimer = requestAnimationFrame(loop)
    return this.intervalTimer
  },
  clearInterval() {
    cancelAnimationFrame(this.intervalTimer)
  }
}

const LOAD_INVENTORY_HISTORY = {
  currentPage: 0, // 当前请求页
  lastLoadTime: new Date().getTime(), // 最后请求时间
  checkPageLoadTimer: null,

  /**
   * @description: 页面加载超时检测
   * @return {boolean}
   */
  checkPageLoad() {
    return new Date().getTime() - LOAD_INVENTORY_HISTORY.lastLoadTime > 60 * 1000 ? true : false
  },

  /**
   * @description: 加载全部库存变更历史
   * @param {Number} page
   * @return {*}
   */
  async inventoryHistory_LoadAll(page) {
    $J('#load_more_button').hide()
    if (LOAD_INVENTORY_HISTORY.checkPageLoadTimer == null)
      LOAD_INVENTORY_HISTORY.checkPageLoadTimer = RAF.setInterval(LOAD_INVENTORY_HISTORY.checkPageLoad, 5000)
    if (unsafeWindow.g_historyCursor == null) return

    var request_data = {
      ajax: 1,
      cursor: unsafeWindow.g_historyCursor,
      sessionid: unsafeWindow.g_sessionID
    }

    if (unsafeWindow.g_rgFilterApps && unsafeWindow.g_rgFilterApps.length > 0) {
      request_data.app = unsafeWindow.g_rgFilterApps
    }

    var prevCursor = unsafeWindow.g_historyCursor
    unsafeWindow.g_historyCursor = null

    $J('#inventory_history_loading').show()
    await sleep(1000)
    $J.ajax({
      type: 'GET',
      url: unsafeWindow.g_strProfileURL + '/inventoryhistory/',
      data: request_data,
      timeout: 6000
    })
      .done(function (data) {
        if (data.success) {
          for (var appid in data.apps) {
            unsafeWindow.g_rgAppContextData[appid] = data.apps[appid]
          }

          $J('#inventory_history_count').text(parseInt($J('#inventory_history_count').text()) + data.num)

          if (data.html) {
            var elem_prev = $J('#inventory_history_table').children().last()

            $J('#inventory_history_table').append(data.html)

            var new_elems = elem_prev.nextAll()
            new_elems.hide()
            new_elems.fadeIn(500)

            InventoryHistory_BindTooltips(new_elems, data.descriptions)
          }
          LOAD_INVENTORY_HISTORY.currentPage++
          LOAD_INVENTORY_HISTORY.lastLoadTime = new Date().getTime()
          if (data.cursor) {
            unsafeWindow.g_historyCursor = data.cursor
            $J('#load_more_button').fadeIn(50)
            $J('#check_inventory_history_box').text(`正在清点(${page}页) | `)
            LOAD_INVENTORY_HISTORY.inventoryHistory_LoadAll(LOAD_INVENTORY_HISTORY.currentPage)
          } else {
            $J('#load_more_button').hide()
            RAF.clearInterval(LOAD_INVENTORY_HISTORY.checkPageLoadTimer)
            LOAD_INVENTORY_HISTORY.handleInventoryHistory()
          }
        } else {
          unsafeWindow.g_historyCursor = prevCursor
          $J('#load_more_button').fadeIn(50)
          LOAD_INVENTORY_HISTORY.inventoryHistory_LoadAll(LOAD_INVENTORY_HISTORY.currentPage)
          if (data.error) {
            ShowAlertDialog('错误', data.error, '确定')
          }
        }
      })
      .fail(function (jqXHR, textStatus) {
        unsafeWindow.g_historyCursor = prevCursor
        $J('#load_more_button').fadeIn(50)
        if (textStatus === 'timeout') {
          LOAD_INVENTORY_HISTORY.inventoryHistory_LoadAll(page)
          return
        }
        if (jqXHR.status == 429) {
          console.log(`${LOG_PREFIX}请求页(${page})速率限制,正在重试。原因:您最近作出的请求太多了。请稍候再重试您的请求。`)
          LOAD_INVENTORY_HISTORY.inventoryHistory_LoadAll(page)
        } else {
          ShowAlertDialog('错误', '遍历已停止,服务器返回错误状态,稍后再试。<br>原因:载入您的库存历史记录时出现问题。', '确定')
          RAF.clearInterval(LOAD_INVENTORY_HISTORY.checkPageLoadTimer)
        }
      })
      .always(function () {
        $J('#inventory_history_loading').hide()
      })
  },

  /**
   * @description: 获取开箱统计
   * @return {*}
   */
  boxCount() {
    let results = {
      boxNumber: 0,
      goldNumber: 0,
      capsuleNumber: 0
    }
    $J('.tradehistory_content').each(function () {
      if ($J(this).children('.tradehistory_event_description').text().indexOf('已开启武器箱') == -1) {
        return
      }
      let nodeBoxItem = $J(this).find('.tradehistory_items.tradehistory_items_withimages')
      let openItemName = nodeBoxItem.eq(0).find('.tradehistory_items_group span.history_item_name').eq(0).text()
      let getItemName = nodeBoxItem.eq(1).find('.tradehistory_items_group a span.history_item_name').eq(0).text()

      if (openItemName.indexOf('印花') != -1) {
        results.capsuleNumber++
        return
      }

      if (getItemName.indexOf('★') != -1) {
        results.goldNumber++
      }

      results.boxNumber++
    })
    return results
  },

  /**
   * @description: 处理历史库存变更记录
   * @return {*}
   */
  handleInventoryHistory() {
    const boxStat = LOAD_INVENTORY_HISTORY.boxCount()
    const tips = `已开${boxStat.boxNumber}箱、${boxStat.capsuleNumber}胶囊,箱子出金${boxStat.goldNumber}次`
    $J('#check_inventory_history_box').text(`清点完成(${tips}) | `)
    // 0金非洲人
    if (boxStat.goldNumber == 0) {
      const careMail = IMSORR.replaceAll('!#{userName}', UI.userName)
      ShowAlertDialog('提示', careMail, '确定')
    }
    // 特殊用户
    if (UI.isUserHu() && boxStat.goldNumber == 1) {
      const careMail = IMSORR.replaceAll('!#{userName}', UI.userName)
      ShowAlertDialog('提示', careMail, '确定')
    }
    ShowAlertDialog('清点完成', tips, '确定')
  },

  /**
   * @description: 开始清点历史库存变更
   * @return {*}
   */
  startInventoryHistory() {
    ShowAlertDialog('提示', `正在清点,需要几分钟不等,请稍等...`, '确定')
    LOAD_INVENTORY_HISTORY.inventoryHistory_LoadAll(0)
  }
}

// 与页面交互的逻辑
const UI = {
  userProfilesUrl: null,
  userName: null,
  inventoryHistoryUrl: null,

  initialization() {
    UI.userProfilesUrl = $J('.profile_small_header_name a').attr('href')
    UI.inventoryHistoryUrl = UI.userProfilesUrl + '/inventoryhistory/?app%5B%5D=730&checkBox=1'
    UI.userName = $J('.profile_small_header_name a').text().trim()
  },

  insertCheckButton() {
    return new Promise((resolve, reject) => {
      const steamMenu = $J('.inventory_rightnav')
      if (!steamMenu) {
        console.error(`${LOG_PREFIX} 找不到插入按钮元素`)
        throw new Error(`${LOG_PREFIX} 找不到插入按钮元素 .inventory_rightnav`)
      }
      steamMenu.prepend(
        `<a id="check_inventory_history_box_button" href="${UI.inventoryHistoryUrl}" class="btn_darkblue_white_innerfade btn_medium_wide reload_inventory" style="margin-right:12px"><span>CSGO开箱统计</span></a>`
      )
    })
  },

  insertCheckInfo() {
    return new Promise((resolve, reject) => {
      const steamMenu = $J('.inventory_history_nextbtn')
      if (!steamMenu) {
        console.error(`${LOG_PREFIX} 找不到插入按钮元素`)
        throw new Error(`${LOG_PREFIX} 找不到插入按钮元素 .inventory_history_nextbtn`)
      }
      steamMenu.prepend(`<a id="check_inventory_history_box" href="${UI.inventoryHistoryUrl}'">清点开箱 | </a>`)
    })
  },
  // 库存页面
  isInventory() {
    return window.location.href.includes('/inventory/')
  },
  // 历史库存页面
  isInventoryHistory() {
    return window.location.href.includes('/inventoryhistory/')
  },

  isCheckBox() {
    return window.location.href.includes('&checkBox=1')
  },

  isUserHu() {
    const isUserID = window.location.href.includes('76561198401556084')
    const isUserName = $J('.profile_small_header_name a').text().indexOf('CN-qiezi') != -1
    return isUserID && isUserName
  },

  isStartCheckBox() {}
}

;(function () {
  // 库存页面
  if (UI.isInventory()) {
    UI.initialization()
    UI.insertCheckButton()
  }
  // 历史库存页面
  if (UI.isInventoryHistory()) {
    UI.initialization()
    UI.insertCheckInfo()
    if (UI.isCheckBox()) {
      LOAD_INVENTORY_HISTORY.startInventoryHistory()
    }
  }
})()