├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── build
└── prod.js
├── bun.lock
├── bunfig.toml
├── package.json
├── packages
├── auto-scroll
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.ts
├── bilibili-live-auto-click-like
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.ts
├── cocomanga-subscription-sort
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.ts
├── douyin-live-auto-click-like
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.ts
├── mooc-skip-questions
│ ├── README.md
│ ├── package.json
│ └── src
│ │ └── index.ts
└── tencent-kt-box
│ ├── README.md
│ ├── package.json
│ └── src
│ └── index.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
2 |
3 | # Logs
4 |
5 | logs
6 | _.log
7 | npm-debug.log_
8 | yarn-debug.log*
9 | yarn-error.log*
10 | lerna-debug.log*
11 | .pnpm-debug.log*
12 |
13 | # Caches
14 |
15 | .cache
16 |
17 | # Diagnostic reports (https://nodejs.org/api/report.html)
18 |
19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
20 |
21 | # Runtime data
22 |
23 | pids
24 | _.pid
25 | _.seed
26 | *.pid.lock
27 |
28 | # Directory for instrumented libs generated by jscoverage/JSCover
29 |
30 | lib-cov
31 |
32 | # Coverage directory used by tools like istanbul
33 |
34 | coverage
35 | *.lcov
36 |
37 | # nyc test coverage
38 |
39 | .nyc_output
40 |
41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
42 |
43 | .grunt
44 |
45 | # Bower dependency directory (https://bower.io/)
46 |
47 | bower_components
48 |
49 | # node-waf configuration
50 |
51 | .lock-wscript
52 |
53 | # Compiled binary addons (https://nodejs.org/api/addons.html)
54 |
55 | build/Release
56 |
57 | # Dependency directories
58 |
59 | node_modules/
60 | jspm_packages/
61 |
62 | # Snowpack dependency directory (https://snowpack.dev/)
63 |
64 | web_modules/
65 |
66 | # TypeScript cache
67 |
68 | *.tsbuildinfo
69 |
70 | # Optional npm cache directory
71 |
72 | .npm
73 |
74 | # Optional eslint cache
75 |
76 | .eslintcache
77 |
78 | # Optional stylelint cache
79 |
80 | .stylelintcache
81 |
82 | # Microbundle cache
83 |
84 | .rpt2_cache/
85 | .rts2_cache_cjs/
86 | .rts2_cache_es/
87 | .rts2_cache_umd/
88 |
89 | # Optional REPL history
90 |
91 | .node_repl_history
92 |
93 | # Output of 'npm pack'
94 |
95 | *.tgz
96 |
97 | # Yarn Integrity file
98 |
99 | .yarn-integrity
100 |
101 | # dotenv environment variable files
102 |
103 | .env
104 | .env.development.local
105 | .env.test.local
106 | .env.production.local
107 | .env.local
108 |
109 | # parcel-bundler cache (https://parceljs.org/)
110 |
111 | .parcel-cache
112 |
113 | # Next.js build output
114 |
115 | .next
116 | out
117 |
118 | # Nuxt.js build / generate output
119 |
120 | .nuxt
121 | dist
122 |
123 | # Gatsby files
124 |
125 | # Comment in the public line in if your project uses Gatsby and not Next.js
126 |
127 | # https://nextjs.org/blog/next-9-1#public-directory-support
128 |
129 | # public
130 |
131 | # vuepress build output
132 |
133 | .vuepress/dist
134 |
135 | # vuepress v2.x temp and cache directory
136 |
137 | .temp
138 |
139 | # Docusaurus cache and generated files
140 |
141 | .docusaurus
142 |
143 | # Serverless directories
144 |
145 | .serverless/
146 |
147 | # FuseBox cache
148 |
149 | .fusebox/
150 |
151 | # DynamoDB Local files
152 |
153 | .dynamodb/
154 |
155 | # TernJS port file
156 |
157 | .tern-port
158 |
159 | # Stores VSCode versions used for testing VSCode extensions
160 |
161 | .vscode-test
162 |
163 | # yarn v2
164 |
165 | .yarn/cache
166 | .yarn/unplugged
167 | .yarn/build-state.yml
168 | .yarn/install-state.gz
169 | .pnp.*
170 |
171 | # IntelliJ based IDEs
172 | .idea
173 |
174 | # Finder (MacOS) folder config
175 | .DS_Store
176 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 2,
3 | "editor.formatOnSave": true,
4 | "editor.codeActionsOnSave": {
5 | "source.organizeImports": "explicit"
6 | },
7 | "prettier.tabWidth": 2,
8 | "prettier.semi": false,
9 | "prettier.printWidth": 120,
10 | "prettier.singleQuote": true,
11 | "prettier.arrowParens": "avoid",
12 | "prettier.trailingComma": "none",
13 | "prettier.htmlWhitespaceSensitivity": "ignore"
14 | }
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2025, Kaiter-Plus
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | 3. Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 油猴脚本
2 |
3 | ### 支持作者
4 |
5 | 
6 | 
7 |
8 |
9 | ## 1 项目介绍
10 |
11 | - 用来保存平时学习时写的油猴脚本的项目
12 |
13 | ## 2 项目脚本功能介绍
14 |
15 | ### 2.1 网页翻译(重构中)
16 |
17 | #### 2.1.1 Translate
18 |
19 | - 网页翻译(整页翻译),给每个非中文的网页添加一个 google 翻译图标
20 | - 位置:默认右下角,可以设置到左下角
21 | - 设置:点击浏览器的油猴或者暴力猴插件图标即可看见脚本的配置选项,点击配置选项即可切换按钮的位置
22 |
23 | #### 2.1.2 Translate_ext
24 |
25 | - 网页翻译(整页翻译),给每个非中文的网页添加一个 google 翻译图标
26 | - 位置:默认右下角
27 | - 简介:本版本主要适配不能安装 Tampermonkey 或 Violentmonkey 的手机浏览器
28 |
29 | #### 2.1.2 Translate_only_chinese
30 |
31 | - 网页翻译(整页翻译),给每个非中文的网页添加一个 google 翻译图标
32 | - 位置:默认右下角
33 | - 简介:本版本主要针对只需要把外语翻译为中文的用户使用
34 |
35 | ### 2.2 AutoScroll
36 |
37 | - 自动滚动,给每个网页添加两个按钮,当鼠标分别覆盖这两个按钮时,页面将会自动向上或者向下滚动
38 |
39 | ### 2.3 MOOCSkipQuestion
40 |
41 | - 慕课网自动跳过播放过程中的题目,同时自动播放
42 |
43 | ### 2.4 TencentKTBox
44 |
45 | - 腾讯课堂自动自动签到脚本
46 |
47 | ### 2.5 COCO 漫画收藏按更新时间排序
48 |
49 | - 顾名思义,给[COCO 漫画](http://www.cocomanhua.com/)的收藏界面添加按照更新时间排序的功能
50 | - 最近的更新排在最上面
51 |
52 | ### 2.6 抖音自动点赞
53 |
54 | - 网页版抖音看直播自动点赞工具,同时优化了抖音官方点赞过多网页卡顿的问题(bug)
55 |
56 | ### 2.7 虎牙直播功能增强(重构中)
57 |
58 | - 给虎牙直播添加两个功能:时间同步和镜像画面
59 | - 时间同步:同步到最新时间
60 | - 镜像画面:顾名思义,直接让画面反转 180°
61 | - 自动选择最高画质
62 | - 自动领取百宝箱奖励
63 | - 自动网页全屏
64 |
--------------------------------------------------------------------------------
/build/prod.js:
--------------------------------------------------------------------------------
1 | import { Glob } from 'bun'
2 | import minimist from 'minimist'
3 | import { resolve } from 'node:path'
4 |
5 | // 获取打包命令的参数
6 | const args = minimist(Bun.argv.slice(2))
7 |
8 | // 需要打包的项目
9 | const project = args.p
10 |
11 | // 如果没有指定打包的项目,默认全部打包
12 | if (!project) {
13 | // 扫描路径
14 | const scanPath = resolve(__dirname, `../packages`)
15 | // 创建一个全局搜索对象,并指定搜索的表达式
16 | const glob = new Glob(`**/index.ts`)
17 | // 开始搜索,找到项目名称
18 | for await (const file of glob.scan(scanPath)) {
19 | // 拿到项目名称
20 | const project = file.split(/[\\\/]/)[0]
21 | // 打包
22 | await build(project)
23 | }
24 | } else {
25 | await build(project)
26 | }
27 |
28 | function getBanner(pkg) {
29 | // 公共头部
30 | const commonBanner = `
31 | // @name ${pkg.buildOptions.name.default}
32 | // @author ${pkg.author}
33 | // @description ${pkg.description}
34 | // @namespace ${pkg.repository.url}
35 | // @license ${pkg.license}
36 | // @version ${pkg.version}`
37 |
38 | // 每个脚本自定义头部
39 | let payloadBanner = ``
40 | const spaceLength = pkg.buildOptions.spaces
41 | const payload = pkg.buildOptions.payload
42 | if (payload) {
43 | for (const key in payload) {
44 | for (const item of payload[key]) {
45 | payloadBanner += `\n// @${key.padEnd(spaceLength, ' ')}${item}`
46 | }
47 | }
48 | }
49 |
50 | return `// ==UserScript==${commonBanner}${payloadBanner}\n// ==/UserScript==\n;`
51 | }
52 |
53 | async function build(projectName) {
54 | const entry = resolve(__dirname, `../packages/${projectName}/src/index.ts`)
55 | const pkg = require(`../packages/${projectName}/package.json`)
56 | const banner = getBanner(pkg)
57 | // 打包
58 | await Bun.build({
59 | entrypoints: [entry],
60 | outdir: resolve(__dirname, '../dist'),
61 | target: 'browser',
62 | format: 'iife',
63 | banner,
64 | naming: `[dir]/${projectName}.user.[ext]`
65 | }).catch(err => {
66 | console.log('打包失败,原因: ', err)
67 | })
68 | }
69 |
--------------------------------------------------------------------------------
/bun.lock:
--------------------------------------------------------------------------------
1 | {
2 | "lockfileVersion": 0,
3 | "workspaces": {
4 | "": {
5 | "devDependencies": {
6 | "@types/bun": "latest",
7 | "@types/tampermonkey": "^5.0.4",
8 | "minimist": "^1.2.8",
9 | },
10 | "peerDependencies": {
11 | "typescript": "^5.0.0",
12 | },
13 | },
14 | "packages/auto-scroll": {
15 | "name": "auto-scroll",
16 | "version": "1.0.1",
17 | },
18 | },
19 | "packages": {
20 | "@types/bun": ["@types/bun@1.1.14", "https://registry.npmmirror.com/@types/bun/-/bun-1.1.14.tgz", { "dependencies": { "bun-types": "1.1.37" } }, "sha512-opVYiFGtO2af0dnWBdZWlioLBoxSdDO5qokaazLhq8XQtGZbY4pY3/JxY8Zdf/hEwGubbp7ErZXoN1+h2yesxA=="],
21 |
22 | "@types/node": ["@types/node@20.12.14", "https://registry.npmmirror.com/@types/node/-/node-20.12.14.tgz", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
23 |
24 | "@types/tampermonkey": ["@types/tampermonkey@5.0.4", "https://registry.npmmirror.com/@types/tampermonkey/-/tampermonkey-5.0.4.tgz", {}, "sha512-HEJ0O5CkDZSwIgd9Zip4xM8o7gZC8zBmJuH1YEXNINIC+aCWEXD10pnpo3NQG5IWHx+Xr4fMSGq1jqeKXH2lpA=="],
25 |
26 | "@types/ws": ["@types/ws@8.5.13", "https://registry.npmmirror.com/@types/ws/-/ws-8.5.13.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA=="],
27 |
28 | "auto-scroll": ["auto-scroll@workspace:packages/auto-scroll", {}],
29 |
30 | "bun-types": ["bun-types@1.1.37", "https://registry.npmmirror.com/bun-types/-/bun-types-1.1.37.tgz", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA=="],
31 |
32 | "minimist": ["minimist@1.2.8", "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
33 |
34 | "typescript": ["typescript@5.7.2", "https://registry.npmmirror.com/typescript/-/typescript-5.7.2.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg=="],
35 |
36 | "undici-types": ["undici-types@5.26.5", "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/bunfig.toml:
--------------------------------------------------------------------------------
1 | [install]
2 | saveTextLockfile = true
3 | registry = "https://registry.npmmirror.com"
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tampermonkeyscript",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "repository": {
7 | "url": "https://github.com/Kaiter-Plus/TampermonkeyScript"
8 | },
9 | "scripts": {
10 | "build": "bun build/prod.js"
11 | },
12 | "workspaces": [
13 | "packages/*"
14 | ],
15 | "devDependencies": {
16 | "@types/bun": "latest",
17 | "@types/tampermonkey": "^5.0.4",
18 | "minimist": "^1.2.8"
19 | },
20 | "peerDependencies": {
21 | "typescript": "^5.0.0"
22 | }
23 | }
--------------------------------------------------------------------------------
/packages/auto-scroll/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 支持作者
4 |
5 | 
6 |
7 |
8 | ### 所有脚本开源地址,欢迎 star ⭐
9 |
10 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
11 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
12 |
13 | ## 1 功能介绍
14 |
15 | 给网页添加自动向上、向下滚动的按钮。对于一些经常需要滚动的场景很有用,比如看文章,看小说,看漫画等场景
16 |
17 | ### 1.1 如何使用它
18 |
19 | 使用很简单,直接使用【鼠标指针】移动覆盖到相应的按钮上即可使网页自动滚动,【鼠标指针】移动覆盖到【中间数值】,然后使用【鼠标滚轮】滚动即可调整滚动速度
20 |
21 | ### 1.2 功能截图
22 |
23 | 
24 |
25 | ## 2 更新日志
26 |
27 | ### 2.1 2022 更新日志
28 |
29 | - 2023/04/09 添加拖动功能
30 | - 2023/04/07 优化显示
31 | - 2023/04/06 添加滚动速度调整功能
32 | - 2021/03/17 实现鼠标覆盖自动向上向下滚动功能
33 |
--------------------------------------------------------------------------------
/packages/auto-scroll/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auto-scroll",
3 | "version": "1.0.1",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "给网页添加自动向上、向下滚动的按钮,对于看文章,看小说,看漫画等场景下使用极为舒适",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/auto-scroll"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "自动滚动"
14 | },
15 | "spaces": 12,
16 | "payload": {
17 | "include": ["*://*"],
18 | "grant": [
19 | "GM_addStyle",
20 | "GM_getValue",
21 | "GM_setValue",
22 | "GM_addElement"
23 | ],
24 | "noframes": [""]
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/packages/auto-scroll/src/index.ts:
--------------------------------------------------------------------------------
1 | interface Position {
2 | top: number
3 | left: number
4 | }
5 |
6 | enum DIRECTION {
7 | UP = -1, DOWN = 1
8 | }
9 |
10 | // 默认速度
11 | let defaultSpeed: number = 5
12 | // 定时器id
13 | let currentFrameId: number = 0
14 | // 记录上一次执行的时间
15 | let prevTIme: number = 0
16 | // 按下的位置
17 | const pressPosition: Position = { top: 0, left: 0 }
18 |
19 | // 初始化速度
20 | const speed: string = GM_getValue('speed')
21 | speed ? (defaultSpeed = +speed) : GM_setValue('speed', defaultSpeed)
22 |
23 | // 创建一个滚动容器
24 | const scrollContainer = GM_addElement(document.body, 'div', {
25 | id: 'scroll-container',
26 | class: 'scroll-container'
27 | })
28 | scrollContainer.addEventListener('mousedown', press)
29 |
30 | // 创建自动向上的按钮
31 | const scrollUp = GM_addElement(scrollContainer, 'div', {
32 | id: 'scroll-up',
33 | class: 'scroll-up'
34 | })
35 | scrollUp.addEventListener('mouseover', () => {
36 | autoScroll(DIRECTION.UP)
37 | })
38 | scrollUp.addEventListener('mouseout', stopScroll)
39 |
40 | // 创建速度显示
41 | const scrollSpeed = GM_addElement(scrollContainer, 'div', {
42 | id: 'scroll-speed',
43 | class: 'scroll-speed',
44 | textContent: speed
45 | })
46 | scrollSpeed.addEventListener('wheel', settingSpeed)
47 |
48 | // 创建自动向下的按钮
49 | const scrollDown = GM_addElement(scrollContainer, 'div', {
50 | id: 'scroll-down',
51 | class: 'scroll-down'
52 | })
53 | scrollDown.addEventListener('mouseover', () => {
54 | autoScroll(DIRECTION.DOWN)
55 | })
56 | scrollDown.addEventListener('mouseout', stopScroll)
57 |
58 | // 自动滚动
59 | function autoScroll(direction: DIRECTION) {
60 | scroll(direction)
61 | }
62 |
63 | // 滚动
64 | function scroll(direction: DIRECTION) {
65 | currentFrameId = window.requestAnimationFrame(time => {
66 | if (!prevTIme) prevTIme = time
67 | const elapsed = (time - prevTIme) / 1000
68 | // 每 50ms 执行一次
69 | window.scrollBy(0, defaultSpeed * 10 * direction * elapsed)
70 | prevTIme = time
71 | scroll(direction)
72 | })
73 | }
74 |
75 | // 停止滚动
76 | function stopScroll() {
77 | prevTIme = 0
78 | window.cancelAnimationFrame(currentFrameId)
79 | }
80 |
81 | // 设置滚动速度
82 | function settingSpeed(e: WheelEvent) {
83 | e.preventDefault()
84 | if (e.deltaY < 0) defaultSpeed += 1
85 | else defaultSpeed -= 1
86 | scrollSpeed.textContent = `${defaultSpeed}`
87 | GM_setValue('speed', defaultSpeed)
88 | }
89 |
90 | // 按下事件
91 | function press(e: MouseEvent) {
92 | // 设置只有在速度显示区域才能拖动
93 | if ((e.target as HTMLElement).id === 'scroll-speed') {
94 | // 记录位置
95 | pressPosition.top = e.clientY - (e.currentTarget as HTMLDivElement).offsetTop
96 | pressPosition.left = e.clientX - (e.currentTarget as HTMLDivElement).offsetLeft
97 | // 修改样式显示
98 | scrollSpeed.style.cursor = 'move'
99 | // 开始监听移动事件
100 | document.addEventListener('mousemove', move)
101 | document.addEventListener('mouseup', release)
102 | }
103 | }
104 |
105 | // 移动事件
106 | function move(e: MouseEvent) {
107 | const top = e.clientY - pressPosition.top
108 | const left = e.clientX - pressPosition.left
109 | scrollContainer.style.right = `unset`
110 | scrollContainer.style.top = `${top}px`
111 | scrollContainer.style.left = `${left}px`
112 | }
113 |
114 | // 抬起事件
115 | function release() {
116 | // 修改样式显示
117 | scrollSpeed.style.cursor = 's-resize'
118 | // 清除事件
119 | document.removeEventListener('mousemove', move)
120 | document.removeEventListener('mouseup', release)
121 | }
122 |
123 | // 添加自定义样式
124 | GM_addStyle(`
125 | .scroll-container {
126 | position: fixed;
127 | top: 50%;
128 | right: 10px;
129 | z-index: 99999;
130 | text-align: center;
131 | transform: translateY(-50%);
132 | border-radius: 20px;
133 | overflow: hidden;
134 | background-color: rgba(204, 204, 204, 0.4);
135 | line-height: 40px;
136 | color: rgba(60, 60, 67, .92);
137 | }
138 | .scroll-up,
139 | .scroll-down {
140 | width: 40px;
141 | height: 40px;
142 | text-align: center;
143 | }
144 | .scroll-up::after,
145 | .scroll-down::after {
146 | content: '';
147 | display: inline-block;
148 | width: 16px;
149 | height: 16px;
150 | font-size: 16px;
151 | box-sizing: border-box;
152 | border-width: 2px;
153 | border-style: solid;
154 | }
155 | .scroll-up::after {
156 | transform: rotate(-45deg);
157 | border-color: rgba(60, 60, 67, .92) rgba(60, 60, 67, .92) transparent transparent;
158 | margin-top: 14.3425px;
159 | }
160 | .scroll-down::after {
161 | transform: rotate(-45deg);
162 | border-color: transparent transparent rgba(60, 60, 67, .92) rgba(60, 60, 67, .92);
163 | margin-top: 8.685px;
164 | }
165 | .scroll-up:hover,
166 | .scroll-down:hover {
167 | background-color: rgba(204, 204, 204, 0.8);
168 | }
169 |
170 | .scroll-speed {
171 | font-size: 18px;
172 | user-select: none;
173 | cursor: s-resize;
174 | }
175 | `)
--------------------------------------------------------------------------------
/packages/bilibili-live-auto-click-like/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 支持作者
4 |
5 | 
6 |
7 |
8 | ### 所有脚本开源地址,欢迎 star ⭐
9 |
10 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
11 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
12 |
13 | # !!注意!!
14 |
15 | - 本脚本仅供学习交流使用,请勿用于非法用途!
16 | - 使用本脚本用于非法用途后果自负!
17 | - 请于下载后 24 小时内删除!
18 | - 作者本人不负任何法律责任!
19 |
20 | ## 1 脚本介绍
21 |
22 | 实现网页版 Bilibili 直播自动点赞功能
23 |
24 | ## 更新日志
25 |
26 | - 2023/07/12 脚本发布
27 |
--------------------------------------------------------------------------------
/packages/bilibili-live-auto-click-like/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bilibili-live-auto-click-like",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "网页版哔哩哔哩直播添加自动点赞功能",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/bilibili-live-auto-click-like"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "哔哩哔哩直播自动点赞"
14 | },
15 | "spaces": 12,
16 | "payload": {
17 | "icon": [
18 | "https://www.google.com/s2/favicons?sz=64&domain=bilibili.com"
19 | ],
20 | "match": [
21 | "*://live.bilibili.com/*"
22 | ],
23 | "run-at": [
24 | "document-end"
25 | ],
26 | "grant": [
27 | "unsafeWindow",
28 | "GM_getValue",
29 | "GM_setValue",
30 | "GM_notification",
31 | "GM_registerMenuCommand",
32 | "GM_unregisterMenuCommand"
33 | ],
34 | "noframes": [
35 | ""
36 | ]
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/packages/bilibili-live-auto-click-like/src/index.ts:
--------------------------------------------------------------------------------
1 | // 多久点击一次
2 | const CLICK_DURATION: number = 300
3 | // 点击层的类名
4 | const CLICK_MODAL_CLASS: string = '.like-btn'
5 | // 点击事件层
6 | let clickModal = document.querySelector(CLICK_MODAL_CLASS)
7 | // 定时器
8 | let timer: number | null = null
9 |
10 | // 循环点击
11 | let prevTImestamp = 0 // 记录上一次执行的时间
12 | function autoClick(timestamp: number) {
13 | const duration = timestamp - prevTImestamp
14 | if (duration >= CLICK_DURATION + Math.random() * 100 - 50) {
15 | if (clickModal) {
16 | // 获取元素的坐标
17 | const rect = clickModal.getBoundingClientRect()
18 | const x = rect.top + Math.random() * 50 + 50
19 | const y = rect.left + Math.random() * 50 + 50
20 | // 创建模拟点击事件
21 | const clickEvent = new MouseEvent('click', {
22 | view: unsafeWindow,
23 | bubbles: true,
24 | cancelable: true,
25 | clientX: x,
26 | clientY: y
27 | })
28 | // 触发模拟点击事件
29 | clickModal.dispatchEvent(clickEvent)
30 | } else {
31 | clickModal = document.querySelector(CLICK_MODAL_CLASS)
32 | }
33 | prevTImestamp = timestamp
34 | }
35 | timer = requestAnimationFrame(autoClick)
36 | }
37 |
38 | interface Tip {
39 | open: string
40 | close: string
41 | }
42 |
43 | interface MenuItem {
44 | key: string
45 | name: string
46 | value: boolean
47 | showNotification: boolean
48 | tip: Tip
49 | click: () => void
50 | }
51 |
52 | // 菜单
53 | const menu: MenuItem[] = [
54 | {
55 | key: 'switch',
56 | name: '自动点赞',
57 | value: true,
58 | showNotification: true,
59 | tip: {
60 | open: '✅',
61 | close: '❌'
62 | },
63 | click: switchFn
64 | }
65 | ]
66 |
67 | // 保存已注册的菜单
68 | const menuRegister: number[] = []
69 |
70 | // 配置默认菜单
71 | menu.forEach(v => {
72 | if (GM_getValue(v.key) === undefined || GM_getValue(v.key) === null) GM_setValue(v.key, v.value)
73 | })
74 |
75 | // 注册菜单
76 | function registerMenuCommand() {
77 | if (menuRegister.length === menu.length) {
78 | menuRegister.forEach(v => {
79 | GM_unregisterMenuCommand(v)
80 | })
81 | }
82 | menu.forEach((v, i) => {
83 | v.value = GM_getValue(v.key)
84 | menuRegister[i] = GM_registerMenuCommand(`${v.value ? v.tip.open : v.tip.close} ${v.name}`, () => {
85 | menuSwitch(v)
86 | })
87 | })
88 | }
89 |
90 | // 切换菜单
91 | function menuSwitch(item: MenuItem) {
92 | // 设置数据
93 | item.value = !item.value
94 | GM_setValue(item.key, item.value)
95 | // 系统通知
96 | if (item.showNotification) {
97 | GM_notification({
98 | text: `已${item.value ? item.tip.open : item.tip.close}[${item.name}] 功能`,
99 | title: ' Bilibili 自动点赞',
100 | timeout: 1000
101 | })
102 | }
103 | // 如果有点击事件,执行
104 | if (item.click) item.click()
105 | // 重新注册
106 | registerMenuCommand()
107 | }
108 |
109 | // 切换开关
110 | function switchFn() {
111 | if (GM_getValue('switch')) timer = requestAnimationFrame(autoClick)
112 | else cancelAnimationFrame(timer!)
113 | }
114 |
115 | function init() {
116 | clickModal = document.querySelector(CLICK_MODAL_CLASS)
117 | registerMenuCommand()
118 | if (GM_getValue('switch')) timer = requestAnimationFrame(autoClick)
119 | }
120 |
121 | // 延迟 3 秒开始, 获取必要数据
122 | setTimeout(() => {
123 | init()
124 | }, 3000)
--------------------------------------------------------------------------------
/packages/cocomanga-subscription-sort/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 支持作者
4 |
5 | 
6 |
7 |
8 | ### 所有脚本开源地址,欢迎 star ⭐
9 |
10 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
11 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
12 |
13 | ## 1 痛点分析
14 |
15 | - 每次打开 COCO 漫画的 “我的收藏” 界面,看一下有什么漫画更新了,但是每次都要自己找最新的日期看,太麻烦了
16 |
17 | ## 2 功能介绍
18 |
19 | - 直接给在 “我的收藏” 界面添加了按更新时间排序的功能,当然如果有多页看完请手动下一页,脚本只是在当前页面排序功能,不会访问其它页
20 |
21 | ## 3 更新记录
22 |
23 | - 2024/07/12 修复脚本图标不显示
24 | - 2023/10/07 COCO 漫画域名更新
25 | - 2021/10/31 COCO 漫画域名更新
26 | - 2021/03/04 更新访问过的最新标题为黑色,不用自己记有没有访问过了
27 | - 2021/03/03 最新的更新标题标为红色,更加显眼
28 | - 2021/03/02 保留表格标题
29 | - 2021/03/01 COCO 漫画 我的收藏 界面根据 更新日进行排序
30 |
--------------------------------------------------------------------------------
/packages/cocomanga-subscription-sort/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cocomanga-subscription-sort",
3 | "version": "0.8.0",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "COCO 漫画“我的收藏”界面根据“更新日”进行排序",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/cocomanga-subscription-sort"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "COCO漫画收藏按更新时间排序"
14 | },
15 | "spaces": 12,
16 | "payload": {
17 | "icon": [
18 | "https://www.colamanga.com/favicon.ico"
19 | ],
20 | "match": [
21 | "*://*.cocomanhua.com/dynamic/user/subscription",
22 | "*://*.cocomanga.com/dynamic/user/subscription",
23 | "*://*.colamanhua.com/dynamic/user/subscription",
24 | "*://*.colamanga.com/dynamic/user/subscription"
25 | ],
26 | "run-at": [
27 | "document-end"
28 | ],
29 | "grant": [
30 | "GM_addStyle"
31 | ]
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/packages/cocomanga-subscription-sort/src/index.ts:
--------------------------------------------------------------------------------
1 |
2 | const container: Element = document.getElementsByClassName('fed-user-list fed-part-rows fed-back-whits')[0]
3 | const all: HTMLCollectionOf = document.getElementsByClassName('fed-padding-x fed-part-rows fed-line-top')
4 | // 实现排序
5 | container.innerHTML =
6 | document.getElementsByClassName('fed-padding-x fed-part-rows')[0].outerHTML +
7 | Array.from(all)
8 | .sort((a, b) => getDateTime(b) - getDateTime(a))
9 | .map(item => item.outerHTML)
10 | .join('')
11 |
12 | // 添加最新更新样式
13 | GM_addStyle(`
14 | .lastUpdate a {
15 | color: red;
16 | }
17 | .lastUpdate a:visited {
18 | color: #000;
19 | }
20 | .lastUpdate a:hover {
21 | color: #27ae60;
22 | }
23 | `)
24 |
25 | // 获取更新时间戳
26 | function getDateTime(DOM: Element) {
27 | const updateTime = new Date(DOM.children[0].children[3].innerHTML).getTime()
28 | if (new Date(updateTime).toLocaleDateString() === new Date().toLocaleDateString()) {
29 | DOM.classList.add('lastUpdate')
30 | }
31 | return updateTime
32 | }
--------------------------------------------------------------------------------
/packages/douyin-live-auto-click-like/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 支持作者
4 |
5 | 
6 |
7 |
8 | ### 所有脚本开源地址,欢迎 star ⭐
9 |
10 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
11 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
12 |
13 | # !!注意!!
14 |
15 | - 本脚本仅供学习交流使用,请勿用于非法用途!
16 | - 使用本脚本用于非法用途后果自负!
17 | - 请于下载后 24 小时内删除!
18 | - 作者本人不负任何法律责任!
19 |
20 | ## 1 脚本介绍
21 |
22 | 最近网页版的抖音直播终于添加了点赞功能,手动点赞太伤鼠标了。所以写了该脚本实现自动点赞。
23 |
24 | ## 更新日志
25 |
26 | - 2023/11/27 修复【手速太快】提示移除失败的 bug
27 | - 2023/11/25 修复脚本失效的问题
28 | - 2023/10/07 修复【手速太快】提示移除失败的 bug
29 | - 2023/06/09 修复功能关闭之后刷新页面还是自动点赞的 bug
30 | - 2023/06/02 添加脚本开关菜单
31 | - 2023/06/01 修复 TamperMonkey 无法使用的 bug
32 | - 2023/05/31 优化显示,在左上角显示点赞效果
33 | - 2023/05/30 代码优化,移除【您手速太快了,请休息一下】提示
34 | - 2023/05/29 解决官方没有优化,点赞太多,元素不会自动清理导致浏览器卡顿的问题
35 | - 2023/05/28 抖音直播自动点赞功能
36 |
--------------------------------------------------------------------------------
/packages/douyin-live-auto-click-like/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "douyin-live-auto-click-like",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "网页版抖音直播添加自动点赞功能",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/douyin-live-auto-click-like"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "抖音直播自动点赞"
14 | },
15 | "spaces": 12,
16 | "payload": {
17 | "icon": [
18 | "https://lf1-cdn-tos.bytegoofy.com/goofy/ies/douyin_web/public/favicon.ico"
19 | ],
20 | "match": [
21 | "*://live.douyin.com/*"
22 | ],
23 | "run-at": [
24 | "document-end"
25 | ],
26 | "grant": [
27 | "unsafeWindow",
28 | "GM_getValue",
29 | "GM_setValue",
30 | "GM_notification",
31 | "GM_registerMenuCommand",
32 | "GM_unregisterMenuCommand"
33 | ],
34 | "noframes": [
35 | ""
36 | ]
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/packages/douyin-live-auto-click-like/src/index.ts:
--------------------------------------------------------------------------------
1 | // 多久点击一次
2 | const CLICK_DURATION: number = 300
3 | // 点击层的类名
4 | const CLICK_MODAL_CLASS: string = '.LO5TGkc0'
5 | // 点击事件层
6 | let clickModal = document.querySelector(CLICK_MODAL_CLASS)
7 | // 定时器
8 | let timer: number | null = null
9 | // 重新恢复点赞的定时器
10 | let restartTimer: number | null = null
11 | // 重新开始点赞的时间
12 | let restartTimestamp: number = GM_getValue('restartTimestamp') ? Number(GM_getValue('restartTimestamp')) : 0
13 |
14 | // 循环点击
15 | let prevTImestamp: number = 0 // 记录上一次执行的时间
16 | function autoClick(timestamp: number) {
17 | const duration = timestamp - prevTImestamp
18 | if (duration >= CLICK_DURATION + Math.random() * 100 - 50) {
19 | if (clickModal) {
20 | clearLikeIcon()
21 | // 获取元素的坐标
22 | const rect = clickModal.getBoundingClientRect()
23 | const x = rect.top + Math.random() * 50 + 50
24 | const y = rect.left + Math.random() * 50 + 50
25 | // 创建模拟点击事件
26 | const clickEvent = new MouseEvent('click', {
27 | view: unsafeWindow,
28 | bubbles: true,
29 | cancelable: true,
30 | clientX: x,
31 | clientY: y
32 | })
33 | // 触发模拟点击事件
34 | clickModal.dispatchEvent(clickEvent)
35 | } else {
36 | clickModal = document.querySelector(CLICK_MODAL_CLASS)
37 | }
38 | prevTImestamp = timestamp
39 | }
40 | timer = requestAnimationFrame(autoClick)
41 | }
42 |
43 | // 自动清理点赞之后留下的元素(抖音前端工程师长点心吧!无限添加元素,想卡死用户是吧!不会复用元素?)
44 | function clearLikeIcon() {
45 | if (clickModal!.children.length > 30) {
46 | clickModal!.textContent = ''
47 | }
48 | }
49 |
50 | // 如果已经提示【手速太快】,暂停 1 分钟再重新开始
51 | let prevRestartTimestamp = 0
52 | function restart(timestamp: number) {
53 | cancelAnimationFrame(timer!)
54 | const duration = timestamp - prevRestartTimestamp
55 | if (duration >= CLICK_DURATION) {
56 | const currentTimestamp = +new Date()
57 | if (currentTimestamp >= restartTimestamp) {
58 | if (GM_getValue('switch')) {
59 | timer = requestAnimationFrame(autoClick)
60 | restartTimer = null
61 | return
62 | }
63 | }
64 | prevRestartTimestamp = timestamp
65 | }
66 | restartTimer = requestAnimationFrame(restart)
67 | }
68 |
69 | // 移除【您手速太快了,请休息一下】提示
70 | let prevRemoveTipTimestamp = 0
71 | function removeTip(timestamp: number) {
72 | const duration = timestamp - prevRemoveTipTimestamp
73 | if (duration >= CLICK_DURATION) {
74 | const reg = /.*手速太快.*/
75 | const toastContainer = document.getElementById('toastContainer')
76 | if (toastContainer) {
77 | if (toastContainer.children[0]) {
78 | toastContainer.textContent = ``
79 | if (!restartTimer) {
80 | const nextTimestamp = +new Date() + 60000
81 | restartTimestamp = nextTimestamp - restartTimestamp > 60000 ? nextTimestamp : restartTimestamp
82 | GM_setValue('restartTimestamp', restartTimestamp)
83 | restart(timestamp)
84 | }
85 | }
86 | }
87 | const toast = document.querySelector('[data-e2e="toast"]')
88 | if (toast && reg.test(toast.textContent!)) {
89 | toast.parentNode?.removeChild(toast)
90 | if (!restartTimer) {
91 | const nextTimestamp = +new Date() + 60000
92 | restartTimestamp = nextTimestamp - restartTimestamp > 60000 ? nextTimestamp : restartTimestamp
93 | GM_setValue('restartTimestamp', restartTimestamp)
94 | restart(timestamp)
95 | }
96 | }
97 | prevRemoveTipTimestamp = timestamp
98 | }
99 | requestAnimationFrame(removeTip)
100 | }
101 |
102 | interface Tip {
103 | open: string
104 | close: string
105 | }
106 |
107 | interface MenuItem {
108 | key: string
109 | name: string
110 | value: boolean
111 | showNotification: boolean
112 | tip: Tip
113 | click: () => void
114 | }
115 |
116 | // 菜单
117 | const menu: MenuItem[] = [
118 | {
119 | key: 'switch',
120 | name: '自动点赞',
121 | value: true,
122 | showNotification: true,
123 | tip: {
124 | open: '✅',
125 | close: '❌'
126 | },
127 | click: switchFn
128 | }
129 | ]
130 |
131 | // 保存已注册的菜单
132 | const menuRegister: number[] = []
133 |
134 | // 配置默认菜单
135 | menu.forEach(v => {
136 | if (GM_getValue(v.key) === undefined || GM_getValue(v.key) === null) GM_setValue(v.key, v.value)
137 | })
138 |
139 | // 注册菜单
140 | function registerMenuCommand() {
141 | if (menuRegister.length === menu.length) {
142 | menuRegister.forEach(v => {
143 | GM_unregisterMenuCommand(v)
144 | })
145 | }
146 | menu.forEach((v, i) => {
147 | v.value = GM_getValue(v.key)
148 | menuRegister[i] = GM_registerMenuCommand(`${v.value ? v.tip.open : v.tip.close} ${v.name}`, () => {
149 | menuSwitch(v)
150 | })
151 | })
152 | }
153 |
154 | // 切换菜单
155 | function menuSwitch(item: MenuItem) {
156 | // 设置数据
157 | item.value = !item.value
158 | GM_setValue(item.key, item.value)
159 | // 系统通知
160 | if (item.showNotification) {
161 | GM_notification({
162 | text: `已${item.value ? item.tip.open : item.tip.close}[${item.name}] 功能`,
163 | title: '抖音自动点赞',
164 | timeout: 1000
165 | })
166 | }
167 | // 如果有点击事件,执行
168 | if (item.click) item.click()
169 | // 重新注册
170 | registerMenuCommand()
171 | }
172 |
173 | // 切换开关
174 | function switchFn() {
175 | if (GM_getValue('switch')) timer = requestAnimationFrame(autoClick)
176 | else cancelAnimationFrame(timer!)
177 | }
178 |
179 | function init() {
180 | clickModal = document.querySelector(CLICK_MODAL_CLASS)
181 | registerMenuCommand()
182 | requestAnimationFrame(removeTip)
183 | if (GM_getValue('switch')) timer = requestAnimationFrame(autoClick)
184 | }
185 |
186 | // 延迟 3 秒开始,抖音需要获取登录数据
187 | setTimeout(() => {
188 | init()
189 | }, 3000)
--------------------------------------------------------------------------------
/packages/mooc-skip-questions/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 所有脚本开源地址,欢迎 star ⭐
4 |
5 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
6 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
7 |
8 | # !!注意!!
9 |
10 | - 本脚本仅供学习使用,请勿用于非法用途!
11 | - 使用本脚本用于非法用途后果自负!
12 | - 请于下载后 24 小时内删除!
13 |
14 | ## 功能介绍
15 |
16 | - 中国大学 MOOC,icourse163 视频中题目自动跳过,移除弹题元素,防止暂停
17 |
--------------------------------------------------------------------------------
/packages/mooc-skip-questions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mooc-skip-questions",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "中国大学MOOC,icourse163视频中题目自动跳过,移除弹题元素,防止暂停(本脚本仅供学习使用,请在24小时内删除!)",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/mooc-skip-questions"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "中国大学MOOC视频中题目自动跳过"
14 | },
15 | "spaces": 12,
16 | "payload": {
17 | "match": [
18 | "*://www.icourse163.org/learn/*"
19 | ],
20 | "grant": [
21 | "none"
22 | ]
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/packages/mooc-skip-questions/src/index.ts:
--------------------------------------------------------------------------------
1 | setInterval(function () {
2 | let question = document.querySelector('.u-btn.u-btn-default.cont.j-continue')
3 | if (question) {
4 | (question.parentNode as HTMLElement)?.remove()
5 | }
6 | let video = document.querySelector('video')
7 | if (video?.paused) {
8 | video.play()
9 | }
10 | }, 5000)
--------------------------------------------------------------------------------
/packages/tencent-kt-box/README.md:
--------------------------------------------------------------------------------
1 | ## 前言
2 |
3 | ### 所有脚本开源地址,欢迎 star ⭐
4 |
5 | - gitee:[https://gitee.com/Kaiter-Plus/TampermonkeyScript](https://gitee.com/Kaiter-Plus/TampermonkeyScript)
6 | - github:[https://github.com/Kaiter-Plus/TampermonkeyScript](https://github.com/Kaiter-Plus/TampermonkeyScript)
7 |
8 | ## 1 脚本介绍
9 |
10 | - 腾讯课堂自动签到以及去除“xxx 正在观看 xx”水印!
11 |
12 | ## 2 更新日志
13 |
14 | - 2020/03/26 去除腾讯课堂“xxx 正在观看 xx”的水印,提高学习效率!
15 | - 2020/03/31 增加自动签到功能!避免学习被打扰!
16 | - 2020/04/11 添加自动签到开关按钮,默认打开,不用可以关闭,节约内存!
17 | - 2020/04/13 修改命名空间,预防 Bug!
18 | - 2020/04/17 修复开关按钮挡住“分享”的 bug
19 | - 2020/04/17 紧急修复自动签到不能使用的 bug
20 | - 2020/04/21 最近腾讯课堂又更新了,自动签到暂时不能用,先下架功能研究一下,后期完善再上架
21 | - 2020/04/21 脚本重新加入了自动签到功能,但是没有课堂可以测试,希望可以帮忙测试之后,反馈一下
22 | - 2020/04/22 添加自动签到如果成功会弹框提示,没有弹框提示则没有签到
23 | - 2020/04/23 修改签到成功提示在自动签到开关的左边进行显示
24 | - 2020/05/07 修复可能不会点击确定按钮的 Bug
25 |
--------------------------------------------------------------------------------
/packages/tencent-kt-box/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tencent-kt-box",
3 | "version": "1.4.5",
4 | "type": "module",
5 | "author": "Kaiter-Plus",
6 | "description": "主要功能是腾讯课堂自动签到以及去除“xxx正在观看xx”水印!",
7 | "repository": {
8 | "url": "https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/packages/tencent-kt-box"
9 | },
10 | "license": "BSD-3-Clause",
11 | "buildOptions": {
12 | "name": {
13 | "default": "腾讯课堂自动签到 + 去除“xxx正在观看xx”水印"
14 | },
15 | "spaces": 12,
16 | "icon": [
17 | "https://8.url.cn/edu/edu_modules/edu-ui/img/nohash/favicon.ico"
18 | ],
19 | "payload": {
20 | "match": [
21 | "https://ke.qq.com/webcourse/*"
22 | ],
23 | "grant": [
24 | "GM_addStyle",
25 | "GM_addElement"
26 | ]
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/packages/tencent-kt-box/src/index.ts:
--------------------------------------------------------------------------------
1 | // 签到成功次数
2 | let count = 0
3 |
4 | //去除水印, 添加开关样式
5 | GM_addStyle(
6 | [
7 | "a[class*='marquee animation'],txpdiv[class*='player-inject'],.switchButton-checkbox {",
8 | ' display: none!important;',
9 | '}',
10 | '/* 开关 */',
11 | '.switchButton {',
12 | ' position: relative;',
13 | ' width: 90px;',
14 | ' margin: 15px 514.33px 15px auto;',
15 | ' z-index: 9999;',
16 | ' user-select: none;',
17 | ' -webkit-user-select: none;',
18 | ' -moz-user-select: none;',
19 | ' -ms-user-select: none;',
20 | '}',
21 | '.switchButton::before {',
22 | ' display: block;',
23 | " content: '自动签到开关';",
24 | ' color: #aaa;',
25 | ' font-size: 18px;',
26 | ' line-height: 33px;',
27 | ' position: absolute;',
28 | ' left: -115px;',
29 | '}',
30 | '.switchButton-label {',
31 | ' display: block;',
32 | ' overflow: hidden;',
33 | ' cursor: pointer;',
34 | ' border: 2px solid #999999;',
35 | ' border-radius: 20px;',
36 | '}',
37 | '.switchButton-inner {',
38 | ' display: block;',
39 | ' width: 200%;',
40 | ' margin-left: -100%;',
41 | ' transition: margin 0.3s ease-in 0s;',
42 | '}',
43 | '.switchButton-inner::before,',
44 | '.switchButton-inner::after {',
45 | ' display: block;',
46 | ' float: right;',
47 | ' width: 50%;',
48 | ' height: 30px;',
49 | ' padding: 0;',
50 | ' line-height: 30px;',
51 | ' font-size: 14px;',
52 | ' color: white;',
53 | ' font-family: Trebuchet, Arial, sans-serif;',
54 | ' font-weight: bold;',
55 | ' box-sizing: border-box;',
56 | '}',
57 | '.switchButton-inner::after {',
58 | ' content: attr(data-on);',
59 | ' padding-left: 10px;',
60 | ' background-color: #23b8ff;',
61 | ' color: #FFFFFF;',
62 | '}',
63 | '.switchButton-inner::before {',
64 | ' content: attr(data-off);',
65 | ' padding-right: 10px;',
66 | ' background-color: ##1d1d1d;',
67 | ' color: #FFFFFF;',
68 | ' text-align: right;',
69 | '}',
70 | '.switchButton-switch {',
71 | ' position: absolute;',
72 | ' display: block;',
73 | ' width: 26px;',
74 | ' height: 26px;',
75 | ' margin: 4px;',
76 | ' background: #FFFFFF;',
77 | ' top: 0;',
78 | ' bottom: 0;',
79 | ' right: 56px;',
80 | ' border: 2px solid #999999;',
81 | ' border-radius: 20px;',
82 | ' transition: all 0.3s ease-in 0s;',
83 | '}',
84 | '.switchButton-checkbox:checked+.switchButton-label .switchButton-inner {',
85 | ' margin-left: 0;',
86 | '}',
87 | '.switchButton-checkbox:checked+.switchButton-label .switchButton-switch {',
88 | ' right: 0px;',
89 | '}',
90 | '.myTips {',
91 | ' display: none;',
92 | ' position: absolute;',
93 | ' font-size: 18px;',
94 | ' line-height: 33px;',
95 | ' color: #aaa;',
96 | ' left: -270px;',
97 | ' top: 0;',
98 | '}'
99 | ].join('\n')
100 | )
101 |
102 | // 创建开关
103 | const switchButton = GM_addElement(document.body, 'div', {
104 | class: 'switchButton'
105 | })
106 | GM_addElement(switchButton, 'input', {
107 | id: 'ON_OFF',
108 | type: 'checkbox',
109 | checked: true
110 | })
111 | const label = GM_addElement(switchButton, 'label', {
112 | class: 'switchButton-label',
113 | for: 'ON_OFF'
114 | })
115 | GM_addElement(label, 'span', {
116 | class: 'switchButton-inner',
117 | 'data-on': 'ON',
118 | 'data-off': 'OFF'
119 | })
120 | GM_addElement(label, 'span', {
121 | class: 'switchButton-switch'
122 | })
123 |
124 |
125 | // 签到成功提示
126 | const tips = GM_addElement(switchButton, 'div', {
127 | class: 'myTips'
128 | })
129 |
130 | // 点击确认按钮
131 | function autoConfirm() {
132 | const confirmButton = document.querySelector('.s-btn.s-btn--primary.s-btn--m') as HTMLElement
133 | try {
134 | if (/确.*定/g.test(confirmButton.innerHTML)) {
135 | confirmButton!.click()
136 | }
137 | } catch (e) {
138 | console.error('点击确定按钮失败,原因: ', e)
139 | }
140 | }
141 |
142 | // 点击签到按钮
143 | function autoSign() {
144 | const signButton = document.querySelector('.s-btn.s-btn--primary.s-btn--m') as HTMLElement
145 | try {
146 | if (/签.*到/g.test(signButton.innerHTML)) {
147 | signButton.click()
148 | count += 1
149 | tips.innerHTML = `签到成功${count}次!`
150 | tips.style.display = `block`
151 | setTimeout(autoConfirm, 2000)
152 | }
153 | } catch (e) {
154 | console.error('点击签到按钮失败,原因: ', e)
155 | }
156 | }
157 |
158 | // 默认开启自动签到
159 | let timer = setInterval(autoSign, 3500)
160 |
161 | // 控制自动签到的开关状态
162 | const switchBtn = document.getElementById('ON_OFF') as HTMLInputElement
163 | switchBtn?.addEventListener('click', () => {
164 |
165 | if (switchBtn.checked) {
166 | // 开启自动签到
167 | timer = setInterval(autoSign, 3500)
168 | } else {
169 | // 关闭自动签到
170 | clearInterval(timer)
171 | }
172 | })
173 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | // Enable latest features
4 | "lib": ["ESNext", "DOM"],
5 | "target": "ESNext",
6 | "module": "ESNext",
7 | "moduleDetection": "force",
8 | "jsx": "react-jsx",
9 | "allowJs": true,
10 |
11 | // Bundler mode
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "verbatimModuleSyntax": true,
15 | "noEmit": true,
16 |
17 | // Best practices
18 | "strict": true,
19 | "skipLibCheck": true,
20 | "noFallthroughCasesInSwitch": true,
21 |
22 | // Some stricter flags (disabled by default)
23 | "noUnusedLocals": false,
24 | "noUnusedParameters": false,
25 | "noPropertyAccessFromIndexSignature": false,
26 |
27 | "baseUrl": ".",
28 | "paths": {
29 | "@kaiter/*": ["packages/*"]
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------