├── .gitattributes
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── Trucksbook-CNY
└── greasyfork.user.js
├── assets
└── g.png
├── douyin-download
└── greasyfork.user.js
├── example-scripts
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── index.html
├── package.json
├── src
│ ├── app.vue
│ ├── assets
│ │ └── app.less
│ ├── main.js
│ └── vite-env.d.ts
├── vite.config.js
└── yarn.lock
├── export-wechat-articles
└── greasyfork.user.js
├── feeder-zhcn
└── greasyfork.user.js
├── icomoonio-clearAll.user.js
├── lobechat-webdav
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── dist
│ └── lobechat-webdav.user.js
├── index.html
├── package.json
├── src
│ ├── app.vue
│ ├── assets
│ │ └── app.less
│ ├── main.js
│ └── vite-env.d.ts
├── vite.config.js
└── yarn.lock
├── netlify-zhcn
└── greasyfork.user.js
├── nextchat-themes
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── dist
│ └── nextchat-themes.user.js
├── index.html
├── package.json
├── src
│ ├── app.vue
│ ├── assets
│ │ └── app.less
│ ├── main.js
│ └── vite-env.d.ts
├── vite.config.js
└── yarn.lock
├── producthunt-zhcn
└── greasyfork.user.js
├── scripts-template.js
├── v2ex-ai-summary
└── greasyfork.user.js
└── v2ex-lightbox
└── greasyfork.user.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "liveServer.settings.port": 5502,
3 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UserScript 脚本集合
2 |
3 | ```js
4 | //
5 | _ _ ____ _ _
6 | | | | |___ ___ _ __/ ___| ___ _ __(_)_ __ | |_
7 | | | | / __|/ _ \ '__\___ \ / __| '__| | '_ \| __|
8 | | |_| \__ \ __/ | ___) | (__| | | | |_) | |_
9 | \___/|___/\___|_| |____/ \___|_| |_| .__/ \__|
10 | |_|
11 | //
12 | ```
13 |
14 | ## 简介
15 |
16 | 这是一个实用的油猴脚本(UserScript)集合仓库,包含了多个实用的浏览器增强脚本。这些脚本旨在提升网页浏览体验,增加网站功能,优化用户界面等。
17 |
18 | ## 脚本列表
19 |
20 | | 脚本名称 | 脚本说明 | 安装链接 |
21 | | ---------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
22 | | [Lobechat Webdav 同步功能](./lobechat-webdav/) | 给 lobechat 程序添加 webdav 同步的功能。 | [Greasyfork](https://greasyfork.org/scripts/516358) |
23 | | Trucksbook 欧元换算人民币单位 | trucksbook.eu 欧元换算人民币单位插件,安装即可使用生效。 | [Greasyfork](https://greasyfork.org/scripts/515007) |
24 | | [nextchat-themes](./nextchat-themes/) | NextChat 插件,修改 UI 主题 | [Greasyfork](https://greasyfork.org/scripts/513677) |
25 | | linuxdo 增强插件 | linux.do 多功能脚本。 | [Greasyfork](https://greasyfork.org/scripts/501827) |
26 | | v2ex 图片灯箱插件 | v2ex 图片灯箱插件,可以使用滚轮放大缩小。 | [Greasyfork](https://greasyfork.org/scripts/454963) |
27 | | v2ex AI 总结帖子 | 自定义 api key 等信息,实现 AI 总结帖子,会保留缓存记录到本地避免大量消耗 token。 | [Greasyfork](https://greasyfork.org/scripts/505714) |
28 | | feeder 汉化脚本 | 由于官方不支持中文,对 feeder 进行汉化翻译。 | [Greasyfork](https://greasyfork.org/scripts/481157) |
29 | | Netlify 汉化脚本 | 由于官方不支持中文,汉化 Netlify 大部分的翻译。 | [Greasyfork](https://greasyfork.org/scripts/484197) |
30 | | Notion 增强脚本 | 修改字体大小,多余的遮罩,个性化目录弹窗,浮动在右侧(目录必须作为第一个块元素)。 | [Greasyfork](https://greasyfork.org/scripts/485105) |
31 | | 导出微信公众号文章为 PDF | 在微信公众号文章页面中添加按钮,点击后导出文章为 PDF 格式,并显示标题、作者和时间等元信息。 | [Greasyfork](https://greasyfork.org/scripts/510683) |
32 | | 抖音视频下载 | 在浏览器中打开抖音,实现快速下载视频。 | [Greasyfork](https://raw.githubusercontent.com/dlzmoe/scripts/refs/heads/main/douyin-download/greasyfork.user.js) |
33 | | Product Hunt 汉化 | 由于官方不支持中文,汉化大部分的翻译。 | [Greasyfork](https://raw.githubusercontent.com/dlzmoe/scripts/refs/heads/main/producthunt-zhcn/greasyfork.user.js) |
34 | | icomoon.io 一键删除 | 添加一个按钮,点击时触发所有ng-click="removeSet($index)"按钮 | [Greasyfork](https://greasyfork.org/scripts/529673) |
35 |
36 | ## 使用说明
37 |
38 | 1. 首先需要安装浏览器扩展:
39 | - Chrome/Edge 浏览器:安装 [Tampermonkey](https://www.tampermonkey.net/)
40 | - Firefox 浏览器:安装 [Greasemonkey](https://addons.mozilla.org/firefox/addon/greasemonkey/)
41 |
42 | 2. 点击上方脚本列表中的 Greasyfork 链接,进入脚本页面。
43 |
44 | 3. 点击安装按钮,即可完成脚本安装。
45 |
46 | 4. 访问对应网站,脚本会自动运行并生效。
47 |
48 | ## 许可证
49 |
50 | 本项目采用 MIT 许可证,详情请参阅 [LICENSE](./LICENSE) 文件。
51 |
--------------------------------------------------------------------------------
/Trucksbook-CNY/greasyfork.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Trucksbook 欧元换算人民币单位
3 | // @version 1.0
4 | // @namespace https://github.com/dlzmoe/Userscript
5 | // @author dlzmoe
6 | // @description trucksbook.eu 欧元换算人民币单位插件,安装即可使用生效。
7 | // @match https://trucksbook.eu/*
8 | // @grant none
9 | // @icon https://trucksbook.eu/data/system/favicon.ico
10 | // @license Apache-2.0 license
11 | // ==/UserScript==
12 |
13 | (function () {
14 | 'use strict';
15 | $(document).ready(function () {
16 | var exchangeRate = 7.73; // 汇率
17 |
18 | $('*').contents().each(function () {
19 | if (this.nodeType === Node.TEXT_NODE) {
20 | var text = this.nodeValue;
21 |
22 | var regex = /(\d[\d\s]*)\s*€/g;
23 | var matches;
24 |
25 | while ((matches = regex.exec(text)) !== null) {
26 | var euroValue = parseFloat(matches[1].replace(/\s+/g, ''));
27 | var rmbValue = (euroValue * exchangeRate).toFixed(2);
28 | var newText = text.replace(matches[0], rmbValue + ' 元');
29 | $(this).replaceWith(newText);
30 | }
31 | }
32 | });
33 | });
34 |
35 | })();
--------------------------------------------------------------------------------
/assets/g.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlzmoe/UserScript/2b8dbbe485a9e6e7ee99fbabb38af80f6ce1352f/assets/g.png
--------------------------------------------------------------------------------
/douyin-download/greasyfork.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name 抖音视频下载 - 需进入详情页
3 | // @namespace https://github.com/dlzmoe/scripts
4 | // @version 0.0.1
5 | // @description 在浏览器中打开抖音,实现快速下载视频。
6 | // @author dlzmoe
7 | // @match https://*.douyin.com/*
8 | // @icon https://p-pc-weboff.byteimg.com/tos-cn-i-9r5gewecjs/favicon.png
9 | // @require https://cdn.bootcss.com/jquery/3.6.0/jquery.min.js
10 | // @grant none
11 | // @license Apache-2.0 license
12 | // ==/UserScript==
13 |
14 | (function () {
15 | 'use strict';
16 | $(function () {
17 | setTimeout(function () {
18 | $('.danMuPlayerStyle .jkfSVWLT .wobrT4EE:nth-child(4)').remove();
19 | $('.xgplayer.xgplayer-pc .xg-right-grid').append(`
20 |
21 |
22 |
下载
23 |
24 | `)
25 |
26 | $('#xgplayer-download').click(function () {
27 | var videoUrl = $('.xgplayer video').find('source:nth-child(1)').attr('src');
28 | $('body').append(``)
29 | $('#newdownload')[0].click();
30 | })
31 | }, 1000)
32 |
33 | })
34 | })();
--------------------------------------------------------------------------------
/example-scripts/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/example-scripts/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/example-scripts/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/example-scripts/README.md:
--------------------------------------------------------------------------------
1 | ## example-scripts
2 |
--------------------------------------------------------------------------------
/example-scripts/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlzmoe/UserScript/2b8dbbe485a9e6e7ee99fbabb38af80f6ce1352f/example-scripts/index.html
--------------------------------------------------------------------------------
/example-scripts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-scripts",
3 | "version": "0.0.1",
4 | "author": "dlzmoe",
5 | "description": "a sample script.",
6 | "type": "module",
7 | "license": "Apache-2.0",
8 | "scripts": {
9 | "dev": "vite --mode development",
10 | "build": "vite build",
11 | "preview": "vite preview"
12 | },
13 | "dependencies": {
14 | "vue": "^3.4.27",
15 | "webdav": "^5.7.1"
16 | },
17 | "devDependencies": {
18 | "@vitejs/plugin-vue": "^5.0.4",
19 | "less": "^4.1.0",
20 | "less-loader": "^8.0.0",
21 | "style-loader": "^2.0.0",
22 | "vite": "^5.2.12",
23 | "vite-plugin-monkey": "^4.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/example-scripts/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/example-scripts/src/assets/app.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlzmoe/UserScript/2b8dbbe485a9e6e7ee99fbabb38af80f6ce1352f/example-scripts/src/assets/app.less
--------------------------------------------------------------------------------
/example-scripts/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './app.vue';
3 | const app = createApp(App);
4 |
5 | import "./assets/app.less";
6 |
7 | app.mount(
8 | (() => {
9 | const appDiv = document.createElement('div');
10 | document.body.append(appDiv);
11 | return appDiv;
12 | })(),
13 | );
--------------------------------------------------------------------------------
/example-scripts/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ////
4 |
--------------------------------------------------------------------------------
/example-scripts/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 | import monkey, { cdn } from 'vite-plugin-monkey';
4 | import pkg from './package.json';
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [
9 | vue(),
10 | monkey({
11 | entry: 'src/main.js',
12 | userscript: {
13 | icon: 'https://raw.githubusercontent.com/dlzmoe/UserScript/refs/heads/main/assets/g.png',
14 | name: "example-scripts",
15 | namespace: 'https://github.com/dlzmoe/UserScript',
16 | description: "a sample script.",
17 | version: pkg.version,
18 | match: ['*://app.nextchat.dev/*'],
19 | },
20 | build: {
21 | externalGlobals: {
22 | // require 引入
23 | vue: cdn.unpkg('Vue', 'dist/vue.global.prod.js'),
24 | },
25 | minify: false, // 不混淆
26 | },
27 | }),
28 | ],
29 | });
30 |
--------------------------------------------------------------------------------
/export-wechat-articles/greasyfork.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name 导出微信公众号文章为 PDF
3 | // @namespace https://github.com/dlzmoe/scripts
4 | // @version 0.5
5 | // @author dlzmoe
6 | // @description 在微信公众号文章页面中添加按钮,点击后导出文章为 PDF 格式,并显示标题、作者和时间等元信息。
7 | // @match https://mp.weixin.qq.com/s/*
8 | // @grant none
9 | // @license Apache-2.0 license
10 | // @require https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js
11 | // ==/UserScript==
12 |
13 | (function () {
14 | 'use strict';
15 |
16 | // 创建一个按钮
17 | var button = document.createElement('button');
18 | button.innerHTML = '导出为 PDF';
19 | button.style.position = 'fixed';
20 | button.style.top = '10px';
21 | button.style.right = '10px';
22 | button.style.zIndex = '9999';
23 | button.style.backgroundColor = '#4CAF50';
24 | button.style.color = 'white';
25 | button.style.border = 'none';
26 | button.style.padding = '10px 20px';
27 | button.style.fontSize = '16px';
28 | button.style.cursor = 'pointer';
29 | button.style.transition = 'background-color 0.3s ease'; // 添加过渡效果
30 | document.body.appendChild(button);
31 |
32 | // 标志位:防止连续多次点击
33 | let isExporting = false;
34 |
35 | // 添加加载动画
36 | function startLoading() {
37 | button.disabled = true; // 禁用按钮
38 | button.style.backgroundColor = '#888'; // 变成灰色表示加载中
39 | button.innerHTML = '正在导出...'; // 更改按钮文本为加载状态
40 | }
41 |
42 | // 停止加载动画
43 | function stopLoading() {
44 | button.disabled = false; // 启用按钮
45 | button.style.backgroundColor = '#4CAF50'; // 恢复原始颜色
46 | button.innerHTML = '导出为 PDF'; // 恢复按钮文本
47 | }
48 |
49 | // 点击按钮时执行导出 PDF 的操作
50 | button.addEventListener('click', function () {
51 | if (isExporting) {
52 | return; // 如果已经在导出过程中,则不允许再次点击
53 | }
54 |
55 | isExporting = true; // 设置为正在导出
56 | startLoading(); // 启动加载动画
57 |
58 | // 获取文章内容和标题、作者、时间等元信息
59 | var article = document.querySelector('.rich_media_content');
60 | var title = document.querySelector('.rich_media_title');
61 | var author = document.querySelector('.weui-wa-hotarea'); // 文章作者
62 | var publishTime = document.querySelector('#publish_time'); // 文章时间
63 |
64 | if (article) {
65 | // 创建一个容器用于添加元信息
66 | var metaInfoDiv = document.createElement('div');
67 | metaInfoDiv.style.marginBottom = '20px';
68 | metaInfoDiv.style.borderBottom = '1px solid #eee';
69 | metaInfoDiv.style.paddingBottom = '15px';
70 |
71 | // 标题
72 | var titleElement = document.createElement('h1');
73 | titleElement.innerText = title ? title.innerText.trim() : '未命名文章';
74 | titleElement.style.fontSize = '24px';
75 | titleElement.style.marginBottom = '10px';
76 | metaInfoDiv.appendChild(titleElement);
77 |
78 | // 作者
79 | if (author) {
80 | var authorElement = document.createElement('p');
81 | authorElement.innerText = '作者:' + author.innerText.trim();
82 | authorElement.style.fontSize = '14px';
83 | authorElement.style.margin = '5px 0';
84 | metaInfoDiv.appendChild(authorElement);
85 | }
86 |
87 | // 时间
88 | if (publishTime) {
89 | var timeElement = document.createElement('p');
90 | timeElement.innerText = '发布时间:' + publishTime.innerText.trim();
91 | timeElement.style.fontSize = '14px';
92 | timeElement.style.margin = '5px 0';
93 | metaInfoDiv.appendChild(timeElement);
94 | }
95 |
96 | // 将元信息插入到文章内容的顶部
97 | article.insertBefore(metaInfoDiv, article.firstChild);
98 |
99 | // 添加防止图片分页的 CSS 样式
100 | var style = document.createElement('style');
101 | style.innerHTML = `
102 | .rich_media_content img {
103 | page-break-inside: avoid;
104 | break-inside: avoid;
105 | max-width: 100%;
106 | height: auto;
107 | }
108 | .rich_media_content p, .rich_media_content div {
109 | page-break-inside: avoid;
110 | break-inside: avoid;
111 | }
112 | `;
113 | document.head.appendChild(style);
114 |
115 | // 确保所有图片加载完成
116 | let images = article.querySelectorAll('img');
117 | let imagePromises = [];
118 |
119 | images.forEach(function (img) {
120 | // 处理懒加载的图片,确保图片的真实 URL 被加载
121 | if (img.dataset && img.dataset.src) {
122 | img.src = img.dataset.src;
123 | }
124 |
125 | // 通过跨域获取图片,并将图片转换为 base64 格式
126 | imagePromises.push(
127 | new Promise(function (resolve) {
128 | var imgElement = new Image();
129 | imgElement.crossOrigin = 'Anonymous';
130 | imgElement.src = img.src;
131 | imgElement.onload = function () {
132 | var canvas = document.createElement('canvas');
133 | canvas.width = imgElement.width;
134 | canvas.height = imgElement.height;
135 | var ctx = canvas.getContext('2d');
136 | ctx.drawImage(imgElement, 0, 0);
137 | img.src = canvas.toDataURL('image/jpeg'); // 使用 JPEG 格式并压缩质量到 70%
138 | resolve();
139 | };
140 | imgElement.onerror = resolve; // 即使图片加载失败,继续处理
141 | })
142 | );
143 | });
144 |
145 | // 确保图片加载完成后再导出 PDF
146 | Promise.all(imagePromises).then(function () {
147 | // 使用文章标题作为文件名
148 | var fileName = title ? title.innerText.trim() + '.pdf' : 'WeChat_Article.pdf';
149 |
150 | var opt = {
151 | margin: 0.5,
152 | filename: fileName,
153 | image: {
154 | type: 'jpeg',
155 | quality: 1 // 降低图片质量以减小 PDF 体积
156 | },
157 | html2canvas: {
158 | scale: 1.5, // 降低渲染比例以减小 PDF 体积
159 | useCORS: true, // 允许跨域图片
160 | logging: false, // 关闭日志
161 | // 可以根据需要添加其他 html2canvas 选项
162 | },
163 | jsPDF: {
164 | unit: 'in',
165 | format: 'a4', // 使用 A4 格式,比 letter 更常用且体积可能更小
166 | orientation: 'portrait'
167 | },
168 | pagebreak: {
169 | mode: ['avoid-all', 'css', 'legacy']
170 | } // 遵循 CSS 中的 page-break 规则
171 | };
172 |
173 | // 使用 html2pdf 将文章内容导出为 PDF
174 | html2pdf().from(article).set(opt).save().then(function () {
175 | // 导出完成后,恢复按钮状态
176 | stopLoading();
177 | isExporting = false; // 重置导出状态
178 | }).catch(function (error) {
179 | alert('导出过程中出现问题:' + error.message);
180 | stopLoading(); // 即使出现错误也恢复按钮状态
181 | isExporting = false; // 重置导出状态
182 | });
183 | }).catch(function (error) {
184 | alert('处理图片时出现问题:' + error.message);
185 | stopLoading(); // 即使出现错误也恢复按钮状态
186 | isExporting = false; // 重置导出状态
187 | });
188 | } else {
189 | alert('未找到文章内容');
190 | stopLoading(); // 如果未找到文章内容,恢复按钮状态
191 | isExporting = false; // 重置导出状态
192 | }
193 | });
194 | })();
--------------------------------------------------------------------------------
/feeder-zhcn/greasyfork.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name feeder 汉化脚本
3 | // @namespace https://github.com/dlzmoe/scripts
4 | // @version 0.0.2
5 | // @author dlzmoe
6 | // @description feeder.com 汉化脚本
7 | // @include *://feeder.co/*
8 | // @license Apache-2.0 license
9 | // @icon https://feeder.co/favicon.ico
10 | // @grant none
11 | // ==/UserScript==
12 |
13 | const zh_Hans = [
14 | ['All feeds', '全部订阅'],
15 | ['Unread', '未读'],
16 | ['Starred', '星标'],
17 | ['Home', '首页'],
18 | ['Dashboard', '图表'],
19 | ['Rules', '规则'],
20 | ['Team', '团队'],
21 | ['Library', '列表'],
22 | ['Account', '账户'],
23 | ['Help', '帮助'],
24 | ['Collapse', '收起'],
25 | ['Reload feeds', '重新加载源数据'],
26 | ['Open all unread...', '打开所有未读'],
27 | ['Mark all as read', '全部标为已读'],
28 | ['Mark feed as read', '将 feed 标为已读'],
29 | ['Export posts', '导出帖子'],
30 | ['Go to page', '跳转到网站'],
31 | ['Edit feed', '编辑 feed'],
32 | ['Delete feed', '删除 feed'],
33 | ['Filters', '过滤'],
34 | ['Display', '展示'],
35 | ['Order', '排序'],
36 | ['Newest first', '最新'],
37 | ['Oldest first', '最旧'],
38 | ['Realtime', '实时'],
39 | ['Auto-update', '自动更新'],
40 | ['Content style', '风格'],
41 | ['Timestamp', '时间戳'],
42 | ['Previous post', '上一篇'],
43 | ['Next post', '下一篇'],
44 | ['Share post', '分享'],
45 | ['Mark as unread', '标记为已读'],
46 | ['Star post', '收藏'],
47 | ['Toggle collections', '切换集合'],
48 | ['Simple', '简单'],
49 | ['Full', '源站'],
50 | ['Free', '免费'],
51 | ['My account', '我的账户'],
52 | ['Settings', '设置'],
53 | ['Share', '分享'],
54 | ['Add to collections', '添加到收藏夹'],
55 | ['Appearance', '外观'],
56 | ['Log out', '退出'],
57 | ['Change display mode', '更改显示模式'],
58 | ['Minimal', '极小'],
59 | ['Reader', '读者'],
60 | ['3-pane', '3 窗格'],
61 | ['Reader', '读者'],
62 | ['Two panes with collapsing folders', '两个包含折叠文件夹的窗格'],
63 | ['Read posts inline for fast consuming', '内联阅读帖子,快速查看'],
64 | ['The entire hierarchy for the best overview', '最佳预览的层次结构'],
65 | ['Change theme', '更改主题'],
66 | ['Light', '明亮'],
67 | ['Dark', '暗黑'],
68 | ['Holiday', '假期'],
69 | ['Orange', '橙色'],
70 | ['Holiday', '假期'],
71 | ['Sand', '沙滩'],
72 | ['Grey', '灰色'],
73 | ['Follow OS setting', '跟随操作系统设置'],
74 | ['Reload', '重新加载'],
75 | ['Expanded', '放大'],
76 | ['Collapsed', '缩小'],
77 | ['Column width', '全宽'],
78 | ['Notifications', '通知'],
79 | ['Sound', '声音'],
80 | ['iOS/Android', 'iOS/Android'],
81 | ['Get Feeder Plus', '获取 Feeder Plus'],
82 | ['Toggle all feeds', '选择全部'],
83 | ['Email summaries', '邮件摘要'],
84 | ['Connections', '连接'],
85 | ['Advanced', '高级'],
86 | ['Global', '全球'],
87 | ['Ask before marking many as read', '在标记已读前询问'],
88 | ['Track unread posts -', '跟踪未读帖子'],
89 | ['When OFF stops marking incoming posts as unread', '当 OFF 时,停止将收到的帖子标记为未读'],
90 | ['Notify me when my feeds stop working', '当我的 Feed 停止工作时通知我'],
91 | ['Connected', '连接'],
92 | ['Receive e-mail summaries', '接受邮件订阅'],
93 | ['Get a periodical with the latest posts from your feeds. Daily, weekly or monthly. You decide.', '每天、每周或每月获取包含源中最新帖子的期刊。'],
94 | ['Enable e-mail summaries', '开始邮箱订阅'],
95 | ['Plan', '计划'],
96 | ['Email and password', '邮箱和密码'],
97 | ['Invoices', '发票'],
98 | ['Billing address', '账单'],
99 | ['Your plan', '你的计划'],
100 | ['Change plan', '更改计划'],
101 | ['Payment details', '付款明细'],
102 | ['No payment method', '没有付款计划'],
103 | ['Upgrade for more', '升级获取更多'],
104 | ['Change email', '修改邮箱'],
105 | ['Current email address is', '当前邮箱地址为'],
106 | ['New email', '新邮箱'],
107 | ['Repeat new email', '重复新邮箱'],
108 | ['Update email', '更新邮箱'],
109 | ['Change password', '修改密码'],
110 | ['Current password', '当前密码'],
111 | ['New password', '新密码'],
112 | ['Update password', '更新密码'],
113 | ['Delete your account', '删除你的账户'],
114 | ['All your data will be deleted, and there will be no way to retrieve them.', '您的所有数据都将被删除,并且无法检索它们。'],
115 | ['Current email address', '当前邮箱'],
116 | ['Remove your account', '确认删除账户'],
117 | ['Invoice date', '发票日期'],
118 | ['VAT', '增值税'],
119 | ['Total', '总计'],
120 | ['You have no invoices', '您没有发票'],
121 | ['Once your first payment is generated it will be shown here', '如果你付款成功,它将会显示在这里。'],
122 | ['Your billing address', '你的账单邮寄地址'],
123 | ['This information will be on your invoices.', '此信息将出现在您的发票上'],
124 | ['Your name', '你的姓名'],
125 | ['Company name', '公司名称'],
126 | ['Address', '地址'],
127 | ['Address (line 2)', '地址(第二行)'],
128 | ['Zip code', '邮政编码'],
129 | ['VAT Number', '增值税号'],
130 | ['Country', '国家'],
131 | ['Additional information', '其他信息'],
132 | ['Update billing address', '更新账单邮寄地址'],
133 | ['Help center', '帮助中心'],
134 | ["What's new?", "最新新闻"],
135 | ['Keyboard navigation', '键盘导航'],
136 | ['Contact support', '联系支持人员'],
137 | ['Downloads', '下载安装'],
138 | ['Automate your workflow with Rules', '使用规则自动执行工作流程'],
139 | ['Define your keywords and choose what happens next. Filter posts, add them to collections, post content to Slack and Microsoft teams, and more.', '定义关键字并选择接下来要执行的操作。筛选帖子、将其添加到收藏夹、将内容发布到 Slack 和 Microsoft 团队等。'],
140 | ['Upgrade to Feeder Plus', '升级到 Feeder Plus'],
141 | ['Collaborate with your team', '与你的团队协作'],
142 | ['Share feeds, manage users in one place and work together.', '共享,在一个地方管理用户并协同工作。'],
143 | ['Get started', '开始使用'],
144 | ['Want to try it first?', '想先试试嘛?'],
145 | ['Feeds', '订阅'],
146 | ['Collections', '收集'],
147 | ['Sources', '来源'],
148 | ['Import & Export', '导入导出'],
149 | ];
150 |
151 | class ReplaceText {
152 | constructor(i18n, mode = 'equal') {
153 | this.W = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;
154 | this.done = new Set();
155 | this.alert = this.W.alert.bind(this.W);
156 | this.confirm = this.W.confirm.bind(this.W);
157 | this.prompt = this.W.prompt.bind(this.W);
158 | const i18nMap = new Map(i18n);
159 | const i18nArr = i18n.map(value => value[0]);
160 | if (mode === 'regexp') {
161 | this.textReplace = (text) => {
162 | if (i18nMap.has(text))
163 | text = i18nMap.get(text);
164 | else {
165 | const key = i18nArr.find(key => (key instanceof RegExp && text.match(key) !== null));
166 | if (key !== undefined)
167 | text = text.replace(key, i18nMap.get(key));
168 | }
169 | return text;
170 | };
171 | } else if (mode === 'match') {
172 | this.textReplace = (text) => {
173 | const key = i18nArr.find(key => (text.match(key) !== null));
174 | if (key !== undefined)
175 | text = text.replace(key, i18nMap.get(key));
176 | return text;
177 | };
178 | } else {
179 | this.textReplace = (text) => {
180 | if (i18nMap.has(text))
181 | text = i18nMap.get(text);
182 | return text;
183 | };
184 | }
185 | this.replaceAlert();
186 | this.replaceObserver();
187 | }
188 | replaceAlert() {
189 | this.W.alert = (message) => this.alert(this.textReplace(message));
190 | this.W.confirm = (message) => this.confirm(this.textReplace(message));
191 | this.W.prompt = (message, _default) => this.prompt(this.textReplace(message), _default);
192 | }
193 | replaceNode(node, self = false) {
194 | const list = this.getReplaceList(node, self);
195 | for (let index in list) {
196 | list[index].forEach(node => {
197 | if (this.done.has(node[index]))
198 | return;
199 | const newText = this.textReplace(node[index]);
200 | if (node[index] !== newText) {
201 | this.done.add(newText);
202 | node[index] = newText;
203 | }
204 | });
205 | }
206 | }
207 | replaceObserver() {
208 | const bodyObserver = new MutationObserver(mutations => {
209 | mutations.forEach(mutation => {
210 | if (mutation.type === 'attributes' || mutation.type === 'characterData')
211 | this.replaceNode(mutation.target, true);
212 | else if (mutation.type === 'childList') {
213 | mutation.addedNodes.forEach(addedNode => this.replaceNode(addedNode));
214 | }
215 | });
216 | });
217 | document.addEventListener('readystatechange', () => {
218 | bodyObserver.observe(document.body, {
219 | attributes: true,
220 | characterData: true,
221 | childList: true,
222 | subtree: true
223 | });
224 | this.replaceNode(document.body);
225 | }, {
226 | capture: true,
227 | once: true
228 | });
229 | }
230 | getReplaceList(node, self = false) {
231 | const list = {
232 | data: new Set(),
233 | placeholder: new Set(),
234 | title: new Set(),
235 | value: new Set(),
236 | };
237 | const nodeList = self ? [node] : this.nodeForEach(node);
238 | nodeList.forEach(node => {
239 | if (node.parentElement instanceof HTMLScriptElement || node.parentElement instanceof HTMLStyleElement)
240 | return;
241 | if (node instanceof HTMLElement && node.title !== '')
242 | list.title.add(node);
243 | if (node instanceof HTMLInputElement && ['button', 'reset', 'submit'].includes(node.type) && node.value !== '')
244 | list.value.add(node);
245 | else if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement && node.placeholder !== '')
246 | list.placeholder.add(node);
247 | else if (node instanceof Text)
248 | list.data.add(node);
249 | });
250 | return list;
251 | }
252 | nodeForEach(node) {
253 | const list = [];
254 | list.push(node);
255 | if (node.hasChildNodes())
256 | node.childNodes.forEach(child => list.push(...this.nodeForEach(child)));
257 | return list;
258 | }
259 | }
260 |
261 | new ReplaceText(zh_Hans, 'regexp');
--------------------------------------------------------------------------------
/icomoonio-clearAll.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name icomoon.io 一键删除所有集合
3 | // @namespace https://github.com/dlzmoe/scripts
4 | // @version 0.1
5 | // @description 添加一个按钮,点击时触发所有ng-click="removeSet($index)"按钮
6 | // @author dlzmoe
7 | // @match *://icomoon.io/*
8 | // @grant none
9 | // @license MIT
10 | // ==/UserScript==
11 |
12 | (function() {
13 | 'use strict';
14 |
15 | // 创建一个按钮
16 | const triggerButton = document.createElement('button');
17 | triggerButton.textContent = '删除所有集合';
18 | triggerButton.style.position = 'fixed';
19 | triggerButton.style.top = '60px';
20 | triggerButton.style.right = '10px';
21 | triggerButton.style.zIndex = '9999';
22 | triggerButton.style.padding = '8px 12px';
23 | triggerButton.style.backgroundColor = '#f44336';
24 | triggerButton.style.color = 'white';
25 | triggerButton.style.border = 'none';
26 | triggerButton.style.borderRadius = '4px';
27 | triggerButton.style.cursor = 'pointer';
28 | triggerButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';
29 |
30 | // 鼠标悬停效果
31 | triggerButton.addEventListener('mouseover', function() {
32 | this.style.backgroundColor = '#d32f2f';
33 | });
34 |
35 | triggerButton.addEventListener('mouseout', function() {
36 | this.style.backgroundColor = '#f44336';
37 | });
38 |
39 | // 创建一个临时通知弹窗的函数
40 | function showNotification(message, duration = 2000) {
41 | const notification = document.createElement('div');
42 | notification.textContent = message;
43 | notification.style.position = 'fixed';
44 | notification.style.top = '40px';
45 | notification.style.left = '50%';
46 | notification.style.transform = 'translateX(-50%)';
47 | notification.style.backgroundColor = '#4CAF50';
48 | notification.style.color = 'white';
49 | notification.style.padding = '12px 20px';
50 | notification.style.borderRadius = '4px';
51 | notification.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';
52 | notification.style.zIndex = '10000';
53 | notification.style.transition = 'opacity 0.3s ease-in-out';
54 |
55 | document.body.appendChild(notification);
56 |
57 | setTimeout(() => {
58 | notification.style.opacity = '0';
59 | setTimeout(() => {
60 | document.body.removeChild(notification);
61 | }, 300);
62 | }, duration);
63 | }
64 |
65 | // 点击事件
66 | triggerButton.addEventListener('click', function() {
67 | // 获取所有符合条件的按钮
68 | const buttons = document.querySelectorAll('button[ng-click="removeSet($index)"]');
69 |
70 | if (buttons.length === 0) {
71 | showNotification(`未找到任何"removeSet($index)"按钮!`);
72 | return;
73 | }
74 |
75 | // 确认操作
76 | if (confirm(`确定要触发全部 ${buttons.length} 个删除按钮吗?`)) {
77 | // 遍历并点击每个按钮
78 | buttons.forEach(button => {
79 | button.click();
80 | });
81 | // 使用自定义通知代替alert
82 | showNotification(`成功触发了 ${buttons.length} 个删除按钮!`);
83 | }
84 | });
85 |
86 | // 将按钮添加到页面
87 | document.body.appendChild(triggerButton);
88 | })();
89 |
--------------------------------------------------------------------------------
/lobechat-webdav/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/lobechat-webdav/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/lobechat-webdav/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/lobechat-webdav/README.md:
--------------------------------------------------------------------------------
1 | ## lobechat-webdav
2 |
3 | 给 lobechat 程序添加 webdav 同步的功能。
--------------------------------------------------------------------------------
/lobechat-webdav/dist/lobechat-webdav.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Lobechat Webdav 同步功能
3 | // @namespace https://github.com/dlzmoe/UserScript
4 | // @version 0.0.9
5 | // @author dlzmoe
6 | // @description 给 lobechat 程序添加 webdav 同步的功能。
7 | // @license Apache-2.0
8 | // @icon https://chat.oaipro.com/favicon-32x32.ico
9 | // @match *://chat.oaipro.com/*
10 | // @match *://chat-preview.lobehub.com/*
11 | // @match *://lobechat.zishu.me/*
12 | // @require https://unpkg.com/vue@3.4.38/dist/vue.global.prod.js
13 | // @grant GM_addStyle
14 | // @grant GM_xmlhttpRequest
15 | // ==/UserScript==
16 |
17 | (e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const o=document.createElement("style");o.textContent=e,document.head.append(o)})(" .lobewebdav{position:fixed;left:10px;bottom:100px;z-index:100}.lobewebdav .lobewebdav-dialog{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:600px;height:400px;overflow-y:scroll;padding:30px;border-radius:20px;background:#fff;box-shadow:1px 5px 10px #0003;color:#333}.lobewebdav .lobewebdav-dialog .close{position:absolute;right:20px;top:30px;cursor:pointer;transition:all .2s linear}.lobewebdav .lobewebdav-dialog .close:hover{color:#666}.lobewebdav .lobewebdav-dialog h2{margin-bottom:20px}.lobewebdav .lobewebdav-dialog .item{display:flex;align-items:center;margin-top:1em}.lobewebdav .lobewebdav-dialog .item label{width:120px;text-align:right;white-space:nowrap}.lobewebdav .lobewebdav-dialog .item input{flex:1;border-radius:4px;height:28px;border:1px solid #999;transition:all .1s linear;padding:0 10px;background:#fff;color:#333}.lobewebdav .lobewebdav-dialog .item input:focus{border-color:#666}.lobewebdav .lobewebdav-dialog button{outline:none;border:none;border-radius:5px;background:#333;color:#fff;height:30px;padding:0 15px;transition:all .1s linear;cursor:pointer}.lobewebdav .lobewebdav-dialog button+button{margin-left:10px}.lobewebdav .lobewebdav-dialog button:hover{background:#666} ");
18 |
19 | (function (vue) {
20 | 'use strict';
21 |
22 | const name = "lobechat-webdav";
23 | const version = "0.0.9";
24 | const author = "dlzmoe";
25 | const description = "Add webdav synchronization function to lobechat program.";
26 | const type = "module";
27 | const license = "Apache-2.0";
28 | const scripts = {
29 | dev: "vite --mode development",
30 | build: "vite build",
31 | preview: "vite preview"
32 | };
33 | const dependencies = {
34 | vue: "^3.4.27",
35 | webdav: "^5.7.1"
36 | };
37 | const devDependencies = {
38 | "@vitejs/plugin-vue": "^5.0.4",
39 | less: "^4.1.0",
40 | "less-loader": "^8.0.0",
41 | "style-loader": "^2.0.0",
42 | vite: "^5.2.12",
43 | "vite-plugin-monkey": "^4.0.0"
44 | };
45 | const packageJson = {
46 | name,
47 | version,
48 | author,
49 | description,
50 | type,
51 | license,
52 | scripts,
53 | dependencies,
54 | devDependencies
55 | };
56 | const _export_sfc = (sfc, props) => {
57 | const target = sfc.__vccOpts || sfc;
58 | for (const [key, val] of props) {
59 | target[key] = val;
60 | }
61 | return target;
62 | };
63 | const _sfc_main = {
64 | data() {
65 | return {
66 | open: false,
67 | exportData: {},
68 | importData: {},
69 | webdav: {
70 | baseurl: "",
71 | username: "",
72 | password: ""
73 | },
74 | msg: ""
75 | };
76 | },
77 | methods: {
78 | // 打开弹窗
79 | opendialog() {
80 | this.open = !this.open;
81 | },
82 | // 保存密码
83 | savewebdav() {
84 | localStorage.setItem("lobechat-webdav", JSON.stringify(this.webdav));
85 | this.msg = "WebDav 密码已保存!";
86 | },
87 | // 获取 lobechat 数据生成 json
88 | getIndexedDB() {
89 | const dbName = "LOBE_CHAT_DB";
90 | const storeNames = ["messages", "sessionGroups", "sessions", "topics", "users"];
91 | let request = indexedDB.open(dbName);
92 | request.onsuccess = (event) => {
93 | const db = event.target.result;
94 | let state = {
95 | messages: [],
96 | sessionGroups: [],
97 | sessions: [],
98 | topics: [],
99 | users: []
100 | };
101 | let pendingStores = 0;
102 | storeNames.forEach((storeName) => {
103 | if (db.objectStoreNames.contains(storeName)) {
104 | pendingStores++;
105 | const transaction = db.transaction([storeName], "readonly");
106 | const objectStore = transaction.objectStore(storeName);
107 | const allRecords = objectStore.getAll();
108 | allRecords.onsuccess = (event2) => {
109 | const result = event2.target.result;
110 | state[storeName] = result;
111 | pendingStores--;
112 | if (pendingStores === 0) {
113 | this.exportData = JSON.stringify({
114 | exportType: "all",
115 | state,
116 | version: 7
117 | });
118 | }
119 | };
120 | allRecords.onerror = (event2) => {
121 | console.error(`Error fetching data from ${storeName}:`, event2);
122 | };
123 | } else {
124 | console.warn(`Object store ${storeName} not found in database ${dbName}`);
125 | }
126 | });
127 | if (pendingStores === 0) {
128 | console.log("No valid object stores found in the database.");
129 | }
130 | };
131 | request.onerror = (event) => {
132 | console.error("Error opening database:", event);
133 | };
134 | },
135 | // 检查文件夹是否存在
136 | checkFolderExists(folderUrl) {
137 | return new Promise((resolve, reject) => {
138 | GM_xmlhttpRequest({
139 | method: "PROPFIND",
140 | url: folderUrl,
141 | headers: {
142 | Authorization: "Basic " + btoa(`${this.webdav.username}:${this.webdav.password}`),
143 | Depth: "1"
144 | // 只检查一层
145 | },
146 | onload: function(response) {
147 | if (response.status === 207) {
148 | resolve(true);
149 | } else if (response.status === 404) {
150 | resolve(false);
151 | } else {
152 | reject(new Error(`Error checking folder: ${response.statusText}`));
153 | }
154 | },
155 | onerror: function(error) {
156 | reject(error);
157 | }
158 | });
159 | });
160 | },
161 | // 创建文件夹
162 | createFolder(folderUrl) {
163 | return new Promise((resolve, reject) => {
164 | GM_xmlhttpRequest({
165 | method: "MKCOL",
166 | url: folderUrl,
167 | headers: {
168 | Authorization: "Basic " + btoa(`${this.webdav.username}:${this.webdav.password}`)
169 | },
170 | onload: function(response) {
171 | if (response.status === 201) {
172 | resolve(true);
173 | } else {
174 | reject(new Error(`Error creating folder: ${response.statusText}`));
175 | }
176 | },
177 | onerror: function(error) {
178 | reject(error);
179 | }
180 | });
181 | });
182 | },
183 | // 检查并创建文件夹
184 | async checkAndCreateFolder() {
185 | this.getIndexedDB();
186 | const folderUrl = `${this.webdav.baseurl}lobechat-webdav-backup/`;
187 | try {
188 | const exists = await this.checkFolderExists(folderUrl);
189 | if (!exists) {
190 | await this.createFolder(folderUrl);
191 | console.log("Folder 'lobechat-webdav-backup' created successfully.");
192 | } else {
193 | console.log("Folder 'lobechat-webdav-backup' already exists.");
194 | }
195 | const data = this.exportData;
196 | if (!data) {
197 | console.error("Export data is not initialized properly.");
198 | return;
199 | }
200 | const uploadUrl = `${this.webdav.baseurl}lobechat-webdav-backup/data.json`;
201 | try {
202 | const uploadResponse = await this.uploadFile(uploadUrl, data);
203 | this.msg = "同步到云端成功!3秒后清空";
204 | setTimeout(() => {
205 | this.msg = "";
206 | }, 3e3);
207 | } catch (error) {
208 | console.error("Upload failed:", error);
209 | this.msg = "同步失败!";
210 | setTimeout(() => {
211 | this.msg = "";
212 | }, 3e3);
213 | }
214 | } catch (error) {
215 | console.error(error);
216 | }
217 | },
218 | uploadFile(url, fileData) {
219 | return new Promise((resolve, reject) => {
220 | GM_xmlhttpRequest({
221 | method: "PUT",
222 | url,
223 | data: fileData,
224 | headers: {
225 | "Content-Type": "text/plain",
226 | Authorization: "Basic " + btoa(`${this.webdav.username}:${this.webdav.password}`)
227 | },
228 | onload: function(response) {
229 | if (response.status >= 200 && response.status < 300) {
230 | resolve(response);
231 | } else {
232 | reject(new Error(`Upload failed: ${response.statusText}`));
233 | }
234 | },
235 | onerror: function(error) {
236 | reject(error);
237 | }
238 | });
239 | });
240 | },
241 | downloadFile(url) {
242 | return new Promise((resolve, reject) => {
243 | GM_xmlhttpRequest({
244 | method: "GET",
245 | url,
246 | headers: {
247 | Authorization: "Basic " + btoa(`${this.webdav.username}:${this.webdav.password}`)
248 | },
249 | onload: function(response) {
250 | if (response.status >= 200 && response.status < 300) {
251 | resolve(response.responseText);
252 | } else {
253 | reject(new Error(`Download failed: ${response.statusText}`));
254 | }
255 | },
256 | onerror: function(error) {
257 | reject(error);
258 | }
259 | });
260 | });
261 | },
262 | // 上传
263 | async uploadSampleFile() {
264 | this.checkAndCreateFolder();
265 | },
266 | // 下载
267 | async downloadSampleFile() {
268 | const downloadUrl = `${this.webdav.baseurl}lobechat-webdav-backup/data.json`;
269 | try {
270 | const downloadResponse = await this.downloadFile(downloadUrl);
271 | const importData = JSON.parse(downloadResponse);
272 | console.log(importData);
273 | this.msg = "下载成功,即将同步数据,请勿操作页面!";
274 | const dbName = "LOBE_CHAT_DB";
275 | const storeNames = ["messages", "sessionGroups", "sessions", "topics", "users"];
276 | let request = indexedDB.open(dbName);
277 | request.onsuccess = function(event) {
278 | const db = event.target.result;
279 | const state = importData.state;
280 | console.log(importData);
281 | storeNames.forEach((storeName) => {
282 | if (db.objectStoreNames.contains(storeName)) {
283 | const transaction = db.transaction([storeName], "readwrite");
284 | const objectStore = transaction.objectStore(storeName);
285 | const clearRequest = objectStore.clear();
286 | clearRequest.onsuccess = function() {
287 | console.log(`${storeName} store cleared.`);
288 | const data = state[storeName];
289 | if (Array.isArray(data)) {
290 | data.forEach((item) => {
291 | const addRequest = objectStore.add(item);
292 | addRequest.onsuccess = function() {
293 | console.log(`Item added to ${storeName} store.`);
294 | };
295 | addRequest.onerror = function(event2) {
296 | console.error(`Error adding item to ${storeName}:`, event2);
297 | };
298 | });
299 | }
300 | };
301 | clearRequest.onerror = function(event2) {
302 | console.error(`Error clearing ${storeName} store:`, event2);
303 | };
304 | } else {
305 | console.warn(`Object store ${storeName} not found in database ${dbName}`);
306 | }
307 | });
308 | };
309 | setTimeout(() => {
310 | this.msg = "同步完成,请刷新页面!";
311 | location.reload();
312 | }, 2e3);
313 | request.onerror = function(event) {
314 | console.error("Error opening database:", event);
315 | };
316 | } catch (error) {
317 | console.error(error);
318 | this.msg = "下载失败,请检查是否存在备份!";
319 | }
320 | }
321 | },
322 | created() {
323 | const lobechat_webdav = JSON.parse(localStorage.getItem("lobechat-webdav"));
324 | if (lobechat_webdav) {
325 | this.webdav = lobechat_webdav;
326 | }
327 | console.log(
328 | `%c ${packageJson.name} %c 已开启 `,
329 | "padding: 2px 1px; color: #fff; background: #606060;",
330 | "padding: 2px 1px; color: #fff; background: #42c02e;"
331 | );
332 | }
333 | };
334 | const _hoisted_1 = { class: "lobewebdav" };
335 | const _hoisted_2 = /* @__PURE__ */ vue.createElementVNode("div", {
336 | style: { "border-radius": "8px", "height": "44px", "width": "44px" },
337 | class: "layoutkit-flexbox css-5wokcq acss-1rzhzi1"
338 | }, [
339 | /* @__PURE__ */ vue.createElementVNode("span", {
340 | class: "anticon acss-17q14cp",
341 | role: "img"
342 | }, [
343 | /* @__PURE__ */ vue.createElementVNode("svg", {
344 | xmlns: "http://www.w3.org/2000/svg",
345 | width: "24",
346 | height: "24",
347 | viewBox: "0 0 24 24",
348 | fill: "none",
349 | stroke: "currentColor",
350 | "stroke-width": "2",
351 | "stroke-linecap": "round",
352 | "stroke-linejoin": "round",
353 | class: "icon icon-tabler icons-tabler-outline icon-tabler-brand-webflow"
354 | }, [
355 | /* @__PURE__ */ vue.createElementVNode("path", {
356 | stroke: "none",
357 | d: "M0 0h24v24H0z",
358 | fill: "none"
359 | }),
360 | /* @__PURE__ */ vue.createElementVNode("path", { d: "M17 10s-1.376 3.606 -1.5 4c-.046 -.4 -1.5 -8 -1.5 -8c-2.627 0 -3.766 1.562 -4.5 3.5c0 0 -1.843 4.593 -2 5c-.013 -.368 -.5 -4.5 -.5 -4.5c-.15 -2.371 -2.211 -3.98 -4 -3.98l2 12.98c2.745 -.013 4.72 -1.562 5.5 -3.5c0 0 1.44 -4.3 1.5 -4.5c.013 .18 1 8 1 8c2.758 0 4.694 -1.626 5.5 -3.5l3.5 -9.5c-2.732 0 -4.253 2.055 -5 4z" })
361 | ])
362 | ])
363 | ], -1);
364 | const _hoisted_3 = [
365 | _hoisted_2
366 | ];
367 | const _hoisted_4 = { class: "lobewebdav-dialog" };
368 | const _hoisted_5 = /* @__PURE__ */ vue.createElementVNode("svg", {
369 | xmlns: "http://www.w3.org/2000/svg",
370 | width: "24",
371 | height: "24",
372 | viewBox: "0 0 24 24",
373 | fill: "none",
374 | stroke: "currentColor",
375 | "stroke-width": "2",
376 | "stroke-linecap": "round",
377 | "stroke-linejoin": "round",
378 | class: "icon icon-tabler icons-tabler-outline icon-tabler-x"
379 | }, [
380 | /* @__PURE__ */ vue.createElementVNode("path", {
381 | stroke: "none",
382 | d: "M0 0h24v24H0z",
383 | fill: "none"
384 | }),
385 | /* @__PURE__ */ vue.createElementVNode("path", { d: "M18 6l-12 12" }),
386 | /* @__PURE__ */ vue.createElementVNode("path", { d: "M6 6l12 12" })
387 | ], -1);
388 | const _hoisted_6 = [
389 | _hoisted_5
390 | ];
391 | const _hoisted_7 = /* @__PURE__ */ vue.createElementVNode("h2", null, "同步 Lobechat 数据到 WebDav", -1);
392 | const _hoisted_8 = { class: "item" };
393 | const _hoisted_9 = /* @__PURE__ */ vue.createElementVNode("label", null, "WebDav 地址:", -1);
394 | const _hoisted_10 = { class: "item" };
395 | const _hoisted_11 = /* @__PURE__ */ vue.createElementVNode("label", null, "WebDav 用户名:", -1);
396 | const _hoisted_12 = { class: "item" };
397 | const _hoisted_13 = /* @__PURE__ */ vue.createElementVNode("label", null, "WebDav 密码:", -1);
398 | const _hoisted_14 = { class: "item" };
399 | const _hoisted_15 = { class: "item" };
400 | const _hoisted_16 = { class: "item" };
401 | const _hoisted_17 = { class: "msg" };
402 | function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
403 | return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
404 | vue.createElementVNode("a", {
405 | "aria-label": "webdav",
406 | onClick: _cache[0] || (_cache[0] = (...args) => $options.opendialog && $options.opendialog(...args)),
407 | href: "javascript:void(0)"
408 | }, _hoisted_3),
409 | vue.withDirectives(vue.createElementVNode("div", _hoisted_4, [
410 | vue.createElementVNode("div", {
411 | class: "close",
412 | onClick: _cache[1] || (_cache[1] = ($event) => this.open = false)
413 | }, _hoisted_6),
414 | _hoisted_7,
415 | vue.createElementVNode("div", _hoisted_8, [
416 | _hoisted_9,
417 | vue.withDirectives(vue.createElementVNode("input", {
418 | type: "text",
419 | "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.webdav.baseurl = $event),
420 | placeholder: "https://xxx.com/dav/"
421 | }, null, 512), [
422 | [vue.vModelText, $data.webdav.baseurl]
423 | ])
424 | ]),
425 | vue.createElementVNode("div", _hoisted_10, [
426 | _hoisted_11,
427 | vue.withDirectives(vue.createElementVNode("input", {
428 | type: "text",
429 | "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.webdav.username = $event)
430 | }, null, 512), [
431 | [vue.vModelText, $data.webdav.username]
432 | ])
433 | ]),
434 | vue.createElementVNode("div", _hoisted_12, [
435 | _hoisted_13,
436 | vue.withDirectives(vue.createElementVNode("input", {
437 | type: "password",
438 | "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.webdav.password = $event)
439 | }, null, 512), [
440 | [vue.vModelText, $data.webdav.password]
441 | ])
442 | ]),
443 | vue.createElementVNode("div", _hoisted_14, [
444 | vue.createElementVNode("button", {
445 | onClick: _cache[5] || (_cache[5] = (...args) => $options.savewebdav && $options.savewebdav(...args))
446 | }, "保存密码")
447 | ]),
448 | vue.createElementVNode("div", _hoisted_15, [
449 | vue.createElementVNode("button", {
450 | onClick: _cache[6] || (_cache[6] = (...args) => $options.uploadSampleFile && $options.uploadSampleFile(...args))
451 | }, "同步到云端"),
452 | vue.createElementVNode("button", {
453 | onClick: _cache[7] || (_cache[7] = (...args) => $options.downloadSampleFile && $options.downloadSampleFile(...args))
454 | }, "下载到本地")
455 | ]),
456 | vue.createElementVNode("div", _hoisted_16, [
457 | vue.createElementVNode("div", _hoisted_17, vue.toDisplayString($data.msg), 1)
458 | ])
459 | ], 512), [
460 | [vue.vShow, $data.open]
461 | ])
462 | ]);
463 | }
464 | const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
465 | const app = vue.createApp(App);
466 | app.mount(
467 | (() => {
468 | const appDiv = document.createElement("div");
469 | document.body.append(appDiv);
470 | return appDiv;
471 | })()
472 | );
473 |
474 | })(Vue);
--------------------------------------------------------------------------------
/lobechat-webdav/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlzmoe/UserScript/2b8dbbe485a9e6e7ee99fbabb38af80f6ce1352f/lobechat-webdav/index.html
--------------------------------------------------------------------------------
/lobechat-webdav/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lobechat-webdav",
3 | "version": "0.0.9",
4 | "author": "dlzmoe",
5 | "description": "Add webdav synchronization function to lobechat program.",
6 | "type": "module",
7 | "license": "Apache-2.0",
8 | "scripts": {
9 | "dev": "vite --mode development",
10 | "build": "vite build",
11 | "preview": "vite preview"
12 | },
13 | "dependencies": {
14 | "vue": "^3.4.27",
15 | "webdav": "^5.7.1"
16 | },
17 | "devDependencies": {
18 | "@vitejs/plugin-vue": "^5.0.4",
19 | "less": "^4.1.0",
20 | "less-loader": "^8.0.0",
21 | "style-loader": "^2.0.0",
22 | "vite": "^5.2.12",
23 | "vite-plugin-monkey": "^4.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lobechat-webdav/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
73 |
74 |
75 |
396 |
--------------------------------------------------------------------------------
/lobechat-webdav/src/assets/app.less:
--------------------------------------------------------------------------------
1 | .lobewebdav {
2 | position: fixed;
3 | left: 10px;
4 | bottom: 100px;
5 | z-index: 100;
6 |
7 | .lobewebdav-dialog {
8 | position: fixed;
9 | left: 50%;
10 | top: 50%;
11 | transform: translate(-50%, -50%);
12 | width: 600px;
13 | height: 400px;
14 | overflow-y: scroll;
15 | padding: 30px;
16 | border-radius: 20px;
17 | background: #fff;
18 | box-shadow: 1px 5px 10px rgba(0, 0, 0, 0.2);
19 | color: #333;
20 |
21 | .close {
22 | position: absolute;
23 | right: 20px;
24 | top: 30px;
25 | cursor: pointer;
26 | transition: all 0.2s linear;
27 |
28 | &:hover {
29 | color: #666;
30 | }
31 | }
32 |
33 | h2 {
34 | margin-bottom: 20px;
35 | }
36 |
37 | .item {
38 | display: flex;
39 | align-items: center;
40 | margin-top: 1em;
41 |
42 | label {
43 | width: 120px;
44 | text-align: right;
45 | white-space: nowrap;
46 | }
47 |
48 | input {
49 | flex: 1;
50 | border-radius: 4px;
51 | height: 28px;
52 | border: 1px solid #999;
53 | transition: all 0.1s linear;
54 | padding: 0 10px;
55 | background: #fff;
56 | color: #333;
57 |
58 | &:focus {
59 | border-color: #666;
60 | }
61 | }
62 | }
63 |
64 | button {
65 | outline: none;
66 | border: none;
67 | border-radius: 5px;
68 | background: #333;
69 | color: #fff;
70 | height: 30px;
71 | padding: 0 15px;
72 | transition: all 0.1s linear;
73 | cursor: pointer;
74 |
75 | &+button {
76 | margin-left: 10px;
77 | }
78 |
79 | &:hover {
80 | background: #666;
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/lobechat-webdav/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './app.vue';
3 | const app = createApp(App);
4 |
5 | import "./assets/app.less";
6 |
7 | app.mount(
8 | (() => {
9 | const appDiv = document.createElement('div');
10 | document.body.append(appDiv);
11 | return appDiv;
12 | })(),
13 | );
--------------------------------------------------------------------------------
/lobechat-webdav/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ////
4 |
--------------------------------------------------------------------------------
/lobechat-webdav/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 | import monkey, { cdn } from 'vite-plugin-monkey';
4 | import pkg from './package.json';
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [
9 | vue(),
10 | monkey({
11 | entry: 'src/main.js',
12 | userscript: {
13 | icon: 'https://chat.oaipro.com/favicon-32x32.ico',
14 | name: "Lobechat Webdav 同步功能",
15 | namespace: 'https://github.com/dlzmoe/UserScript',
16 | description: "给 lobechat 程序添加 webdav 同步的功能。",
17 | version: pkg.version,
18 | match: [
19 | '*://chat.oaipro.com/*',
20 | '*://chat-preview.lobehub.com/*',
21 | '*://lobechat.zishu.me/*',
22 | ],
23 | },
24 | build: {
25 | externalGlobals: {
26 | // require 引入
27 | vue: cdn.unpkg('Vue', 'dist/vue.global.prod.js'),
28 | },
29 | minify: false, // 不混淆
30 | },
31 | }),
32 | ],
33 | });
34 |
--------------------------------------------------------------------------------
/netlify-zhcn/greasyfork.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Netlify 汉化脚本
3 | // @namespace https://github.com/dlzmoe/scripts
4 | // @version 0.0.1
5 | // @author dlzmoe
6 | // @description 由于官方不支持中文,汉化 Netlify 大部分的翻译
7 | // @include *://*.netlify.com/*
8 | // @license Apache-2.0 license
9 | // @icon https://app.netlify.com/favicon-48x48.png
10 | // @grant none
11 | // @run-at document-start
12 | // @downloadURL https://update.greasyfork.org/scripts/484197/Netlify%20%E6%B1%89%E5%8C%96%E8%84%9A%E6%9C%AC.user.js
13 | // @updateURL https://update.greasyfork.org/scripts/484197/Netlify%20%E6%B1%89%E5%8C%96%E8%84%9A%E6%9C%AC.meta.js
14 | // ==/UserScript==
15 |
16 | const zh_Hans = [
17 | ['Team overview', '团队概况'],
18 | ['Sites', '站点'],
19 | ['Builds', '构建'],
20 | ['Integrations', '集成'],
21 | ['Domains', '域名'],
22 | ['Members', '成员'],
23 | ['Audit log', '审核日志'],
24 | ['Security Scorecard', '安全评分'],
25 | ['Billing', '计费'],
26 | ['Team settings', '团队设置'],
27 | ['Upgrade', '升级'],
28 | ['Bandwidth', '带宽'],
29 | ['Build minutes', '构建时间'],
30 | ['Concurrent builds', '构建并发'],
31 | ['Team members', '团队成员'],
32 | ['Site overview', '概览'],
33 | ['Site configuration', '配置'],
34 | ['Deploys', '部署'],
35 | ['Logs', '日志'],
36 | ['Metrics', '指标'],
37 | ['Domain management', '域名管理'],
38 | ['Forms', '形式'],
39 | ['Favorite site', '收藏站点'],
40 | ['Unfavorite site', '取消收藏'],
41 | ['General', '常规'],
42 | ['Site details', '站点详情'],
43 | ['Status badges', '状态徽章'],
44 | ['Site members', '网站会员'],
45 | ['Danger zone', '危险操作'],
46 | ['Site information', '站点信息'],
47 | ['Site name', '站点名称'],
48 | ['Owner', '所有人'],
49 | ['Site ID', '站点 ID'],
50 | ['Created', '创建时间'],
51 | ['Last update', '最后更新'],
52 | ['Change site name', '更改名称'],
53 | ['Add-ons', '附加组件'],
54 | ['This site is not using any add-ons', '该网站未使用任何附加组件'],
55 | ['Take your static site further with rich add-ons built right into your dashboard. Automatically upgrade tiers as your usage grows, paying only for what you use.', '通过仪表板中内置的丰富附加组件进一步提升您的静态网站。随着使用量的增长自动升级等级,只需按使用量付费。'],
56 | ['Deploy status badge', '部署状态徽章'],
57 | ['Team: ', '团队:'],
58 | ['Build & deploy', '构建和部署'],
59 | ['Post processing', '后期处理'],
60 | ['Split Testing', '对比测试'],
61 | ['Deploy notifications', '部署通知'],
62 | ['Environment variables', '环境变量'],
63 | ['Notifications', '通知'],
64 | ['Identity', '身份'],
65 | ['Access & security', '访问和安全'],
66 | ['Continuous deployment', '持续部署'],
67 | ['Manage repository', '管理存储库'],
68 | ['Build settings', '构建设置'],
69 | ['Runtime', '运行'],
70 | ['Base directory', '基本目录'],
71 | ['Package directory', '包目录'],
72 | ['Build command', '构建命令'],
73 | ['Publish directory', '发布目录'],
74 | ['Functions directory', '函数目录'],
75 | ['Build status', '构建状态'],
76 | ['Configure', '修改'],
77 | ['Functions region', '功能区'],
78 | ['Configure how functions are deployed for your site.', '配置如何为您的站点部署功能。'],
79 | ['Region', '地区'],
80 | ['Dependency management', '依赖管理'],
81 | ['Manage the software and tool versions installed in the build environment for your site.', '管理站点构建环境中安装的软件和工具版本。'],
82 | ['Branches and deploy contexts', '分支和部署上下文'],
83 | ['Deploy contexts are branch-based environments that enable you to configure builds depending on the context. This includes production and preview environments.', '部署上下文是基于分支的环境,使您能够根据上下文配置构建。这包括生产和预览环境。'],
84 | ['Production branch', '生产分支'],
85 | ['Branch deploys', '分支部署'],
86 | ['Deploy Previews', '部署预览'],
87 | ['Collaboration tools', '协同工具'],
88 | ['Build hooks', '构建 hooks'],
89 | ['Deploy key', '部署密钥'],
90 | ['Build image selection ', '构建图像选择'],
91 | ['Automatic deploy deletion', '自动部署删除'],
92 | ['Add a variable', '新增变量'],
93 | ['New environment variable', '新环境变量'],
94 | ['Scopes', '范围'],
95 | ['All scopes', '全部范围'],
96 | ['Specific scopes', '具体范围'],
97 | ['Limit this environment variable to specific scopes, such as builds, functions, or post processing', '将此环境变量限制为特定范围,例如构建、函数或后处理'],
98 | ['Upgrade to unlock', '升级解锁'],
99 | ['Create variable', '新增变量'],
100 | ['Cancel', '取消'],
101 | ['Docs', '文档'],
102 | ['Pricing', '价格'],
103 | ['Support', '支持'],
104 | ['Blog', '博客'],
105 | ['Changelog', '变更日志'],
106 | ['Terms', '条款'],
107 | ['Add a single variable', '新增一个变量'],
108 | ['Import from a .env file', '导入 .env 文件'],
109 | ['Environment variables allow you to change site behavior across different deploy contexts and scopes. For example, use variables to set different configuration options for builds or to store secret API keys for use in your functions.', '环境变量允许您跨不同的部署上下文和范围更改站点行为。例如,使用变量为构建设置不同的配置选项或存储秘密 API 密钥以供在函数中使用。'],
110 | ['Deploy settings', '部署设置'],
111 | ['Lock to stop auto publishing', '锁定并停止发布'],
112 | ['Options', '选项'],
113 | ['Retry with latest branch commit', '重新部署'],
114 | ['Clear cache and retry with latest branch commit', '清除缓存并重新部署'],
115 | ['Repository', '存储库'],
116 | ['Your site is linked to a Git repository for continuous deployment.', '您的站点链接到 Git 存储库以进行持续部署。'],
117 | ['Current repository', '当前存储库'],
118 | ['Production domains', '生产环境'],
119 | ['Your site is always accessible at a netlify.app subdomain based on the site name. Custom domains allow visitors to access your site at your own domains.', '您的网站始终可以根据网站名称通过 netlify.app 子域进行访问。自定义域允许访问者通过您自己的域访问您的网站。'],
120 | ['Add domain alias', '新增自定义域名'],
121 | ['Visual editor dashboard', '可视化编辑器仪表板'],
122 | ['Extensions', '扩展'],
123 | ];
124 |
125 | class ReplaceText {
126 | constructor(i18n, mode = 'equal') {
127 | this.W = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;
128 | this.done = new Set();
129 | this.alert = this.W.alert.bind(this.W);
130 | this.confirm = this.W.confirm.bind(this.W);
131 | this.prompt = this.W.prompt.bind(this.W);
132 | const i18nMap = new Map(i18n);
133 | const i18nArr = i18n.map(value => value[0]);
134 | if (mode === 'regexp') {
135 | this.textReplace = (text) => {
136 | if (i18nMap.has(text))
137 | text = i18nMap.get(text);
138 | else {
139 | const key = i18nArr.find(key => (key instanceof RegExp && text.match(key) !== null));
140 | if (key !== undefined)
141 | text = text.replace(key, i18nMap.get(key));
142 | }
143 | return text;
144 | };
145 | } else if (mode === 'match') {
146 | this.textReplace = (text) => {
147 | const key = i18nArr.find(key => (text.match(key) !== null));
148 | if (key !== undefined)
149 | text = text.replace(key, i18nMap.get(key));
150 | return text;
151 | };
152 | } else {
153 | this.textReplace = (text) => {
154 | if (i18nMap.has(text))
155 | text = i18nMap.get(text);
156 | return text;
157 | };
158 | }
159 | this.replaceAlert();
160 | this.replaceObserver();
161 | }
162 | replaceAlert() {
163 | this.W.alert = (message) => this.alert(this.textReplace(message));
164 | this.W.confirm = (message) => this.confirm(this.textReplace(message));
165 | this.W.prompt = (message, _default) => this.prompt(this.textReplace(message), _default);
166 | }
167 | replaceNode(node, self = false) {
168 | const list = this.getReplaceList(node, self);
169 | for (let index in list) {
170 | list[index].forEach(node => {
171 | if (this.done.has(node[index]))
172 | return;
173 | const newText = this.textReplace(node[index]);
174 | if (node[index] !== newText) {
175 | this.done.add(newText);
176 | node[index] = newText;
177 | }
178 | });
179 | }
180 | }
181 | replaceObserver() {
182 | const bodyObserver = new MutationObserver(mutations => {
183 | mutations.forEach(mutation => {
184 | if (mutation.type === 'attributes' || mutation.type === 'characterData')
185 | this.replaceNode(mutation.target, true);
186 | else if (mutation.type === 'childList') {
187 | mutation.addedNodes.forEach(addedNode => this.replaceNode(addedNode));
188 | }
189 | });
190 | });
191 | document.addEventListener('readystatechange', () => {
192 | bodyObserver.observe(document.body, {
193 | attributes: true,
194 | characterData: true,
195 | childList: true,
196 | subtree: true
197 | });
198 | this.replaceNode(document.body);
199 | }, {
200 | capture: true,
201 | once: true
202 | });
203 | }
204 | getReplaceList(node, self = false) {
205 | const list = {
206 | data: new Set(),
207 | placeholder: new Set(),
208 | title: new Set(),
209 | value: new Set(),
210 | };
211 | const nodeList = self ? [node] : this.nodeForEach(node);
212 | nodeList.forEach(node => {
213 | if (node.parentElement instanceof HTMLScriptElement || node.parentElement instanceof HTMLStyleElement)
214 | return;
215 | if (node instanceof HTMLElement && node.title !== '')
216 | list.title.add(node);
217 | if (node instanceof HTMLInputElement && ['button', 'reset', 'submit'].includes(node.type) && node.value !== '')
218 | list.value.add(node);
219 | else if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement && node.placeholder !== '')
220 | list.placeholder.add(node);
221 | else if (node instanceof Text)
222 | list.data.add(node);
223 | });
224 | return list;
225 | }
226 | nodeForEach(node) {
227 | const list = [];
228 | list.push(node);
229 | if (node.hasChildNodes())
230 | node.childNodes.forEach(child => list.push(...this.nodeForEach(child)));
231 | return list;
232 | }
233 | }
234 |
235 | new ReplaceText(zh_Hans, 'regexp');
--------------------------------------------------------------------------------
/nextchat-themes/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/nextchat-themes/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/nextchat-themes/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/nextchat-themes/README.md:
--------------------------------------------------------------------------------
1 | ## nextchat-themes
2 |
3 | NextChat 插件,修改 UI 主题!
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/nextchat-themes/dist/nextchat-themes.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name nextchat-themes
3 | // @namespace https://github.com/dlzmoe/UserScript
4 | // @version 0.0.5
5 | // @author dlzmoe
6 | // @description NextChat 插件,修改 UI 主题!
7 | // @license Apache-2.0
8 | // @icon https://framerusercontent.com/images/tCHbBovHGLAJDNKRG1lKfavenFs.png
9 | // @match *://app.nextchat.dev/*
10 | // @match *://nextchat.oaipro.com/*
11 | // @require https://unpkg.com/vue@3.4.38/dist/vue.global.prod.js
12 | // @grant GM_addStyle
13 | // ==/UserScript==
14 |
15 | (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const i=document.createElement("style");i.textContent=t,document.head.append(i)})(" :root{--primary: #333 !important}.home_sidebar-logo__Cd7hL svg path{fill:#999!important}.button_icon-button-text__my76e{font-size:14px!important}.home_container__4PEJZ{width:98vw!important;height:98vh!important;max-width:100%!important}.home_sidebar__fPZfq{background:#f9f9f9!important;box-shadow:none!important}.chat_chat-input__PQ_oF{min-height:130px!important}.settings_settings__427bK{max-width:1000px!important}.chat_chat-input-actions__mwYC_ .chat_chat-input-action__DMW7Y{width:auto!important}.chat_chat-input-actions__mwYC_ .chat_chat-input-action__DMW7Y .chat_text__TkPfN{opacity:1!important;transform:none!important}.chat_chat-message-avatar__3QeMq .chat_chat-message-edit__h58of button{display:none!important}.chat_chat-message-avatar__3QeMq .no-dark svg g rect{fill:#fff!important}.chat_chat-message-user__ZtTEj>.chat_chat-message-container__O_X8_>.chat_chat-message-item__dKqMl{background-color:#fff!important}.chat_chat-message-action-date__RsXTn{display:none!important}.ui-lib_list-item__YH0DO .ui-lib_list-header__RwThu .ui-lib_list-item-title__Fsa9c{font-size:16px}.ui-lib_list-item__YH0DO .ui-lib_list-header__RwThu .ui-lib_list-item-sub-title__jSgHb{font-size:14px;padding-top:6px}.input-range_input-range__SuxRd,.ui-lib_select-with-icon__L6FLF .ui-lib_select-with-icon-select__JhHwp{font-size:14px}.home_sidebar-tail__T2_u7{flex-direction:column-reverse;width:100%}.home_sidebar-actions__LcDT9>.home_sidebar-action__IVfyJ:nth-child(3){display:none!important}.home_sidebar-actions__LcDT9:nth-child(2){width:100%!important;margin-bottom:10px}.home_sidebar-actions__LcDT9:nth-child(2) .button_shadow__G4m_0{width:100%!important;height:40px!important;background:#333!important;color:#fff!important}.home_sidebar-actions__LcDT9:nth-child(2) .button_shadow__G4m_0 .button_icon-button-icon__AMZta{transform:scale(1.2)}.home_sidebar-actions__LcDT9:nth-child(2) .button_shadow__G4m_0 svg{fill:#fff!important}.home_chat-item-info__9r6z_{display:none!important}.home_chat-item__Oblai{margin-bottom:5px!important;position:relative!important}.home_chat-item-delete__3qV5m{top:50%!important;transform:translateY(-50%)!important;right:10px!important}.home_chat-item-title__sRstw{font-weight:500!important}#webdavBtn{position:fixed;bottom:25px;left:85px;display:flex;align-items:center;display:none}#webdavBtn button{margin-right:10px!important}#webdavBtn .button_icon-button-icon__AMZta{width:auto!important}.chat_chat-body__QFv5x,.chat_chat-input-panel__rO72m{padding:20px 16% 40px!important}.chat_chat-input-send__GFQZo{right:17%!important;bottom:50px!important}.exporter_image-previewer__uKfNQ .exporter_preview-body__qK5Zf .exporter_chat-info__N_j5m{display:none!important}.exporter_image-previewer__uKfNQ .exporter_preview-body__qK5Zf .exporter_message-assistant__sDmHi .exporter_body__gcKIl{background:#f2f2f2!important}.exporter_image-previewer__uKfNQ .exporter_preview-body__qK5Zf .exporter_message-user__2t254 .exporter_body__gcKIl{background:#fff!important}.chat_chat-message-item-image__2jbb0{max-width:400px!important} ");
16 |
17 | (function (vue) {
18 | 'use strict';
19 |
20 | const name = "nextchat-themes";
21 | const version = "0.0.5";
22 | const author = "dlzmoe";
23 | const description = "NextChat plug-in, modify the UI theme!";
24 | const type = "module";
25 | const license = "Apache-2.0";
26 | const scripts = {
27 | dev: "vite --mode development",
28 | build: "vite build",
29 | preview: "vite preview"
30 | };
31 | const dependencies = {
32 | vue: "^3.4.27",
33 | webdav: "^5.7.1"
34 | };
35 | const devDependencies = {
36 | "@vitejs/plugin-vue": "^5.0.4",
37 | less: "^4.1.0",
38 | "less-loader": "^8.0.0",
39 | "style-loader": "^2.0.0",
40 | vite: "^5.2.12",
41 | "vite-plugin-monkey": "^4.0.0"
42 | };
43 | const packageJson = {
44 | name,
45 | version,
46 | author,
47 | description,
48 | type,
49 | license,
50 | scripts,
51 | dependencies,
52 | devDependencies
53 | };
54 | const _export_sfc = (sfc, props) => {
55 | const target = sfc.__vccOpts || sfc;
56 | for (const [key, val] of props) {
57 | target[key] = val;
58 | }
59 | return target;
60 | };
61 | const _sfc_main = {
62 | methods: {
63 | addWebdavBtn() {
64 | }
65 | },
66 | created() {
67 | console.log(
68 | `%c ${packageJson.name} %c 已开启 `,
69 | "padding: 2px 1px; color: #fff; background: #606060;",
70 | "padding: 2px 1px; color: #fff; background: #42c02e;"
71 | );
72 | this.addWebdavBtn();
73 | }
74 | };
75 | const _hoisted_1 = { id: "webdavBtn" };
76 | const _hoisted_2 = /* @__PURE__ */ vue.createElementVNode("button", {
77 | class: "button_icon-button__VwAMf undefined button_shadow__G4m_0 clickable undefined",
78 | role: "button",
79 | "aria-label": "ChatGPT"
80 | }, [
81 | /* @__PURE__ */ vue.createElementVNode("div", { class: "button_icon-button-icon__AMZta false" }, "上传到云端")
82 | ], -1);
83 | const _hoisted_3 = /* @__PURE__ */ vue.createElementVNode("button", {
84 | class: "button_icon-button__VwAMf undefined button_shadow__G4m_0 clickable undefined",
85 | role: "button",
86 | "aria-label": "ChatGPT"
87 | }, [
88 | /* @__PURE__ */ vue.createElementVNode("div", { class: "button_icon-button-icon__AMZta false" }, "同步到本地")
89 | ], -1);
90 | const _hoisted_4 = [
91 | _hoisted_2,
92 | _hoisted_3
93 | ];
94 | function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
95 | return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, _hoisted_4);
96 | }
97 | const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
98 | const app = vue.createApp(App);
99 | app.mount(
100 | (() => {
101 | const appDiv = document.createElement("div");
102 | document.body.append(appDiv);
103 | return appDiv;
104 | })()
105 | );
106 |
107 | })(Vue);
--------------------------------------------------------------------------------
/nextchat-themes/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlzmoe/UserScript/2b8dbbe485a9e6e7ee99fbabb38af80f6ce1352f/nextchat-themes/index.html
--------------------------------------------------------------------------------
/nextchat-themes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextchat-themes",
3 | "version": "0.0.5",
4 | "author": "dlzmoe",
5 | "description": "NextChat plug-in, modify the UI theme!",
6 | "type": "module",
7 | "license": "Apache-2.0",
8 | "scripts": {
9 | "dev": "vite --mode development",
10 | "build": "vite build",
11 | "preview": "vite preview"
12 | },
13 | "dependencies": {
14 | "vue": "^3.4.27",
15 | "webdav": "^5.7.1"
16 | },
17 | "devDependencies": {
18 | "@vitejs/plugin-vue": "^5.0.4",
19 | "less": "^4.1.0",
20 | "less-loader": "^8.0.0",
21 | "style-loader": "^2.0.0",
22 | "vite": "^5.2.12",
23 | "vite-plugin-monkey": "^4.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/nextchat-themes/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |