// ==UserScript==
// @name 鼻涕直播专用
// @namespace http://tampermonkey.net/
// @version 0.2
// @author Mag
// @description 一:5到15分钟上一次链接(这个时间最好可以自定义),小黄车一共会挂20个以上的链接 ,不上连接的时候放在后面(20号以后) 二:每次上连接时,需要弹讲解改到1号链接 每8到10秒弹一次 共弹3 次(需要自定义)。第三次弹完取消讲解之后 放到1号链接20秒 后又放到20链接以后
// @license Mag
// @match https://buyin.jinritemai.com/dashboard/live/control*
// @icon https://www.google.com/s2/favicons?sz=64&domain=jinritemai.com
// @grant none
// ==/UserScript==
(function() {
'use strict';
if (document.getElementById("custom-script")) {
console.log("脚本已存在,无需重复添加。");
return;
}
var scriptContainer = document.createElement("script");
scriptContainer.id = "custom-script";
scriptContainer.type = "text/javascript";
function clickButton(button) {
button.click();
}
var buttonContainer = document.createElement("div");
buttonContainer.style.position = "fixed";
buttonContainer.style.top = "50%";
buttonContainer.style.left = "20px";
buttonContainer.style.transform = "translateY(-50%)";
buttonContainer.style.zIndex = "9999";
// 商品序号
var goodIndexInput = document.createElement("input");
goodIndexInput.type = "text";
goodIndexInput.value = "32";
buttonContainer.appendChild(document.createTextNode("主商品序号:"));
buttonContainer.appendChild(goodIndexInput);
buttonContainer.appendChild(document.createElement("br"));
// 录播视频时长
var videoTotalTimeInput = document.createElement("input");
videoTotalTimeInput.type = "number";
videoTotalTimeInput.value = "3600";
buttonContainer.appendChild(document.createTextNode("录播视频时长:"));
buttonContainer.appendChild(videoTotalTimeInput);
buttonContainer.appendChild(document.createElement("br"));
// 录播视频内,即将上链接讲解的节点
var videoSellTimeInput = document.createElement("input");
videoSellTimeInput.type = "text";
videoSellTimeInput.value = "5, 100, 200, 300, 400";
buttonContainer.appendChild(document.createTextNode("上链接的时间节点, 单位是秒:"));
buttonContainer.appendChild(videoSellTimeInput);
buttonContainer.appendChild(document.createElement("br"));
// 每次上链接讲解的时长
var sellDurationInput = document.createElement("input");
sellDurationInput.type = "text";
sellDurationInput.value = "30, 30, 20, 30, 40";
buttonContainer.appendChild(document.createTextNode("上链接的讲解时长, 单位是秒:"));
buttonContainer.appendChild(sellDurationInput);
buttonContainer.appendChild(document.createElement("br"));
var startButton = document.createElement("button");
startButton.textContent = "执行";
buttonContainer.appendChild(startButton);
var stopButton = document.createElement("button");
stopButton.textContent = "终止";
buttonContainer.appendChild(stopButton);
document.body.appendChild(buttonContainer);
var isDragging = false;
var startPosX, startPosY;
// 录播视频总时长
var totalCycleTime = 1200;
// 录播视频内,即将上链接讲解的节点
var pointArrays = [5, 100, 200, 300, 400];
// 一步一秒计时器
var currentTime = 0;
// 每次上链接讲解的时长
var talkTimeArrays = [30, 30, 20, 30, 40];
// 商品初始的位置
var goodInitIndex = 32;
// @Deprecated(暂时不加这个逻辑) 主商品不讲解的时候,副商品处于讲解的状态
var backupGoodsId = "3510715978856188902";
var loopTimeInterval = null;
let findTargetInterval = null;
let talkInterval = null;
let findIdByIndexInterval = null;
buttonContainer.addEventListener("mousedown", function(e) {
isDragging = true;
startPosX = e.clientX - buttonContainer.offsetLeft;
startPosY = e.clientY - buttonContainer.offsetTop;
});
document.addEventListener("mousemove", function(e) {
if (isDragging) {
var offsetX = e.clientX - startPosX;
var offsetY = e.clientY - startPosY;
buttonContainer.style.left = offsetX + "px";
buttonContainer.style.top = offsetY + "px";
}
});
document.addEventListener("mouseup", function() {
isDragging = false;
});
function initInput() {
try {
if (isInputEmpty(goodIndexInput) || isInputEmpty(videoTotalTimeInput) || isInputEmpty(videoSellTimeInput) || isInputEmpty(sellDurationInput)) {
console.log("输入为空")
return false;
}
pointArrays = strArrays2intArrays(videoSellTimeInput.value.split(","));
console.log("pointArrays " + pointArrays)
talkTimeArrays = strArrays2intArrays(sellDurationInput.value.split(","));
console.log("talkTimeArrays " + talkTimeArrays)
if (pointArrays.length != talkTimeArrays.length) {
console.log("videoTotalTimeInput与videoSellTimeInput的长度不匹配")
return false;
}
goodInitIndex = goodIndexInput.value;
totalCycleTime = videoTotalTimeInput.value;
console.log("initInput正常")
return true;
} catch(err) {
console.error(err)
}
return false;
}
function startLoopClick() {
console.log("开始程序")
getProductionId(goodInitIndex, function(goodsId) {
currentTime = 0;
// 一秒的计时器循环
loopTimeInterval = setInterval(function() {
// todo 这里可能用时间戳来计算准确些
currentTime += 1;
console.log("计时器 " + currentTime + "秒");
if (pointArrays.includes(currentTime)) { // 准备上链接
var index = pointArrays.indexOf(currentTime);
console.log("准备上链接");
startTalk(goodsId);
// 上链接结束
setTimeout(function() {
stopTalk(goodsId)
}, talkTimeArrays[index] * 1000);
} else if (totalCycleTime == currentTime) { // 录播视频结束了, 重新开始
stopLoopClick();
startLoopClick();
}
}, 1000);
});
}
function stopLoopClick() {
console.log("结束程序");
clearLoopTimeInterval();
clearFindTargetInterval();
clearTalkInterval();
clearFindIdByIndexInterval();
currentTime = 0;
}
/**
** 讲解商品, 先找到列表中的商品, 修改商品顺序,修改完后,再开始讲解
**/
function startTalk(goodsId) {
console.log("startTalk 开始讲解 " + goodsId);
findTargetGoods(goodsId, function(parentElement) {
setGoodsRank(parentElement, 1, function() {
findTargetGoods(goodsId, function(parentElement) {
realStartTalk(parentElement, goodsId);
})
})
})
}
/**
** 结束上链接
**/
function stopTalk(goodsId) {
console.log("结束上链接 " + goodsId);
findTargetGoods(goodsId, function(parentElement) {
setButtonState(parentElement, false);
setGoodsRank(parentElement, goodInitIndex, function() {
console.log("结束上链接, 商品顺序设置为" + goodInitIndex);
})
});
clearTalkInterval();
}
/**
** 从列表开头遍历寻找商品
**/
function findTargetGoods(goodsId, callback) {
var scoll = document.querySelector('#live-control-goods-list-container > div');
scoll.scrollTop = 0;
var scollTimes = 1;
findTargetInterval = setInterval(function() {
var parentElement = document.querySelector('[data-rbd-draggable-id="' + goodsId + '"]');
if (parentElement) { // 找到商品了, 开始讲解
console.log("startTalk, 找到商品", "good id = ", goodsId);
clearFindTargetInterval();
callback(parentElement);
} else {
scoll.scrollTop = (scoll.scrollHeight * (6 / 34) * scollTimes) % scoll.scrollHeight;
scollTimes = scollTimes + 1;
console.log("startTalk, 找不到商品, 尝试滚动列表 scollTimes " + scollTimes + " scoll.scrollTop " + scoll.scrollTop);
}
}, 100);
}
/**
** 开始讲解商品, 每隔8秒会取消讲解 + 讲解, 这样商品卡片能一直展现
**/
function realStartTalk(parentElement, goodsId) {
setButtonState(parentElement, true);
talkInterval = setInterval(function() {
setButtonState(parentElement, false);
setTimeout(function() {
setButtonState(parentElement, true);
}, 800);
}, 8000);
}
/**
** 切换商品的讲解状态
**/
function setButtonState(parentElement, isTalking) {
console.log('切换讲解状态 ' + isTalking);
var buttons = parentElement.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].textContent === "讲解" && isTalking) {
clickButton(buttons[i]);
} else if (buttons[i].textContent === "取消讲解" && !isTalking) {
clickButton(buttons[i]);
}
}
}
/**
** 设置商品顺序
**/
function setGoodsRank(parentElement, rank, callback) {
console.log("设置商品顺序 " + rank);
var inputElement = parentElement.querySelector('input');
let lastValue = inputElement.value;
inputElement.value = rank;
let event = new Event('input', {
bubbles: true
});
// react支持的事件 https://reactjs.org/docs/events.html#supported-events
// hack React15
event.simulated = true;
// hack React16 内部定义了descriptor拦截value,此处重置状态
let tracker = inputElement._valueTracker;
if (tracker) {
tracker.setValue(lastValue);
}
inputElement.dispatchEvent(event);
// 触发input事件,通知浏览器输入框的值已改变
var inputEvent = new InputEvent('input', {
bubbles: true,
cancelable: true,
data: rank
});
inputElement.dispatchEvent(inputEvent);
// 触发change事件,通知浏览器输入框的值已经完成更改
var changeEvent = new Event('change', {
bubbles: true,
cancelable: true
});
inputElement.dispatchEvent(changeEvent);
// 模拟回车键按下
// 注意:keydown事件的keyCode为13代表回车键
var keydownEvent = new KeyboardEvent('keydown', {
bubbles: true,
cancelable: true,
keyCode: 13,
// 回车键的keyCode
key: 'Enter',
// 回车键的key
ctrlKey: false // 确保Ctrl键没有被同时按下
});
inputElement.dispatchEvent(keydownEvent);
setTimeout(function() {
callback()
}, 800);
}
/**
** 根据序号寻找商品id
**/
function getProductionId(index, callback) {
console.log('getProductionId 寻找第' + index + "的商品号");
let goodListElement = document.querySelector('#live-control-goods-list-container > div > div');
// console.error(goodListElement);
let scollTimes = 1;
let scoll = document.querySelector('#live-control-goods-list-container > div');
// console.error(scoll);
findIdByIndexInterval = setInterval(function() {
var goodsList = goodListElement.childNodes;
// console.error(goodsList);
if (goodsList) {
for (let i = 0; i < goodsList.length; i++) {
// console.error(goodsList[i]);
if (goodsList[i].querySelector('.index__goodsItem___38cLa .auxo-input').value == index) {
console.log('getProductionId 找到第' + index + '商品的位置了');
let productionElement = document.querySelector('#live-control-goods-list-container > div > div > div:nth-child(' + i + ')');
let goodsId = productionElement.dataset.rbdDraggableId;
// console.error(productionElement);
// console.error(productionId);
clearFindIdByIndexInterval();
callback(goodsId);
return;
}
}
scoll.scrollTop = (scoll.scrollHeight * (5 / 34) * scollTimes) % scoll.scrollHeight;
scollTimes = scollTimes + 1;
console.log("getProductionId, 找不到商品, 尝试滚动列表 scollTimes " + scollTimes + " scoll.scrollTop " + scoll.scrollTop);
}
}, 100);
}
function clearLoopTimeInterval() {
if (loopTimeInterval != null) {
console.log("clearLoopTimeInterval");
clearInterval(loopTimeInterval);
loopTimeInterval = null;
}
}
function clearFindTargetInterval() {
if (findTargetInterval != null) {
console.log("clearFindTargetInterval");
clearInterval(findTargetInterval);
findTargetInterval = null;
}
}
function clearTalkInterval() {
if (talkInterval != null) {
console.log("clearTalkInterval");
clearInterval(talkInterval);
talkInterval = null;
}
}
function clearFindIdByIndexInterval() {
if (findIdByIndexInterval != null) {
console.log("clearFindIdByIndexInterval");
clearInterval(findIdByIndexInterval);
findIdByIndexInterval = null;
}
}
function isInputEmpty(inputElement) {
return !inputElement.value.trim();
}
function strArrays2intArrays(strArray) {
const intArray = [];
for (let i = 0; i < strArray.length; i++) {
intArray.push(parseInt(strArray[i]));
}
return intArray;
}
startButton.addEventListener("click", function() {
let result = initInput();
if (result) {
startLoopClick();
startButton.disabled = true;
stopButton.disabled = false;
}
});
stopButton.addEventListener("click", function() {
stopLoopClick()
startButton.disabled = false;
stopButton.disabled = true;
});
document.body.appendChild(scriptContainer);
})();