Greasy Fork is available in English.

自研 - 多个站点 - 自动签到

自动完成周期性签到。目前已适配中图网、阿里云开发者社区和母带吧音乐论坛。

  1. // ==UserScript==
  2. // @name 自研 - 多个站点 - 自动签到
  3. // @name:en_US Self-made - Multi-site - Auto Check-in
  4. // @description 自动完成周期性签到。目前已适配中图网、阿里云开发者社区和母带吧音乐论坛。
  5. // @description:en_US Automatically complete periodic check-ins. Currently compatible with options BooksChina, Alibaba Cloud Developer BBS, and MuDaiBa MUSIC BBS.
  6. // @version 1.0.3
  7. // @author CPlayerCHN
  8. // @license MulanPSL-2.0
  9. // @namespace https://www.gitlink.org.cn/CPlayerCHN
  10. // @match https://www.bookschina.com/vieworder/default.aspx
  11. // @match https://link.bilibili.com/p/center/index
  12. // @match https://live.bilibili.com/*
  13. // @match https://developer.aliyun.com/
  14. // @match https://developer.aliyun.com/?accounttraceid=*
  15. // @match https://developer.aliyun.com/live/251214
  16. // @match https://developer.aliyun.com/score
  17. // @match https://mudaiba.com/
  18. // @exclude https://mudaiba.com/user-login.htm
  19. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  20. // @grant GM_openInTab
  21. // @grant window.close
  22. // @run-at document-idle
  23. // @noframes
  24. // ==/UserScript==
  25. /*
  26. {
  27. "name": "[站点名称]( - 签到项)",
  28. "enable": ["true 启用", "false 禁用"],
  29. "url": /页面正则/,
  30. "checks": {
  31. "login": { // 登录状态检测
  32. "enable": ["true 启用", "false 禁用"],
  33. "mode": ["elm 元素存在", "text 元素内文本", "attribute 元素属性"],
  34. "elm": "元素选择器",
  35. "data": ["元素内文本或元素属性键", "元素属性值"]
  36. },
  37. "signIn": { // 签到检测
  38. "mode": ["elm 元素存在", "text 元素内文本", "attribute 元素属性"],
  39. "elm": "元素选择器",
  40. "data": ["元素内文本或元素属性键", "元素属性值"]
  41. },
  42. },
  43. "actions": {
  44. "signIn": [
  45. {
  46. "name": "行动名称",
  47. "mode": ["click 点击元素", "open 新建页面", "openSelf 当前页面跳转", "reload 重载页面", "close 关闭页面", "script 脚本"],
  48. "data": "元素选择器或页面链接",
  49. "sleep": "执行前等待(单位为秒)"
  50. }
  51. ],
  52. "unLogin": [],
  53. "hasSignIn": [
  54. {
  55. "name": "关闭页面",
  56. "mode": "close",
  57. "data": "",
  58. "sleep": 1
  59. }
  60. ]
  61. }
  62. },
  63. */
  64.  
  65.  
  66. (function() {
  67. 'use strict';
  68.  
  69. // 定义「配置信息」「网页标题」变量和「元素选择器」「操作执行」函数
  70. const config = [
  71. {
  72. "name": "中图网",
  73. "enable": true,
  74. "url": /https:\/\/www.bookschina.com\/vieworder\/default.aspx/,
  75. "checks": {
  76. "login": {
  77. "enable": true,
  78. "mode": "",
  79. "elm": "",
  80. "data": [""]
  81. },
  82. "signIn": {
  83. "mode": "text",
  84. "elm": ".signBtn a",
  85. "data": ["签到送书币"]
  86. },
  87. },
  88. "actions": {
  89. "signIn": [
  90. {
  91. "name": "打开签到弹框",
  92. "mode": "click",
  93. "data": ".signBtn a",
  94. "sleep": 2
  95. },
  96. {
  97. "name": "点击签到按钮",
  98. "mode": "click",
  99. "data": ".flopCon #cover1",
  100. "sleep": 2
  101. },
  102. {
  103. "name": "关闭页面",
  104. "mode": "close",
  105. "data": "",
  106. "sleep": 6
  107. }
  108. ],
  109. "unLogin": [],
  110. "hasSignIn": [
  111. {
  112. "name": "关闭页面",
  113. "mode": "close",
  114. "data": "",
  115. "sleep": 1
  116. }
  117. ]
  118. }
  119. },
  120. {
  121. "name": "阿里云开发者社区 - 签到",
  122. "enable": true,
  123. "url": /https:\/\/developer.aliyun.com\/(\?accounttraceid=\w+)?$/,
  124. "checks": {
  125. "login": {
  126. "enable": true,
  127. "mode": "text",
  128. "elm": ".aliyun-register",
  129. "data": ["登录/注册"]
  130. },
  131. "signIn": {
  132. "mode": "elm",
  133. "elm": ".user-sign-day-box.active .user-sign-day-box-num",
  134. "data": [""]
  135. },
  136. },
  137. "actions": {
  138. "signIn": [
  139. {
  140. "name": "点击签到按钮",
  141. "mode": "click",
  142. "data": ".user-sign-day-box.active .user-sign-day-box-num",
  143. "sleep": .5
  144. },
  145. {
  146. "name": "打开视频任务页面",
  147. "mode": "openSelf",
  148. "data": "https://developer.aliyun.com/live/251214",
  149. "sleep": .5
  150. }
  151. ],
  152. "unLogin": [
  153. {
  154. "name": "访问登录页面",
  155. "mode": "click",
  156. "data": ".aliyun-register",
  157. "sleep": 0
  158. }
  159. ],
  160. "hasSignIn": [
  161. {
  162. "name": "关闭页面",
  163. "mode": "close",
  164. "data": "",
  165. "sleep": 1
  166. }
  167. ]
  168. }
  169. },
  170. {
  171. "name": "阿里云开发者社区 - 视频任务",
  172. "enable": true,
  173. "url": /https:\/\/developer.aliyun.com\/live\/251214/,
  174. "checks": {
  175. "login": {
  176. "enable": true,
  177. "mode": "text",
  178. "elm": ".aliyun-register",
  179. "data": ["登录/注册"]
  180. },
  181. "signIn": {
  182. "mode": "elm",
  183. "elm": "114514",
  184. "data": [""]
  185. },
  186. },
  187. "actions": {
  188. "signIn": [
  189. {
  190. "name": "将视频静音",
  191. "mode": "script",
  192. "data": () => {
  193. function waitForElm(selector) {
  194. // https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists
  195. return new Promise(resolve => {
  196. if (document.querySelector(selector)) {
  197. return resolve(document.querySelector(selector));
  198. }
  199. const observer = new MutationObserver(mutations => {
  200. if (document.querySelector(selector)) {
  201. observer.disconnect();
  202. resolve(document.querySelector(selector));
  203. }
  204. });
  205. observer.observe(document.body, {
  206. childList: true,
  207. subtree: true
  208. });
  209. });
  210. };
  211.  
  212. waitForElm('video').then((vid) => {
  213. document.querySelector('video').muted = true;
  214. })
  215. },
  216. "sleep": 0
  217. },
  218. {
  219. "name": "打开积分领取页面",
  220. "mode": "openSelf",
  221. "data": "https://developer.aliyun.com/score",
  222. "sleep": 120
  223. }
  224. ],
  225. "unLogin": [
  226. {
  227. "name": "访问登录页面",
  228. "mode": "click",
  229. "data": ".aliyun-register",
  230. "sleep": 0
  231. }
  232. ],
  233. "hasSignIn": [
  234. {
  235. "name": "关闭页面",
  236. "mode": "close",
  237. "data": "",
  238. "sleep": 1
  239. }
  240. ]
  241. }
  242. },
  243. {
  244. "name": "阿里云开发者社区 - 积分领取",
  245. "enable": true,
  246. "url": /https:\/\/developer.aliyun.com\/score/,
  247. "checks": {
  248. "login": {
  249. "enable": true,
  250. "mode": "text",
  251. "elm": ".aliyun-register",
  252. "data": ["登录/注册"]
  253. },
  254. "signIn": {
  255. "mode": "elm",
  256. "elm": ".user-level-bottom-box-wrapper-button",
  257. "data": [""]
  258. },
  259. },
  260. "actions": {
  261. "signIn": [
  262. {
  263. "name": "点击签到按钮",
  264. "mode": "click",
  265. "data": ".user-level-bottom-box-wrapper-button",
  266. "sleep": 3
  267. },
  268. ],
  269. "unLogin": [
  270. {
  271. "name": "访问登录页面",
  272. "mode": "click",
  273. "data": ".aliyun-register",
  274. "sleep": 0
  275. }
  276. ],
  277. "hasSignIn": []
  278. }
  279. },
  280. {
  281. "name": "母带吧音乐论坛",
  282. "enable": true,
  283. "url": /https:\/\/mudaiba.com\//,
  284. "checks": {
  285. "login": {
  286. "enable": true,
  287. "mode": "elm",
  288. "elm": ".nav-link[href=\"user-login.htm\"]",
  289. "data": [""]
  290. },
  291. "signIn": {
  292. "mode": "text",
  293. "elm": "#header .navbar-nav:nth-child(2) li:nth-child(5) a",
  294. "data": [" 签到"]
  295. },
  296. },
  297. "actions": {
  298. "signIn": [
  299. {
  300. "name": "点击签到按钮",
  301. "mode": "click",
  302. "data": "#header .navbar-nav:nth-child(2) li:nth-child(5) a",
  303. "sleep": 0
  304. },
  305. ],
  306. "unLogin": [
  307. {
  308. "name": "访问登录页面",
  309. "mode": "click",
  310. "data": ".nav-link[href=\"user-login.htm\"]",
  311. "sleep": 0
  312. }
  313. ],
  314. "hasSignIn": []
  315. }
  316. }
  317. ],
  318. title = document.title;
  319.  
  320. function $(elm, node = 0) {
  321. try {
  322. return document.querySelectorAll(elm)[node]
  323. }catch (e) {
  324. return true
  325. }
  326. }
  327. function action(data) {
  328. document.title = `[正在执行「${data.name}」中]${title}`
  329. // 等待指定时间加噪音时间后,正式执行对应操作
  330. setTimeout(() => {
  331. if(data.mode === "click" && $(data.data)) {
  332. $(data.data).click();
  333. }else if(data.mode === "open") {
  334. GM_openInTab(data.data, {"active": true})
  335. }else if(data.mode === "openSelf") {
  336. window.open(data.data,"_self")
  337. }else if(data.mode === "reload") {
  338. location.reload()
  339. }else if(data.mode === "close") {
  340. window.close()
  341. }else if(data.mode === "script") {
  342. data.data()
  343. }
  344. }, (data.sleep + Math.random()) * 1000);
  345. }
  346.  
  347. // 等待 3 秒
  348. setTimeout(() => {
  349. // 遍历「配置信息」
  350. config.forEach((datas) => {
  351. // 如果匹配且配置启用
  352. if(datas.url.test(location.href) && datas.enable) {
  353. document.title = `[已匹配规则「${datas.name}」]${title}`
  354. // 判断是否登录,如果未登录就执行对应操作
  355. if(datas.checks.login.enable && datas.checks.login.mode === "elm" && $(datas.checks.login.elm) || datas.checks.login.enable && datas.checks.login.mode === "text" && $(datas.checks.login.elm) && $(datas.checks.login.elm).textContent === datas.checks.login.data[0] || datas.checks.login.enable && datas.checks.login.mode === "attribute" && $(datas.checks.login.elm) && $(datas.checks.login.elm).getAttribute(datas.checks.login.data[0]) === datas.checks.login.data[1]) {
  356. document.title = `[未登录]${title}`
  357. datas.actions.unLogin.forEach((data) => {
  358. action(data)
  359. })
  360. // 判断是否签到,如果未签到就执行对应操作
  361. }else if(datas.checks.signIn.mode === "elm" && $(datas.checks.signIn.elm) || datas.checks.signIn.mode === "text" && $(datas.checks.signIn.elm) && $(datas.checks.signIn.elm).textContent === datas.checks.signIn.data[0] || datas.checks.signIn.mode === "attribute" && $(datas.checks.signIn.elm) && $(datas.checks.signIn.elm).getAttribute(datas.checks.signIn.data[0]) === datas.checks.signIn.data[1]) {
  362. document.title = `[签到中]${title}`
  363. datas.actions.signIn.forEach((data) => {
  364. action(data)
  365. })
  366. // 否则就执行已签到对应操作
  367. }else {
  368. document.title = `[已签到]${title}`
  369. datas.actions.hasSignIn.forEach((data) => {
  370. action(data)
  371. });
  372. }
  373. }
  374. });
  375. }, 3000);
  376.  
  377. })();