喜加一

xiawanshe.com一键领取喜加一游戏

// ==UserScript==
// @name 喜加一
// @version v2024-08-09
// @description xiawanshe.com一键领取喜加一游戏
// @author xiawanshetudou
// @match https://*.xiawanshe.com/*
// @match https://xiawanshe.com/*
// @match https://*.epicgames.com/*
// @match https://*.steampowered.com/*
// @license MIT
// @grant none
// @namespace http://tampermonkey.net/
// ==/UserScript==

function postMessage(message) {
  let domain_list = ['https://www.xiawanshe.com', 'https://xiawanshe.com']
  for(let domain of domain_list) {
    console.log('向', domain, '发送消息', message)
    window.opener.postMessage(message, domain);
  }
}


function setLocalData(c_name, value) {
  let expdate = new Date(new Date().getTime() + (3 * 60 * 1000));
  let c_value = escape(value) + "; expires=" + expdate.toUTCString();
  document.cookie = c_name + "=" + c_value;
  window.localStorage.setItem(c_name, value.toString());
}

function getLocalData(c_name) {
  let i, x, y, ARRcookies = document.cookie.split(";");
  for (i = 0; i < ARRcookies.length; i++) {
    x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
    y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
    x = x.replace(/^\s+|\s+$/g, "");
    if (x === c_name) {
      return unescape(y);
    }
  }
  return window.localStorage.getItem(c_name)
}

const xijiayiCookieKey = '_xws_xjy'


function createCenteredModal(htmlContent) {
  // 创建模态背景
  let modal = document.createElement("div");
  modal.style.position = "fixed";
  modal.style.zIndex = "1000";
  modal.style.left = "0";
  modal.style.top = "0";
  modal.style.width = "100%";
  modal.style.height = "100%";
  modal.style.backgroundColor = "rgba(0,0,0,0.4)";
  modal.style.display = "flex";
  modal.style.justifyContent = "center";
  modal.style.alignItems = "center";

  // 创建模态内容容器
  let modalContent = document.createElement("div");
  modalContent.style.background = "#fefefe";
  modalContent.style.padding = "20px";
  modalContent.style.border = "1px solid #888";
  modalContent.style.borderRadius = "5px";
  modalContent.style.boxShadow = "0 4px 8px rgba(0,0,0,0.1)";
  modalContent.style.minWidth = "300px"; // 最小宽度

  // 创建显示HTML内容的容器
  let contentHolder = document.createElement("div");
  contentHolder.innerHTML = htmlContent;
  modalContent.appendChild(contentHolder);

  // 创建确认按钮
  let confirmBtn = document.createElement("button");
  confirmBtn.textContent = "确认";
  confirmBtn.style.background = "#007BFF";
  confirmBtn.style.color = "white";
  confirmBtn.style.border = "none";
  confirmBtn.style.padding = "8px 16px";
  confirmBtn.style.fontSize = "16px";
  confirmBtn.style.borderRadius = "5px";
  confirmBtn.style.cursor = "pointer";
  confirmBtn.style.marginTop = "10px";
  confirmBtn.style.alignSelf = "center";

  confirmBtn.onclick = function () {
    document.body.removeChild(modal);
  };

  // 组装模态窗口
  modalContent.appendChild(confirmBtn);
  modal.appendChild(modalContent);
  document.body.appendChild(modal);
}

