koishi-plugin-adapter-onebot-multi 0.0.11 → 0.0.12
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/lib/index.js +145 -35
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1628,6 +1628,32 @@ var StatusPanel = class {
|
|
|
1628
1628
|
this.ctx.logger.info(`重启 Bot 配置: #${id} ${config.name}`);
|
|
1629
1629
|
ctx.body = { success: true };
|
|
1630
1630
|
});
|
|
1631
|
+
router.post(`${adminPath}/api/bots/update`, authMiddleware, async (ctx) => {
|
|
1632
|
+
const data = await this.parseJsonBody(ctx);
|
|
1633
|
+
const id = Number(data.id);
|
|
1634
|
+
const existing = await this.configManager.getConfigById(id);
|
|
1635
|
+
if (!existing) {
|
|
1636
|
+
ctx.status = 404;
|
|
1637
|
+
ctx.body = { error: `配置 #${id} 不存在` };
|
|
1638
|
+
return;
|
|
1639
|
+
}
|
|
1640
|
+
const updates = {};
|
|
1641
|
+
if (data.name !== void 0) updates.name = data.name;
|
|
1642
|
+
if (data.protocol !== void 0) updates.protocol = data.protocol;
|
|
1643
|
+
if (data.endpoint !== void 0) updates.endpoint = data.endpoint;
|
|
1644
|
+
if (data.path !== void 0) updates.path = data.path;
|
|
1645
|
+
if (data.token !== void 0) updates.token = data.token;
|
|
1646
|
+
await this.configManager.updateConfigById(id, updates);
|
|
1647
|
+
this.ctx.logger.info(`更新 Bot 配置: #${id} ${existing.name}`);
|
|
1648
|
+
if (existing.enabled && existing.selfId) {
|
|
1649
|
+
await this.stopBot(existing.selfId);
|
|
1650
|
+
const newConfig = await this.configManager.getConfigById(id);
|
|
1651
|
+
if (newConfig) {
|
|
1652
|
+
await this.startBot(this.configManager.toBotConfig(newConfig));
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
ctx.body = { success: true };
|
|
1656
|
+
});
|
|
1631
1657
|
router.post(`${adminPath}/api/bots/profile`, authMiddleware, async (ctx) => {
|
|
1632
1658
|
const data = await this.parseJsonBody(ctx);
|
|
1633
1659
|
const selfId = String(data.selfId);
|
|
@@ -1975,30 +2001,67 @@ var StatusPanel = class {
|
|
|
1975
2001
|
</div>
|
|
1976
2002
|
</div>
|
|
1977
2003
|
|
|
1978
|
-
<!-- 编辑 Bot
|
|
1979
|
-
<div class="modal" id="
|
|
2004
|
+
<!-- 编辑 Bot 配置模态框 -->
|
|
2005
|
+
<div class="modal" id="configModal">
|
|
2006
|
+
<div class="modal-content">
|
|
2007
|
+
<h2>编辑 Bot 配置</h2>
|
|
2008
|
+
<form id="configForm">
|
|
2009
|
+
<input type="hidden" id="configId">
|
|
2010
|
+
<div class="form-group">
|
|
2011
|
+
<label for="configEditName">配置名称 *</label>
|
|
2012
|
+
<input type="text" id="configEditName" required placeholder="例如: 主号、小号">
|
|
2013
|
+
</div>
|
|
2014
|
+
<div class="form-group">
|
|
2015
|
+
<label for="configProtocol">协议</label>
|
|
2016
|
+
<select id="configProtocol" onchange="toggleConfigEndpoint()">
|
|
2017
|
+
<option value="ws-reverse">反向 WebSocket (ws-reverse)</option>
|
|
2018
|
+
<option value="ws">正向 WebSocket (ws)</option>
|
|
2019
|
+
</select>
|
|
2020
|
+
</div>
|
|
2021
|
+
<div class="form-group" id="configEndpointGroup" style="display: none;">
|
|
2022
|
+
<label for="configEndpoint">Endpoint *</label>
|
|
2023
|
+
<input type="text" id="configEndpoint" placeholder="例如: ws://127.0.0.1:6700">
|
|
2024
|
+
</div>
|
|
2025
|
+
<div class="form-group" id="configPathGroup">
|
|
2026
|
+
<label for="configPath">路径</label>
|
|
2027
|
+
<input type="text" id="configPath" placeholder="例如: /onebot">
|
|
2028
|
+
</div>
|
|
2029
|
+
<div class="form-group">
|
|
2030
|
+
<label for="configToken">Token(可选)</label>
|
|
2031
|
+
<input type="password" id="configToken" placeholder="访问令牌(留空不修改)">
|
|
2032
|
+
</div>
|
|
2033
|
+
<div class="modal-actions">
|
|
2034
|
+
<button type="submit" class="btn">保存</button>
|
|
2035
|
+
<button type="button" class="btn btn-secondary" onclick="hideConfigModal()">取消</button>
|
|
2036
|
+
</div>
|
|
2037
|
+
</form>
|
|
2038
|
+
</div>
|
|
2039
|
+
</div>
|
|
2040
|
+
|
|
2041
|
+
<!-- 修改 Bot 资料模态框 -->
|
|
2042
|
+
<div class="modal" id="profileModal">
|
|
1980
2043
|
<div class="modal-content">
|
|
1981
|
-
<h2
|
|
1982
|
-
<form id="
|
|
1983
|
-
<input type="hidden" id="
|
|
2044
|
+
<h2>修改 Bot 资料</h2>
|
|
2045
|
+
<form id="profileForm">
|
|
2046
|
+
<input type="hidden" id="profileSelfId">
|
|
1984
2047
|
<div class="form-group">
|
|
1985
|
-
<label for="
|
|
1986
|
-
<input type="text" id="
|
|
2048
|
+
<label for="profileNickname">昵称</label>
|
|
2049
|
+
<input type="text" id="profileNickname" placeholder="新的QQ昵称">
|
|
1987
2050
|
</div>
|
|
1988
2051
|
<div class="form-group">
|
|
1989
|
-
<label for="
|
|
1990
|
-
<input type="file" id="
|
|
2052
|
+
<label for="profileAvatar">头像</label>
|
|
2053
|
+
<input type="file" id="profileAvatar" accept="image/*" style="display:none">
|
|
1991
2054
|
<div style="display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;">
|
|
1992
2055
|
<img id="avatarPreview" style="width:64px;height:64px;border:var(--nl-border);border-radius:50%;object-fit:cover;">
|
|
1993
|
-
<button type="button" class="btn btn-secondary" onclick="document.getElementById('
|
|
2056
|
+
<button type="button" class="btn btn-secondary" onclick="document.getElementById('profileAvatar').click()" style="padding:0.5rem 1rem;">选择图片</button>
|
|
1994
2057
|
<span id="avatarFileName" style="font-size:0.85rem;color:#92400e;"></span>
|
|
1995
2058
|
</div>
|
|
1996
2059
|
<p style="font-size:0.8rem;color:#92400e;margin-top:0.5rem;">支持本地图片或输入图片URL</p>
|
|
1997
|
-
<input type="text" id="
|
|
2060
|
+
<input type="text" id="profileAvatarUrl" placeholder="或输入图片URL" style="margin-top:0.5rem;">
|
|
1998
2061
|
</div>
|
|
1999
2062
|
<div class="modal-actions">
|
|
2000
2063
|
<button type="submit" class="btn">保存</button>
|
|
2001
|
-
<button type="button" class="btn btn-secondary" onclick="
|
|
2064
|
+
<button type="button" class="btn btn-secondary" onclick="hideProfileModal()">取消</button>
|
|
2002
2065
|
</div>
|
|
2003
2066
|
</form>
|
|
2004
2067
|
</div>
|
|
@@ -2212,8 +2275,9 @@ var StatusPanel = class {
|
|
|
2212
2275
|
'<div class="bot-actions">' +
|
|
2213
2276
|
'<button class="btn btn-secondary" onclick="toggleBot(' + bot.id + ')">' + (bot.enabled ? '禁用' : '启用') + '</button>' +
|
|
2214
2277
|
'<button class="btn btn-secondary" onclick="restartBot(' + bot.id + ')">重启</button>' +
|
|
2215
|
-
|
|
2216
|
-
'<button class="btn btn-
|
|
2278
|
+
'<button class="btn btn-secondary" onclick="showConfigModal(' + bot.id + ', \\'' + bot.name.replace(/'/g, "\\\\'") + '\\', \\'' + (bot.protocol || 'ws-reverse') + '\\', \\'' + (bot.endpoint || '').replace(/'/g, "\\\\'") + '\\', \\'' + (bot.path || '/onebot').replace(/'/g, "\\\\'") + '\\')">配置</button>' +
|
|
2279
|
+
(bot.status === 'online' ? '<button class="btn btn-secondary" onclick="showProfileModal(\\'' + bot.selfId + '\\', \\'' + (bot.nickname || '').replace(/'/g, "\\\\'") + '\\')">资料</button>' : '') +
|
|
2280
|
+
'<button class="btn btn-danger" onclick="deleteBot(' + bot.id + ', \\'' + bot.name.replace(/'/g, "\\\\'") + '\\')">删除</button>' +
|
|
2217
2281
|
'</div>' +
|
|
2218
2282
|
'</div>'
|
|
2219
2283
|
}).join('')
|
|
@@ -2296,29 +2360,75 @@ var StatusPanel = class {
|
|
|
2296
2360
|
}
|
|
2297
2361
|
})
|
|
2298
2362
|
|
|
2299
|
-
// 编辑 Bot
|
|
2300
|
-
|
|
2363
|
+
// 编辑 Bot 配置模态框
|
|
2364
|
+
function showConfigModal(id, name, protocol, endpoint, path) {
|
|
2365
|
+
document.getElementById('configId').value = id
|
|
2366
|
+
document.getElementById('configEditName').value = name || ''
|
|
2367
|
+
document.getElementById('configProtocol').value = protocol || 'ws-reverse'
|
|
2368
|
+
document.getElementById('configEndpoint').value = endpoint || ''
|
|
2369
|
+
document.getElementById('configPath').value = path || '/onebot'
|
|
2370
|
+
document.getElementById('configToken').value = ''
|
|
2371
|
+
toggleConfigEndpoint()
|
|
2372
|
+
document.getElementById('configModal').classList.add('active')
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
function hideConfigModal() {
|
|
2376
|
+
document.getElementById('configModal').classList.remove('active')
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
function toggleConfigEndpoint() {
|
|
2380
|
+
const protocol = document.getElementById('configProtocol').value
|
|
2381
|
+
document.getElementById('configEndpointGroup').style.display = protocol === 'ws' ? 'block' : 'none'
|
|
2382
|
+
document.getElementById('configPathGroup').style.display = protocol === 'ws-reverse' ? 'block' : 'none'
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
document.getElementById('configForm').addEventListener('submit', async (e) => {
|
|
2386
|
+
e.preventDefault()
|
|
2387
|
+
const id = document.getElementById('configId').value
|
|
2388
|
+
const data = {
|
|
2389
|
+
id: Number(id),
|
|
2390
|
+
name: document.getElementById('configEditName').value,
|
|
2391
|
+
protocol: document.getElementById('configProtocol').value,
|
|
2392
|
+
endpoint: document.getElementById('configEndpoint').value || undefined,
|
|
2393
|
+
path: document.getElementById('configPath').value || undefined,
|
|
2394
|
+
}
|
|
2395
|
+
// Token 留空不修改
|
|
2396
|
+
const token = document.getElementById('configToken').value
|
|
2397
|
+
if (token) data.token = token
|
|
2398
|
+
|
|
2399
|
+
try {
|
|
2400
|
+
await api('/bots/update', data)
|
|
2401
|
+
showToast('配置更新成功')
|
|
2402
|
+
hideConfigModal()
|
|
2403
|
+
refreshBots()
|
|
2404
|
+
} catch (e) {
|
|
2405
|
+
showToast('更新失败: ' + e.message, 'error')
|
|
2406
|
+
}
|
|
2407
|
+
})
|
|
2408
|
+
|
|
2409
|
+
// 修改 Bot 资料模态框
|
|
2410
|
+
let profileAvatarFile = null
|
|
2301
2411
|
|
|
2302
|
-
function
|
|
2303
|
-
document.getElementById('
|
|
2304
|
-
document.getElementById('
|
|
2412
|
+
function showProfileModal(selfId, nickname) {
|
|
2413
|
+
document.getElementById('profileSelfId').value = selfId
|
|
2414
|
+
document.getElementById('profileNickname').value = nickname || ''
|
|
2305
2415
|
document.getElementById('avatarPreview').src = 'http://q.qlogo.cn/headimg_dl?dst_uin=' + selfId + '&spec=640'
|
|
2306
2416
|
document.getElementById('avatarFileName').textContent = ''
|
|
2307
|
-
document.getElementById('
|
|
2308
|
-
|
|
2309
|
-
document.getElementById('
|
|
2417
|
+
document.getElementById('profileAvatarUrl').value = ''
|
|
2418
|
+
profileAvatarFile = null
|
|
2419
|
+
document.getElementById('profileModal').classList.add('active')
|
|
2310
2420
|
}
|
|
2311
2421
|
|
|
2312
|
-
function
|
|
2313
|
-
document.getElementById('
|
|
2314
|
-
|
|
2422
|
+
function hideProfileModal() {
|
|
2423
|
+
document.getElementById('profileModal').classList.remove('active')
|
|
2424
|
+
profileAvatarFile = null
|
|
2315
2425
|
}
|
|
2316
2426
|
|
|
2317
2427
|
// 头像文件选择
|
|
2318
|
-
document.getElementById('
|
|
2428
|
+
document.getElementById('profileAvatar').addEventListener('change', function(e) {
|
|
2319
2429
|
const file = e.target.files[0]
|
|
2320
2430
|
if (file) {
|
|
2321
|
-
|
|
2431
|
+
profileAvatarFile = file
|
|
2322
2432
|
document.getElementById('avatarFileName').textContent = file.name
|
|
2323
2433
|
// 预览
|
|
2324
2434
|
const reader = new FileReader()
|
|
@@ -2329,12 +2439,12 @@ var StatusPanel = class {
|
|
|
2329
2439
|
}
|
|
2330
2440
|
})
|
|
2331
2441
|
|
|
2332
|
-
//
|
|
2333
|
-
document.getElementById('
|
|
2442
|
+
// 资料表单提交
|
|
2443
|
+
document.getElementById('profileForm').addEventListener('submit', async (e) => {
|
|
2334
2444
|
e.preventDefault()
|
|
2335
|
-
const selfId = document.getElementById('
|
|
2336
|
-
const nickname = document.getElementById('
|
|
2337
|
-
const avatarUrl = document.getElementById('
|
|
2445
|
+
const selfId = document.getElementById('profileSelfId').value
|
|
2446
|
+
const nickname = document.getElementById('profileNickname').value
|
|
2447
|
+
const avatarUrl = document.getElementById('profileAvatarUrl').value
|
|
2338
2448
|
|
|
2339
2449
|
let hasChange = false
|
|
2340
2450
|
|
|
@@ -2350,7 +2460,7 @@ var StatusPanel = class {
|
|
|
2350
2460
|
}
|
|
2351
2461
|
|
|
2352
2462
|
// 修改头像
|
|
2353
|
-
if (
|
|
2463
|
+
if (profileAvatarFile) {
|
|
2354
2464
|
// 本地文件转 base64
|
|
2355
2465
|
const reader = new FileReader()
|
|
2356
2466
|
reader.onload = async function(ev) {
|
|
@@ -2362,7 +2472,7 @@ var StatusPanel = class {
|
|
|
2362
2472
|
showToast('头像修改失败: ' + e.message, 'error')
|
|
2363
2473
|
}
|
|
2364
2474
|
}
|
|
2365
|
-
reader.readAsDataURL(
|
|
2475
|
+
reader.readAsDataURL(profileAvatarFile)
|
|
2366
2476
|
hasChange = true
|
|
2367
2477
|
} else if (avatarUrl) {
|
|
2368
2478
|
// URL 方式
|
|
@@ -2376,7 +2486,7 @@ var StatusPanel = class {
|
|
|
2376
2486
|
}
|
|
2377
2487
|
|
|
2378
2488
|
if (hasChange) {
|
|
2379
|
-
|
|
2489
|
+
hideProfileModal()
|
|
2380
2490
|
setTimeout(refreshBots, 1000)
|
|
2381
2491
|
} else {
|
|
2382
2492
|
showToast('未做任何修改', 'error')
|
package/package.json
CHANGED