CSGO开箱历史统计

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

// ==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()
    }
  }
})()

QingJ © 2025

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