├── .editorconfig
├── .eslintrc.js
├── .github
├── ISSUE_TEMPLATE.md
└── workflows
│ └── deploy-scripts.yml
├── .gitignore
├── .npmrc
├── .prettierrc.js
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── meta
├── blank.ts
└── debug.ts
├── package.json
├── packages
├── captcha
│ ├── README.md
│ ├── captcha.user.js
│ └── package.json
├── completion
│ ├── README.md
│ ├── completion.user.js
│ └── package.json
├── copy-currency
│ ├── README.md
│ ├── meta.json
│ ├── package.json
│ └── src
│ │ ├── global.d.ts
│ │ ├── index.css
│ │ ├── index.ts
│ │ ├── register.ts
│ │ └── utils.ts
├── copy
│ ├── README.md
│ ├── meta.json
│ ├── package.json
│ ├── src
│ │ ├── constant
│ │ │ └── event.ts
│ │ ├── deploy.ts
│ │ ├── index.ts
│ │ ├── init.ts
│ │ ├── modules
│ │ │ ├── 17k.ts
│ │ │ ├── aiyuke.ts
│ │ │ ├── baiduwk.ts
│ │ │ ├── bilibili.ts
│ │ │ ├── boke112.ts
│ │ │ ├── ciweimao.ts
│ │ │ ├── cnitpm.ts
│ │ │ ├── cnki.ts
│ │ │ ├── common-e.ts
│ │ │ ├── common-p.ts
│ │ │ ├── common.ts
│ │ │ ├── csdn.ts
│ │ │ ├── diyifanwen.ts
│ │ │ ├── doc88.ts
│ │ │ ├── docin.ts
│ │ │ ├── docqq.ts
│ │ │ ├── edu30.ts
│ │ │ ├── kdocs.ts
│ │ │ ├── leetcode.ts
│ │ │ ├── mbalib.ts
│ │ │ ├── mihoyo.ts
│ │ │ ├── qidian.ts
│ │ │ ├── qq-slider.ts
│ │ │ ├── qqbook.ts
│ │ │ ├── sf.ts
│ │ │ ├── uemeds.ts
│ │ │ ├── utaten.ts
│ │ │ ├── wk.ts
│ │ │ ├── xiaohongshu.ts
│ │ │ ├── youdao.ts
│ │ │ ├── zhihu.ts
│ │ │ └── zongheng.ts
│ │ ├── styles
│ │ │ ├── app.css
│ │ │ └── style.css
│ │ ├── types
│ │ │ └── global.d.ts
│ │ ├── utils
│ │ │ ├── copy.ts
│ │ │ ├── dom.ts
│ │ │ ├── event.ts
│ │ │ ├── helper.ts
│ │ │ ├── instance.ts
│ │ │ └── is.ts
│ │ └── websites.ts
│ └── tsconfig.json
├── expansion
│ ├── README.md
│ ├── expansion.user.js
│ └── package.json
├── force-copy
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── locales
│ │ │ ├── en
│ │ │ │ └── messages.json
│ │ │ └── zh_cn
│ │ │ │ └── messages.json
│ │ ├── misc
│ │ │ ├── brick.png
│ │ │ ├── favicon.dark.png
│ │ │ └── poster.png
│ │ ├── popup.html
│ │ └── static
│ │ │ ├── favicon.128.png
│ │ │ └── favicon.png
│ ├── rspack.config.js
│ ├── script
│ │ ├── files
│ │ │ └── index.js
│ │ ├── if-def
│ │ │ ├── if-def.code-snippets
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── manifest
│ │ │ └── index.js
│ │ ├── reload
│ │ │ └── index.js
│ │ ├── utils
│ │ │ └── node.js
│ │ └── wrapper
│ │ │ └── index.js
│ ├── src
│ │ ├── bridge
│ │ │ ├── content-inject
│ │ │ │ ├── constant.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── request.ts
│ │ │ ├── content-worker
│ │ │ │ ├── constant.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── request.ts
│ │ │ ├── popup-content
│ │ │ │ ├── constant.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── request.ts
│ │ │ │ └── response.ts
│ │ │ ├── popup-worker
│ │ │ │ ├── constant.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── request.ts
│ │ │ └── worker-content
│ │ │ │ ├── constant.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── request.ts
│ │ ├── content
│ │ │ ├── channel
│ │ │ │ └── popup.ts
│ │ │ ├── index.ts
│ │ │ └── runtime
│ │ │ │ ├── initialize.ts
│ │ │ │ └── script.ts
│ │ ├── inject
│ │ │ ├── channel
│ │ │ │ └── content.ts
│ │ │ ├── index.ts
│ │ │ ├── modules
│ │ │ │ ├── basic.ts
│ │ │ │ ├── doc88.ts
│ │ │ │ ├── docin.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── qq-doc.ts
│ │ │ │ ├── qq-ppt.ts
│ │ │ │ ├── wenku.ts
│ │ │ │ └── zhihu.ts
│ │ │ ├── types
│ │ │ │ ├── global.d.ts
│ │ │ │ ├── state.ts
│ │ │ │ └── website.ts
│ │ │ └── utils
│ │ │ │ ├── bus.ts
│ │ │ │ ├── delay.ts
│ │ │ │ ├── events.ts
│ │ │ │ └── styles.ts
│ │ ├── manifest
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── popup
│ │ │ ├── components
│ │ │ │ ├── app
│ │ │ │ │ ├── index.module.scss
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── console
│ │ │ │ │ ├── index.module.scss
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── footer
│ │ │ │ │ ├── index.module.scss
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── header
│ │ │ │ │ ├── index.module.scss
│ │ │ │ │ └── index.tsx
│ │ │ │ └── tools
│ │ │ │ │ ├── index.module.scss
│ │ │ │ │ └── index.tsx
│ │ │ ├── hooks
│ │ │ │ └── use-memoized-fn.ts
│ │ │ ├── i18n
│ │ │ │ ├── en.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── zh.ts
│ │ │ ├── index.tsx
│ │ │ └── utils
│ │ │ │ └── badge.ts
│ │ ├── types
│ │ │ └── global.d.ts
│ │ ├── utils
│ │ │ ├── constant.ts
│ │ │ ├── global.ts
│ │ │ ├── is.ts
│ │ │ ├── logger.ts
│ │ │ ├── reload.ts
│ │ │ └── types.ts
│ │ └── worker
│ │ │ ├── channel
│ │ │ └── content.ts
│ │ │ ├── index.ts
│ │ │ ├── runtime
│ │ │ ├── initialize.ts
│ │ │ └── script.ts
│ │ │ └── utils
│ │ │ └── constant.ts
│ └── tsconfig.json
├── site-director
│ ├── README.md
│ ├── meta.json
│ ├── package.json
│ └── src
│ │ ├── index.ts
│ │ ├── modules
│ │ ├── csdn.ts
│ │ ├── google.ts
│ │ ├── jianshu.ts
│ │ ├── juejin.ts
│ │ ├── qq-mail.ts
│ │ └── zhihu.ts
│ │ ├── style.css
│ │ ├── utils.ts
│ │ └── websites.ts
└── water-mark
│ ├── README.md
│ ├── meta.json
│ ├── package.json
│ ├── src
│ ├── index.ts
│ ├── modules
│ │ └── basic.ts
│ ├── types
│ │ ├── global.d.ts
│ │ └── website.ts
│ └── utils
│ │ ├── constant.ts
│ │ ├── dom.ts
│ │ └── styles.ts
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── publish-scripts.sh
├── rollup.config.js
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["eslint:recommended", "plugin:prettier/recommended"],
3 | env: {
4 | browser: true,
5 | node: true,
6 | commonjs: true,
7 | es2021: true,
8 | },
9 | parserOptions: {
10 | requireConfigFile: false,
11 | ecmaVersion: 2020,
12 | sourceType: "module",
13 | },
14 | overrides: [
15 | {
16 | files: ["*.ts"],
17 | parser: "@typescript-eslint/parser",
18 | plugins: ["@typescript-eslint"],
19 | extends: ["plugin:@typescript-eslint/recommended"],
20 | },
21 | {
22 | files: ["*.tsx"],
23 | parser: "@typescript-eslint/parser",
24 | plugins: ["react", "react-hooks", "@typescript-eslint/eslint-plugin"],
25 | extends: ["plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"],
26 | },
27 | ],
28 | ignorePatterns: ["node_modules", "build", "dist", "coverage", "public"],
29 | rules: {
30 | "semi": "error",
31 | "quote-props": ["error", "consistent-as-needed"],
32 | "arrow-parens": ["error", "as-needed"],
33 | "no-var": "error",
34 | "prefer-const": "error",
35 | "no-console": "off",
36 | "@typescript-eslint/explicit-module-boundary-types": "off",
37 | "@typescript-eslint/ban-ts-ignore": "off",
38 | "@typescript-eslint/ban-ts-comment": "off",
39 | "@typescript-eslint/consistent-type-imports": "error",
40 | },
41 | };
42 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## 问题描述
2 |
3 |
4 |
5 |
6 |
7 |
8 | ## 项目所属
9 |
10 |
11 |
12 | - [ ] Copy
13 | - [ ] Force Copy
14 | - [ ] Copy Currency
15 | - [ ] Site Director
16 | - [ ] Water Mark
17 | - [ ] Captcha
18 | - [ ] Expansion
19 | - [ ] Completion
20 | - [ ] Unknown
21 |
22 | ## 相关链接
23 |
24 |
25 |
26 |
27 |
28 |
29 | ## 预期表现
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-scripts.yml:
--------------------------------------------------------------------------------
1 | name: deploy-scripts gh-pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build-and-deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: checkout
13 | uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 | persist-credentials: false
17 |
18 | - name: install node-v16
19 | uses: actions/setup-node@v3
20 | with:
21 | node-version: '16.16.0'
22 |
23 | - name: install dependencies
24 | run: |
25 | node -v
26 | npm install -g pnpm@8.11.0
27 | pnpm --filter=\!force-copy --registry=https://registry.npmjs.org/ install
28 |
29 | - name: build project
30 | run: |
31 | pnpm run build:scripts
32 |
33 | - name: deploy
34 | uses: JamesIves/github-pages-deploy-action@releases/v3
35 | with:
36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 | BRANCH: gh-pages
38 | FOLDER: dist
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # base
2 | backup
3 | node_modules
4 | *.log
5 | .DS_Store
6 | .idea
7 | *.zip
8 |
9 | # dependencies
10 | node_modules
11 | .pnp
12 | .pnp.js
13 |
14 | # testing
15 | coverage
16 |
17 | # production
18 | build
19 | dist
20 |
21 | # misc
22 | .DS_Store
23 | .env.local
24 | .env.development.local
25 | .env.test.local
26 | .env.production.local
27 |
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmmirror.com/
2 | # strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "printWidth": 100,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": false,
7 | "quoteProps": "preserve",
8 | "jsxSingleQuote": false,
9 | "trailingComma": "es5",
10 | "bracketSpacing": true,
11 | "jsxBracketSameLine": false,
12 | "arrowParens": "avoid",
13 | "requirePragma": false,
14 | "insertPragma": false,
15 | "proseWrap": "preserve",
16 | "htmlWhitespaceSensitivity": "ignore",
17 | "endOfLine": "lf",
18 | };
19 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "rspack"
4 | ]
5 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Czy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TKScript
2 |
3 |
4 | GitHub
5 | |
6 | GreasyFork
7 | |
8 | FirefoxAddOns
9 | |
10 | ChromeWebStore
11 | |
12 | BLOG
13 |
14 |
15 | `GreaseMonkey`油猴脚本与`BrowserAddon`浏览器扩展,如果觉得不错,点个`star`吧 😁
16 |
17 |
18 | ## Install
19 |
20 | 使用油猴脚本需要首先安装`GreaseMonkey/TamperMonkey`扩展,版本库中有如下脚本,可以直接点击安装按钮进行安装,浏览器扩展程序直接在浏览器相关应用市场安装即可。
21 |
22 |
23 |
24 |
25 |
26 | 名称 |
27 | 详情 |
28 | 安装 |
29 | 简介 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | 文本选中复制 |
37 | 详情 |
38 |
39 | 安装
40 | |
41 | 备用
42 | |
43 | 解除网站不允许复制的限制,需要适配新的网站可提issue 。 |
44 |
45 |
46 |
47 | 文本选中复制-通用 |
48 | 详情 |
49 |
50 | 安装
51 | |
52 | 备用
53 | |
54 | 文本选中复制通用处理版本,具体使用方式请查阅详情。 |
55 |
56 |
57 |
58 | Force Copy |
59 | 详情 |
60 |
61 | 安装
62 | |
63 | 备用
64 | |
65 | 浏览器扩展程序,集成文本选中复制与通用能力。 |
66 |
67 |
68 |
69 | 跳转链接直达 |
70 | 详情 |
71 |
72 | 安装
73 | |
74 | 备用
75 | |
76 | 去掉确定跳转链接页面,用于谷歌、知乎、CSDN 、简书等。 |
77 |
78 |
79 |
80 | 移除页面水印 |
81 | 详情 |
82 |
83 | 安装
84 | |
85 | 备用
86 | |
87 | 移除常见网页的水印,请自行处理@match 到匹配地址。 |
88 |
89 |
90 |
91 | 自动展开阅读全文 |
92 | 详情 |
93 |
94 | 安装
95 | |
96 | 备用
97 | |
98 | 展开阅读全文,用于CSDN 、知乎等。 |
99 |
100 |
101 |
102 | 强智教务验证码识别 |
103 | 详情 |
104 |
105 | 安装
106 | |
107 | 备用
108 | |
109 | 自动填写强智的验证码,请自行处理@match 到匹配地址。 |
110 |
111 |
112 |
113 |
114 | 阿里图标库HTTP |
115 | 详情 |
116 |
117 | 安装
118 | |
119 | 备用
120 | |
121 | 添加HTTP 按钮,简化手动填写。 |
122 |
123 |
124 |
125 |
126 |
127 | ## Release
128 |
129 | 如果需要从源码构建脚本与扩展,请使用`pnpm`安装依赖,如果不需要这步操作,可以直接在上方表格点击安装按钮即可安装打包好的脚本与扩展。版本库中`dist`为脚本打包目录,其中仅`copy`、`site-director`、`copy-currency`脚本需`rollup`打包使用,其他脚本直接安装即可。浏览器扩展的打包位置为各自`monorepo package`下的`build`目录,调试开发过程需要主动指定浏览器加载目标位置。
130 |
131 | ```bash
132 | $ pnpm install
133 | $ pnpm run build
134 | $ pnpm run build:force-copy
135 | $ pnpm run build:force-copy:gecko
136 | ```
137 |
138 | ## Contributors
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/meta/blank.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/meta/debug.ts:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name DEBUG
3 | // @description DEBUG MODE
4 | // @namespace https://github.com/WindrunnerMax/TKScript
5 | // @version 1.0.0
6 | // @author Czy
7 | // @match http://*/*
8 | // @match https://*/*
9 | // @license GPL License
10 | // @run-at document-end
11 | // @grant GM_notification
12 | // @require file:///Users/czy/Project/TKScript/dist/copy-currency.user.js
13 | // ==/UserScript==
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "script",
3 | "version": "1.0.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "git://github.com/WindrunnerMax/TKScript"
7 | },
8 | "scripts": {
9 | "dev": "npm run dev:scripts",
10 | "build": "npm run build:scripts",
11 | "dev:scripts": "rollup -c --watch",
12 | "build:scripts": "./publish-scripts.sh",
13 | "dev:force-copy": "pnpm --filter force-copy run dev",
14 | "build:force-copy": "pnpm --filter force-copy run build",
15 | "dev:force-copy:gecko": "pnpm --filter force-copy run dev:gecko",
16 | "build:force-copy:gecko": "pnpm --filter force-copy run build:gecko",
17 | "lint:es": "eslint --fix --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore .",
18 | "lint:ts": "pnpm --filter '*' run lint:ts"
19 | },
20 | "author": "Czy",
21 | "license": "MIT",
22 | "devDependencies": {
23 | "@rollup/plugin-commonjs": "20.0.0",
24 | "@rollup/plugin-node-resolve": "13.0.4",
25 | "@rollup/plugin-replace": "5.0.2",
26 | "@types/node": "20.8.0",
27 | "@typescript-eslint/eslint-plugin": "5.4.0",
28 | "@typescript-eslint/parser": "5.4.0",
29 | "cross-env": "7.0.3",
30 | "esbuild": "0.15.10",
31 | "eslint": "7.32.0",
32 | "eslint-config-prettier": "8.3.0",
33 | "eslint-plugin-prettier": "3.3.1",
34 | "eslint-plugin-react": "7.27.0",
35 | "eslint-plugin-react-hooks": "4.3.0",
36 | "postcss": "8.3.11",
37 | "prettier": "2.3.2",
38 | "rollup": "2.56.3",
39 | "rollup-plugin-esbuild": "4.10.1",
40 | "rollup-plugin-postcss": "4.0.1",
41 | "rollup-plugin-userscript-metablock": "0.3.1",
42 | "tslib": "2.6.2",
43 | "typescript": "4.6.2"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/packages/captcha/README.md:
--------------------------------------------------------------------------------
1 | # 强智教务系统验证码识别
2 |
3 | 自动填写强智的验证码,请自行处理`@match`到需要匹配的网站。
4 |
--------------------------------------------------------------------------------
/packages/captcha/captcha.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name SWVerifyCode
3 | // @namespace https://github.com/WindrunnerMax/TKScript
4 | // @version 1.1
5 | // @description try to take over the world!
6 | // @author Czy
7 | // @match *://jwgl.sdust.edu.cn/
8 | // @match *://jwgl.sdust.edu.cn/jsxsd/
9 | // @grant none
10 | // ==/UserScript==
11 |
12 | /**
13 | * 配置账号密码信息(选填)
14 | */
15 | const username = ""; //账号
16 | const password = ""; //密码
17 | const autologin = false; //自动登录
18 |
19 | const height = 22;
20 | const width = 62;
21 | const rgbThres = 150;
22 | const charMap = {
23 | 1: "111100111110000111110000111111100111111100111111100111111100111111100111111100111111100111110000001110000001",
24 | 2: "100000111000000011111111001111111001111111001111110011111000111110011111100111111001111111000000001000000001",
25 | 3: "100000111000000011111110001111111001111110011110000111110000011111110001111111001111110001100000011100000111",
26 | b: "001111111001111111001111111001000011000000001000111000001111100001111100001111100000111000000000001001000011",
27 | c: "111111111111111111111111111110000011100000011000111111001111111001111111001111111000111111100000011110000011",
28 | m: "111111111111111111111111111001000011000000000000111000001111001001111001001111001001111001001111001001111001",
29 | n: "111111111111111111111111111001100001001000000000011100000111100001111100001111100001111100001111100001111100",
30 | v: "111111111111111111111111111111111011001110011001110011001110011100100111100100111100100111110001111110001111",
31 | x: "111111111111111111111111111001110011001110011100100111110001111110001111110001111100100111001110011001110011",
32 | z: "111111111111111111111111111000000011000000011111100111111001111110011111100111111001111111000000011000000011",
33 | };
34 |
35 | function binaryImage(ctx) {
36 | const imageData = ctx.getImageData(0, 0, width, height).data;
37 | const imgArr = [];
38 | for (let x = 0; x < width; ++x) {
39 | for (let y = 0; y < height; ++y) {
40 | if (!imgArr[y]) imgArr[y] = [];
41 | if (x === 0 || y === 0 || x === width - 1 || y === height - 1) {
42 | imgArr[y][x] = 1;
43 | continue;
44 | }
45 | const i = (y * width + x) * 4;
46 | if (imageData[i] < rgbThres && imageData[i + 1] < rgbThres && imageData[i + 2] < rgbThres) {
47 | imgArr[y][x] = 0;
48 | } else {
49 | imgArr[y][x] = 1;
50 | }
51 | }
52 | }
53 | return imgArr;
54 | }
55 |
56 | function removeByLine(imgArr) {
57 | const xCount = imgArr[0].length;
58 | const yCount = imgArr.length;
59 | for (let i = 1; i < yCount - 1; ++i) {
60 | for (let k = 1; k < xCount - 1; ++k) {
61 | if (imgArr[i][k] === 0) {
62 | const countOne = imgArr[i][k - 1] + imgArr[i][k + 1] + imgArr[i - 1][k] + imgArr[i + 1][k];
63 | if (countOne > 2) imgArr[i][k] = 1;
64 | }
65 | }
66 | }
67 | return imgArr;
68 | }
69 |
70 | function cutImg(imgArr, arrX, arrY, n) {
71 | const imgArrArr = [];
72 | for (let i = 0; i < n; ++i) {
73 | const unitImg = [];
74 | for (let j = arrY[i][0]; j < arrY[i][1]; ++j) {
75 | if (!unitImg[j]) unitImg[j - arrY[i][0]] = [];
76 | for (let k = arrX[i][0]; k < arrX[i][1]; ++k) {
77 | unitImg[j - arrY[i][0]][k - arrX[i][0]] = imgArr[j][k];
78 | }
79 | }
80 | imgArrArr.push(unitImg);
81 | }
82 | return imgArrArr;
83 | }
84 |
85 | function getString(imgArr) {
86 | let s = "";
87 | imgArr.forEach(vx => {
88 | vx.forEach(vy => {
89 | s += vy;
90 | });
91 | });
92 | return s;
93 | }
94 |
95 | function comparedText(s1, s2) {
96 | let percent = 0;
97 | const n = s1.length;
98 | for (let i = 0; i < n; ++i) s1[i] === s2[i] ? ++percent : "";
99 | return percent;
100 | }
101 |
102 | function matchCode(imgArrArr) {
103 | let record = "";
104 | imgArrArr.forEach(imgArr => {
105 | let maxMatch = 0;
106 | let tempRecord = "";
107 | for (const char in charMap) {
108 | const percent = comparedText(getString(imgArr), charMap[char]);
109 | if (percent > maxMatch) {
110 | maxMatch = percent;
111 | tempRecord = char;
112 | }
113 | }
114 | record += tempRecord;
115 | });
116 | return record;
117 | }
118 |
119 | function showImg(imgArr) {
120 | let s = "";
121 | imgArr.forEach(vx => {
122 | vx.forEach(vy => {
123 | s += vy;
124 | });
125 | s += "\n";
126 | });
127 | console.log(s);
128 | }
129 |
130 | function main() {
131 | const img = document.getElementById("SafeCodeImg");
132 | const canvas = document.createElement("canvas");
133 | canvas.width = width;
134 | canvas.height = height;
135 | const ctx = canvas.getContext("2d");
136 | ctx.drawImage(img, 0, 0);
137 | let imgArr = binaryImage(ctx);
138 | imgArr = removeByLine(imgArr);
139 | const imgArrArr = cutImg(
140 | imgArr,
141 | [
142 | [4, 13],
143 | [14, 23],
144 | [24, 33],
145 | [34, 43],
146 | ],
147 | [
148 | [4, 16],
149 | [4, 16],
150 | [4, 16],
151 | [4, 16],
152 | ],
153 | 4
154 | );
155 | showImg(imgArr);
156 | const result = matchCode(imgArrArr);
157 | console.log("识别为:", result);
158 | document.getElementById("RANDOMCODE").value = result;
159 | document.getElementById("userAccount").value = username;
160 | document.getElementById("userPassword").value = password;
161 | if (autologin) document.getElementById("btnSubmit").click();
162 | }
163 |
164 | (function () {
165 | "use strict";
166 | const img = document.getElementById("SafeCodeImg");
167 | img.onload = function () {
168 | main();
169 | };
170 | })();
171 |
--------------------------------------------------------------------------------
/packages/captcha/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "captcha",
3 | "version": "1.0.0",
4 | "author": "Czy",
5 | "license": "MIT",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/WindrunnerMax/TKScript"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/completion/README.md:
--------------------------------------------------------------------------------
1 | # 阿里矢量图标库添加`HTTP`按钮
2 |
3 | 阿里矢量图标库添加`HTTP`按钮,简化手动填写。
4 |
--------------------------------------------------------------------------------
/packages/completion/completion.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name 阿里图标库CDN添加HTTP按钮
3 | // @namespace https://github.com/WindrunnerMax/TKScript
4 | // @version 1.0
5 | // @description try to take over the world!
6 | // @author You
7 | // @match https://www.iconfont.cn/manage/*manage_type=myprojects*
8 | // @grant none
9 | // ==/UserScript==
10 |
11 | function addProtocol() {
12 | const preTags = document.getElementsByTagName("pre");
13 | const n = preTags.length;
14 | for (let i = 0; i < n; ++i)
15 | preTags[i].innerText = preTags[i].innerText.replace(
16 | /\/\/at.alicdn.com/g,
17 | "https://at.alicdn.com"
18 | );
19 | }
20 |
21 | (function () {
22 | "use strict";
23 | console.log(document.getElementsByClassName("block-bar"));
24 | const btn = document.createElement("div");
25 | btn.style.position = "fixed";
26 | btn.style.top = "35%";
27 | btn.style.left = "10px";
28 | btn.style.background = "#4C98F7";
29 | btn.style.color = "#fff";
30 | btn.style.height = "50px";
31 | btn.style.width = "50px";
32 | btn.style.cursor = "pointer";
33 | btn.style["line-height"] = "50px";
34 | btn.style["text-align"] = "center";
35 | btn.style["border-radius"] = "50px";
36 | btn.innerText = "HTTP";
37 | const body = document.getElementsByTagName("body")[0];
38 | btn.onclick = function () {
39 | addProtocol();
40 | };
41 | body.appendChild(btn);
42 | })();
43 |
--------------------------------------------------------------------------------
/packages/completion/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "completion",
3 | "version": "1.0.0",
4 | "author": "Czy",
5 | "license": "MIT",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/WindrunnerMax/TKScript"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/copy-currency/README.md:
--------------------------------------------------------------------------------
1 | # 文本选中复制-通用版
2 | 文本选中复制通用版本,适用于大多数网站。
3 | 由于会匹配所有网站,为了减少对于正常网站的干扰,在打开网站之后,**需要自行在网站左下角找到淡蓝色块,鼠标悬浮之后,点击启动 解除复制限制 按钮**。
4 | 某度文库、道客某某等网站需要特殊处理,不能通用处理,请移步 文本选中复制 脚本。
5 |
6 | 
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/copy-currency/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": {
3 | "default": "🔥🔥🔥文本选中复制(通用)🔥🔥🔥",
4 | "en": "Text Copy Universal",
5 | "zh": "🔥🔥🔥文本选中复制(通用)🔥🔥🔥"
6 | },
7 | "namespace": "https://github.com/WindrunnerMax/TKScript",
8 | "version": "1.1.3",
9 | "description": {
10 | "default": "文本选中复制通用版本,适用于大多数网站",
11 | "en": "Text copy general version, suitable for most websites.",
12 | "zh": "文本选中复制通用版本,适用于大多数网站"
13 | },
14 | "author": "Czy",
15 | "match": ["http://*/*", "https://*/*"],
16 | "supportURL": "https://github.com/WindrunnerMax/TKScript/issues",
17 | "license": "GPL License",
18 | "installURL": "https://github.com/WindrunnerMax/TKScript",
19 | "run-at": "document-end",
20 | "grant": ["GM_registerMenuCommand", "GM_unregisterMenuCommand", "GM_notification"]
21 | }
22 |
--------------------------------------------------------------------------------
/packages/copy-currency/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "copy-currency",
3 | "version": "1.0.0",
4 | "author": "Czy",
5 | "license": "MIT",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/WindrunnerMax/TKScript"
9 | },
10 | "sideEffects": false,
11 | "files": [
12 | "src"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/copy-currency/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare const unsafeWindow = any;
2 |
3 | declare function GM_registerMenuCommand(name: string, fn: () => void, index?: string): number;
4 | declare function GM_unregisterMenuCommand(id: number): void;
5 |
--------------------------------------------------------------------------------
/packages/copy-currency/src/index.css:
--------------------------------------------------------------------------------
1 | .__copy-currency-container{
2 | position: fixed;
3 | left: -150px;
4 | bottom: 0px;
5 | width: 150px;
6 | display: flex;
7 | flex-direction: column;
8 | border-radius: 3px;
9 | background-color: #4C98F7;
10 | transition: all .3s;
11 | z-index: 9999999999;
12 | }
13 |
14 | .__copy-currency-container::before{
15 | content: "";
16 | position: absolute;
17 | right: -6px;
18 | top: calc(50% - 10px);
19 | width: 20px;
20 | height: 20px;
21 | border-radius: 20px;
22 | background-color: #4C98F7;
23 | cursor: pointer;
24 | }
25 |
26 | .__copy-currency-container:hover{
27 | left: 0;
28 | }
29 |
30 | .__copy-currency-container > .__copy-currency-button{
31 | font-size: 12px !important;
32 | margin: 5px;
33 | cursor: pointer;
34 | color: #fff !important;
35 | border: 1px solid #fff;
36 | padding: 5px 3px 5px 4px;
37 | user-select: none;
38 | border-radius: 3px;
39 | z-index: 9999999999;
40 | text-align: center;
41 | }
--------------------------------------------------------------------------------
/packages/copy-currency/src/index.ts:
--------------------------------------------------------------------------------
1 | import type { ControllerItem } from "./register";
2 | import { BUTTON_STATUS, register, STORAGE_KEY_PREFIX } from "./register";
3 | import { styles } from "./utils";
4 |
5 | const stopNativePropagation = (event: Event) => event.stopPropagation();
6 | const CONTROLLER_MAP: ControllerItem[] = [
7 | {
8 | status: BUTTON_STATUS.CLOSE,
9 | storageKey: "selectstart-and-copy",
10 | openName: "✅ 启动解除复制限制",
11 | closeName: "❌ 关闭解除复制限制",
12 | openFunction: () => {
13 | window.addEventListener("selectstart", stopNativePropagation, true);
14 | window.addEventListener("copy", stopNativePropagation, true);
15 | styles.insertCSS(
16 | STORAGE_KEY_PREFIX + "selectstart-and-copy",
17 | "*{user-select: auto !important;-webkit-user-select: auto !important;}"
18 | );
19 | },
20 | closeFunction: () => {
21 | window.removeEventListener("selectstart", stopNativePropagation, true);
22 | window.removeEventListener("copy", stopNativePropagation, true);
23 | styles.removeCSS(STORAGE_KEY_PREFIX + "selectstart-and-copy");
24 | },
25 | },
26 | {
27 | status: BUTTON_STATUS.CLOSE,
28 | storageKey: "contextmenu",
29 | openName: "✅ 启动解除右键限制",
30 | closeName: "❌ 关闭解除右键限制",
31 | openFunction: () => window.addEventListener("contextmenu", stopNativePropagation, true),
32 | closeFunction: () => window.removeEventListener("contextmenu", stopNativePropagation, true),
33 | },
34 | {
35 | status: BUTTON_STATUS.CLOSE,
36 | storageKey: "keydown",
37 | openName: "✅ 启动解除键盘限制",
38 | closeName: "❌ 关闭解除键盘限制",
39 | openFunction: () => window.addEventListener("keydown", stopNativePropagation, true),
40 | closeFunction: () => window.removeEventListener("keydown", stopNativePropagation, true),
41 | },
42 | ];
43 |
44 | (function () {
45 | register(CONTROLLER_MAP);
46 | })();
47 |
--------------------------------------------------------------------------------
/packages/copy-currency/src/register.ts:
--------------------------------------------------------------------------------
1 | import "./index.css";
2 |
3 | const STORAGE_VALUE = {
4 | OPEN: "true",
5 | CLOSE: "false",
6 | };
7 | export enum BUTTON_STATUS {
8 | OPEN,
9 | CLOSE,
10 | }
11 | export type ControllerItem = {
12 | status: BUTTON_STATUS;
13 | storageKey: string;
14 | openName: string;
15 | closeName: string;
16 | openFunction: () => void;
17 | closeFunction: () => void;
18 | };
19 | export const STORAGE_KEY_PREFIX = "copy-currency--";
20 |
21 | export const register = (controllers: ControllerItem[]): void => {
22 | const container = document.createElement("div");
23 | container.className = "__copy-currency-container";
24 | document.body.appendChild(container);
25 | controllers.forEach(controller => {
26 | const button = document.createElement("div");
27 | button.className = "__copy-currency-button";
28 | const localHookInfo = localStorage.getItem(STORAGE_KEY_PREFIX + controller.storageKey);
29 | // 初始加载会直接调用处理函数 状态置反
30 | controller.status =
31 | localHookInfo === STORAGE_VALUE.OPEN ? BUTTON_STATUS.CLOSE : BUTTON_STATUS.OPEN;
32 | const handler = () => {
33 | if (controller.status === BUTTON_STATUS.CLOSE) {
34 | controller.openFunction();
35 | controller.status = BUTTON_STATUS.OPEN;
36 | button.textContent = controller.closeName;
37 | localStorage.setItem(STORAGE_KEY_PREFIX + controller.storageKey, STORAGE_VALUE.OPEN);
38 | } else {
39 | controller.closeFunction();
40 | controller.status = BUTTON_STATUS.CLOSE;
41 | button.textContent = controller.openName;
42 | localStorage.setItem(STORAGE_KEY_PREFIX + controller.storageKey, STORAGE_VALUE.CLOSE);
43 | }
44 | };
45 | handler();
46 | button.addEventListener("click", handler);
47 | container.appendChild(button);
48 | });
49 | };
50 |
--------------------------------------------------------------------------------
/packages/copy-currency/src/utils.ts:
--------------------------------------------------------------------------------
1 | export const styles = {
2 | insertCSS: (id: string, css: string): void => {
3 | const style = document.createElement("style");
4 | style.id = id;
5 | style.innerText = css;
6 | const [body] = document.getElementsByTagName("body");
7 | if (body) {
8 | body.appendChild(style);
9 | } else {
10 | window.addEventListener("DOMContentLoaded", () => document.body.appendChild(style));
11 | }
12 | },
13 | removeCSS: (id: string): void => {
14 | const style = document.getElementById(id);
15 | style && style.remove();
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/packages/copy/README.md:
--------------------------------------------------------------------------------
1 | # 文本选中复制
2 |
3 | 解除网站不允许复制的限制,文本选中后点击复制按钮即可复制,主要用于 百度文库 道客巴巴 无忧考网 学习啦 蓬勃范文 思否社区 力扣 知乎 语雀 等等。
4 |
5 | 某些网站例如某度文库、道客某某等都不允许用户选中文本进行复制,作为一个搞前端的,就感觉离谱,文本都下载到本地了,还不让我复制,于是为了更好的学(复)习(制),实现了一个脚本去解决这些限制。
6 |
7 | ## 描述
8 | 首先来看一下效果图,依旧是以某度文库、道客某某为例展示效果,点击复制按钮即可成功复制。
9 |
10 | 
11 |
12 | 
13 |
14 | 脚本下载地址:[https://greasyfork.org/scripts/405130-文本选中复制](https://greasyfork.org/scripts/405130-%E6%96%87%E6%9C%AC%E9%80%89%E4%B8%AD%E5%A4%8D%E5%88%B6)
15 | Github:[https://github.com/WindrunnerMax/TKScript/tree/master/src/copy](https://github.com/WindrunnerMax/TKScript/tree/master/src/copy)
16 | 脚本主要支持 百度文库 道客巴巴 无忧考网 学习啦 蓬勃范文 中文本的复制
17 |
18 | ## 实现
19 | 在研究实现之前,可能需要知道下面的一些知识,后面的链接是我之前写过的一些博客:
20 | * 事件冒泡:[事件冒泡及阻止](https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/%E4%BA%8B%E4%BB%B6%E5%86%92%E6%B3%A1%E5%8F%8A%E9%98%BB%E6%AD%A2.md)
21 | * 事件流模型:[JS事件流模型](https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/JS%E4%BA%8B%E4%BB%B6%E6%B5%81%E6%A8%A1%E5%9E%8B.md)
22 | * 浏览器事件:[浏览器事件](https://github.com/WindrunnerMax/EveryDay/blob/master/Browser/%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BA%8B%E4%BB%B6.md)
23 | * `ES6`相关语法:[ES6新特性](https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/ES6%E6%96%B0%E7%89%B9%E6%80%A7.md)
24 | * `jQuery`相关使用、`CSS`的基本语法、正则表达式、浏览器调试等
25 |
26 | ### 某度文库
27 | 在某度文库中直接右击检查元素的话,是能够直接看到文字的,可以直接在调试面板的`Elements`审查元素中复制,但是总是有些麻烦。如果在选中某度文库的东西会弹出他自行插入的复制按钮,无论是按`Ctrl+C`或者点击他的复制按钮都无效,除非开通一个`VIP`,本着白嫖的原则,且文本都下载到浏览器了还不让复制有点说不过去,于是首先研究一下他的`Event Listeners`。
28 |
29 | 
30 |
31 | 虽然通过移除一些`Event Listeners`确实能够达到使用`Ctrl+C`来实现复制的效果,但是浏览器并不提供获取所有事件监听的方法,无法移除对于匿名的事件处理函数,对于具名的事件处理函数也不容易获取,谷歌浏览器提供的`getEventListeners`方法也只能在`Console`中使用,在脚本中会出现找不到该方法的异常,于是替换了一种方案,通过自行实现一个复制按钮来规避某度文库对于按键以及复制事件的屏蔽,具体是通过动态地插入`Dom`实现一个按钮,然后使用`ClipboardJS`这个插件去实现复制,其他的操作都是一些细节的处理,例如阻止这个插入的按钮继续冒泡触发`onmouseup`事件等。
32 |
33 | 
34 |
35 | ### 道客某某
36 | 不得不说,这个真的是惊到我了,他的实现是将文本加密,然后解密文本,最后通过使用`Canvas`将文本绘制,拖动鼠标选中时其实只是通过事件监听动态的插入了一个淡蓝色的透明的`div`,看似是选中了,实际文本是并未选中的。
37 |
38 | 
39 |
40 | 见招拆招,既然文本都已经下载到了我本地,那么他的解密方式也必定在本地,于是我首先寻找的就是他对于加密的数据进行解密的代码,在浏览器中`debug`了很长时间,因为他对于代码有加密混淆压缩的行为,解密的相关代码比较混乱,并不太容易去复现,于是我换了一个思路,既然`VIP`是能够复制的,那么对于这个点击复制的按钮一定会有相应的事件处理函数,那么就寻找这个按钮绑定的事件处理函数,通过不断地`debug`我定位了一个加密的`Js`文件,虽然做了加密以及混淆但是将其解析并格式化之后在事件处理函数的部分不是特别影响阅读,此外他的混淆的变量名是动态生成的,所以要做的就是再次请求一遍这个`Js`首先将其解析生成一段字符串然后通过正则表达式匹配正确的变量名,从而实现文本的复制。
41 |
42 | 
43 |
44 | ### 其他
45 | 对于这一部分基本上都是通过监听一个`oncopy`事件去拦截复制操作,对于`DOM0`级模型直接将`oncopy`事件的处理函数指向一个空函数即可,对于`DOM2`级模型,前文提到无法在脚本中直接获取一个元素绑定的所有事件,通过观察这些网站的`Event Listeners`可以发现其绑定的`oncopy`事件都是绑定在`document`上的,而且都是冒泡模型,那么只需要阻止事件向上冒泡就能规避这些网站的`oncopy`事件的触发,实现方案就是在`body`上定义`oncopy`事件为一个空函数并阻止其向上冒泡。
46 |
47 | 
48 |
49 | ## Github
50 |
51 | ```
52 | https://github.com/WindrunnerMax/TKScript
53 | ```
54 |
--------------------------------------------------------------------------------
/packages/copy/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "🔥🔥🔥文本选中复制🔥🔥🔥",
3 | "namespace": "https://github.com/WindrunnerMax/TKScript",
4 | "version": "6.2.9",
5 | "description": "解除网站不允许复制的限制,文本选中后点击复制按钮即可复制,主要用于 百度文库 道客巴巴 腾讯文档 豆丁网 无忧考网 学习啦 蓬勃范文 思否社区 力扣 知乎 语雀 等",
6 | "author": "Czy",
7 | "match": [
8 | "*://wenku.baidu.com/view/*",
9 | "*://wenku.baidu.com/share/*",
10 | "*://wenku.baidu.com/link*",
11 | "*://wenku.baidu.com/aggs/*",
12 | "*://wenku.baidu.com/ndPureView/*",
13 | "*://www.51test.net/show/*",
14 | "*://www.xuexi.la/*",
15 | "*://www.xuexila.com/*",
16 | "*://www.cspengbo.com/*",
17 | "*://*.doc88.com/*",
18 | "*://segmentfault.com/*",
19 | "*://wk.baidu.com/view/*",
20 | "*://leetcode-cn.com/problems/*",
21 | "*://leetcode.cn/problems/*",
22 | "*://*.zhihu.com/*",
23 | "*://z.30edu.com.cn/*",
24 | "*://docs.qq.com/doc/*",
25 | "*://docs.qq.com/sheet/*",
26 | "*://docs.qq.com/slide/*",
27 | "*://boke112.com/post/*",
28 | "*://*.yuque.com/*",
29 | "*://www.commandlinux.com/*",
30 | "*://*.diyifanwen.com/*",
31 | "*://*.mbalib.com/*",
32 | "*://*.cnitpm.com/*",
33 | "*://bbs.mihoyo.com/ys/*",
34 | "*://*.ruiwen.com/*",
35 | "*://www.uemeds.cn/*",
36 | "*://www.oh100.com/*",
37 | "*://www.aiyuke.com/news/*",
38 | "*://www.fwsir.com/*",
39 | "*://www.wenxm.cn/*",
40 | "*://www.unjs.com/*",
41 | "*://www.ahsrst.cn/*",
42 | "*://*.yjbys.com/*",
43 | "*://*.qidian.com/*",
44 | "*://*.zongheng.com/*",
45 | "*://*.17k.com/*",
46 | "*://*.ciweimao.com/*",
47 | "*://book.qq.com/*",
48 | "*://*.360doc.com/content/*",
49 | "*://*.850500.com/news/*",
50 | "*://utaten.com/lyric/*",
51 | "*://*.jianbiaoku.com/*",
52 | "*://*.kt250.com/*",
53 | "*://www.kejudati.com/*",
54 | "*://*.xiaohongshu.com/discovery/*",
55 | "*://*.baibeike.com/*",
56 | "*://*.blog.csdn.net/*",
57 | "*://*.bilibili.com/read/*",
58 | "*://*.cnki.net/KXReader/*",
59 | "*://*.cnrencai.com/*",
60 | "*://*.kodiplayer.cn/*",
61 | "*://tongxiehui.net/*",
62 | "*://*.jianshu.com/p/*",
63 | "*://*.linovelib.com/novel/*",
64 | "*://*.wjx.cn/*",
65 | "*://*.wjx.top/*",
66 | "*://*.chazidian.com/*",
67 | "*://*.juejin.cn/post/*",
68 | "*://*.zgbk.com/ecph/*",
69 | "*://*.wenmi.com/article/*",
70 | "*://yuedu.baidu.com/*",
71 | "*://www.inrrp.com.cn/*",
72 | "*://fanyi.baidu.com/mtpe/*",
73 | "*://www.shubaoc.com/*",
74 | "*://blog.51cto.com/*",
75 | "*://www.ximalaya.com/*",
76 | "*://*.tianqi.com/*",
77 | "*://*.xiexiebang.com/*",
78 | "*://*.docin.com/*",
79 | "*://*.ddwk8.cn/*",
80 | "*://*.php.cn/*",
81 | "*://cooco.net.cn/*",
82 | "*://fanqienovel.com/*",
83 | "*://*.mobiletrain.org/*",
84 | "*://*.examcoo.com/*",
85 | "*://*.rrdynb.com/*",
86 | "*://*.fuwu7.com/*",
87 | "*://*.xiangqiqipu.com/*",
88 | "*://note.youdao.com/*",
89 | "*://*.163.com/*",
90 | "*://*.aipiaxi.com/*",
91 | "*://wenku.csdn.net/*",
92 | "*://www.kdocs.cn/*",
93 | "*://www.xiaoyuzhoufm.com/*",
94 | "*://*.mcmod.cn/*",
95 | "*://*.zsxq.com/",
96 | "*://*.volcengine.com/*",
97 | "*://*.lyrical-nonsense.com/*",
98 | "*://*.xueqiu.com/*",
99 | "*://*.php.cn/*",
100 | "*://*.51cto.com/*",
101 | "*://*.educoder.net/*"
102 | ],
103 | "supportURL": "https://github.com/WindrunnerMax/TKScript/issues",
104 | "license": "GPL License",
105 | "installURL": "https://github.com/WindrunnerMax/TKScript",
106 | "run-at": "document-start",
107 | "grant": ["unsafeWindow", "GM_xmlhttpRequest"],
108 | "connect": "res3.doc88.com"
109 | }
110 |
--------------------------------------------------------------------------------
/packages/copy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "copy",
3 | "version": "1.0.0",
4 | "author": "Czy",
5 | "license": "MIT",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/WindrunnerMax/TKScript"
9 | },
10 | "scripts": {
11 | "lint:ts": "../../node_modules/typescript/bin/tsc --noEmit"
12 | },
13 | "sideEffects": false,
14 | "files": [
15 | "src"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/packages/copy/src/constant/event.ts:
--------------------------------------------------------------------------------
1 | export const DOM_STAGE = {
2 | START: "document-start" as const,
3 | END: "document-end" as const,
4 | };
5 | export const DOM_READY = "DOMContentLoaded";
6 | export const DOM_LOADED = DOM_READY;
7 | export const PAGE_LOADED = "load";
8 | export const MOUSE_UP = "mouseup";
9 | export const MOUSE_DOWN = "mousedown";
10 | export const MOUSE_MOVE = "mousemove";
11 | export const COPY = "copy";
12 | export const SELECT_START = "selectstart";
13 | export const CONTEXT_MENU = "contextmenu";
14 | export const KEY_DOWN = "keydown";
15 | export const TOUCH_START = "touchstart";
16 | export const TOUCH_MOVE = "touchmove";
17 | export const TOUCH_END = "touchend";
18 | export const FOCUS = "focus";
19 | export const BLUR = "blur";
20 | export const FOCUS_IN = "focusin";
21 | export const FOCUS_OUT = "focusout";
22 | export const PASTE = "paste";
23 |
--------------------------------------------------------------------------------
/packages/copy/src/deploy.ts:
--------------------------------------------------------------------------------
1 | import { DOM_READY, DOM_STAGE } from "./constant/event";
2 | import type { CopyParams } from "./utils/copy";
3 | import type { Website, WebsiteConfig } from "./websites";
4 | import websites from "./websites";
5 |
6 | let siteGetSelectedText: (() => CopyParams) | null = null;
7 |
8 | const initWebsite = (): WebsiteConfig => {
9 | let websiteConfig: WebsiteConfig = {
10 | initCopyEvent: true,
11 | runAt: DOM_STAGE.END,
12 | captureInstance: false,
13 | delay: 0,
14 | };
15 | const mather = (regex: RegExp, website: Website) => {
16 | if (regex.test(window.location.href)) {
17 | if (website.config) {
18 | websiteConfig = Object.assign(websiteConfig, website.config);
19 | }
20 | if (websiteConfig.runAt === DOM_STAGE.END) {
21 | window.addEventListener(DOM_READY, () => website.init());
22 | } else {
23 | website.init();
24 | }
25 | if (website.getSelectedText) {
26 | siteGetSelectedText = website.getSelectedText;
27 | }
28 | return true;
29 | }
30 | return false;
31 | };
32 | websites.some(website => mather(website.regexp, website));
33 | return websiteConfig;
34 | };
35 |
36 | const getSelectedText = (): CopyParams => {
37 | if (siteGetSelectedText) return siteGetSelectedText();
38 | if (window.getSelection) return (window.getSelection() || "").toString();
39 | if (document.getSelection) return (document.getSelection() || "").toString();
40 | if (document.selection) return document.selection.createRange().text;
41 | return "";
42 | };
43 |
44 | export { initWebsite, getSelectedText };
45 |
--------------------------------------------------------------------------------
/packages/copy/src/index.ts:
--------------------------------------------------------------------------------
1 | import { initBaseEvent, initBaseStyle } from "./init";
2 | import { initWebsite, getSelectedText } from "./deploy";
3 | import instance from "./utils/instance";
4 | import { isEmptyContent } from "./utils/copy";
5 | import { MOUSE_UP } from "./constant/event";
6 |
7 | (function () {
8 | const websiteConfig = initWebsite();
9 | initBaseEvent(websiteConfig);
10 | initBaseStyle();
11 | window.addEventListener(
12 | MOUSE_UP,
13 | e => {
14 | const handler = () => {
15 | const content = getSelectedText();
16 | if (isEmptyContent(content)) {
17 | instance.hide();
18 | return void 0;
19 | }
20 | instance.onCopy(content, e);
21 | };
22 | websiteConfig.delay ? setTimeout(handler, websiteConfig.delay) : handler();
23 | },
24 | websiteConfig.captureInstance
25 | );
26 | })();
27 |
--------------------------------------------------------------------------------
/packages/copy/src/init.ts:
--------------------------------------------------------------------------------
1 | import appStyle from "./styles/app.css";
2 | import baseStyle from "./styles/style.css";
3 | import { COPY, DOM_READY } from "./constant/event";
4 | import type { WebsiteConfig } from "./websites";
5 | import dom from "./utils/dom";
6 |
7 | export const initBaseEvent = (websiteConfig: WebsiteConfig): void => {
8 | window.addEventListener(DOM_READY, () => {
9 | if (websiteConfig.initCopyEvent) {
10 | document.oncopy = e => e.stopPropagation();
11 | document.body.oncopy = e => e.stopPropagation();
12 | document.addEventListener(COPY, e => e.stopPropagation());
13 | document.body.addEventListener(COPY, e => e.stopPropagation());
14 | }
15 | });
16 | };
17 |
18 | export const initBaseStyle = (): void => {
19 | window.addEventListener(DOM_READY, () => {
20 | dom.append("head", ``);
21 | dom.append("head", ``);
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/17k.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp("17k"),
6 | init: () => {
7 | utils.hideButton();
8 | utils.enableOnCopy(".readAreaBox .p");
9 | },
10 | };
11 |
12 | export default website;
13 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/aiyuke.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp(".+aiyuke.com/news/.+"),
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableUserSelectByCSS();
9 | },
10 | };
11 |
12 | export default website;
13 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/bilibili.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp("bilibili"),
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableOnCopyByCapture();
9 | },
10 | };
11 |
12 | export default website;
13 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/boke112.ts:
--------------------------------------------------------------------------------
1 | import dom from "../utils/dom";
2 | import utils from "../utils/event";
3 | import type { Website } from "../websites";
4 |
5 | const website: Website = {
6 | regexp: new RegExp(".+://boke112.com/post/.+"),
7 | init: function () {
8 | utils.enableOnCopyByCapture();
9 | const template = `
10 |
21 | `;
22 | dom.append("head", template);
23 | },
24 | };
25 |
26 | export default website;
27 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/ciweimao.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp("ciweimao"),
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableUserSelectByCSS();
9 | utils.enableOnCopy("#J_BookCnt");
10 | utils.enableOnContextMenu("body");
11 | utils.enableOnSelectStart("#J_BookCnt");
12 | },
13 | };
14 |
15 | export default website;
16 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/cnitpm.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: /cnitpm/,
6 | init: function () {
7 | utils.hideButton();
8 | window.onload = () => {
9 | utils.removeAttributes("body", ["oncopy", "oncontextmenu", "onselectstart"]);
10 | };
11 | },
12 | };
13 |
14 | export default website;
15 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/cnki.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp("cnki"),
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableOnContextMenuByCapture();
9 | utils.enableOnKeyDownByCapture();
10 | utils.enableOnCopyByCapture();
11 | },
12 | };
13 |
14 | export default website;
15 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/common-e.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp(["wjx", "fanyi\\.baidu", "tianqi", "rrdynb", "fuwu7"].join("|")),
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableUserSelectByCSS();
9 | utils.enableOnCopyByCapture();
10 | utils.enableOnKeyDownByCapture();
11 | utils.enableOnSelectStartByCapture();
12 | utils.enableOnContextMenuByCapture();
13 | },
14 | };
15 |
16 | export default website;
17 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/common-p.ts:
--------------------------------------------------------------------------------
1 | import { DOM_STAGE } from "../constant/event";
2 | import utils from "../utils/event";
3 | import type { Website } from "../websites";
4 |
5 | const website: Website = {
6 | config: {
7 | runAt: DOM_STAGE.START,
8 | },
9 | regexp: new RegExp(["examcoo"].join("|")),
10 | init: function () {
11 | utils.hideButton();
12 | utils.enableUserSelectByCSS();
13 | utils.enableOnCopyByCapture();
14 | utils.enableOnKeyDownByCapture();
15 | utils.enableOnSelectStartByCapture();
16 | utils.enableOnContextMenuByCapture();
17 | },
18 | };
19 |
20 | export default website;
21 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/common.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: new RegExp(
6 | [
7 | "commandlinux",
8 | "cnki",
9 | "ruiwen",
10 | "oh100",
11 | "fwsir",
12 | "wenxm",
13 | "unjs",
14 | "ahsrst",
15 | "yjbys",
16 | "360doc",
17 | "850500",
18 | "jianbiaoku",
19 | "kt250",
20 | "kejudati",
21 | "baibeike",
22 | "yuque",
23 | "cnrencai",
24 | "kodiplayer",
25 | "tongxiehui",
26 | "ndPureView",
27 | "jianshu",
28 | "linovelib",
29 | "chazidian",
30 | "juejin",
31 | "zgbk",
32 | "wenmi",
33 | "yuedu\\.baidu",
34 | "inrrp",
35 | "shubaoc",
36 | "51cto",
37 | "ximalaya",
38 | "xiexiebang",
39 | "ddwk8",
40 | "php\\.cn",
41 | "fanqienovel\\.com/reader",
42 | "cooco\\.net\\.cn",
43 | "mobiletrain",
44 | "xiangqiqipu",
45 | "m\\.163\\.com",
46 | "aipiaxi",
47 | "wenku\\.csdn\\.net",
48 | "xiaoyuzhoufm\\.com",
49 | "mcmod\\.cn",
50 | "zsxq\\.com",
51 | "volcengine\\.com",
52 | "lyrical-nonsense\\.com",
53 | "xueqiu\\.com",
54 | "php\\.cn",
55 | "51cto\\.com",
56 | "educoder\\.net",
57 | ].join("|")
58 | ),
59 | init: function () {
60 | utils.hideButton();
61 | utils.enableUserSelectByCSS();
62 | utils.enableOnCopyByCapture();
63 | },
64 | };
65 |
66 | export default website;
67 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/csdn.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: /csdn/,
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableOnCopyByCapture();
9 | utils.enableUserSelectByCSS();
10 | },
11 | };
12 |
13 | export default website;
14 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/diyifanwen.ts:
--------------------------------------------------------------------------------
1 | import utils from "../utils/event";
2 | import type { Website } from "../websites";
3 |
4 | const website: Website = {
5 | regexp: /diyifanwen/,
6 | init: function () {
7 | utils.hideButton();
8 | utils.enableOnCopyByCapture();
9 | utils.enableOnKeyDownByCapture();
10 | },
11 | };
12 |
13 | export default website;
14 |
--------------------------------------------------------------------------------
/packages/copy/src/modules/doc88.ts:
--------------------------------------------------------------------------------
1 | import dom from "../utils/dom";
2 | import type { Website } from "../websites";
3 |
4 | /*!
5 | * 外部引用 static.doc88.com 声明
6 | * 此部分是在处理 doc88.com 才会加载的资源文件,此资源文件由该网站加载时提供
7 | */
8 |
9 | let path = "";
10 | const website: Website = {
11 | regexp: /.*doc88\.com\/.+/,
12 | init: () => {
13 | dom.append(
14 | "body",
15 | ``
16 | );
17 | GM_xmlhttpRequest({
18 | method: "GET",
19 | url: "https://res3.doc88.com/resources/js/modules/main-v2.min.js?v=3.55",
20 | onload: function (response) {
21 | const result = /\("#cp_textarea"\).val\(([\S]*?)\);/.exec(response.responseText);
22 | if (result) path = result[1];
23 | },
24 | });
25 | window.addEventListener("load", () => {
26 | const cpFn = unsafeWindow.copyText.toString();
27 | const fnResult = /