// ==UserScript== // @name MCBBS自动售卖机 // @namespace https://miaowoo.cc/ // @version 0.8.1 // @description 自动售卖道具 // @author MiaoWoo // @match https://www.mcbbs.net/home.php?mod=magic** // @grant none // ==/UserScript== /* global jq */ (async function () { let store = window.localStorage const lastOrderKey = 'circlebox:lastorder' let params = 0 let checkTimes = 0 let stock = 0 let messagetext = undefined let storeUsername = undefined let gateway = "https://reward.yumc.pw" async function sleep(time) { return new Promise((resolve, reject) => setTimeout(resolve, time)) } function createMenu() { let master = document.createElement('a') master.href = "/home.php?mod=magic&action=mybox&nodeType=master" master.innerText = "售卖机主节点" let slave = document.createElement('a') slave.href = "/home.php?mod=magic&action=mybox&nodeType=slave" slave.innerText = "售卖机子节点" let masterLi = document.createElement('li') masterLi.append(master) let slaveLi = document.createElement('li') slaveLi.append(slave) let tbn = document.getElementsByClassName('tbn')[0].children[1] tbn.append(masterLi) tbn.append(slaveLi) } async function main() { params = location.href.split('?')[1].split('&').map(s => s.split('=')).reduce((pre, cur, index) => { pre[cur[0]] = cur[1]; return pre }, {}) let errorh1 = document.getElementsByTagName('h1')[0] if (errorh1 && errorh1.innerText.startsWith(50)) { return refresh() } setTimeout(refresh, 600000) let taskId = setTimeout(refresh, 60000) createMenu() if (!params.nodeType) { return console.log('nodeType is undefined skip...') } if (!params.action) { return refresh() } console.log(params) try { storeUsername = document.getElementsByClassName('username')[0].innerText messagetext = document.getElementById('messagetext') if (messagetext) { updateStatus(messagetext.innerText) return } else { updateStatus('') } clearTimeout(taskId) switch (params.nodeType) { case "master": master(params) break case "slave": slave(params) break } } catch (ex) { await sleep(1500) refresh() } } async function master(params) { switch (params.action || "shop") { case "shop": await shopAction(params) break case "mybox": stock = await updateStock() await myboxAction(params) break case "log": await logAction(params) break } } async function slave(params) { switch (params.action || "shop") { case "shop": case "log": refresh() break case "mybox": stock = await updateStock() await needReplenishment() break } } async function needReplenishment() { let timeoutTask = setTimeout(() => { refresh() }, 120000) if (stock == 0) { return } let result = await fetch(gateway + '/mcbbs/needReplenishment').then(r => r.json()) if (result.code != 200) { if (++checkTimes > 5) { return refresh() } clearTimeout(timeoutTask) return setTimeout(() => needReplenishment(), 2000) } let masterInfo = result.data sendItem(() => window.showWindow('magics', 'home.php?mod=magic&action=mybox&operation=give&magicid=32', 'get', 0), masterInfo.username, masterInfo.amount || stock) } async function refresh() { try { await fetch('/api/mobile/index.php?version=4&module=credit') location.href = '/home.php?mod=magic&action=mybox&nodeType=' + params.nodeType } catch (error) { setTimeout(refresh, 5000) } } async function shopAction() { await sendOrderAction(() => window.showWindow('magics', 'home.php?mod=magic&action=shop&operation=give&mid=mcbbs_mcserver_plus:serverBump'), true) } async function myboxAction() { await sendOrderAction(() => window.showWindow('magics', 'home.php?mod=magic&action=mybox&operation=give&magicid=32', 'get', 0)) } async function updateStock() { let serverBump = document.getElementById('magic_mcbbs_mcserver_plus:serverBump') let stock = 0 if (serverBump) { stock = serverBump.nextElementSibling.nextElementSibling.children[0].innerText } await fetch(gateway + `/mcbbs/updateStock/username/${storeUsername}/stock/${stock}`).then(r => r.json()) return stock } async function updateStatus(message) { await fetch(gateway + `/mcbbs/updateStatus/username/${storeUsername}/message/${message}`).then(r => r.json()) } async function lowStockNotify(stock, order_id, goods_amount) { await fetch(gateway + `/mcbbs/lowStockNotify/username/${storeUsername}/stock/${stock}/order_id/${order_id}/goods_amount/${goods_amount}`).then(r => r.json()) } async function clearOrderCache(order_id) { await fetch(gateway + '/mcbbs/clearOrderCache/order_id/' + order_id).then(r => r.json()) } async function handleLowStock(order, stock) { if (order.allowAutoBuy) { await clearOrderCache(order.order_id) await sleep(1500) location.href = '/home.php?mod=magic&action=shop&nodeType=' + params.nodeType } else { await lowStockNotify(stock, order.order_id, order.goods_amount) } } async function sendItem(openFn, usernameValue, amountValue) { try { openFn() } catch (ex) { } amountValue = Math.min(stock, amountValue) let username = undefined let count = 0 while ((username = jq('#selectedusername')[0]) == undefined) { if (count > 5) { console.log('检测窗口超时!') return false } await sleep(800) count++ } username.value = usernameValue let amount = username.parentNode.parentNode.nextElementSibling.childNodes[3].childNodes[0] amount.value = amountValue let remark = username.parentNode.parentNode.nextElementSibling.nextElementSibling.childNodes[3].childNodes[0] remark.value = `子节点补货 补货账号: ${storeUsername} 补货数量: ${amountValue}` await sleep(300) jq('#operatesubmit').click() await sleep(500) jq('#fwin_dialog_submit').click() let info = '' let error = '' while ((info = jq('.alert_info').text()) == '') { if (count > 3) { error = jq('#ntcwin').text() break } await sleep(800) count++ } if (error && error.startsWith('抱歉,对方道具包容量不足')) { amountValue = error.replace(/[^0-9]/ig, "") if (amountValue == 0) { return refresh() } await sleep(200) amount.value = amountValue remark.value = `子节点补货 补货账号: ${storeUsername} 补货数量: ${amountValue}` await sleep(300) jq('#operatesubmit').click() await sleep(500) jq('#fwin_dialog_submit').click() } await sleep(800) refresh() } async function sendOrderAction(openFn, back = false) { let timeoutTask = setTimeout(() => { refresh() }, 45000) let count = 0 if (stock < 50) { setTimeout(() => { refresh() }, 15000) } document.getElementById('scbar_txt').value = "订单 第"+(checkTimes+1)+"次 检查中..." let result = await fetch(gateway + '/mcbbs/needSendOrder').then(r => r.json()) if (result.code != 200) { if (checkTimes++ > 10 || back) { refresh() } clearTimeout(timeoutTask) return setTimeout(() => sendOrderAction(openFn), 2000) } let order = result.data if (store.getItem(lastOrderKey) == order.order_id) { let finish = await fetch(gateway + '/mcbbs/updateOrder', { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": order.order_id, "status": 2, "remark": "当前订单可能重复发货 如未到帐 请联系管理员!" }) }).then(r => r.json()) return } try { openFn() } catch (ex) { } if (!order || !order.order_id) { return setTimeout(() => sendOrderAction(openFn), 2000) } console.log(`开始发送订单 ${order.order_id}`) let username = undefined while ((username = jq('#selectedusername')[0]) == undefined) { if (count > 8) { console.log('检测窗口超时!') if (!back) { await handleLowStock(order, stock) } return } await sleep(800) count++ } username.value = order.reciver_name let amount = username.parentNode.parentNode.nextElementSibling.childNodes[3].childNodes[0] amount.value = order.goods_amount let remark = username.parentNode.parentNode.nextElementSibling.nextElementSibling.childNodes[3].childNodes[0] remark.value = `圈云盒子 自动发货订单: ${order.order_id} 物品: ${order.goods_name} 数量: ${order.goods_amount} 发货账号: ${storeUsername}` await sleep(300) jq('#operatesubmit').click() await sleep(500) jq('#fwin_dialog_submit').click() let info = '' let error = '' while ((info = jq('.alert_info').text()) == '') { if (count > 8) { error = jq('#ntcwin').text() break } await sleep(800) count++ } if (error == "抱歉,操作数量不合法") { if (order.goods_amount > stock) { error = `发货账号: ${storeUsername} 库存 ${stock} 不足 ${order.goods_amount} 已通知管理员(QQ: 502647092) 请等待...` } await handleLowStock(order, stock) } try { if (!info && !error) { store.setItem(lastOrderKey, order.order_id) } let finish = await fetch(gateway + '/mcbbs/updateOrder', { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": order.order_id, "status": error ? 3 : 2, "remark": info || error || "未获取到结果!" }) }).then(r => r.json()) console.log(finish) } catch (ex) { console.log(ex) } finally { await sleep(800) refresh() } } async function logAction(params) { switch (params.operation) { case "givelog": await givelogOperation() break } } async function givelogOperation() { let logs = jq('table.dt').children().children().map((index, item) => { let line = jq(item).text().split('\n').filter(f => f) return line.join(' ') }).splice(1)//去除第一行无效数据 console.log(logs) } main() })()