koishi-plugin-eula-regen 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Lipraty
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/lib/index.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import { Argv, Context, Schema, Service, Session, Dict } from 'koishi';
2
+ declare module 'koishi' {
3
+ interface User {
4
+ eula: boolean;
5
+ }
6
+ interface Events {
7
+ 'eula/before'(argv: Argv): void;
8
+ 'eula/update'(session: Session, eula: boolean): void;
9
+ }
10
+ }
11
+ declare class Eula extends Service {
12
+ private configs;
13
+ readonly filter = false;
14
+ readonly usage = "\n## \u6CE8\u610F\u4E8B\u9879\n\n\u672C\u63D2\u4EF6\u53EA\u7528\u4E8E\u4F53\u73B0 Koishi \u90E8\u7F72\u8005\u610F\u5FD7\uFF0C\u5373\uFF1A\u201C\u90E8\u7F72\u8005\u4EC5\u5BF9\u540C\u610F\u4E86\u300A\u6700\u7EC8\u7528\u6237\u534F\u8BAE\u300B\u7684\u6700\u7EC8\u7528\u6237\u63D0\u4F9B\u670D\u52A1\u201D\u3002\n\n\u5BF9\u4E8E\u90E8\u7F72\u8005\u884C\u4E3A\u53CA\u6240\u4EA7\u751F\u7684\u4EFB\u4F55\u7EA0\u7EB7\uFF0C Koishi \u53CA koishi-plugin-eula \u6982\u4E0D\u8D1F\u8D23\u3002\n\n\u534F\u8BAE\u5185\u5BB9\u6587\u672C\u53EF\u4EE5\u5728 <a href=\"/locales/eula/eulaMessage\">\u672C\u5730\u5316 - eula.eulaMessage</a> \u4E2D\u4FEE\u6539\uFF0C\u56E0\u6B64\u4F60\u53EF\u4EE5\u6839\u636E\u4E0D\u540C\u8BED\u8A00\u7ED9\u4E88\u4E0D\u540C\u7684\u534F\u8BAE\u6587\u672C\u3002\n";
15
+ private log;
16
+ constructor(ctx: Context, configs: Eula.Config);
17
+ private eula;
18
+ /**
19
+ *
20
+ * @param userId 用户 id,即 session.user.id
21
+ * @returns false: 该用户未同意 eula,true: 该用户已同意 eula
22
+ */
23
+ vertify(userId: number): Promise<boolean>;
24
+ }
25
+ declare namespace Eula {
26
+ const usage = "\n## \u6CE8\u610F\u4E8B\u9879\n\n\u672C\u63D2\u4EF6\u53EA\u7528\u4E8E\u4F53\u73B0 Koishi \u90E8\u7F72\u8005\u610F\u5FD7\uFF0C\u5373\uFF1A\u201C\u90E8\u7F72\u8005\u4EC5\u5BF9\u540C\u610F\u4E86\u300A\u6700\u7EC8\u7528\u6237\u534F\u8BAE\u300B\u7684\u6700\u7EC8\u7528\u6237\u63D0\u4F9B\u670D\u52A1\u201D\u3002\n\n\u5BF9\u4E8E\u90E8\u7F72\u8005\u884C\u4E3A\u53CA\u6240\u4EA7\u751F\u7684\u4EFB\u4F55\u7EA0\u7EB7\uFF0C Koishi \u53CA koishi-plugin-eula \u6982\u4E0D\u8D1F\u8D23\u3002\n\n\u534F\u8BAE\u5185\u5BB9\u6587\u672C\u53EF\u4EE5\u5728 <a href=\"/locales/eula/eulaMessage\">\u672C\u5730\u5316 - eula.eulaMessage</a> \u4E2D\u4FEE\u6539\uFF0C\u56E0\u6B64\u4F60\u53EF\u4EE5\u6839\u636E\u4E0D\u540C\u8BED\u8A00\u7ED9\u4E88\u4E0D\u540C\u7684\u534F\u8BAE\u6587\u672C\u3002\n";
27
+ interface Config {
28
+ waitTime: number;
29
+ forwardMessgae: boolean;
30
+ replyAuthority: number;
31
+ alias: string;
32
+ content: Dict<string, string>;
33
+ accept: string[];
34
+ enable: boolean;
35
+ model?: boolean;
36
+ commands?: string[];
37
+ }
38
+ const Config: Schema<Config>;
39
+ }
40
+ export default Eula;
package/lib/index.js ADDED
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@satorijs/element/jsx-runtime";
2
+ import { Random, Schema, Service, h } from 'koishi';
3
+ import { createRequire } from 'module';
4
+ const require = createRequire(import.meta.url);
5
+ class Eula extends Service {
6
+ constructor(ctx, configs) {
7
+ super(ctx, 'eula', true);
8
+ this.configs = configs;
9
+ this.filter = false;
10
+ this.usage = Eula.usage;
11
+ this.log = ctx.logger('eula');
12
+ // 使用 createRequire 加载 YAML 本地化文件
13
+ try {
14
+ ctx.i18n.define('zh', require('./locales/zh'));
15
+ ctx.i18n.define('en', require('./locales/en'));
16
+ }
17
+ catch (err) {
18
+ this.log.error('Failed to load locales:', err);
19
+ }
20
+ ctx.model.extend('user', {
21
+ eula: { type: 'boolean', initial: false }
22
+ });
23
+ ctx.before('attach-user', (session, fields) => {
24
+ fields.add('eula');
25
+ fields.add('authority');
26
+ });
27
+ ctx.before('command/execute', async (_) => {
28
+ const session = _.session;
29
+ const authority = session.resolve(session.argv.command.config.authority);
30
+ ctx.emit('eula/before', _);
31
+ if (!session.user.eula
32
+ && authority > 0
33
+ && session.user.authority <= configs.replyAuthority
34
+ && _.command.name !== 'eula')
35
+ if (configs.enable
36
+ || (!configs.model && !configs.commands.includes(_.command.name))
37
+ || (configs.model && configs.commands.includes(_.command.name)))
38
+ return await this.eula(_);
39
+ });
40
+ ctx.command('eula', '最终用户许可协议', { authority: 0, })
41
+ .action((_) => this.eula(_));
42
+ }
43
+ async eula(argv) {
44
+ const session = argv.session;
45
+ const userLocale = session.user.locale || session.user.locales[0] || 'zh';
46
+ const accept = Random.pick(this.configs.accept) ?? session.text('eula.defaultAccept');
47
+ await session.send(_jsxs(_Fragment, { children: [_jsx("message", { id: "{0}", children: _jsx("i18n", { path: "eula.eulaMessage.title", children: [this.configs.alias] }) }), _jsxs("message", { forward: this.configs.forwardMessgae, children: [_jsx("message", { id: "{0}", children: this.configs.content[userLocale] ?? this.configs.content['zh'] }), _jsx("message", { id: "{0}", children: _jsx("i18n", { path: "eula.eulaMessage.confirm", children: [accept] }) })] })] }));
48
+ const prompt = await session.prompt(this.configs.waitTime * 1000);
49
+ this.log.info(`[platfrom: ${session.platform}]user ${session.userId} reply to (${prompt}) eula`);
50
+ if (prompt) {
51
+ const promptEle = h.parse(prompt);
52
+ if (promptEle[0].type === 'at' && promptEle[0].attrs.id === session.bot.selfId)
53
+ promptEle.shift(); // remove `at` element
54
+ const accredit = promptEle[0].attrs.content.replace(/^\//g, '').trim() === accept;
55
+ session.user.eula = accredit;
56
+ this.ctx.emit('eula/update', session, accredit);
57
+ return session.text(`${accredit ? 'eula.acceptedMessage' : 'eula.rejectMessage'}`, [this.configs.alias]);
58
+ }
59
+ else
60
+ return session.text('eula.timeout');
61
+ }
62
+ /**
63
+ *
64
+ * @param userId 用户 id,即 session.user.id
65
+ * @returns false: 该用户未同意 eula,true: 该用户已同意 eula
66
+ */
67
+ async vertify(userId) {
68
+ return (await this.ctx.database.get('user', { id: userId }, ['eula']))[0].eula;
69
+ }
70
+ }
71
+ (function (Eula) {
72
+ Eula.usage = `
73
+ ## 注意事项
74
+
75
+ 本插件只用于体现 Koishi 部署者意志,即:“部署者仅对同意了《最终用户协议》的最终用户提供服务”。
76
+
77
+ 对于部署者行为及所产生的任何纠纷, Koishi 及 koishi-plugin-eula 概不负责。
78
+
79
+ 协议内容文本可以在 <a href="/locales/eula/eulaMessage">本地化 - eula.eulaMessage</a> 中修改,因此你可以根据不同语言给予不同的协议文本。
80
+ `;
81
+ Eula.Config = Schema.intersect([
82
+ Schema.object({
83
+ waitTime: Schema.number().min(30).max(300).step(1).default(60).description('等待回复时长(秒)'),
84
+ replyAuthority: Schema.number().min(1).max(5).default(1).description('协议生效最高等级'),
85
+ forwardMessgae: Schema.boolean().default(true).description('合并发送的协议以及认可段(目前仅在 QQ 生效)')
86
+ }).description('基本设置'),
87
+ Schema.object({
88
+ alias: Schema.string().default('EULA').description('《最终用户许可协议》别名,或其他自拟协议名称'),
89
+ content: Schema.dict(Schema.string().role('textarea', { rows: [2, 4] })).default({
90
+ 'zh': '协议内容',
91
+ }).description('协议内容的多语言设置'),
92
+ accept: Schema.array(String).description('认可协议关键字,如果有多个,则随机某一个作为认可关键字')
93
+ }).description('协议设置'),
94
+ Schema.intersect([
95
+ Schema.object({
96
+ enable: Schema.boolean().default(true).description('限制所有的命令')
97
+ }),
98
+ Schema.union([
99
+ Schema.object({
100
+ enable: Schema.const(false).required(),
101
+ model: Schema.union([
102
+ Schema.const(true).description('白名单'),
103
+ Schema.const(false).description('黑名单'),
104
+ ]).description('限制命令的模式'),
105
+ commands: Schema.array(String).description('指令列表')
106
+ }),
107
+ Schema.object({})
108
+ ])
109
+ ]).description('指令限制')
110
+ ]);
111
+ })(Eula || (Eula = {}));
112
+ export default Eula;
@@ -0,0 +1,12 @@
1
+ eula:
2
+ defaultAccept: 'promise'
3
+ eulaMessage:
4
+ title: 'You have used a service via restricted by "{0}" and is as follows:'
5
+ confirm: 'If you have read it and accpet it, please send "{0}" or send "Disagree" to reject the lisence terms.'
6
+ acceptedMessage: 'You accepted {0} and you can use the services'
7
+ rejectMessage: |-
8
+ <messasge>
9
+ <p>You have not accept the {0} and will be forbidden use the services via restricted by the lisence terms</p>
10
+ <p>Send `eula` command to redo the process if you need.</p>
11
+ </messasge>
12
+ timeout: 'timeout'
@@ -0,0 +1,12 @@
1
+ eula:
2
+ defaultAccept: '同意'
3
+ eulaMessage:
4
+ title: '您使用了需要认可 {0} 后方可使用的服务,以下为具体内容:'
5
+ confirm: '如已仔细阅读并确认,请发送 “{0}” 或 “不同意”。'
6
+ acceptedMessage: '您已同意 {0},服务已生效。'
7
+ rejectMessage: |-
8
+ <messasge>
9
+ <p>您未同意 {0},将不能为您提供条款限制的服务。</p>
10
+ <p>如果您需要使用,可发送 eula 命令来重新执行该流程。</p>
11
+ </messasge>
12
+ timeout: '等待超时'
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "koishi-plugin-eula-regen",
3
+ "description": "EULA(End-user licence agreement) for your koishi bot.",
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "repository": "https://github.com/Lipraty/koishi-plugin-eula",
7
+ "author": "Lipraty <i@lonay.me>",
8
+ "main": "lib/index.js",
9
+ "typings": "lib/index.d.ts",
10
+ "files": [
11
+ "lib",
12
+ "dist"
13
+ ],
14
+ "license": "MIT",
15
+ "scripts": {
16
+ "build": "tsc && cp -r src/locales lib/"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^20.0.0",
20
+ "koishi": "^4.18.10",
21
+ "typescript": "^5.0.0"
22
+ },
23
+ "koishi": {
24
+ "description": {
25
+ "zh": "⚡ 给 Koishi Bot 的使用添加一个《最终用户许可协议》",
26
+ "en": "⚡ Enable EULA(End-user licence agreement) for your Koishi bot",
27
+ "jp": "⚡ Koishi Bot を使用するためのエンド ユーザー ライセンス契約を追加する"
28
+ },
29
+ "service": {
30
+ "required": [
31
+ "database"
32
+ ]
33
+ }
34
+ },
35
+ "keywords": [
36
+ "chatbot",
37
+ "koishi",
38
+ "plugin",
39
+ "eula",
40
+ "用户许可协议",
41
+ "群管"
42
+ ],
43
+ "peerDependencies": {
44
+ "koishi": "^4.12.0"
45
+ }
46
+ }
package/readme.md ADDED
@@ -0,0 +1,176 @@
1
+ # koishi-plugin-eula
2
+
3
+ [![npm](https://img.shields.io/npm/v/koishi-plugin-eula?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-eula) ![Rating](https://badge.koishi.chat/rating/koishi-plugin-eula)
4
+
5
+ 为你的 Koishi bot 添加一个 EULA(End-user licence agreement) 最终用户许可协议。
6
+
7
+ ## 功能特性
8
+
9
+ - ✅ 支持多语言协议内容配置
10
+ - ✅ 可自定义协议别名和认可关键字
11
+ - ✅ 支持命令白名单/黑名单模式
12
+ - ✅ 提供完整的事件系统用于扩展
13
+ - ✅ 支持权限等级控制
14
+
15
+ ## 快速开始
16
+
17
+ ### 普通用户使用
18
+
19
+ 在 Koishi 插件市场中搜索 `eula`,点击添加即可使用。
20
+
21
+ ### 开发者使用
22
+
23
+ #### 安装
24
+
25
+ ```bash
26
+ # 使用 yarn
27
+ yarn add koishi-plugin-eula
28
+
29
+ # 或使用 npm
30
+ npm install koishi-plugin-eula
31
+ ```
32
+
33
+ #### 配置
34
+
35
+ 在 `package.json` 中声明 eula 服务依赖:
36
+
37
+ ```json
38
+ {
39
+ "koishi": {
40
+ "service": {
41
+ "required": ["eula"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ #### 在插件中使用
48
+
49
+ 1. **引入类型定义**(获得 TypeScript 类型提示):
50
+
51
+ ```typescript
52
+ import {} from 'koishi-plugin-eula'
53
+
54
+ export const using = ['eula']
55
+ ```
56
+
57
+ 2. **监听 EULA 更新事件**:
58
+
59
+ ```typescript
60
+ ctx.on('eula/update', (session: Session, eula: boolean) => {
61
+ if (eula) {
62
+ // 用户已同意协议
63
+ console.log(`用户 ${session.userId} 已同意 EULA`)
64
+ } else {
65
+ // 用户未同意协议
66
+ console.log(`用户 ${session.userId} 未同意 EULA`)
67
+ }
68
+ })
69
+ ```
70
+
71
+ 3. **在命令执行前检查**(可选):
72
+
73
+ ```typescript
74
+ ctx.before('command/execute', async (argv) => {
75
+ const session = argv.session
76
+ if (!session.user.eula) {
77
+ return '请先同意最终用户许可协议'
78
+ }
79
+ })
80
+ ```
81
+
82
+ ## API 文档
83
+
84
+ ### 服务:`ctx.eula`
85
+
86
+ #### `vertify(userId: number): Promise<boolean>`
87
+
88
+ 验证指定用户是否已同意 EULA。
89
+
90
+ > **注意**:一般情况下,更推荐使用 `eula/update` 事件来获得认证状态,这将得到完整的 Session 支持。
91
+
92
+ **参数:**
93
+
94
+ - `userId: number` - 用户 ID,即 `session.user.id`
95
+
96
+ **返回值:**
97
+
98
+ - `Promise<boolean>` - `true` 表示用户已同意,`false` 表示未同意
99
+
100
+ **示例:**
101
+
102
+ ```typescript
103
+ const hasAccepted = await ctx.eula.vertify(session.user.id)
104
+ if (!hasAccepted) {
105
+ return '请先同意最终用户许可协议'
106
+ }
107
+ ```
108
+
109
+ ### 事件系统
110
+
111
+ #### 事件:`eula/before`
112
+
113
+ 在命令触发 EULA 流程**之前**触发该事件。
114
+
115
+ **参数:**
116
+
117
+ - `argv: Argv` - 命令参数对象
118
+
119
+ **示例:**
120
+
121
+ ```typescript
122
+ ctx.on('eula/before', (argv) => {
123
+ console.log(`用户 ${argv.session.userId} 即将看到 EULA`)
124
+ })
125
+ ```
126
+
127
+ #### 事件:`eula/update`
128
+
129
+ 当用户回复 EULA 后触发,用于通知用户同意或拒绝的状态。
130
+
131
+ **参数:**
132
+
133
+ - `session: Session` - 会话对象
134
+ - `eula: boolean` - `true` 表示用户已同意,`false` 表示用户拒绝或超时
135
+
136
+ **示例:**
137
+
138
+ ```typescript
139
+ ctx.on('eula/update', (session, eula) => {
140
+ if (eula) {
141
+ // 用户同意协议后的处理逻辑
142
+ session.send('感谢您同意协议!')
143
+ } else {
144
+ // 用户拒绝协议后的处理逻辑
145
+ session.send('您已拒绝协议,部分功能将无法使用。')
146
+ }
147
+ })
148
+ ```
149
+
150
+ ## 配置说明
151
+
152
+ 插件支持以下配置项:
153
+
154
+ - **waitTime**: 等待用户回复的时长(秒),范围 30-300,默认 60
155
+ - **replyAuthority**: 协议生效的最高权限等级,范围 1-5,默认 1
156
+ - **forwardMessgae**: 是否合并发送协议和认可段(目前仅在 QQ 生效),默认 `true`
157
+ - **alias**: 协议别名,默认 `'EULA'`
158
+ - **content**: 协议内容的多语言设置(字典格式)
159
+ - **accept**: 认可协议的关键字数组(如果有多个,将随机选择一个)
160
+ - **enable**: 是否限制所有命令,默认 `true`
161
+ - **model**: 限制命令的模式(`true` 为白名单,`false` 为黑名单)
162
+ - **commands**: 指令列表(配合 `model` 使用)
163
+
164
+ ## 注意事项
165
+
166
+ ⚠️ **重要声明**
167
+
168
+ 本插件只用于体现 Koishi 部署者意志,即:"部署者仅对同意了《最终用户协议》的最终用户提供服务"。
169
+
170
+ 对于部署者行为及所产生的任何纠纷,Koishi 及 koishi-plugin-eula 概不负责。
171
+
172
+ 协议内容文本可以在本地化文件中修改(`src/locales/` 目录下的 YAML 文件),因此你可以根据不同语言给予不同的协议文本。
173
+
174
+ ## 许可证
175
+
176
+ MIT