linux.do自动点赞,自动刷文章

自动刷linuxdo文章

  1. // ==UserScript==
  2. // @name linux.do自动点赞,自动刷文章
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3.0
  5. // @description 自动刷linuxdo文章
  6. // @author linuxdoyyds
  7. // @match https://meta.discourse.org/*
  8. // @match https://linux.do/*
  9. // @grant none
  10. // @license MIT
  11. // @icon https://www.google.com/s2/favicons?domain=linux.do
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. ("use strict");
  16. // 定义可能的基本URL
  17. const possibleBaseURLs = ["https://meta.discourse.org", "https://linux.do"];
  18.  
  19. // 获取当前页面的URL
  20. const currentURL = window.location.href;
  21.  
  22. // 确定当前页面对应的BASE_URL
  23. let BASE_URL = possibleBaseURLs.find((url) => currentURL.startsWith(url));
  24.  
  25. // 环境变量:阅读网址,如果没有找到匹配的URL,则默认为第一个
  26. if (!BASE_URL) {
  27. BASE_URL = possibleBaseURLs[0];
  28. console.log("默认BASE_URL设置为: " + BASE_URL);
  29. } else {
  30. console.log("当前BASE_URL是: " + BASE_URL);
  31. }
  32.  
  33. // 以下是脚本的其余部分
  34. console.log("脚本正在运行在: " + BASE_URL);
  35. //1.进入网页 https://linux.do/t/topic/数字(1,2,3,4)
  36. //2.使滚轮均衡的往下移动模拟刷文章
  37. // 检查是否是第一次运行脚本
  38. function checkFirstRun() {
  39. if (localStorage.getItem("isFirstRun") === null) {
  40. // 是第一次运行,执行初始化操作
  41. console.log("脚本第一次运行,执行初始化操作...");
  42. updateInitialData();
  43.  
  44. // 设置 isFirstRun 标记为 false
  45. localStorage.setItem("isFirstRun", "false");
  46. } else {
  47. // 非第一次运行
  48. console.log("脚本非第一次运行");
  49. }
  50. }
  51.  
  52. // 更新初始数据的函数
  53. function updateInitialData() {
  54. localStorage.setItem("read", "false"); // 开始时自动滚动关闭
  55. localStorage.setItem("autoLikeEnabled", "false"); //默认关闭自动点赞
  56. console.log("执行了初始数据更新操作");
  57. }
  58. const delay = 2000; // 滚动检查的间隔(毫秒)
  59. let scrollInterval = null;
  60. let checkScrollTimeout = null;
  61. let autoLikeInterval = null;
  62.  
  63. function scrollToBottomSlowly(
  64. stopDistance = 9999999999,
  65. callback = undefined,
  66. distancePerStep = 20,
  67. delayPerStep = 50
  68. ) {
  69. if (scrollInterval !== null) {
  70. clearInterval(scrollInterval);
  71. }
  72. scrollInterval = setInterval(() => {
  73. if (
  74. window.innerHeight + window.scrollY >=
  75. document.body.offsetHeight - 100 ||
  76. window.innerHeight + window.scrollY >= stopDistance
  77. ) {
  78. clearInterval(scrollInterval);
  79. scrollInterval = null;
  80. if (typeof callback === "function") {
  81. callback(); // 当滚动结束时调用回调函数
  82. }
  83. } else {
  84. window.scrollBy(0, distancePerStep);
  85. }
  86. }, delayPerStep);
  87. }
  88. // 功能:跳转到下一个话题
  89.  
  90. function navigateToNextTopic() {
  91. // 定义包含文章列表的数组
  92. const urls = [
  93. `${BASE_URL}/latest`,
  94. `${BASE_URL}/top`,
  95. `${BASE_URL}/latest?ascending=false&order=posts`,
  96. // `${BASE_URL}/unread`, // 示例:如果你想将这个URL启用,只需去掉前面的注释
  97. ];
  98.  
  99. // 生成一个随机索引
  100. const randomIndex = Math.floor(Math.random() * urls.length);
  101.  
  102. // 根据随机索引选择一个URL
  103. const nextTopicURL = urls[randomIndex]; // 在跳转之前,标记即将跳转到下一个话题
  104. localStorage.setItem("navigatingToNextTopic", "true");
  105. // 尝试导航到下一个话题
  106. window.location.href = nextTopicURL;
  107. }
  108.  
  109. // 检查是否已滚动到底部(不断重复执行)
  110. function checkScroll() {
  111. if (localStorage.getItem("read")) {
  112. if (
  113. window.innerHeight + window.scrollY >=
  114. document.body.offsetHeight - 100
  115. ) {
  116. console.log("已滚动到底部");
  117. navigateToNextTopic();
  118. } else {
  119. scrollToBottomSlowly();
  120. if (checkScrollTimeout !== null) {
  121. clearTimeout(checkScrollTimeout);
  122. }
  123. checkScrollTimeout = setTimeout(checkScroll, delay);
  124. }
  125. }
  126. }
  127.  
  128. // 入口函数
  129. window.addEventListener("load", () => {
  130. checkFirstRun();
  131. console.log(
  132. "autoRead",
  133. localStorage.getItem("read"),
  134. "autoLikeEnabled",
  135. localStorage.getItem("autoLikeEnabled")
  136. );
  137. if (localStorage.getItem("read") === "true") {
  138. // 检查是否正在导航到下一个话题
  139. if (localStorage.getItem("navigatingToNextTopic") === "true") {
  140. console.log("正在导航到下一个话题");
  141. // 等待一段时间或直到页面完全加载
  142. // 页面加载完成后,移除标记
  143. localStorage.removeItem("navigatingToNextTopic");
  144. // 使用setTimeout延迟执行
  145. setTimeout(() => {
  146. // 先随机滚动一段距离然后再查找链接
  147. scrollToBottomSlowly(
  148. Math.random() * document.body.offsetHeight * 3,
  149. searchLinkClick,
  150. 20,
  151. 20
  152. );
  153. }, 2000); // 延迟2000毫秒(即2秒)
  154. } else {
  155. console.log("执行正常的滚动和检查逻辑");
  156. // 执行正常的滚动和检查逻辑
  157. checkScroll();
  158. if (isAutoLikeEnabled()) {
  159. //自动点赞
  160. autoLike();
  161. }
  162. }
  163. }
  164. });
  165. // 创建一个控制滚动的按钮
  166. function searchLinkClick() {
  167. // 在新页面加载后执行检查
  168. // 使用CSS属性选择器寻找href属性符合特定格式的<a>标签
  169. const links = document.querySelectorAll('a[href^="/t/"]');
  170. // const alreadyReadLinks = JSON.parse(
  171. // localStorage.getItem("alreadyReadLinks") || "[]"
  172. // ); // 获取已阅读链接列表
  173.  
  174. // 筛选出未阅读的链接
  175. const unreadLinks = Array.from(links).filter((link) => {
  176. // 检查链接是否已经被读过
  177. // const isAlreadyRead = alreadyReadLinks.includes(link.href);
  178. // if (isAlreadyRead) {
  179. // return false; // 如果链接已被读过,直接排除
  180. // }
  181.  
  182. // 向上遍历DOM树,查找包含'visited'类的父级元素,最多查找三次
  183. let parent = link.parentElement;
  184. let times = 0; // 查找次数计数器
  185. while (parent && times < 3) {
  186. if (parent.classList.contains("visited")) {
  187. // 如果找到包含'visited'类的父级元素,中断循环
  188. return false; // 父级元素包含'visited'类,排除这个链接
  189. }
  190. parent = parent.parentElement; // 继续向上查找
  191. times++; // 增加查找次数
  192. }
  193.  
  194. // 如果链接未被读过,且在向上查找三次内,其父级元素中没有包含'visited'类,则保留这个链接
  195. return true;
  196. });
  197.  
  198. // 如果找到了这样的链接
  199. if (unreadLinks.length > 0) {
  200. // 从所有匹配的链接中随机选择一个
  201. const randomIndex = Math.floor(Math.random() * unreadLinks.length);
  202. const link = unreadLinks[randomIndex];
  203. // 打印找到的链接(可选)
  204. console.log("Found link:", link.href);
  205. // // 模拟点击该链接
  206. // setTimeout(() => {
  207. // link.click();
  208. // }, delay);
  209. // 将链接添加到已阅读列表并更新localStorage
  210. // alreadyReadLinks.push(link.href);
  211. // localStorage.setItem(
  212. // "alreadyReadLinks",
  213. // JSON.stringify(alreadyReadLinks)
  214. // );
  215.  
  216. // 导航到该链接
  217. window.location.href = link.href;
  218. } else {
  219. // 如果没有找到符合条件的链接,打印消息(可选)
  220. console.log("No link with the specified format was found.");
  221. scrollToBottomSlowly(
  222. Math.random() * document.body.offsetHeight * 3,
  223. searchLinkClick
  224. );
  225. }
  226. }
  227. // 从localStorage获取当前的点击计数,如果不存在则初始化为0
  228. let clickCounter = parseInt(localStorage.getItem("clickCounter") || "0", 10);
  229. function autoLike() {
  230. // 寻找所有的discourse-reactions-reaction-button
  231. const buttons = document.querySelectorAll(
  232. ".discourse-reactions-reaction-button"
  233. );
  234.  
  235. // 逐个点击找到的按钮
  236. buttons.forEach((button, index) => {
  237. if (
  238. (button.title !== "点赞此帖子" && button.title !== "Like this post") ||
  239. clickCounter >= 50
  240. ) {
  241. return;
  242. }
  243.  
  244. // 使用setTimeout来错开每次点击的时间,避免同时触发点击
  245. autoLikeInterval = setTimeout(() => {
  246. // 模拟点击
  247. button.click();
  248. console.log(`Clicked like button ${index + 1}`);
  249. clickCounter++; // 更新点击计数器
  250. // 将新的点击计数存储到localStorage
  251. localStorage.setItem("clickCounter", clickCounter.toString());
  252. // 如果点击次数达到50次,则设置点赞变量为false
  253. if (clickCounter === 50) {
  254. console.log("Reached 50 likes, setting the like variable to false.");
  255. localStorage.setItem("autoLikeEnabled", "false"); // 使用localStorage存储点赞变量状态
  256. }
  257. }, index * 1000); // 这里的1000毫秒是两次点击之间的间隔,可以根据需要调整
  258. });
  259. }
  260. const button = document.createElement("button");
  261. // 初始化按钮文本基于当前的阅读状态
  262. button.textContent =
  263. localStorage.getItem("read") === "true" ? "停止阅读" : "开始阅读";
  264. button.style.position = "fixed";
  265. button.style.bottom = "10px"; // 之前是 top
  266. button.style.left = "10px"; // 之前是 right
  267. button.style.zIndex = 1000;
  268. button.style.backgroundColor = "#f0f0f0"; // 浅灰色背景
  269. button.style.color = "#000"; // 黑色文本
  270. button.style.border = "1px solid #ddd"; // 浅灰色边框
  271. button.style.padding = "5px 10px"; // 内边距
  272. button.style.borderRadius = "5px"; // 圆角
  273. document.body.appendChild(button);
  274.  
  275. button.onclick = function () {
  276. const currentlyReading = localStorage.getItem("read") === "true";
  277. const newReadState = !currentlyReading;
  278. localStorage.setItem("read", newReadState.toString());
  279. button.textContent = newReadState ? "停止阅读" : "开始阅读";
  280. if (!newReadState) {
  281. if (scrollInterval !== null) {
  282. clearInterval(scrollInterval);
  283. scrollInterval = null;
  284. }
  285. if (checkScrollTimeout !== null) {
  286. clearTimeout(checkScrollTimeout);
  287. checkScrollTimeout = null;
  288. }
  289. localStorage.removeItem("navigatingToNextTopic");
  290. } else {
  291. // 如果是Linuxdo,就导航到我的帖子
  292. if (BASE_URL == "https://linux.do") {
  293. window.location.href = "https://linux.do/t/topic/63238";
  294. } else {
  295. window.location.href = `${BASE_URL}/t/topic/1`;
  296. }
  297. checkScroll();
  298. }
  299. };
  300.  
  301. //自动点赞按钮
  302. // 在页面上添加一个控制自动点赞的按钮
  303. const toggleAutoLikeButton = document.createElement("button");
  304. toggleAutoLikeButton.textContent = isAutoLikeEnabled()
  305. ? "禁用自动点赞"
  306. : "启用自动点赞";
  307. toggleAutoLikeButton.style.position = "fixed";
  308. toggleAutoLikeButton.style.bottom = "50px"; // 之前是 top,且与另一个按钮错开位置
  309. toggleAutoLikeButton.style.left = "10px"; // 之前是 right
  310. toggleAutoLikeButton.style.zIndex = "1000";
  311. toggleAutoLikeButton.style.backgroundColor = "#f0f0f0"; // 浅灰色背景
  312. toggleAutoLikeButton.style.color = "#000"; // 黑色文本
  313. toggleAutoLikeButton.style.border = "1px solid #ddd"; // 浅灰色边框
  314. toggleAutoLikeButton.style.padding = "5px 10px"; // 内边距
  315. toggleAutoLikeButton.style.borderRadius = "5px"; // 圆角
  316. document.body.appendChild(toggleAutoLikeButton);
  317.  
  318. // 为按钮添加点击事件处理函数
  319. toggleAutoLikeButton.addEventListener("click", () => {
  320. const isEnabled = !isAutoLikeEnabled();
  321. setAutoLikeEnabled(isEnabled);
  322. toggleAutoLikeButton.textContent = isEnabled
  323. ? "禁用自动点赞"
  324. : "启用自动点赞";
  325. });
  326. // 判断是否启用自动点赞
  327. function isAutoLikeEnabled() {
  328. // 从localStorage获取autoLikeEnabled的值,如果未设置,默认为"true"
  329. return localStorage.getItem("autoLikeEnabled") !== "false";
  330. }
  331.  
  332. // 设置自动点赞的启用状态
  333. function setAutoLikeEnabled(enabled) {
  334. localStorage.setItem("autoLikeEnabled", enabled ? "true" : "false");
  335. }
  336. })();