koishi-plugin-bns-rate 1.1.0 → 1.2.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/README.md +71 -0
- package/index.js +228 -27
- package/package.json +9 -5
- package/.github/workflows/publish.yml +0 -18
- package/.gitignore +0 -6
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# koishi-plugin-bns-rate
|
|
2
|
+
|
|
3
|
+
从 [dd373.com](https://www.dd373.com/s-d5gqt8.html) 获取剑灵怀旧服**神石**实时汇率,输出当前时段最低比例前 N 条。
|
|
4
|
+
|
|
5
|
+
支持**官方 QQ 机器人 Markdown 卡片**回复:标题 + 横幅图 + 红绿报价 + 跳转按钮,全部可在插件设置页配置。
|
|
6
|
+
|
|
7
|
+
## 命令
|
|
8
|
+
|
|
9
|
+
| 命令 | 说明 |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `bnsrate` / `神石` / `shenshi` | 查询当前时段最低神石比例 |
|
|
12
|
+
| `bnsrate -f` | 忽略缓存,强制刷新 |
|
|
13
|
+
| `bnsrate.preview` | 只输出卡片 Markdown 源码(不发送卡片),调试用 |
|
|
14
|
+
|
|
15
|
+
## 卡片效果
|
|
16
|
+
|
|
17
|
+
官方 QQ 机器人的**群聊 / 私聊**下,命令回复会变成 Markdown 卡片,形如:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
# 神石比例实时播报
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
大家关注的 DD373 最低神石比例前5条来啦!当前时段(2026/9/10 10:46)最优价格如下:
|
|
25
|
+
|
|
26
|
+
1元 = <font color="#E60012">151.51</font>神石 | 1神石 = <font color="#00A650">0.0066</font>元
|
|
27
|
+
...
|
|
28
|
+
***
|
|
29
|
+
如需查看完整详情或进行交易,请点击下方按钮直接跳转至 DD373 官网。
|
|
30
|
+
[ 点此直达DD373网站 ]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
其它平台(OneBot / Telegram 等)、QQ 频道(`qqguild`)、以及卡片发送失败时,都会**自动回退为纯文本**,不会发不出消息。
|
|
34
|
+
|
|
35
|
+
## 配置项
|
|
36
|
+
|
|
37
|
+
| 配置 | 默认值 | 说明 |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `url` | dd373 剑灵怀旧服页面 | 目标区服页面 URL |
|
|
40
|
+
| `cacheSeconds` | `60` | 缓存时间(秒),缓存期内重复查询不再请求页面 |
|
|
41
|
+
| `count` | `5` | 显示的条目数量(1–10) |
|
|
42
|
+
| `markdown` | `true` | 用 QQ 官方 Markdown 卡片回复 |
|
|
43
|
+
| `title` | `神石比例实时播报` | 卡片标题 |
|
|
44
|
+
| `bannerUrl` | 空 | **卡片横幅图片直链**,必须是公网可访问的 URL;留空则不显示图片 |
|
|
45
|
+
| `bannerAlt` | `DD373 DATA` | 横幅图片替代文字 |
|
|
46
|
+
| `bannerWidth` / `bannerHeight` | `560` / `120` | 横幅显示尺寸(px),`0` = 交给 QQ 自动缩放。建议与图片原始宽高比一致 |
|
|
47
|
+
| `intro` | 见插件 | 标题下方引导语,可用 `{count}` `{time}` `{date}` 变量 |
|
|
48
|
+
| `footer` | 见插件 | 报价列表下方说明文字(仅在开启按钮时显示) |
|
|
49
|
+
| `button` | `true` | 是否显示底部跳转按钮 |
|
|
50
|
+
| `buttonText` | `点此直达DD373网站` | 按钮文字 |
|
|
51
|
+
| `buttonUrl` | `https://www.dd373.com/s-d5gqt8.html` | 按钮跳转链接 |
|
|
52
|
+
| `colorForward` | `#E60012` | 「1元=xx神石」数字颜色,留空不染色 |
|
|
53
|
+
| `colorReverse` | `#00A650` | 「1神石=xx元」数字颜色,留空不染色 |
|
|
54
|
+
| `decimalsForward` | `2` | 「1元=xx神石」保留小数位(**截断**,不四舍五入),`0` = 原始值 |
|
|
55
|
+
| `decimalsReverse` | `4` | 「1神石=xx元」保留小数位(截断),`0` = 原始值 |
|
|
56
|
+
|
|
57
|
+
## ⚠️ 注意事项
|
|
58
|
+
|
|
59
|
+
1. **颜色只在桌面端生效**。QQ 官方 Markdown 的[支持格式](https://bot.qq.com/wiki/develop/api-v2/server-inter/message/type/markdown.html)中没有字体颜色,颜色依赖 HTML 标签,**只有桌面端 QQNT 会渲染**;安卓 / iOS 会显示为普通文字(卡片本身不会出错)。
|
|
60
|
+
2. **横幅图片必须是公网直链**,QQ 会下载并转存该资源。请勿使用官方的 `server-temp`(首次访问后即删除文件,群里多人同时查看会出现白图)。
|
|
61
|
+
3. 群聊/单聊自定义 Markdown 自 2026/04/23 起已开放给所有机器人,**无需申请 Markdown 模板**;QQ 频道(`qqguild`)场景仍需内邀开通,本插件在频道下自动回退纯文本。
|
|
62
|
+
4. 命令回复属被动消息,不占用主动消息配额。
|
|
63
|
+
|
|
64
|
+
## 依赖
|
|
65
|
+
|
|
66
|
+
- `koishi` ^4.18.0
|
|
67
|
+
- 需要 `http` 服务(`ctx.http`)
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
MIT
|
package/index.js
CHANGED
|
@@ -1,26 +1,93 @@
|
|
|
1
|
-
const { Schema } = require('koishi')
|
|
1
|
+
const { Schema, h } = require('koishi')
|
|
2
2
|
|
|
3
3
|
const DEFAULT_URL = 'https://www.dd373.com/s-d5gqt8-0-0-0-0-0-0-0-0-0-0-0-1-0-5-0.html'
|
|
4
|
+
const DEFAULT_BUTTON_URL = 'https://www.dd373.com/s-d5gqt8.html'
|
|
4
5
|
|
|
5
6
|
const FORWARD_RE = /1元\s*=\s*(\d+\.?\d*)神石/g
|
|
7
|
+
const REVERSE_RE = /(?<!\d)1神石\s*=\s*(\d+\.\d+)元/
|
|
8
|
+
|
|
9
|
+
// ===== 配置 Schema =====
|
|
6
10
|
|
|
7
11
|
const Config = Schema.object({
|
|
8
12
|
url: Schema.string()
|
|
9
13
|
.default(DEFAULT_URL)
|
|
10
|
-
.description('dd373
|
|
14
|
+
.description('dd373 目标区服页面 URL'),
|
|
11
15
|
cacheSeconds: Schema.number()
|
|
12
16
|
.default(60)
|
|
13
17
|
.min(10)
|
|
14
18
|
.max(300)
|
|
15
|
-
.description('
|
|
19
|
+
.description('缓存时间(秒),缓存内重复查询不再请求页面'),
|
|
16
20
|
count: Schema.number()
|
|
17
21
|
.default(5)
|
|
18
22
|
.min(1)
|
|
19
23
|
.max(10)
|
|
20
24
|
.description('显示的条目数量'),
|
|
25
|
+
|
|
26
|
+
markdown: Schema.boolean()
|
|
27
|
+
.default(true)
|
|
28
|
+
.description('💬 用 QQ官方 Markdown 卡片回复(仅官方QQ机器人「群/私聊」生效;频道机器人、OneBot 等其它平台自动回退纯文本,发送失败也会回退)'),
|
|
29
|
+
title: Schema.string()
|
|
30
|
+
.default('神石比例实时播报')
|
|
31
|
+
.description('卡片顶部标题(# 一级标题)'),
|
|
32
|
+
|
|
33
|
+
bannerUrl: Schema.string()
|
|
34
|
+
.default('')
|
|
35
|
+
.description('🖼️ 卡片横幅图片 URL:必须是公网可直接访问的直链(QQ 会下载转存)。留空则不显示图片'),
|
|
36
|
+
bannerAlt: Schema.string()
|
|
37
|
+
.default('DD373 DATA')
|
|
38
|
+
.description('横幅图片的替代文字(图片加载失败时显示)'),
|
|
39
|
+
bannerWidth: Schema.number()
|
|
40
|
+
.default(560)
|
|
41
|
+
.min(0)
|
|
42
|
+
.max(2000)
|
|
43
|
+
.description('横幅宽度(px)。0 = 不指定,交给 QQ 自动缩放'),
|
|
44
|
+
bannerHeight: Schema.number()
|
|
45
|
+
.default(120)
|
|
46
|
+
.min(0)
|
|
47
|
+
.max(2000)
|
|
48
|
+
.description('横幅高度(px)。建议与图片原始宽高比一致,否则会被拉伸。0 = 不指定'),
|
|
49
|
+
|
|
50
|
+
intro: Schema.string()
|
|
51
|
+
.role('textarea', { rows: [2, 4] })
|
|
52
|
+
.default('大家关注的 DD373 最低神石比例前{count}条来啦!当前时段({time})最优价格如下:')
|
|
53
|
+
.description('📝 标题下方的引导语。可用变量:{count} 条数、{time} 日期时间、{date} 日期'),
|
|
54
|
+
footer: Schema.string()
|
|
55
|
+
.role('textarea', { rows: [2, 4] })
|
|
56
|
+
.default('如需查看完整详情或进行交易,请点击下方按钮直接跳转至 DD373 官网。')
|
|
57
|
+
.description('📝 报价列表下方的说明文字(仅在开启按钮时显示)'),
|
|
58
|
+
|
|
59
|
+
button: Schema.boolean()
|
|
60
|
+
.default(true)
|
|
61
|
+
.description('🔘 在卡片底部显示跳转按钮'),
|
|
62
|
+
buttonText: Schema.string()
|
|
63
|
+
.default('点此直达DD373网站')
|
|
64
|
+
.description('按钮文字'),
|
|
65
|
+
buttonUrl: Schema.string()
|
|
66
|
+
.default(DEFAULT_BUTTON_URL)
|
|
67
|
+
.description('按钮跳转的链接'),
|
|
68
|
+
|
|
69
|
+
colorForward: Schema.string()
|
|
70
|
+
.default('#E60012')
|
|
71
|
+
.description('「1元=xx神石」数字的颜色,如 #E60012(红)。留空 = 不染色。⚠️ 颜色仅在桌面端 QQ 显示,安卓/iOS 会显示为普通文字'),
|
|
72
|
+
colorReverse: Schema.string()
|
|
73
|
+
.default('#00A650')
|
|
74
|
+
.description('「1神石=xx元」数字的颜色,如 #00A650(绿)。留空 = 不染色'),
|
|
75
|
+
decimalsForward: Schema.number()
|
|
76
|
+
.default(2)
|
|
77
|
+
.min(0)
|
|
78
|
+
.max(8)
|
|
79
|
+
.description('「1元=xx神石」保留几位小数(直接截断,不四舍五入)。0 = 显示原始值'),
|
|
80
|
+
decimalsReverse: Schema.number()
|
|
81
|
+
.default(4)
|
|
82
|
+
.min(0)
|
|
83
|
+
.max(8)
|
|
84
|
+
.description('「1神石=xx元」保留几位小数(直接截断)。0 = 显示原始值'),
|
|
21
85
|
})
|
|
22
86
|
|
|
87
|
+
// ===== 抓取与解析 =====
|
|
88
|
+
|
|
23
89
|
async function fetchRates(ctx, url, count) {
|
|
90
|
+
const limit = Math.max(1, Math.min(10, Number(count) || 5))
|
|
24
91
|
const response = await ctx.http.get(url, {
|
|
25
92
|
responseType: 'text',
|
|
26
93
|
headers: {
|
|
@@ -38,12 +105,14 @@ async function fetchRates(ctx, url, count) {
|
|
|
38
105
|
const forwardMatches = [...html.matchAll(FORWARD_RE)]
|
|
39
106
|
const rates = []
|
|
40
107
|
for (const m of forwardMatches) {
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
108
|
+
const context = html.substring(Math.max(0, m.index - 50), m.index + 100)
|
|
109
|
+
if (context.includes('1神石=')) {
|
|
43
110
|
const forward = parseFloat(m[1])
|
|
44
|
-
|
|
111
|
+
// 从同一个上下文中提取反向汇率,避免浮点计算误差
|
|
112
|
+
const revMatch = context.match(REVERSE_RE)
|
|
113
|
+
const reverse = revMatch ? parseFloat(revMatch[1]) : Math.round((1 / forward) * 10000) / 10000
|
|
45
114
|
rates.push({ forward, reverse })
|
|
46
|
-
if (rates.length >=
|
|
115
|
+
if (rates.length >= limit) break
|
|
47
116
|
}
|
|
48
117
|
}
|
|
49
118
|
|
|
@@ -54,47 +123,179 @@ async function fetchRates(ctx, url, count) {
|
|
|
54
123
|
return rates
|
|
55
124
|
}
|
|
56
125
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
126
|
+
// ===== 格式化 =====
|
|
127
|
+
|
|
128
|
+
function pad2(n) {
|
|
129
|
+
return String(n).padStart(2, '0')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 固定按东八区(UTC+8)显示,避免依赖运行环境的时区设置
|
|
133
|
+
function formatTime(timestamp, withSeconds) {
|
|
134
|
+
const d = new Date(timestamp + 8 * 3600 * 1000)
|
|
135
|
+
const date = `${d.getUTCFullYear()}/${d.getUTCMonth() + 1}/${d.getUTCDate()}`
|
|
136
|
+
const time = `${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}`
|
|
137
|
+
return withSeconds ? `${date} ${time}:${pad2(d.getUTCSeconds())}` : `${date} ${time}`
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function colorize(text, color) {
|
|
141
|
+
const c = String(color || '').trim()
|
|
142
|
+
return c ? `<font color="${c}">${text}</font>` : String(text)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 按位截断(不四舍五入),并补足小数位;decimals 为 0 时返回原始值
|
|
146
|
+
// 先定点到 d+2 位消除浮点误差(否则 0.0066 * 10000 会得到 65.9999 这种值)
|
|
147
|
+
function truncate(value, decimals) {
|
|
148
|
+
const d = Math.max(0, Math.min(8, Math.floor(Number(decimals) || 0)))
|
|
149
|
+
if (!d) return String(value)
|
|
150
|
+
const fixed = Number(value).toFixed(d + 2)
|
|
151
|
+
const [int, frac = ''] = fixed.split('.')
|
|
152
|
+
return `${int}.${frac.slice(0, d)}`
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function fillTemplate(tpl, vars) {
|
|
156
|
+
let out = String(tpl || '')
|
|
157
|
+
for (const [k, v] of Object.entries(vars)) out = out.split('{' + k + '}').join(String(v))
|
|
158
|
+
return out
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 纯文本格式(非官方QQ平台 / 卡片发送失败时的回退,也是历史版本的表现)
|
|
162
|
+
function formatText(rates, timestamp, opts = {}) {
|
|
61
163
|
const lines = [`DD373当前时段最低神石比例前${rates.length}条如下:`]
|
|
62
164
|
for (const r of rates) {
|
|
63
165
|
lines.push(`1元 = ${r.forward}神石 1神石 = ${r.reverse}元`)
|
|
64
166
|
}
|
|
65
|
-
lines.push(`查询时间: ${
|
|
66
|
-
lines.push(
|
|
167
|
+
lines.push(`查询时间: ${formatTime(timestamp, true)}`)
|
|
168
|
+
lines.push(`详情: ${DEFAULT_BUTTON_URL}`)
|
|
169
|
+
if (opts.stale) {
|
|
170
|
+
lines.push(`[警告] 汇率数据已过期,刷新失败: ${opts.error || '未知错误'}`)
|
|
171
|
+
}
|
|
67
172
|
return lines.join('\n')
|
|
68
173
|
}
|
|
69
174
|
|
|
175
|
+
// QQ官方 Markdown 卡片源码
|
|
176
|
+
function buildCardMarkdown(rates, timestamp, config) {
|
|
177
|
+
const time = formatTime(timestamp, false)
|
|
178
|
+
const lines = [`# ${config.title}`]
|
|
179
|
+
|
|
180
|
+
const banner = String(config.bannerUrl || '').trim()
|
|
181
|
+
if (banner) {
|
|
182
|
+
const w = Math.max(0, Math.round(Number(config.bannerWidth) || 0))
|
|
183
|
+
const ht = Math.max(0, Math.round(Number(config.bannerHeight) || 0))
|
|
184
|
+
lines.push('', ``)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const intro = fillTemplate(config.intro, {
|
|
188
|
+
count: rates.length,
|
|
189
|
+
time,
|
|
190
|
+
date: time.split(' ')[0],
|
|
191
|
+
}).trim()
|
|
192
|
+
if (intro) lines.push('', intro)
|
|
193
|
+
|
|
194
|
+
lines.push('', ...rates.map(r => (
|
|
195
|
+
`1元 = ${colorize(truncate(r.forward, config.decimalsForward), config.colorForward)}神石 | `
|
|
196
|
+
+ `1神石 = ${colorize(truncate(r.reverse, config.decimalsReverse), config.colorReverse)}元`
|
|
197
|
+
)))
|
|
198
|
+
|
|
199
|
+
const footer = String(config.footer || '').trim()
|
|
200
|
+
if (config.button && footer) {
|
|
201
|
+
lines.push('', '***', '', footer)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return lines.join('\n')
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 组装成 koishi 元素:qq:markdown = 原生 markdown 正文,button-group/button = 卡片底部按钮
|
|
208
|
+
// 注意:必须用 qq:markdown 元素包裹,否则适配器会把 # * - > 等符号全部转义成纯文本
|
|
209
|
+
function buildCardElements(markdown, config) {
|
|
210
|
+
const elements = [h('qq:markdown', {}, markdown)]
|
|
211
|
+
if (config.button && String(config.buttonUrl || '').trim()) {
|
|
212
|
+
elements.push(h('button-group', {},
|
|
213
|
+
h('button', {
|
|
214
|
+
type: 'link',
|
|
215
|
+
href: String(config.buttonUrl).trim(),
|
|
216
|
+
class: 'primary',
|
|
217
|
+
}, config.buttonText || '点此查看详情')))
|
|
218
|
+
}
|
|
219
|
+
return elements
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 只有官方QQ机器人的「群聊 / 私聊」支持自定义 markdown + 自定义按钮
|
|
223
|
+
// 频道机器人 platform 是 qqguild(且 markdown 需内邀开通),其它适配器一律走纯文本
|
|
224
|
+
function supportsCard(session) {
|
|
225
|
+
const bot = (session && session.bot) || {}
|
|
226
|
+
return bot.platform === 'qq'
|
|
227
|
+
&& !!bot.internal
|
|
228
|
+
&& typeof bot.internal.sendMessage === 'function'
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ===== 插件主体 =====
|
|
232
|
+
|
|
70
233
|
function apply(ctx, config) {
|
|
234
|
+
const logger = ctx.logger('bns-rate')
|
|
71
235
|
let cache = null
|
|
72
236
|
|
|
237
|
+
// 取数据:优先缓存,失败时回退到过期缓存
|
|
238
|
+
async function resolveRates(force) {
|
|
239
|
+
const ttl = config.cacheSeconds * 1000
|
|
240
|
+
if (!force && cache && Date.now() - cache.timestamp < ttl) {
|
|
241
|
+
return { rates: cache.rates, timestamp: cache.timestamp, stale: false }
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const rates = await fetchRates(ctx, config.url, config.count)
|
|
245
|
+
cache = { rates, timestamp: Date.now() }
|
|
246
|
+
return { rates, timestamp: cache.timestamp, stale: false }
|
|
247
|
+
} catch (e) {
|
|
248
|
+
const message = e instanceof Error ? e.message : String(e)
|
|
249
|
+
if (cache) {
|
|
250
|
+
logger.warn(`刷新失败,使用过期缓存: ${message}`)
|
|
251
|
+
return { rates: cache.rates, timestamp: cache.timestamp, stale: true, error: message }
|
|
252
|
+
}
|
|
253
|
+
throw e
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
73
257
|
ctx.command('bnsrate', '查询剑灵怀旧服神石汇率')
|
|
74
258
|
.alias('神石')
|
|
75
259
|
.alias('shenshi')
|
|
76
|
-
.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (cache && Date.now() - cache.timestamp < ttl) {
|
|
80
|
-
return formatMessage(cache.rates, cache.timestamp)
|
|
81
|
-
}
|
|
82
|
-
|
|
260
|
+
.option('force', '-f 忽略缓存,强制刷新')
|
|
261
|
+
.action(async ({ session, options }) => {
|
|
262
|
+
let data
|
|
83
263
|
try {
|
|
84
|
-
|
|
85
|
-
cache = { rates, timestamp: Date.now() }
|
|
86
|
-
return formatMessage(rates, cache.timestamp)
|
|
264
|
+
data = await resolveRates(!!(options && options.force))
|
|
87
265
|
} catch (e) {
|
|
88
266
|
const message = e instanceof Error ? e.message : String(e)
|
|
267
|
+
return '获取汇率失败: ' + message
|
|
268
|
+
}
|
|
89
269
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
270
|
+
// 官方QQ机器人的群聊/私聊:发 Markdown 卡片
|
|
271
|
+
if (config.markdown && session && supportsCard(session) && typeof session.send === 'function') {
|
|
272
|
+
const markdown = buildCardMarkdown(data.rates, data.timestamp, config)
|
|
273
|
+
try {
|
|
274
|
+
await session.send(buildCardElements(markdown, config))
|
|
275
|
+
return
|
|
276
|
+
} catch (e) {
|
|
277
|
+
logger.warn('Markdown 卡片发送失败,回退纯文本:', (e && e.message) || e)
|
|
93
278
|
}
|
|
279
|
+
}
|
|
94
280
|
|
|
281
|
+
return formatText(data.rates, data.timestamp, { stale: data.stale, error: data.error })
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
// 调试用:只看卡片源码,不发送卡片(在控制台执行时也能看)
|
|
285
|
+
ctx.command('bnsrate.preview', '预览神石 Markdown 卡片源码(不发送卡片)')
|
|
286
|
+
.action(async () => {
|
|
287
|
+
try {
|
|
288
|
+
const data = await resolveRates(false)
|
|
289
|
+
return buildCardMarkdown(data.rates, data.timestamp, config)
|
|
290
|
+
} catch (e) {
|
|
291
|
+
const message = e instanceof Error ? e.message : String(e)
|
|
95
292
|
return '获取汇率失败: ' + message
|
|
96
293
|
}
|
|
97
294
|
})
|
|
98
295
|
}
|
|
99
296
|
|
|
100
|
-
module.exports = {
|
|
297
|
+
module.exports = {
|
|
298
|
+
Config,
|
|
299
|
+
apply,
|
|
300
|
+
_test: { fetchRates, formatText, buildCardMarkdown, buildCardElements, supportsCard, fillTemplate, truncate },
|
|
301
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-bns-rate",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Fetch BNS Classic Divine Stone exchange rate from dd373.com",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Fetch BNS Classic Divine Stone exchange rate from dd373.com, with QQ official Markdown card support",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
6
10
|
"license": "MIT",
|
|
7
|
-
"keywords": ["koishi", "koishi-plugin", "bns", "dd373", "exchange-rate", "神石", "剑灵"],
|
|
11
|
+
"keywords": ["koishi", "koishi-plugin", "bns", "dd373", "exchange-rate", "神石", "剑灵", "markdown"],
|
|
8
12
|
"peerDependencies": {
|
|
9
13
|
"koishi": "^4.18.0"
|
|
10
14
|
},
|
|
@@ -13,8 +17,8 @@
|
|
|
13
17
|
},
|
|
14
18
|
"koishi": {
|
|
15
19
|
"description": {
|
|
16
|
-
"zh": "从 dd373.com
|
|
17
|
-
"en": "Fetch BNS Classic Divine Stone exchange rate from dd373.com"
|
|
20
|
+
"zh": "从 dd373.com 获取剑灵怀旧服神石实时汇率,输入 神石/bnsrate/shenshi 即可查询最低比例。支持官方QQ机器人 Markdown 卡片(标题+横幅图+红绿报价+跳转按钮),横幅图片与配色均可在插件设置页配置。",
|
|
21
|
+
"en": "Fetch BNS Classic Divine Stone exchange rate from dd373.com. Supports QQ official bot Markdown cards (title, banner image, colored rates, jump button), all configurable."
|
|
18
22
|
},
|
|
19
23
|
"service": {
|
|
20
24
|
"required": ["http"]
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [master]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- uses: actions/checkout@v4
|
|
12
|
-
- uses: actions/setup-node@v4
|
|
13
|
-
with:
|
|
14
|
-
node-version: '22'
|
|
15
|
-
registry-url: 'https://registry.npmjs.org'
|
|
16
|
-
- run: npm publish
|
|
17
|
-
env:
|
|
18
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|