From 984adceabee029c5d18cc21decd2f92cc3178e53 Mon Sep 17 00:00:00 2001 From: 502647092 Date: Wed, 13 Dec 2023 06:56:29 +0000 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=20mt/auto-meal-complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mt/auto-meal-complete | 315 ------------------------------------------ 1 file changed, 315 deletions(-) delete mode 100644 mt/auto-meal-complete diff --git a/mt/auto-meal-complete b/mt/auto-meal-complete deleted file mode 100644 index 76bee79..0000000 --- a/mt/auto-meal-complete +++ /dev/null @@ -1,315 +0,0 @@ -// ==UserScript== -// @name 美团外卖自动出餐 -// @namespace https://circlecloud.ltd/ -// @version 0.0.1 -// @description 自动出餐 -// @author MiaoWoo -// @match https://e.waimai.meituan.com/**region_id=**®ion_version=** -// @icon https://www.google.com/s2/favicons?sz=64&domain=meituan.com -// @grant none -// ==/UserScript== - -(function () { - 'use strict'; - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - function generateRandomString(length) { - var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - var result = ''; - var charactersLength = characters.length; - for (var i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; - } - function convertSecondsToMinutesSeconds(seconds) { - var minutes = Math.floor(seconds / 60); - var remainingSeconds = seconds % 60; - return minutes + "分" + remainingSeconds.toFixed(0) + "秒"; - } - function request(path, params) { - return fetch(`https://e.waimai.meituan.com/${path}?region_id=${cookies.region_id}®ion_version=${cookies.region_version}`, { - "headers": { - "accept": "application/json, text/plain, */*", - "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", - "content-type": "application/x-www-form-urlencoded", - "sec-ch-ua": "\"Microsoft Edge\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"", - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": "\"Windows\"", - "sec-fetch-dest": "empty", - "sec-fetch-mode": "cors", - "sec-fetch-site": "same-origin" - }, - "referrer": "https://e.waimai.meituan.com/new_fe/business_gw", - "referrerPolicy": "unsafe-url", - "body": (new URLSearchParams(params)).toString(), - "method": "POST", - "mode": "cors", - "credentials": "include" - }).then(r => r.json()) - } - async function requestGet(path, params) { - return await fetch(`https://e.waimai.meituan.com/gw/phf${path}?${(new URLSearchParams({ - region_id: cookies.region_id, - region_version: cookies.region_version, - ...params - })).toString()}`, { - "headers": { - "accept": "application/json, text/plain, */*", - "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", - "sec-ch-ua": "\"Microsoft Edge\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"", - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": "\"Windows\"", - "sec-fetch-dest": "empty", - "sec-fetch-mode": "cors", - "sec-fetch-site": "same-origin" - }, - "referrer": "https://e.waimai.meituan.com/new_fe/business_gw", - "referrerPolicy": "unsafe-url", - "body": null, - "method": "GET", - "mode": "cors", - "credentials": "include" - }).then(r => r.json()); - } - function listUnprocessedOrder() { - return request('/gw/api/order/mix/unprocessed/list/common', { - tag: "process", - pageSize: 10, - pageNum: 1, - pageGray: 1, - }) - } - async function completeMealTime(order, cookTime = order.cookTime, tip = order.deliveOnShop ? '骑手已到店' : '骑手未到店') { - let wmOrderViewId = order.wmOrderViewIdStr - let daySeq = order.daySeq - let result = await request('/v2/common/w/reported/completeMealTime', { - wmPoiId: mt.wmPoiId, - wmOrderViewId: wmOrderViewId - }) - debug('订单 #' + daySeq + ' 上报出餐结束.') - mt.submitOrders.push({ - completeTime: new Date().toLocaleTimeString(), - daySn: daySeq, orderId: wmOrderViewId, tip, cookTime - }) - if (mt.submitOrders.length > mt.maxLogOrderLength) { - mt.submitOrders = mt.submitOrders.slice(mt.submitOrders.length - mt.maxLogOrderLength) - } - localStorage.setItem(SubmitOrdersKey, JSON.stringify(mt.submitOrders)) - await sleep(5) - await syncOrders() - return result - } - async function checkCooking() { - if (!mt.processOrders) return - for (const order of mt.processOrders) { - if (order.isFoodDone) continue - order.cookTime -= 5 - order.leftTime -= 5 - order.submitLeft -= 5 - if (order.submitLeft < 0) { - if (order.cookTime < 180) { - console.log(order) - debug('订单 #' + order.daySeq + ' 出餐时间 ' + order.cookTime + 's 小于 ' + 180 + 's 取消自动上报.') - continue - } - if (order.deliveOnShop) { - debug('订单 #' + order.daySeq + ' 骑手已到店.') - debug('订单 #' + order.daySeq + ' 剩余出餐时间 ' + order.leftTime + 's 小于 ' + mt.autoSubmitLeftTimeWhenOnShop + 's 模拟提交出餐.') - } else { - debug('订单 #' + order.daySeq + ' 骑手未到店.') - debug('订单 #' + order.daySeq + ' 剩余出餐时间 ' + order.leftTime + 's 小于 ' + mt.autoSubmitLeftTime + 's 模拟提交出餐.') - } - return await completeMealTime(order, order.cookTime) - } - if (order.submitLeft < 20) { - debug('订单 #' + order.daySeq + ' 还剩 ' + order.leftTime + 's 上报超时 将于 ' + order.submitLeft + 's 后自动上报.') - } else { - updateInfo() - } - } - } - - async function syncPhfOrderMeal(wmOrderViewId) { - let result = await requestGet('/v2/order/receive/processed/r/orderAsyncInfos/v3', { - orderInfos: JSON.stringify([{ - "wmOrderViewId": wmOrderViewId, - "wmPoiId": cookies.wmPoiId, - "cityId": cookies.city_id - }]) - }) - return result.data[wmOrderViewId] - } - async function syncPhfOrderlLgistic(wmOrderViewId) { - let result = await requestGet('/v2/order/receive/processed/r/distribute/list/v2', { - orderInfos: JSON.stringify([{ - "wmOrderViewId": wmOrderViewId, - "wmPoiId": cookies.wmPoiId, - "cityId": cookies.city_id - }]) - }) - return result.data[wmOrderViewId] - } - async function syncOrderInfo(order) { - let now = Math.floor(Date.now() / 1000) - order.wordLogo = '' - order.daySeq = order.commonInfo.wm_poi_order_dayseq - order.cookTime = now - order.commonInfo.confirmTime - order.leftTime = order.commonInfo.confirmTime + 480 - now - if (order.businessType == 1) { - // 获取订单类型 普通订单存在预订单 - order.wordLogo = order.orderInfo.orderInfo.wordLogo || '普' - order.wmOrderViewIdStr = order.orderInfo.orderInfo.wmOrderViewId - order.isFoodDone = !order.orderInfo.mealInfo.foodDoneButtonVo.isShow - order.cookTime = now - order.orderInfo.mealInfo.countDownTimerVo.timerShowVo.preMealBeginTime - order.logisticsStatus = order.orderInfo.logisticsInfo.logisticsProcessVo.processDesc - // 部分数据存在长 结束备餐时间可能是0 需要计算开始时间 + 480(配置的出餐时间) - 当前时间 - if (order.orderInfo.mealInfo.countDownTimerVo.timerShowVo.preMealEndTime) { - order.leftTime = order.orderInfo.mealInfo.countDownTimerVo.timerShowVo.preMealEndTime - now - } else { - order.leftTime = order.orderInfo.mealInfo.countDownTimerVo.timerShowVo.preMealBeginTime + 480 - now - } - if (order.wordLogo == '预' && !order.isFoodDone) { - // 预订单需要从提醒时间开始计算备餐时间 - order.leftTime = order.orderInfo.mealInfo.foodDoneTitleVo.reminderTime + 480 - now - } - order.submitCanClickLimitTime = order.orderInfo.mealInfo.foodDoneButtonVo.buttonClickVo?.canClickLimitTime || 0 - } else if (order.businessType == 2) { - order.wordLogo = '拼' - order.wmOrderViewIdStr = order.orderInfo.wm_order_id_view_str - order.mealInfo = await syncPhfOrderMeal(order.wmOrderViewIdStr) - order.logisticsInfo = await syncPhfOrderlLgistic(order.wmOrderViewIdStr) - order.isFoodDone = order.mealInfo.prepareStauts == 2 || order.phfOperationContent - order.logisticsStatus = order.logisticsInfo.latestLogisticsLogDesc.split(' ')[1] - order.submitCanClickLimitTime = order.mealInfo.buttonTimeLimit - } - order.deliveOnShop = order.logisticsStatus == '骑手已到店' - // 剩余时间取最小出餐时间和剩余出餐时间大的值 - order.submitLeft = Math.max(order.submitCanClickLimitTime - now, - order.leftTime - (order.deliveOnShop ? mt.autoSubmitLeftTimeWhenOnShop : mt.autoSubmitLeftTime)) - } - async function syncOrders() { - let originCount = mt.processOrders.length - let orders = await listUnprocessedOrder() - orders = orders.data.wmOrderList?.map(o => { - o.commonInfo = JSON.parse(o.commonInfo) - o.orderInfo = JSON.parse(o.orderInfo) - return o - }) - await Promise.all(orders.map(syncOrderInfo)) - mt.processOrders = orders || [] - if (originCount != mt.processOrders.length) { - debug('更新订单数据 目前进行中订单: ' + mt.processOrders.length + '个') - } else { - updateInfo() - } - } - function printOrderInfo(order) { - let leftTime = order.submitCanClickLimitTime < Date.now() / 1000 - ? order.submitLeft : order.submitCanClickLimitTime - Date.now() / 1000 - return `订单: #${order.daySeq} ${order.wordLogo} - 出餐状态 ${order.isFoodDone ? '已出餐' : `未出餐(${leftTime.toFixed(0)}s)`} - 配送状态 ${order.logisticsStatus}` - } - function debug(msg) { - mt.logs.push('[' + (new Date().toLocaleTimeString()) + '] ' + msg) - if (mt.logs.length > mt.maxLogLength) { - mt.logs = mt.logs.slice(mt.logs.length - mt.maxLogLength) - } - updateInfo() - } - function updateInfo() { - try { - let title = `${mt.title} Version: ${mt.version} By ${mt.author}` - let configInfo = `当前配置:
-
- 订单 刷新间隔: ${mt.syncInterval}s 检测间隔: ${mt.checkInterval}s
- 出餐 最长时间: ${mt.autoSubmitMaxCookTime}s - 骑手未到店: ${mt.autoSubmitLeftTime}s 骑手已到店: ${mt.autoSubmitLeftTimeWhenOnShop}s
-
` - let orderInfo = `进行中的订单信息 更新时间:${new Date().toLocaleTimeString()}
- ${mt.processOrders.map(printOrderInfo).join('
')}` - let submitInfo = `已自动出餐的订单信息:
-
- ${mt.submitOrders.length - ? mt.submitOrders - .map(o => '[' + o.completeTime + '] 订单: #' + o.daySn - + ' 出餐用时 ' + convertSecondsToMinutesSeconds(o.cookTime) + ' ' + o.tip).join('
') - : '当前没有自动出餐的订单.'} -
` - let logs = `运行日志:
-
- ${mt.logs.join('
')} -
` - window.appContainerNoticeBar.innerHTML = ` -
-
- ${title} -
- ${configInfo} -
-
- ${orderInfo} -
-
-
- ${submitInfo} -
-
- ${logs} -
-
` - } catch (error) { - console.log(msg) - } - } - async function scheduleCheck() { - await checkCooking() - await sleep(mt.checkInterval * 1000) - scheduleCheck() - } - async function main() { - while (!document.getElementById('hashframe')) { - await sleep(300) - } - console.log(`${mt.title} Version: ${mt.version} By ${mt.author}`) - window.appContainerNoticeBar = document.createElement('div') - let iframe = document.getElementById('hashframe') - iframe.parentNode.insertBefore(window.appContainerNoticeBar, iframe) - debug('页面注入成功 开始运行...') - syncOrders() - scheduleCheck() - setInterval(() => syncOrders(), mt.syncInterval * 1000) - } - let cookies = document.cookie.split('; ').map(cookie => cookie.split('=')).reduce((c, [key, value]) => { - c[key] = decodeURIComponent(value); - return c; - }, {}); - var SubmitOrdersKey = 'AutoMealComplete:SubmitOrders' - let mt = { - title: '美团自动出餐', - version: '0.0.5', - author: 'MiaoWoo', - wmPoiId: localStorage.product_local_first_enter_screen, - checkInterval: 5, - syncInterval: 15, - maxLogLength: 20, - maxLogOrderLength: 20, - autoSubmitLeftTime: 260, - autoSubmitMaxCookTime: 420, - autoSubmitLeftTimeWhenOnShop: 280, - logs: [], - processOrders: [], - submitOrders: JSON.parse(localStorage.getItem(SubmitOrdersKey)) || [], - debug: debug, - syncOrders: syncOrders, - } - window.mt = mt - main() -})(); \ No newline at end of file