// xijiayi_receive 喜加一林领取
function xijiayi_receive() {
  let u = new URL(window.location.href);
  if (!window.opener) {
    return
  }
  window.addEventListener('message', (event) => {
    let data = event.data;
    if (data && event.origin.includes('xiawanshe.com')) {
      console.log('接收到父窗口的消息:', event.origin, event.data);
      if (data.new_url) {
        window.location.href = data.new_url
      } else if (data.close) {
        window.close();
      }
    }
  }, false);
  let idx = parseInt(u.searchParams.get('index'));
  if (isNaN(idx)) {
    console.log('获取出来的idx为空', idx)
    idx = -1;
  }
  let parseIdx = function () {
    let v = getLocalData(xijiayiCookieKey);
    if (v === '' || v === null) {
      return -1;
    }
    return parseInt(v);
  }
  if (u.hostname.includes('steampowered')) {
    if (u.searchParams.get('xijiayi')) {
      setLocalData(xijiayiCookieKey, idx);
      postMessage({
        'url': window.location.href,
        'msg': '喜加一页面',
        'idx': parseIdx()
      });
      if (document.getElementById('account_pulldown')) {
        // 点击领取逻辑
        // postMessage({'url': window.location.href, 'msg': '包含account_pulldown', 'x': Array.from(document.getElementsByClassName('game_purchase_action')).toString()});
        let found = false;
        Array.from(document.getElementsByClassName('game_purchase_action')).forEach(item => {
          // console.log(item.textContent);
          if (item.textContent.includes('-100%')) {
            console.log('找到折扣100%');
            let btn = item.getElementsByClassName('btn_green_steamui btn_medium');
            if (btn) {
              btn[0].click();
              found = true;
            } else {
              postMessage({
                'url': window.location.href,
                'msg': '喜加一页面',
                'data': '已领取,无需重复领取',
                'idx': parseIdx()
              });
            }
          }
        });
        if (!found) {
          postMessage({
            'url': window.location.href,
            'msg': '喜加一页面',
            'data': '已领取,无需重复领取',
            'idx': parseIdx()
          });
        }
      } else {
        postMessage({
          'url': window.location.href,
          'msg': '喜加一页面',
          'data': '领取失败,用户未登录,请先前往<a href="https://store.steampowered.com/" target="_blank">store.steampowered.com</a>登录',
          'idx': parseIdx()
        });
      }
    } else {
      postMessage({
        'url': window.location.href,
        'data': '领取完成',
        'idx': parseIdx()
      });
    }
  } else if (u.hostname.includes('epicgames')) {
    if (u.searchParams.get('xijiayi')) {
      setLocalData(xijiayiCookieKey, idx);
      postMessage({
        'url': window.location.href,
        'msg': '喜加一页面',
        'idx': parseIdx()
      });
      let epicWaitPage = 0;
      const epicInterval = setInterval(function () {
        console.log('epic定时器执行')
        let ele = document.getElementById('dieselReactWrapper');
        if (ele && ele.textContent.toLowerCase().includes('missing account id')) {
          console.log('发现账号未登录, 清理定时器')
          clearInterval(epicInterval);
          postMessage({
            'url': window.location.href,
            'data': '领取失败,用户未登录,请先前往<a href="https://store.epicgames.com/" target="_blank">store.epicgames.com</a>登录',
            'idx': parseIdx()
          });
          return
        }
        let block_ele = document.getElementsByClassName('payment-blocked__container');
        if (Array.from(block_ele).length > 0 ) {
          let msg = document.getElementsByClassName('payment-blocked__container')[0].getElementsByTagName('h2')[0];
          if(!msg) {
            msg = '领取失败'
          } else {
            msg = '领取失败, ' + msg.textContent
          }
          console.log('发现账号无法领取, 清理定时器', msg)
          clearInterval(epicInterval);
          postMessage({
            'url': window.location.href,
            'data': msg,
            'idx': parseIdx()
          });
          return
        }
        const btns = document.getElementsByClassName('payment-order-confirm__btn');
        epicWaitPage += 1;
        console.log('获取下订单按钮', btns);
        postMessage({
          'url': window.location.href,
          'idx': parseIdx(),
          'msg': '发现按钮' + btns.toString()
        });
        if (Array.from(btns).length > 0) {
          console.log('准备点击喜加一按钮');
          postMessage({
            'url': window.location.href,
            'idx': parseIdx(),
            'msg': '准备点击喜加一按钮'
          });
          let hasSubmit = false;
          // window.addEventListener('beforeunload', function (event) {
          //   console.log('页面准备跳转');
          //   if (!hasSubmit) {
          //     postMessage({
          //       'url': window.location.href,
          //       'data': '领取完成',
          //       'idx': parseIdx(),
          //       'msg': 'page_jump'
          //     });
          //     hasSubmit = true;
          //   }
          // });
          clearInterval(epicInterval);
          btns[0].click();
          postMessage({
            'url': window.location.href,
            'idx': parseIdx(),
            'msg': '完成点击'
          });
          let epicWaitResult = 0;
          const epicWaitResultInterval = setInterval(function () {
            if (btns[0] === null || btns[0] === undefined) {
              clearInterval(epicWaitResultInterval);
              postMessage({
                'url': window.location.href,
                'data': '领取完成',
                'idx': parseIdx()
              });
              return
            }
            btns[0].click();
            epicWaitResult += 1;
            let captcha = document.getElementById('h_captcha_challenge_checkout_free_prod');
            if (captcha) {
              let iframes = captcha.getElementsByTagName('iframe');
              let found = true;

              for (let i = 0; i < iframes.length; i++) {
                if (iframes[i].getAttribute('aria-hidden') === 'true' || iframes[i].style.visibility === 'hidden'){
                  found = false;
                  break;
                }
              }
              if (found) {
                // console.log('网页中存在验证码');
                postMessage({
                  'url': window.location.href,
                  'idx': parseIdx(),
                  'msg': '网页中存在验证码'
                });
                if (epicWaitResult > 60) {
                  clearInterval(epicWaitResultInterval);
                  postMessage({
                    'url': window.location.href,
                    'data': '存在验证码,可能未领取成功',
                    'idx': parseIdx()
                  });
                }
              }
            }
            if (epicWaitResult > 20) {
              clearInterval(epicWaitResultInterval);
              postMessage({
                'url': window.location.href,
                'data': '领取完成,但不确定订单状态,请到epic查看',
                'idx': parseIdx()
              });
              return
            }
            const resultText = document.getElementsByClassName('payment-alert__content');
            console.log('获取到的订单结果数据为', resultText)
            if (Array.from(resultText).length > 0 && resultText[0] && resultText[0].textContent) {
              console.log('订单有结果', resultText[0].textContent);
              hasSubmit = true;
              clearInterval(epicWaitResultInterval);
              postMessage({
                'url': window.location.href,
                'data': '领取结果: ' + resultText[0].textContent,
                'idx': parseIdx()
              });
            }
          }, 1000)
        }
      }, 1000);
    }
  } else {
    postMessage({
      'url': window.location.href,
      'data': '未知页面,领取错误',
      'idx': parseIdx()
    });
  }
}

