🏠 Home 

Greasy Fork is available in English.

Haru君の蹲票

参考浩劫者12345大佬的脚本


安装此脚本?
// ==UserScript==
// @name         Haru君の蹲票
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  参考浩劫者12345大佬的脚本
// @author       黎騒君
// @match        https://*.youzan.com/*
// @icon         https://img01.yzcdn.cn/v2/image/yz_fc.ico
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==
(async function () {
// 初始化购票信息
var ticketToBuy_regex
try {
ticketToBuy_regex = GM_getValue('autoBuyRegex') ? new RegExp(GM_getValue('autoBuyRegex')) : /电子预售票/;
} catch (error) {
console.log('正则表达式解析失败,正在使用默认值')
ticketToBuy_regex = /电子预售票/;
}
const idcard = GM_getValue('autoBuyIDCard') ? GM_getValue('autoBuyIDCard') : '';
const realname = GM_getValue('autoBuyRealname') ? GM_getValue('autoBuyRealname') : '';
const phonenumber = GM_getValue('autoBuyPhonenumber') ? GM_getValue('autoBuyPhonenumber') : '';
function checkAutoBuyInfo() {
return idcard && idcard.length == 18 && realname && realname.length >= 2 && phonenumber && phonenumber.length == 11
}
function saveAutoBuyInfo() {
console.log('正在保存蹲票配置')
GM_setValue('autoBuyRegex', document.getElementById('settingsRegex').value)
GM_setValue('autoBuyIDCard', document.getElementById('settingsIDCard').value)
GM_setValue('autoBuyRealname', document.getElementById('settingsRealname').value)
GM_setValue('autoBuyPhonenumber', document.getElementById('settingsPhonenumber').value)
location.reload()
}
// 设置按钮和设置界面
const settingsEl = document.createElement('template')
settingsEl.innerHTML = `
<button id="settingsBtn" onclick="document.getElementById('settingsOverlay').style.display = 'block'" style="
position: fixed;
left: 4px;
top: 30%;
border-radius: 25%;
background-color: #0f0;
padding: 8px;
line-height: 1em;
z-index: 999;
">蹲票<br>设置</button>
<div id="settingsOverlay" style="
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 8px;
border: 2px solid;
background-color: white;
overflow: auto;
z-index: 999;
">
<p>票名(支持正则表达式匹配):</p>
<input id="settingsRegex" style="height: initial; background-color: #ff0;" value="${ticketToBuy_regex.source}">
<p>
举例:<br>
所有普票:电子预售票<br>
所有32nd普票:电子预售票.*32<br>
所有32nd 5月1号普票:5月1日电子预售票.*32<br>
所有32nd所有票(包括VIP):32<br>
(正则表达式用于匹配商品标题,如果不会请百度)
</p><br><br>
<p>身份证:</p>
<input id="settingsIDCard" style="height: initial; background-color: #ff0;" value="${idcard}"><br><br>
<p>姓名:</p>
<input id="settingsRealname" style="height: initial; background-color: #ff0;" value="${realname}"><br><br>
<p>手机号:</p>
<input id="settingsPhonenumber" style="height: initial; background-color: #ff0;" value="${phonenumber}"><br>
<button id="settingsSetBtn" style="float: right">确定</button>
</div>
`
document.body.appendChild(settingsEl.content)
document.getElementById('settingsSetBtn').onclick = saveAutoBuyInfo
// 所有商品页
//
if (location.href.includes('/wscshop/feature/goods/all')) {
// 蹲票状态覆盖层
const overlayEl = document.createElement('template')
overlayEl.innerHTML = `
<div id="autoBuyStatus" style="
position: fixed;
left: 8px;
bottom: 8px;
box-sizing: border-box;
max-width: 60%;
max-height: 30%;
padding: 8px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
font-size: 12px;
line-height: 1.2;
overflow: auto;
"></div>
`
document.body.appendChild(overlayEl.content)
// 检查蹲票信息是否正确,不正确则留下提示然后退出
if (!checkAutoBuyInfo()) {
console.log('购票信息有误')
document.getElementById('autoBuyStatus').innerHTML = '请先正确填写蹲票信息!'
document.getElementById('autoBuyStatus').style.fontSize = '20px'
document.getElementById('autoBuyStatus').style.color = '#ff0'
return
}
// 申请浏览器通知权限
Notification.requestPermission().then(() => {
new Notification('蹲票脚本已启动', {
body: '有票时将通过浏览器通知提醒支付',
});
})
// 启动 worker 以便页面挂起时也能继续蹲票
function workerInterval() {
setInterval(() => {
postMessage('')
}, 1000);
}
const workerBlob = URL.createObjectURL(new Blob([`(${workerInterval.toString()})()`], { type: 'application/javascript' }));
const worker = new Worker(workerBlob)
let count = 0
worker.onmessage = () => {
/*
https://shop46404892.youzan.com/wscshop/showcase/goods/allGoods.json?
pageSize=20&
page=1&
offlineId=0&
openIndependentPrice=0&
order=&
json=1&
uuid=a5f75232-3ec1-66c4-5ec2-b0db133d7765&
activityPriceIndependent=1&
order_by=algPVD30&
goodsType=2&
needActivity=0&
clientSource=2&
tagAlias=&
needGroupFilter=false&
needGoodsRank=true&
supportCombo=true&
excludedComboSubType=%5B%22none%22%5D", {
*/
// 获取前20个商品
fetch("/wscshop/showcase/goods/allGoods.json?json=1&order_by=algPVD30", {
"method": "GET",
"credentials": "include"
}).then(response => {
return response.json();
}).then(data => {
// 清空蹲票信息显示
document.getElementById('autoBuyStatus').innerHTML = `正在蹲以下票(${Notification.permission == "granted" ? '浏览器通知已启用' : '请启用浏览器通知以便接收结果'}):<br>`
// 遍历商品
data.data.list.forEach((item) => {
// 匹配商品标题
if (item.title.match(ticketToBuy_regex)) {
// 蹲票状态显示在覆盖层
document.getElementById('autoBuyStatus').innerHTML += `${item.title}&emsp;余票: ${item.totalStock}<br>`
if (item.totalStock > 0) {
// 有票时发送浏览器通知并跳转商品详情页
new Notification('发现有票,请10分钟内前往手动支付', {
body: item.title,
});
document.querySelectorAll('.cap-goods-layout__container>.cap-goods-layout__wrapper>.cap-goods-layout__item').forEach((el) => {
if (el.innerText.match(item.title)) {
console.log('正在打开商品详情页')
el.click()
}
})
}
}
})
count++
document.getElementById('autoBuyStatus').innerHTML += `已蹲票次数:${count}<br>`
})
}
}
if (!checkAutoBuyInfo()) {
console.log('购票信息有误')
return
}
if (location.href.includes('/wscgoods/detail') || location.href.includes('/pay/wscgoods_order')) {
await new Promise(r => setTimeout(r, 1000))
if (!document.querySelector('.goods-title__main-text').innerText.match(ticketToBuy_regex)) {
console.log('商品不匹配,跳过自动点击')
return
}
if (document.querySelector('.mrb__no-goods')) {
console.log('没票了!')
return
}
console.log('正在打开购买页面')
// 两种“立即购买”按钮,其中一种要点击更内层的 div 才可触发购买界面
try {
document.querySelector('.goods-btns__button.button--last .goods-btns__authorize .user-authorize__btn-empty').click()
} catch (error) {
document.querySelector('.goods-btns__button.button--last .goods-btns__authorize').click()
}
await new Promise(r => setTimeout(r, 500))
console.log('正在填写信息')
// 填实名信息(需手动触发 input 刷新变量,blur 事件确认购买价),两种页面通用
document.querySelectorAll('.sku-messages>.tee-view').forEach((el) => {
el.querySelector('.t-cell__value input').focus()
if (el.querySelector('.t-cell__title').innerText.includes('身份证')) {
el.querySelector('.t-cell__value input').value = idcard
}
if (el.querySelector('.t-cell__title').innerText.includes('姓名')) {
el.querySelector('.t-cell__value input').value = realname
}
if (el.querySelector('.t-cell__title').innerText.includes('电话') || el.querySelector('.t-cell__title').innerText.includes('手机')) {
el.querySelector('.t-cell__value input').value = phonenumber
}
el.querySelector('.t-cell__value input').dispatchEvent(new Event('input'))
el.querySelector('.t-cell__value input').dispatchEvent(new Event('blur'))
})
setInterval(() => {
console.log('正在跳转提交订单界面')
// 两种确认购买按钮
try {
document.querySelector('.pay-btn-order').click()
} catch (error) {
document.querySelector('.sku-actions__btn--main').click()
}
}, 500);
}
// 提交订单页面
//
if (location.href.includes('/pay/wsctrade_buy')) {
await new Promise(r => setTimeout(r, 1000))
if (!document.querySelector('.new-goods-list-card__title__text').innerText.match(ticketToBuy_regex)) {
console.log('商品不匹配,跳过自动点击')
return
}
console.log('正在提交订单')
document.querySelector('.submit-bar__button').click()
}
})();