koishi-plugin-adapter-onebot-multi 0.0.10 → 0.0.11

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.
Files changed (2) hide show
  1. package/lib/index.js +162 -0
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -1628,6 +1628,51 @@ 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/profile`, authMiddleware, async (ctx) => {
1632
+ const data = await this.parseJsonBody(ctx);
1633
+ const selfId = String(data.selfId);
1634
+ const nickname = data.nickname || "";
1635
+ const bot = this.ctx.bots.find((b) => b.selfId === selfId && b.platform === "onebot");
1636
+ if (!bot) {
1637
+ ctx.status = 404;
1638
+ ctx.body = { error: `Bot ${selfId} 未在线` };
1639
+ return;
1640
+ }
1641
+ try {
1642
+ await bot.internal.setQqProfile(nickname, "", "", "", "");
1643
+ this.ctx.logger.info(`修改 Bot ${selfId} 昵称为: ${nickname}`);
1644
+ ctx.body = { success: true };
1645
+ } catch (error) {
1646
+ this.ctx.logger.error("修改资料失败:", error);
1647
+ ctx.status = 500;
1648
+ ctx.body = { error: "修改失败: " + error.message };
1649
+ }
1650
+ });
1651
+ router.post(`${adminPath}/api/bots/avatar`, authMiddleware, async (ctx) => {
1652
+ const data = await this.parseJsonBody(ctx);
1653
+ const selfId = String(data.selfId);
1654
+ const file = data.file;
1655
+ const bot = this.ctx.bots.find((b) => b.selfId === selfId && b.platform === "onebot");
1656
+ if (!bot) {
1657
+ ctx.status = 404;
1658
+ ctx.body = { error: `Bot ${selfId} 未在线` };
1659
+ return;
1660
+ }
1661
+ if (!file) {
1662
+ ctx.status = 400;
1663
+ ctx.body = { error: "请提供图片" };
1664
+ return;
1665
+ }
1666
+ try {
1667
+ await bot.internal.setQqAvatar(file);
1668
+ this.ctx.logger.info(`修改 Bot ${selfId} 头像`);
1669
+ ctx.body = { success: true };
1670
+ } catch (error) {
1671
+ this.ctx.logger.error("修改头像失败:", error);
1672
+ ctx.status = 500;
1673
+ ctx.body = { error: "修改失败: " + error.message };
1674
+ }
1675
+ });
1631
1676
  if (this.config.port) {
1632
1677
  this.app = new import_koa.default();
1633
1678
  this.app.use(router.routes());
@@ -1930,6 +1975,35 @@ var StatusPanel = class {
1930
1975
  </div>
1931
1976
  </div>
1932
1977
 
1978
+ <!-- 编辑 Bot 模态框 -->
1979
+ <div class="modal" id="editModal">
1980
+ <div class="modal-content">
1981
+ <h2>编辑 Bot 资料</h2>
1982
+ <form id="editForm">
1983
+ <input type="hidden" id="editSelfId">
1984
+ <div class="form-group">
1985
+ <label for="editNickname">昵称</label>
1986
+ <input type="text" id="editNickname" placeholder="新的QQ昵称">
1987
+ </div>
1988
+ <div class="form-group">
1989
+ <label for="editAvatar">头像</label>
1990
+ <input type="file" id="editAvatar" accept="image/*" style="display:none">
1991
+ <div style="display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;">
1992
+ <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('editAvatar').click()" style="padding:0.5rem 1rem;">选择图片</button>
1994
+ <span id="avatarFileName" style="font-size:0.85rem;color:#92400e;"></span>
1995
+ </div>
1996
+ <p style="font-size:0.8rem;color:#92400e;margin-top:0.5rem;">支持本地图片或输入图片URL</p>
1997
+ <input type="text" id="editAvatarUrl" placeholder="或输入图片URL" style="margin-top:0.5rem;">
1998
+ </div>
1999
+ <div class="modal-actions">
2000
+ <button type="submit" class="btn">保存</button>
2001
+ <button type="button" class="btn btn-secondary" onclick="hideEditModal()">取消</button>
2002
+ </div>
2003
+ </form>
2004
+ </div>
2005
+ </div>
2006
+
1933
2007
  <!-- Toast -->
1934
2008
  <div class="toast" id="toast"></div>
1935
2009
 
@@ -2138,6 +2212,7 @@ var StatusPanel = class {
2138
2212
  '<div class="bot-actions">' +
2139
2213
  '<button class="btn btn-secondary" onclick="toggleBot(' + bot.id + ')">' + (bot.enabled ? '禁用' : '启用') + '</button>' +
2140
2214
  '<button class="btn btn-secondary" onclick="restartBot(' + bot.id + ')">重启</button>' +
2215
+ (bot.status === 'online' ? '<button class="btn btn-secondary" onclick="showEditModal(\\'' + bot.selfId + '\\', \\'' + (bot.nickname || '').replace(/'/g, "\\\\'") + '\\')">编辑</button>' : '') +
2141
2216
  '<button class="btn btn-danger" onclick="deleteBot(' + bot.id + ', \\'' + bot.name + '\\')">删除</button>' +
2142
2217
  '</div>' +
2143
2218
  '</div>'
@@ -2221,6 +2296,93 @@ var StatusPanel = class {
2221
2296
  }
2222
2297
  })
2223
2298
 
2299
+ // 编辑 Bot 模态框
2300
+ let editAvatarFile = null
2301
+
2302
+ function showEditModal(selfId, nickname) {
2303
+ document.getElementById('editSelfId').value = selfId
2304
+ document.getElementById('editNickname').value = nickname || ''
2305
+ document.getElementById('avatarPreview').src = 'http://q.qlogo.cn/headimg_dl?dst_uin=' + selfId + '&spec=640'
2306
+ document.getElementById('avatarFileName').textContent = ''
2307
+ document.getElementById('editAvatarUrl').value = ''
2308
+ editAvatarFile = null
2309
+ document.getElementById('editModal').classList.add('active')
2310
+ }
2311
+
2312
+ function hideEditModal() {
2313
+ document.getElementById('editModal').classList.remove('active')
2314
+ editAvatarFile = null
2315
+ }
2316
+
2317
+ // 头像文件选择
2318
+ document.getElementById('editAvatar').addEventListener('change', function(e) {
2319
+ const file = e.target.files[0]
2320
+ if (file) {
2321
+ editAvatarFile = file
2322
+ document.getElementById('avatarFileName').textContent = file.name
2323
+ // 预览
2324
+ const reader = new FileReader()
2325
+ reader.onload = function(ev) {
2326
+ document.getElementById('avatarPreview').src = ev.target.result
2327
+ }
2328
+ reader.readAsDataURL(file)
2329
+ }
2330
+ })
2331
+
2332
+ // 编辑表单提交
2333
+ document.getElementById('editForm').addEventListener('submit', async (e) => {
2334
+ e.preventDefault()
2335
+ const selfId = document.getElementById('editSelfId').value
2336
+ const nickname = document.getElementById('editNickname').value
2337
+ const avatarUrl = document.getElementById('editAvatarUrl').value
2338
+
2339
+ let hasChange = false
2340
+
2341
+ // 修改昵称
2342
+ if (nickname) {
2343
+ try {
2344
+ await api('/bots/profile', { selfId, nickname })
2345
+ showToast('昵称修改成功')
2346
+ hasChange = true
2347
+ } catch (e) {
2348
+ showToast('昵称修改失败: ' + e.message, 'error')
2349
+ }
2350
+ }
2351
+
2352
+ // 修改头像
2353
+ if (editAvatarFile) {
2354
+ // 本地文件转 base64
2355
+ const reader = new FileReader()
2356
+ reader.onload = async function(ev) {
2357
+ try {
2358
+ await api('/bots/avatar', { selfId, file: ev.target.result })
2359
+ showToast('头像修改成功')
2360
+ refreshBots()
2361
+ } catch (e) {
2362
+ showToast('头像修改失败: ' + e.message, 'error')
2363
+ }
2364
+ }
2365
+ reader.readAsDataURL(editAvatarFile)
2366
+ hasChange = true
2367
+ } else if (avatarUrl) {
2368
+ // URL 方式
2369
+ try {
2370
+ await api('/bots/avatar', { selfId, file: avatarUrl })
2371
+ showToast('头像修改成功')
2372
+ hasChange = true
2373
+ } catch (e) {
2374
+ showToast('头像修改失败: ' + e.message, 'error')
2375
+ }
2376
+ }
2377
+
2378
+ if (hasChange) {
2379
+ hideEditModal()
2380
+ setTimeout(refreshBots, 1000)
2381
+ } else {
2382
+ showToast('未做任何修改', 'error')
2383
+ }
2384
+ })
2385
+
2224
2386
  // 自动刷新
2225
2387
  setInterval(() => {
2226
2388
  if (document.getElementById('adminView').classList.contains('show')) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-adapter-onebot-multi",
3
3
  "description": "奶龙bot定制版onebot适配器,支持自动负载均衡,适配器级黑名单/白名单,提供webui,可指定端口",
4
- "version": "0.0.10",
4
+ "version": "0.0.11",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [