b-live-random-send-test

定时从设置的字幕中随机取出一条在B站直播间发送,需先登录B站账号

当前为 2023-03-11 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/447936/1160091/b-live-random-send-test.js

  1. // ==UserScript==
  2. // @author Gamyou
  3. // @version 1.5.0
  4. // @note 23-03-11 1.5.0 适配框架2.4.0版本
  5. // @note 23-03-08 1.4.6 隐藏弹幕输入框上层显示的登录提示层
  6. // @note 23-02-10 1.4.5 隐藏播放器左上角的“小橙车”提示
  7. // @note 22-08-28 1.4.4 解決定時器在浏览器繁忙时时间出现偏差的问题
  8. // @note 22-08-26 1.4.3 修复正则替换方法not found的问题
  9. // @note 22-08-14 1.4.2 修复B站直播间因活动而嵌套网页而导致房间号解析出错的BUG
  10. // @note 22-08-14 1.4.1 修复B站直播间因活动而嵌套网页而导致脚本加载出错的BUG
  11. // @note 22-08-13 1.4.0 实现阿B各直播间数据分离保存和油猴脚本更新提示功能
  12. // @note 22-08-05 1.3.0 增加播放器底部登录提示和Haruna的隐藏功能
  13. // @note 22-07-29 1.2.6 修复初始化后的常量被赋值和没能初始化成功组件时系统提示加载超时的问题
  14. // @note 22-07-24 1.2.5 增加分组启用按钮,并优化设置面板样式
  15. // @note 22-07-23 1.2.4 修复弹幕分组数据都为空时,旧数据重复合并的BUG
  16. // @note 22-07-16 1.2.3 修复设置弹幕时旧(初始)数据没有清空的BUG
  17. // @note 22-06-24 1.2.2 优化部分代码
  18. // @note 22-06-20 1.2.1 修复定时停止不能再开始的BUG
  19. // @note 22-06-19 1.2.0 添加弹幕设置功能
  20. // ==/UserScript==
  21.  
  22.  
  23. (function () {
  24. window.autoSendDanmuModuleLoaded = false;
  25. const blobURL = URL.createObjectURL(
  26. new Blob(
  27. [
  28. '(',
  29. function () {
  30. const ids = {};
  31. // 监听message 开始执行定时器或者销毁
  32. self.onmessage = (e) => {
  33. switch (e.data.command) {
  34. case 'interval:start': // 开启定时器
  35. const intervalId = setInterval(() => postMessage({ message: 'interval:tick', id: e.data.id }), e.data.interval);
  36. // postMessage({ message: 'interval:started', id: e.data.id });
  37. ids[e.data.id] = intervalId;
  38. break;
  39. case 'interval:clear': // 销毁
  40. clearInterval(ids[e.data.id]);
  41. postMessage({ message: 'interval:cleared', id: e.data.id });
  42. delete ids[e.data.id];
  43. break;
  44. case 'timeout:start':
  45. const timeoutId = setTimeout(() => postMessage({ message: 'timeout:tick', id: e.data.id }), e.data.timeout);
  46. // postMessage({ message: 'timeout:started', id: e.data.id });
  47. ids[e.data.id] = timeoutId;
  48. break;
  49. case 'timeout:clear':
  50. clearTimeout(ids[e.data.id]);
  51. postMessage({ message: 'timeout:cleared', id: e.data.id });
  52. delete ids[e.data.id];
  53. break;
  54. }
  55. };
  56. }.toString(),
  57. ')()',
  58. ],
  59. { type: 'application/javascript' },
  60. ),
  61. );
  62. const worker = new Worker(blobURL);
  63. URL.revokeObjectURL(blobURL); //用完释放URL对象
  64. const workerTimer = {
  65. id: 0,
  66. callbacks: {},
  67. setInterval: (cb, interval, context) => {
  68. const id = ++workerTimer.id;
  69. workerTimer.callbacks[id] = { fn: cb, context: context };
  70. worker.postMessage({ command: 'interval:start', interval: interval, id: id });
  71. return id;
  72. },
  73. setTimeout: (cb, timeout, context) => {
  74. const id = ++workerTimer.id;
  75. workerTimer.callbacks[id] = { fn: cb, context: context };
  76. worker.postMessage({ command: 'timeout:start', timeout: timeout, id: id });
  77. return id;
  78. },
  79.  
  80. // 监听worker 里面的定时器发送的message 然后执行回调函数
  81. onMessage: (e) => {
  82. switch (e.data.message) {
  83. case 'interval:tick':
  84. case 'timeout:tick':
  85. const callbackItem = workerTimer.callbacks[e.data.id];
  86. if (callbackItem && callbackItem.fn)
  87. callbackItem.fn.apply(callbackItem.context);
  88.  
  89. break;
  90. case 'interval:cleared':
  91. case 'timeout:cleared':
  92. delete workerTimer.callbacks[e.data.id];
  93. break;
  94. }
  95. },
  96.  
  97. // 往worker里面发送销毁指令
  98. clearInterval: (id) => worker.postMessage({ command: 'interval:clear', id: id }),
  99. clearTimeout: (id) => worker.postMessage({ command: 'timeout:clear', id: id }),
  100. };
  101. worker.onmessage = workerTimer.onMessage.bind(workerTimer);
  102.  
  103. let source = {
  104. version: 3,
  105. random: true,
  106. data1: { available: true, values: ['弹幕①', '弹幕②'] },
  107. data2: { available: true, values: ['弹幕③', '弹幕④'] },
  108. data3: { available: true, values: ['弹幕⑤', '弹幕⑥'] },
  109. data4: { available: true, values: ['弹幕⑦', '弹幕⑧'] },
  110. data5: { available: true, values: ['弹幕⑨', '弹幕Ⅹ'] }
  111. },
  112. pdata = {}, waiters = [], data = [], sendTimer = null, removeElementsTimer = null,
  113. count = 0, waitCount = 20, arrayIndex = 0, removeElementsTimerCount = 0, default_timeout = 600,
  114. rdCheckbox, group1Checkbox, group2Checkbox, group3Checkbox, group4Checkbox, group5Checkbox,
  115. dmButtonSend, dmInput, divSetting, dataText1, dataText2, dataText3, dataText4, dataText5, spanApplyTip,
  116. gmNotice = obj => { alert('请更新油猴脚本'); window.location.href = parentUrl; },
  117. getGmValue = (key, defaultValue) => { return null; },
  118. setGmValue = (key, obj) => { console.warn('===> No implementation "setGmValue" method.'); },
  119. delGmValue = key => { console.warn('===> No implementation "delGmValue" method.'); };
  120.  
  121. const minVersion = '2.4.0', noticeTimeout = 10000,
  122. icoUrl = 'https://www.bilibili.com/favicon.ico',
  123. parentUrl = 'https://greasyfork.org/scripts/446725-b%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95/code/B%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95.user.js',
  124. roomId = window.__NEPTUNE_IS_MY_WAIFU__
  125. ? window.__NEPTUNE_IS_MY_WAIFU__.roomInfoRes.data.room_info.room_id
  126. : window.location.pathname.replace(/^\/(\S+\/)*/g, ''),
  127. setGmGetValue = callback => getGmValue = callback,
  128. setGmSetValue = callback => setGmValue = callback,
  129. setGmDelValue = callback => delGmValue = callback,
  130. setGmNotice = callback => gmNotice = callback,
  131. setParentData = obj => pdata = obj,
  132. arrayInfo = () => console.info(data),
  133. setLoadedFlag = flag => window.autoSendDanmuModuleLoaded = flag,
  134. isOldVersion = value => {
  135. if (!value) {
  136. return true;
  137. }
  138. if (minVersion === value) {
  139. return false;
  140. } else {
  141. let vals = value.split('.');
  142. let mins = minVersion.split('.');
  143. if (vals.length != mins.length) {
  144. return true;
  145. } else {
  146. for (let i = 0; i < vals.length; i++) {
  147. if (mins[i] > vals[i]) {
  148. return true;
  149. }
  150. }
  151.  
  152. return false;
  153. }
  154. }
  155. },
  156. initCss = () => {
  157. let linkElement = document.createElement('link');
  158. linkElement.rel = 'stylesheet';
  159. linkElement.href = 'https://unpkg.com/element-ui@2.15.9/lib/theme-chalk/index.css';
  160. document.head.appendChild(linkElement);
  161.  
  162. // 图标库 https://ionic.io/ionicons
  163. // let scriptElement = document.createElement('script');
  164. // scriptElement.src = 'https://unpkg.com/ionicons@5.5.2/dist/ionicons.js';
  165. // document.head.appendChild(scriptElement);
  166.  
  167. let customerStyle = document.createElement('style');
  168. customerStyle.setAttribute('type', 'text/css');
  169. customerStyle.innerHTML = '.danmu-group-title{font-size:14px;padding-left:2px;color:rgb(18, 56, 141);display:inline;margin-right:60%;vertical-align:middle;}.danmu-group-textarea{width:98%;min-height:100px;height:16%;margin:1px 0px 4px;border:0px;resize:none;}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#FFF;border:1px solid #DCDFE6;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;padding:12px 20px;font-size:14px;border-radius:4px}.el-button.is-circle{border-radius:50%;padding:12px}.el-button--mini.is-circle{padding:3px;}.el-button:focus,.el-button:hover{color:#409EFF;border-color:#c6e2ff;background-color:#ecf5ff}.el-icon-close.is-circle{padding:5px;color:#ff0000;border:1px solid #ff0000;margin-left:20px;}.el-icon-check.is-circle{padding:5px;color:#0000ff;border:1px solid #0000ff;margin-left:20px;}input[type="checkbox"]{display:none;}.switch-check{display:inline-block;margin:0 5px;vertical-align:middle;}.switch-check-label{display:inline-block;vertical-align:middle;border:1px solid #bdc3c7;border-radius:60px;width:40px;height:18px;position:relative;transition:all .3s;cursor:pointer;}.switch-check-label:before{width:14px;height:14px;content:"";display:inline-block;background-color:#bdc3c7;border-radius:100%;position:absolute;top:2px;left:4px;transition:all .3s;}.switch-check :checked ~ label{background-color:#26b22b;border-color:#26b22b;}.switch-check :checked ~ label:before{left:22px;background-color:#fff;}.danmu-random-setting-panel{background-color:#d4f2e0;border-radius:2px;width:100%;height:100%;overflow-y:auto;position:absolute;left:0px;top:0px;z-index:999;display:none;}.danmu-random-setting-title{text-align:center;font-size:16px;font-weight:700;color:#1c5adc;line-height:30px;}.danmu-random-setting-tips{color:#0b81cc;text-align:center;font-style:italic;}.danmu-random-update-tips{color:#0b81cc;text-align:center;font-size:13px;font-weight:700;margin:10px 0px;}.danmu-random-setting-bottom{width:100%;line-height:35px;}.danmu-random-switch-button-title{font-size:16px;vertical-align:middle;margin-right:4px;color:#095ca2;cursor:help;}.danmu-random-setting-success-tips{text-align:center;display:inline-block;vertical-align:middle;width:34%;}.danmu-random-setting-success-text{font-size:16px;color:#128712;display:none;}.danmu-random-set-button-container{display:inline-block;vertical-align:middle;}';
  170. document.head.appendChild(customerStyle);
  171. },
  172. getCurrentTimestamp = () => new Date().getTime(),
  173. send = (msg, index) => {
  174. let dmTextArea = document.getElementById('aside-area-vm').getElementsByClassName('chat-input border-box')[0];
  175. if (!dmTextArea) {
  176. alert('找不到输入弹幕文本框,请尝试刷新页面');
  177. return;
  178. }
  179.  
  180. let btnSend = document.getElementsByClassName('bl-button live-skin-highlight-button-bg live-skin-button-text bl-button--primary bl-button--small')[0];
  181. if (!btnSend) {
  182. alert('找不到发送按钮,请尝试刷新页面');
  183. return;
  184. }
  185. // if (getCurrentTimestamp() - lastSent < 5000) {
  186. // setTimeout(() => send(msg, index), 5000);
  187. // console.log('===> 发送间隔少于5秒,进入递归处理');
  188. // } else {
  189. dmTextArea.value = msg;
  190. // 定义事件, 定义才可发送
  191. dmTextArea.dispatchEvent(new Event('input', { "bubbles": true, "cancelable": true }));
  192. btnSend.click();
  193. lastSent = getCurrentTimestamp();
  194. ++count;
  195. console.log('===> ' + new Date().toLocaleString() + ' 弹幕发送成功 ' + count + ' 次,第【' + index + '】条数据 === ' + msg);
  196. // }
  197. },
  198. isNull = str => {
  199. if (!str || str == "")
  200. return true;
  201.  
  202. let regu = "^[ ]+$";
  203. let re = new RegExp(regu);
  204. return re.test(str);
  205. },
  206. randomSort = arr => {
  207. for (let i = 0; i < arr.length; i++) {
  208. const rdIndex = Math.floor(Math.random() * arr.length);
  209. const temp = arr[i];
  210. arr[i] = arr[rdIndex];
  211. arr[rdIndex] = temp;
  212. }
  213.  
  214. return arr;
  215. },
  216. clearWaiters = () => {
  217. for (let i = 0; i < waiters.length; i++) {
  218. workerTimer.clearInterval(waiters[i]);
  219. waiters[i] = null;
  220. }
  221.  
  222. waiters = [];
  223. },
  224. signIn = () => {
  225. let timestamp = new Date(new Date(new Date().setDate(new Date().getDate() + 1)).toDateString()).getTime() - getCurrentTimestamp();
  226. console.log('===> 设置凌晨签到定时器【' + timestamp + '】');
  227. workerTimer.setTimeout(() => {
  228. if (dmButtonSend.textContent === '停止')
  229. send(pdata.signText ? pdata.signText : '打卡', 0);
  230.  
  231. console.log('===> 进入下一轮递归签到');
  232. signIn();
  233. }, timestamp);
  234. },
  235. // selectRandom = () => source.random = rdCheckbox.checked,
  236. setCheckboxChecked = () => {
  237. rdCheckbox.checked = source.random;
  238. group1Checkbox.checked = source.data1.available;
  239. group2Checkbox.checked = source.data2.available;
  240. group3Checkbox.checked = source.data3.available;
  241. group4Checkbox.checked = source.data4.available;
  242. group5Checkbox.checked = source.data5.available;
  243. },
  244. openSetting = () => divSetting.style.display = 'block',
  245. closeSetting = () => {
  246. setCheckboxChecked();
  247. divSetting.style.display = 'none';
  248. },
  249. initData = () => {
  250. if (source.data1.values.length <= 0
  251. && source.data2.values.length <= 0
  252. && source.data3.values.length <= 0
  253. && source.data4.values.length <= 0
  254. && source.data5.values.length <= 0) {
  255. return data ? data : [];
  256. }
  257.  
  258. let result = [];
  259. result = source.data1.available ? result.concat(source.data1.values) : result;
  260. result = source.data2.available ? result.concat(source.data2.values) : result;
  261. result = source.data3.available ? result.concat(source.data3.values) : result;
  262. result = source.data4.available ? result.concat(source.data4.values) : result;
  263. result = source.data5.available ? result.concat(source.data5.values) : result;
  264. data = result;
  265. source.random ? data = randomSort(result) : arrayIndex = 0;
  266. },
  267. applySetting = () => {
  268. source.data1.values = isNull(dataText1.value) ? [] : dataText1.value.split('|');
  269. source.data2.values = isNull(dataText2.value) ? [] : dataText2.value.split('|');
  270. source.data3.values = isNull(dataText3.value) ? [] : dataText3.value.split('|');
  271. source.data4.values = isNull(dataText4.value) ? [] : dataText4.value.split('|');
  272. source.data5.values = isNull(dataText5.value) ? [] : dataText5.value.split('|');
  273. source.random = rdCheckbox.checked;
  274. source.data1.available = group1Checkbox.checked;
  275. source.data2.available = group2Checkbox.checked;
  276. source.data3.available = group3Checkbox.checked;
  277. source.data4.available = group4Checkbox.checked;
  278. source.data5.available = group5Checkbox.checked;
  279. initData();
  280. setGmValue(roomId, source);
  281. spanApplyTip.style.display = 'block';
  282. setTimeout(() => {
  283. spanApplyTip.style.display = 'none';
  284. divSetting.style.display = 'none';
  285. }, 1500);
  286. },
  287. danmu = () => {
  288. if (data.length < 1) {
  289. // alert('请任意在一个分组里输入一条弹幕');
  290. gmNotice({
  291. text: '请任意在一个分组里输入一条弹幕',
  292. title: '没有弹幕数据,请先设置',
  293. image: icoUrl,
  294. highlight: true,
  295. timeout: noticeTimeout
  296. });
  297. return false;
  298. }
  299. if (source.random)
  300. arrayIndex = Math.floor((Math.random() * data.length));
  301.  
  302. send(data[arrayIndex], arrayIndex);
  303. ++arrayIndex;
  304. if (arrayIndex >= data.length)
  305. arrayIndex = 0;
  306.  
  307. return true;
  308. },
  309. offOrOn = () => {
  310. let timeout = 0;
  311. if (sendTimer) {
  312. workerTimer.clearInterval(sendTimer);
  313. sendTimer = null;
  314. dmButtonSend.style.background = 'rgba(217,157,27,1)';
  315. dmButtonSend.textContent = '开始';
  316. dmInput.removeAttribute("disabled");
  317. } else {
  318. timeout = isNull(dmInput.value) ? default_timeout * 1000 : dmInput.value * 1000;
  319. if (!danmu())
  320. return;
  321.  
  322. sendTimer = workerTimer.setInterval(danmu, timeout);
  323. dmButtonSend.style.background = '#ff0000';
  324. dmButtonSend.textContent = '停止';
  325. dmInput.setAttribute('disabled', 'disabled');
  326. }
  327. },
  328. buildPanel = divButton => {
  329. /* ----------------------------------------- head ----------------------------------------- */
  330. let divSettingTitle = document.createElement('div');
  331. divSettingTitle.textContent = '弹幕设置';
  332. divSettingTitle.classList.add('danmu-random-setting-title');
  333.  
  334. let divTip = document.createElement('div');
  335. divTip.classList.add('danmu-random-setting-tips');
  336. divTip.innerHTML = '任一分组内输入弹幕即可,多条用<span style="color:#dc6b07;margin:0 2px 0 4px;font-weight:700;font-style:normal;">竖线</span>分隔';
  337.  
  338. let divUpdateTip = document.createElement('div');
  339. divUpdateTip.classList.add('danmu-random-update-tips');
  340. divUpdateTip.innerHTML = '<span style="color:#f00">更新提示:</span>近期油猴网络不稳影响脚本加载';
  341. /* ----------------------------------------- head ----------------------------------------- */
  342.  
  343. /* ----------------------------------------- textarea 1 ----------------------------------------- */
  344. let divText1 = document.createElement('div');
  345. divText1.textContent = '分组 1 :';
  346. divText1.classList.add('danmu-group-title');
  347.  
  348. group1Checkbox = document.createElement('input');
  349. group1Checkbox.type = 'checkbox';
  350. group1Checkbox.id = 'group1Checkbox';
  351. group1Checkbox.checked = true;
  352.  
  353. let lblGroup1Checkbox = document.createElement('label');
  354. lblGroup1Checkbox.setAttribute('for', 'group1Checkbox');
  355. lblGroup1Checkbox.classList.add('switch-check-label');
  356.  
  357. let divGroup1Checkbox = document.createElement('div');
  358. divGroup1Checkbox.classList.add('switch-check');
  359. divGroup1Checkbox.appendChild(group1Checkbox);
  360. divGroup1Checkbox.appendChild(lblGroup1Checkbox);
  361.  
  362. dataText1 = document.createElement('textarea');
  363. dataText1.classList.add('danmu-group-textarea');
  364. dataText1.setAttribute('placeholder', '请输入弹幕,多条弹幕请用“|”分隔');
  365. /* ----------------------------------------- textarea 1 ----------------------------------------- */
  366.  
  367. /* ----------------------------------------- textarea 2 ----------------------------------------- */
  368. let divText2 = document.createElement('div');
  369. divText2.textContent = '分组 2 :';
  370. divText2.classList.add('danmu-group-title');
  371.  
  372. group2Checkbox = document.createElement('input');
  373. group2Checkbox.type = 'checkbox';
  374. group2Checkbox.id = 'group2Checkbox';
  375. group2Checkbox.checked = true;
  376.  
  377. let lblGroup2Checkbox = document.createElement('label');
  378. lblGroup2Checkbox.setAttribute('for', 'group2Checkbox');
  379. lblGroup2Checkbox.classList.add('switch-check-label');
  380.  
  381. let divGroup2Checkbox = document.createElement('div');
  382. divGroup2Checkbox.classList.add('switch-check');
  383. divGroup2Checkbox.appendChild(group2Checkbox);
  384. divGroup2Checkbox.appendChild(lblGroup2Checkbox);
  385.  
  386. dataText2 = document.createElement('textarea');
  387. dataText2.classList.add('danmu-group-textarea');
  388. dataText2.setAttribute('placeholder', '请输入弹幕,多条弹幕请用“|”分隔');
  389. /* ----------------------------------------- textarea 2 ----------------------------------------- */
  390.  
  391. /* ----------------------------------------- textarea 3 ----------------------------------------- */
  392. let divText3 = document.createElement('div');
  393. divText3.textContent = '分组 3 :';
  394. divText3.classList.add('danmu-group-title');
  395.  
  396. group3Checkbox = document.createElement('input');
  397. group3Checkbox.type = 'checkbox';
  398. group3Checkbox.id = 'group3Checkbox';
  399. group3Checkbox.checked = true;
  400.  
  401. let lblGroup3Checkbox = document.createElement('label');
  402. lblGroup3Checkbox.setAttribute('for', 'group3Checkbox');
  403. lblGroup3Checkbox.classList.add('switch-check-label');
  404.  
  405. let divGroup3Checkbox = document.createElement('div');
  406. divGroup3Checkbox.classList.add('switch-check');
  407. divGroup3Checkbox.appendChild(group3Checkbox);
  408. divGroup3Checkbox.appendChild(lblGroup3Checkbox);
  409.  
  410. dataText3 = document.createElement('textarea');
  411. dataText3.classList.add('danmu-group-textarea');
  412. dataText3.setAttribute('placeholder', '请输入弹幕,多条弹幕请用“|”分隔');
  413. /* ----------------------------------------- textarea 3 ----------------------------------------- */
  414.  
  415. /* ----------------------------------------- textarea 4 ----------------------------------------- */
  416. let divText4 = document.createElement('div');
  417. divText4.textContent = '分组 4 :';
  418. divText4.classList.add('danmu-group-title');
  419.  
  420. group4Checkbox = document.createElement('input');
  421. group4Checkbox.type = 'checkbox';
  422. group4Checkbox.id = 'group4Checkbox';
  423. group4Checkbox.checked = true;
  424.  
  425. let lblGroup4Checkbox = document.createElement('label');
  426. lblGroup4Checkbox.setAttribute('for', 'group4Checkbox');
  427. lblGroup4Checkbox.classList.add('switch-check-label');
  428.  
  429. let divGroup4Checkbox = document.createElement('div');
  430. divGroup4Checkbox.classList.add('switch-check');
  431. divGroup4Checkbox.appendChild(group4Checkbox);
  432. divGroup4Checkbox.appendChild(lblGroup4Checkbox);
  433.  
  434. dataText4 = document.createElement('textarea');
  435. dataText4.classList.add('danmu-group-textarea');
  436. dataText4.setAttribute('placeholder', '请输入弹幕,多条弹幕请用“|”分隔');
  437. /* ----------------------------------------- textarea 4 ----------------------------------------- */
  438.  
  439. /* ----------------------------------------- textarea 5 ----------------------------------------- */
  440. let divText5 = document.createElement('div');
  441. divText5.textContent = '分组 5 :';
  442. divText5.classList.add('danmu-group-title');
  443.  
  444. group5Checkbox = document.createElement('input');
  445. group5Checkbox.type = 'checkbox';
  446. group5Checkbox.id = 'group5Checkbox';
  447. group5Checkbox.checked = true;
  448.  
  449. let lblGroup5Checkbox = document.createElement('label');
  450. lblGroup5Checkbox.setAttribute('for', 'group5Checkbox');
  451. lblGroup5Checkbox.classList.add('switch-check-label');
  452.  
  453. let divGroup5Checkbox = document.createElement('div');
  454. divGroup5Checkbox.classList.add('switch-check');
  455. divGroup5Checkbox.appendChild(group5Checkbox);
  456. divGroup5Checkbox.appendChild(lblGroup5Checkbox);
  457.  
  458. dataText5 = document.createElement('textarea');
  459. dataText5.classList.add('danmu-group-textarea');
  460. dataText5.setAttribute('placeholder', '请输入弹幕,多条弹幕请用“|”分隔');
  461. /* ----------------------------------------- textarea 5 ----------------------------------------- */
  462.  
  463. /* ----------------------------------------- random chackbox ----------------------------------------- */
  464. let descCheckbox = document.createElement('span');
  465. descCheckbox.textContent = '随机';
  466. descCheckbox.title = '将合并所有分组数据,从中随机选出一条发送';
  467. descCheckbox.classList.add('danmu-random-switch-button-title');
  468.  
  469. rdCheckbox = document.createElement('input');
  470. rdCheckbox.type = 'checkbox';
  471. rdCheckbox.id = 'rdmCheckbox';
  472. rdCheckbox.checked = true;
  473. // rdCheckbox.addEventListener('click', selectRandom);
  474.  
  475. let lblCheckbox = document.createElement('label');
  476. lblCheckbox.setAttribute('for', 'rdmCheckbox');
  477. lblCheckbox.classList.add('switch-check-label');
  478.  
  479. let divCheckbox = document.createElement('div');
  480. divCheckbox.classList.add('switch-check');
  481. divCheckbox.style.marginLeft = '10px';
  482. divCheckbox.appendChild(descCheckbox);
  483. divCheckbox.appendChild(rdCheckbox);
  484. divCheckbox.appendChild(lblCheckbox);
  485. /* ----------------------------------------- random chackbox ----------------------------------------- */
  486.  
  487. /* ----------------------------------------- div tip ----------------------------------------- */
  488. spanApplyTip = document.createElement('span');
  489. spanApplyTip.textContent = '设置成功';
  490. spanApplyTip.classList.add('danmu-random-setting-success-text');
  491.  
  492. let divApplyTip = document.createElement('div');
  493. divApplyTip.classList.add('danmu-random-setting-success-tips');
  494. divApplyTip.appendChild(spanApplyTip);
  495. /* ----------------------------------------- div tip ----------------------------------------- */
  496.  
  497. /* ----------------------------------------- appley and close button ----------------------------------------- */
  498. let btnApplySetting = document.createElement('i');
  499. btnApplySetting.setAttribute('title', '应用');
  500. btnApplySetting.classList.add('el-button');
  501. btnApplySetting.classList.add('el-icon-check');
  502. btnApplySetting.classList.add('is-circle');
  503. btnApplySetting.addEventListener('click', applySetting);
  504.  
  505. let btnCloseSetting = document.createElement('i');
  506. btnCloseSetting.setAttribute('title', '关闭');
  507. btnCloseSetting.classList.add('el-button');
  508. btnCloseSetting.classList.add('el-icon-close');
  509. btnCloseSetting.classList.add('is-circle');
  510. btnCloseSetting.addEventListener('click', closeSetting);
  511.  
  512. let divSettingButton = document.createElement('div');
  513. divSettingButton.classList.add('danmu-random-set-button-container');
  514. divSettingButton.appendChild(btnApplySetting);
  515. divSettingButton.appendChild(btnCloseSetting);
  516. /* ----------------------------------------- appley and close button ----------------------------------------- */
  517.  
  518. /* ----------------------------------------- container ----------------------------------------- */
  519. let divBottomContainer = document.createElement('div');
  520. divBottomContainer.classList.add('danmu-random-setting-bottom');
  521. divBottomContainer.appendChild(divCheckbox);
  522. divBottomContainer.appendChild(divApplyTip);
  523. divBottomContainer.appendChild(divSettingButton);
  524.  
  525. let divContainer = document.createElement('div');
  526. divContainer.style.height = 'calc(98% - 30px - 25px)';
  527. divContainer.appendChild(divText1);
  528. divContainer.appendChild(divGroup1Checkbox);
  529. divContainer.appendChild(dataText1);
  530. divContainer.appendChild(divText2);
  531. divContainer.appendChild(divGroup2Checkbox);
  532. divContainer.appendChild(dataText2);
  533. divContainer.appendChild(divText3);
  534. divContainer.appendChild(divGroup3Checkbox);
  535. divContainer.appendChild(dataText3);
  536. divContainer.appendChild(divText4);
  537. divContainer.appendChild(divGroup4Checkbox);
  538. divContainer.appendChild(dataText4);
  539. divContainer.appendChild(divText5);
  540. divContainer.appendChild(divGroup5Checkbox);
  541. divContainer.appendChild(dataText5);
  542. divContainer.appendChild(divBottomContainer);
  543. /* ----------------------------------------- container ----------------------------------------- */
  544.  
  545. divSetting = document.createElement('div');
  546. divSetting.id = 'danmu-setting-panel';
  547. divSetting.classList.add('danmu-random-setting-panel');
  548. divSetting.appendChild(divSettingTitle);
  549. divSetting.appendChild(divTip);
  550. divSetting.appendChild(divUpdateTip);
  551. divSetting.appendChild(divContainer);
  552.  
  553. let asideAreaVm = document.getElementById('aside-area-vm');
  554. asideAreaVm.appendChild(divSetting);
  555.  
  556. /* ----------------------------------------- function ----------------------------------------- */
  557. dmButtonSend = document.createElement('button');
  558. dmButtonSend.textContent = '开始';
  559. dmButtonSend.style.minWidth = '65px';
  560. dmButtonSend.style.height = '24px';
  561. dmButtonSend.style.fontSize = '12px';
  562. dmButtonSend.style.borderRadius = '4px';
  563. dmButtonSend.style.color = '#ffffff';
  564. dmButtonSend.style.background = 'rgba(217,157,27,1)';
  565. dmButtonSend.style.border = '0';
  566. dmButtonSend.style.cursor = 'pointer';
  567. //dmButtonSend.onclick = function() { alert('Hello world');}
  568. dmButtonSend.addEventListener('click', offOrOn);
  569.  
  570. let beforeSpan = document.createElement('span');
  571. beforeSpan.textContent = '每';
  572. beforeSpan.style.color = '#ffffff';
  573. beforeSpan.style.fontSize = '12px';
  574. beforeSpan.style.marginLeft = '4px';
  575. beforeSpan.style.backgroundColor = '#ec6c1b';
  576.  
  577. dmInput = document.createElement('input');
  578. dmInput.value = default_timeout;
  579. dmInput.style.width = '25px';
  580. dmInput.style.height = '15px';
  581. dmInput.style.margin = '0 3px';
  582. dmInput.style.border = '0';
  583. dmInput.style.borderRadius = '3px';
  584. dmInput.setAttribute('oninput', "this.value = this.value.replace(/[^0-9]/g, '')");
  585.  
  586. let afterSpan = document.createElement('span');
  587. afterSpan.textContent = '秒发送';
  588. afterSpan.style.color = '#ffffff';
  589. afterSpan.style.fontSize = '12px';
  590. afterSpan.style.backgroundColor = '#ec6c1b';
  591. afterSpan.style.marginRight = '4px';
  592.  
  593. let iElement = document.createElement('i');
  594. iElement.classList.add('el-icon-setting');
  595.  
  596. let btnSetting = document.createElement('button');
  597. btnSetting.title = '设置';
  598. btnSetting.classList.add('el-button');
  599. btnSetting.classList.add('el-button--mini');
  600. btnSetting.classList.add('is-circle');
  601. btnSetting.addEventListener('click', openSetting);
  602. btnSetting.appendChild(iElement);
  603.  
  604. // let btnSetting = document.createElement('ion-icon');
  605. // btnSetting.setAttribute('name', 'settings-sharp');
  606. // btnSetting.classList.add('el-button');
  607. // btnSetting.classList.add('el-button--mini');
  608. // btnSetting.classList.add('is-circle');
  609. // btnSetting.addEventListener('click', openSetting);
  610.  
  611. let div = document.createElement('div');
  612. div.style.position = 'absolute';
  613. div.appendChild(dmButtonSend);
  614. div.appendChild(beforeSpan);
  615. div.appendChild(dmInput);
  616. div.appendChild(afterSpan);
  617. div.appendChild(btnSetting);
  618. divButton.appendChild(div);
  619. /* ----------------------------------------- function ----------------------------------------- */
  620. },
  621. removeElements = () => {
  622. let switchLoginGuideVm = document.getElementById('switch-login-guide-vm');
  623. if (switchLoginGuideVm)
  624. switchLoginGuideVm.style.setProperty('display', 'none', 'important');
  625.  
  626. let myDearHarunaVm = document.getElementById('my-dear-haruna-vm');
  627. if (myDearHarunaVm)
  628. myDearHarunaVm.style.setProperty('display', 'none', 'important');
  629.  
  630. let shopPopoverVm = document.getElementById('shop-popover-vm');
  631. if (shopPopoverVm)
  632. shopPopoverVm.style.setProperty('display', 'none', 'important');
  633.  
  634. removeElementsTimer = workerTimer.setInterval(() => {
  635. ++removeElementsTimerCount;
  636. let ltRow = document.getElementsByClassName('lt-row')[0];
  637. if (ltRow) {
  638. ltRow.style.setProperty('display', 'none', 'important');
  639. if (removeElementsTimer) {
  640. workerTimer.clearInterval(removeElementsTimer);
  641. removeElementsTimer = null;
  642. }
  643. }
  644. if (30 <= removeElementsTimerCount && removeElementsTimer) {
  645. workerTimer.clearInterval(removeElementsTimer);
  646. removeElementsTimer = null;
  647. }
  648. }, 10000);
  649. },
  650. loadData = () => {
  651. let obj = getGmValue(roomId, null);
  652. if (obj) {
  653. if (source.version === obj.version) {
  654. source = obj;
  655. }
  656. else if (obj.version === 2) {
  657. source.data1 = obj.data1;
  658. source.data2 = obj.data2;
  659. source.data3 = obj.data3;
  660. source.data4 = obj.data4;
  661. source.data5 = obj.data5;
  662. setGmValue(roomId, source);
  663. } else {
  664. source.data1.values = obj.data1 ? obj.data1 : source.data1.values;
  665. source.data2.values = obj.data2 ? obj.data2 : source.data2.values;
  666. source.data3.values = obj.data3 ? obj.data3 : source.data3.values;
  667. source.data4.values = obj.data4 ? obj.data4 : source.data4.values;
  668. source.data5.values = obj.data5 ? obj.data5 : source.data5.values;
  669. setGmValue(roomId, source);
  670. }
  671. }
  672.  
  673. setCheckboxChecked();
  674. dataText1.value = source.data1.values.join('|');
  675. dataText2.value = source.data2.values.join('|');
  676. dataText3.value = source.data3.values.join('|');
  677. dataText4.value = source.data4.values.join('|');
  678. dataText5.value = source.data5.values.join('|');
  679. initData();
  680. },
  681. runStart = () => {
  682. console.log('===> 打印pdata对象');
  683. console.info(pdata);
  684. let settingPanel = document.getElementById('danmu-setting-panel');
  685. if (!settingPanel) {
  686. console.log('===> 没有弹幕设置界面,进行初始化');
  687. let divButton = document.getElementsByClassName('bottom-actions p-relative')[0];
  688. if (divButton) {
  689. clearWaiters();
  690. buildPanel(divButton);
  691. setLoadedFlag(true);
  692. console.log('===> 弹幕设置界面初始化完成');
  693. } else {
  694. console.log('===> 页面改版,所属元数丢失');
  695. return;
  696. }
  697. }
  698.  
  699. loadData();
  700. };
  701.  
  702. window.runStart = runStart;
  703. window.arrayInfo = arrayInfo;
  704. window.setGmNotice = setGmNotice;
  705. window.setGmGetValue = setGmGetValue;
  706. window.setGmSetValue = setGmSetValue;
  707. window.setGmDelValue = setGmDelValue;
  708. window.setParentData = setParentData;
  709. initCss();
  710. window.addEventListener("load", () => {
  711. let script = document.getElementById(pdata.moduleId);
  712. if (script) {
  713. if (isOldVersion(script.version)) {
  714. alert('11111111发随机弹幕脚本需 >=' + minVersion + ' 版本,请及时更新');
  715. window.location.href = parentUrl;
  716. return;
  717. }
  718. } else {
  719. // setLoadedFlag(true);
  720. // workerTimer.setTimeout(() => {
  721. alert('22222222发随机弹幕脚本需 >=' + minVersion + ' 版本,请及时更新');
  722. window.location.href = parentUrl;
  723. // gmNotice({
  724. // text: '当前脚本不是最新版,请更新再使用功能',
  725. // title: '油猴脚本有更新,点击进行安装',
  726. // image: icoUrl,
  727. // highlight: true,
  728. // timeout: 120000,
  729. // onclick: () => window.open(parentUrl, '_blank')
  730. // });
  731. // }, 1000);
  732. return;
  733. }
  734.  
  735. waiters[waiters.length] = workerTimer.setInterval(() => {
  736. let divButton = document.getElementsByClassName('bottom-actions p-relative')[0];
  737. if (divButton) {
  738. clearWaiters();
  739. buildPanel(divButton);
  740. setLoadedFlag(true);
  741. } else {
  742. --waitCount;
  743. if (0 >= waitCount) {
  744. setLoadedFlag(true);
  745. clearWaiters();
  746. console.warn('===> 页面改版,没能找到发送按钮的所属元素');
  747. // debugger;
  748. // gmNotice({
  749. // text: '没能找到发送按钮的所属元素,请刷新重试',
  750. // title: '加载错误,点击刷新页面',
  751. // image: icoUrl,
  752. // highlight: true,
  753. // timeout: noticeTimeout,
  754. // onclick: () => location.reload()
  755. // });
  756. }
  757. }
  758. }, 1500);
  759.  
  760. removeElements();
  761. signIn();
  762. });
  763. })();