抖音直播自动点赞-作者:1kb(云看北)

在抖音直播间自动点赞,支持自定义设置,随机点击间隔,理论其他网站也支持

  1. // ==UserScript==
  2. // @name 抖音直播自动点赞-作者:1kb(云看北)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description 在抖音直播间自动点赞,支持自定义设置,随机点击间隔,理论其他网站也支持
  6. // @author 1KB(云看北)
  7. // @license MIT
  8. // @match https://live.douyin.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // 配置项
  16. const config = {
  17. enabled: false,
  18. clickPosition: null,
  19. clickInterval: 150, // 基础点击间隔
  20. clickDuration: 50, // 点击持续时间
  21. intervalVariation: 20, // 间隔波动范围(±500ms)
  22. clickCount: 0,
  23. isSettingPosition: false,
  24. isPanelExpanded: false
  25. };
  26.  
  27. // 创建控制面板
  28. function createControlPanel() {
  29. const mainButton = document.createElement('div');
  30. mainButton.innerHTML = '⚙️';
  31. mainButton.style.cssText = `
  32. position: fixed;
  33. top: 10px;
  34. right: 350px;
  35. z-index: 9999999;
  36. width: 32px;
  37. height: 32px;
  38. background: rgba(0, 0, 0, 0.6);
  39. color: white;
  40. border-radius: 50%;
  41. display: flex;
  42. align-items: center;
  43. justify-content: center;
  44. cursor: pointer;
  45. font-size: 18px;
  46. transition: all 0.3s;
  47. `;
  48.  
  49. const panel = document.createElement('div');
  50. panel.innerHTML = `
  51. <div id="autoLikePanel" style="
  52. position: fixed;
  53. top: 50px;
  54. right: 90px;
  55. z-index: 9999998;
  56. background: rgba(0, 0, 0, 0.8);
  57. color: white;
  58. padding: 10px;
  59. border-radius: 4px;
  60. font-size: 14px;
  61. display: none;
  62. flex-direction: column;
  63. gap: 5px;
  64. min-width: 200px;
  65. box-shadow: 0 2px 10px rgba(0,0,0,0.2);
  66. ">
  67. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
  68. <span style="font-weight: bold;">自动点赞设置</span>
  69. <span id="closePanel" style="cursor: pointer; padding: 2px 6px;">×</span>
  70. </div>
  71.  
  72. <button id="setClickArea" style="
  73. padding: 5px;
  74. margin: 2px;
  75. background: #2196F3;
  76. border: none;
  77. color: white;
  78. cursor: pointer;
  79. border-radius: 4px;
  80. ">设置点击位置</button>
  81.  
  82. <div style="display: flex; align-items: center; gap: 5px; margin: 5px 0;">
  83. <label style="flex: 1;">基础间隔(ms):</label>
  84. <input type="number" id="intervalInput"
  85. value="${config.clickInterval}"
  86. min="100"
  87. max="5000"
  88. style="width: 70px; padding: 2px;">
  89. </div>
  90.  
  91. <div style="display: flex; align-items: center; gap: 5px; margin: 5px 0;">
  92. <label style="flex: 1;">间隔波动(±ms):</label>
  93. <input type="number" id="variationInput"
  94. value="${config.intervalVariation}"
  95. min="0"
  96. max="2000"
  97. style="width: 70px; padding: 2px;">
  98. </div>
  99.  
  100. <div style="display: flex; align-items: center; gap: 5px; margin: 5px 0;">
  101. <label style="flex: 1;">点击持续(ms):</label>
  102. <input type="number" id="durationInput"
  103. value="${config.clickDuration}"
  104. min="50"
  105. max="1000"
  106. style="width: 70px; padding: 2px;">
  107. </div>
  108.  
  109. <button id="startBtn" style="
  110. padding: 5px;
  111. margin: 2px;
  112. background: #fe2c55;
  113. border: none;
  114. color: white;
  115. cursor: pointer;
  116. border-radius: 4px;
  117. ">开始点赞</button>
  118.  
  119. <div style="font-size: 12px; margin-top: 5px;">
  120. <div id="status">未设置点击位置</div>
  121. <div id="clickCount">点击次数: 0</div>
  122. <div id="nextClick">下次点击: - ms</div>
  123. </div>
  124. </div>
  125. `;
  126.  
  127. document.body.appendChild(mainButton);
  128. document.body.appendChild(panel);
  129.  
  130. // 绑定面板显示/隐藏事件
  131. mainButton.addEventListener('click', () => {
  132. const panelEl = document.getElementById('autoLikePanel');
  133. config.isPanelExpanded = !config.isPanelExpanded;
  134. panelEl.style.display = config.isPanelExpanded ? 'flex' : 'none';
  135. mainButton.style.transform = config.isPanelExpanded ? 'rotate(180deg)' : 'rotate(0)';
  136. });
  137.  
  138. document.getElementById('closePanel').addEventListener('click', () => {
  139. config.isPanelExpanded = false;
  140. document.getElementById('autoLikePanel').style.display = 'none';
  141. mainButton.style.transform = 'rotate(0)';
  142. });
  143.  
  144. bindEventHandlers();
  145. }
  146.  
  147. // 绑定事件处理程序
  148. function bindEventHandlers() {
  149. document.getElementById('setClickArea').addEventListener('click', startPositionSelection);
  150.  
  151. document.getElementById('startBtn').addEventListener('click', function() {
  152. if (!config.clickPosition) {
  153. alert('请先设置点击位置!');
  154. return;
  155. }
  156.  
  157. config.enabled = !config.enabled;
  158. this.textContent = config.enabled ? '停止点赞' : '开始点赞';
  159. this.style.background = config.enabled ? '#ff4444' : '#fe2c55';
  160.  
  161. if (config.enabled) {
  162. startAutoClick();
  163. } else {
  164. stopAutoClick();
  165. }
  166. });
  167.  
  168. document.getElementById('intervalInput').addEventListener('change', function() {
  169. const value = parseInt(this.value);
  170. if (value >= 100 && value <= 5000) {
  171. config.clickInterval = value;
  172. if (config.enabled) {
  173. startAutoClick();
  174. }
  175. } else {
  176. alert('基础间隔请设置在100-5000ms之间');
  177. this.value = config.clickInterval;
  178. }
  179. });
  180.  
  181. document.getElementById('variationInput').addEventListener('change', function() {
  182. const value = parseInt(this.value);
  183. if (value >= 0 && value <= 2000) {
  184. config.intervalVariation = value;
  185. } else {
  186. alert('波动范围请设置在0-2000ms之间');
  187. this.value = config.intervalVariation;
  188. }
  189. });
  190.  
  191. document.getElementById('durationInput').addEventListener('change', function() {
  192. const value = parseInt(this.value);
  193. if (value >= 50 && value <= 1000) {
  194. config.clickDuration = value;
  195. } else {
  196. alert('点击持续时间请设置在50-1000ms之间');
  197. this.value = config.clickDuration;
  198. }
  199. });
  200. }
  201.  
  202. // 开始位置选择
  203. function startPositionSelection() {
  204. if (config.isSettingPosition) return;
  205.  
  206. config.isSettingPosition = true;
  207. const statusEl = document.getElementById('status');
  208. statusEl.textContent = '请点击要点赞的位置...';
  209.  
  210. const overlay = document.createElement('div');
  211. overlay.style.cssText = `
  212. position: fixed;
  213. top: 0;
  214. left: 0;
  215. width: 100%;
  216. height: 100%;
  217. background: transparent;
  218. cursor: crosshair;
  219. z-index: 9999998;
  220. `;
  221.  
  222. document.body.appendChild(overlay);
  223.  
  224. overlay.addEventListener('click', function handleClick(e) {
  225. e.preventDefault();
  226. e.stopPropagation();
  227.  
  228. config.clickPosition = {
  229. x: e.clientX,
  230. y: e.clientY
  231. };
  232.  
  233. statusEl.textContent = `点击位置已设置: (${e.clientX}, ${e.clientY})`;
  234. config.isSettingPosition = false;
  235.  
  236. overlay.remove();
  237. }, { once: true });
  238. }
  239.  
  240. // 获取随机间隔时间
  241. function getRandomInterval() {
  242. const variation = Math.random() * 2 * config.intervalVariation - config.intervalVariation;
  243. return Math.max(100, config.clickInterval + variation);
  244. }
  245.  
  246. // 更新下次点击时间显示
  247. function updateNextClickTime(interval) {
  248. const nextClickEl = document.getElementById('nextClick');
  249. if (nextClickEl) {
  250. nextClickEl.textContent = `下次点击: ${Math.round(interval)}ms`;
  251. }
  252. }
  253.  
  254. // 执行点击
  255. async function performClick() {
  256. if (!config.enabled || !config.clickPosition) return;
  257.  
  258. try {
  259. const element = document.elementFromPoint(
  260. config.clickPosition.x,
  261. config.clickPosition.y
  262. );
  263.  
  264. if (element) {
  265. // 模拟鼠标按下
  266. element.dispatchEvent(new MouseEvent('mousedown', {
  267. bubbles: true,
  268. cancelable: true,
  269. view: window,
  270. clientX: config.clickPosition.x,
  271. clientY: config.clickPosition.y
  272. }));
  273.  
  274. // 等待设定的持续时间
  275. await new Promise(resolve => setTimeout(resolve, config.clickDuration));
  276.  
  277. // 模拟鼠标松开和点击
  278. ['mouseup', 'click'].forEach(eventType => {
  279. element.dispatchEvent(new MouseEvent(eventType, {
  280. bubbles: true,
  281. cancelable: true,
  282. view: window,
  283. clientX: config.clickPosition.x,
  284. clientY: config.clickPosition.y
  285. }));
  286. });
  287.  
  288. config.clickCount++;
  289. document.getElementById('clickCount').textContent = `点击次数: ${config.clickCount}`;
  290. }
  291. } catch (error) {
  292. console.error('点击失败:', error);
  293. }
  294. }
  295.  
  296. // 开始自动点击
  297. function startAutoClick() {
  298. stopAutoClick();
  299.  
  300. function scheduleNextClick() {
  301. if (!config.enabled) return;
  302.  
  303. const nextInterval = getRandomInterval();
  304. updateNextClickTime(nextInterval);
  305.  
  306. window.clickTimer = setTimeout(() => {
  307. performClick();
  308. scheduleNextClick();
  309. }, nextInterval);
  310. }
  311.  
  312. performClick();
  313. scheduleNextClick();
  314. }
  315.  
  316. // 停止自动点击
  317. function stopAutoClick() {
  318. if (window.clickTimer) {
  319. clearTimeout(window.clickTimer);
  320. window.clickTimer = null;
  321. }
  322. }
  323.  
  324. // 初始化
  325. function init() {
  326. createControlPanel();
  327. }
  328.  
  329. // 页面加载完成后初始化
  330. if (document.readyState === 'loading') {
  331. document.addEventListener('DOMContentLoaded', init);
  332. } else {
  333. init();
  334. }
  335.  
  336. // 页面卸载时清理
  337. window.addEventListener('unload', stopAutoClick);
  338. })();