// check_xijiayi_btn 检查页面是否包含喜加一页面并包含喜加一按钮,没有的话创建按钮
function check_xijiayi_btn() {
  const xijiayiElement = document.getElementById('xijiayi');
  if(!xijiayiElement) {
    return
  }

  // 创建按钮
  if (document.getElementById('xijiayi_btn')) {
    return;
  }
  const createBtn = function (id, text) {
    const button = document.createElement('button');
    button.id = id;
    button.textContent = text;
    button.style.background = "#007BFF";
    button.style.color = "white";
    button.style.border = "none";
    button.style.padding = "8px 16px";
    button.style.fontSize = "13px";
    button.style.borderRadius = "5px";
    button.style.cursor = "pointer";
    button.style.marginTop = "10px";
    button.style.alignSelf = "center";
    return button
  }
  const button = createBtn('xijiayi_btn', '一键喜加一入库');
  xijiayiElement.appendChild(button);

  let urls = [];
  let names = [];
  let doing = false;
  let index = 0;
  let results = {};
  let name_urls = {};
  let childWindow = null;

  window.addEventListener('message', (event) => {
    if (event.origin.includes("steampowered.com") || event.origin.includes('epicgames.com')) {
      console.log('收到子窗口的消息:', event.data);
      if (event.data && event.data.data) {
        let new_idx = event.data.idx;
        if(isNaN(new_idx) || new_idx < 0) {
            console.log('未知下标,复用旧下标', new_idx)
            new_idx = index
        }
        if (new_idx >= 0) {
          index = new_idx;
        }
        results[names[new_idx]] = event.data.data;
        index = index + 1;
        console.log('处理下一个index', new_idx, index)
        processUrl();
      }
    }
  }, false);

  function processUrl() {
    if (index >= urls.length) { // 如果处理完所有URL,结束递归
      if (!childWindow) {
        alert("出现异常,请关闭页面并重试");
        return
      }
      doing = false;
      childWindow.postMessage({'close': 1}, 'https://' + new URL(urls[urls.length - 1]).hostname);
      console.log('所有窗口已处理完毕');
      setTimeout(function () {
        let display = '';
        Object.keys(results).forEach(key => {
          let value = results[key];
          display += `<span><a href="${name_urls[key]}" target="_blank">${key}</a> ${value}</span><br/>`;
        })
        createCenteredModal(display);
      }, 1000);
      return;
    }
    const u = new URL(urls[index]);
    u.searchParams.set('xijiayi', '1');
    u.searchParams.set('index', index.toString());
    const url = u.toString();
    if (childWindow) {
      console.log('开始处理url,复用旧窗口', url, names[index], index);
      setTimeout(function () {
        if (childWindow) {
          childWindow.postMessage({'new_url': url}, 'https://' + new URL(urls[index - 1]).hostname);
        }
      }, 1000);
      return
    }
    console.log('开始处理url,创建窗口', url, names[index]);

    // 创建窗口
    const width = 1000;
    const height = 800;
    const left = (window.screen.width / 2) - (width / 2);
    const top = (window.screen.height / 2) - (height / 2);
    const features = `width=${width},height=${height},left=${left},top=${top}`;
    childWindow = window.open(url, 'SmallWindow', features);
    // const newWindow = window.open(url);
    console.log('windows', childWindow);
    if (!childWindow) {
      alert('请设置浏览器上方允许弹出式窗口,或者关闭浏览器禁止弹出式窗口插件,并重新刷新页面');
      return
    }
    childWindow.postMessage({'msg': '打开了窗口'}, 'https://' + u.hostname);
    // 检查新窗口是否关闭
    const checkClosedInterval = setInterval(function () {
      if (childWindow.closed) {
        clearInterval(checkClosedInterval);
        console.log(`窗口已关闭`);
        if (doing) {
          alert('处理中断,窗口被强制关闭,请重试')
        }
        doing = false;
        index = 0;
        childWindow = null;
      }
    }, 1000);
  }

  button.addEventListener('click', function () {
    if (doing) {
      return
    }
    let currentFree = document.getElementById('current_free');
    if (!currentFree) {
      alert("获取不到喜加一")
      return;
    }
    let links = {};
    Array.from(currentFree.getElementsByClassName('link')).forEach(item => {
      if (item.href) {
        links[item.textContent] = item.href;
      }
    });
    if (Object.keys(links).length === 0) {
      alert("获取不到喜加一")
      return;
    }
    Object.keys(links).forEach(key => {
      urls[index] = links[key];
      names[index] = key;
      name_urls[key] = links[key];
      index = index + 1;
    })
    names.forEach(name => {
      results[name] = '未领取';
    })
    index = 0;
    console.log('处理数据', urls, names);

    childWindow = null;
    index = 0;
    doing = true;
    processUrl();
  });
}

(function () {
  'use strict';

  xijiayi_receive();
  check_xijiayi_btn();
  setInterval(function () {
    check_xijiayi_btn();
  }, 1000);
})();