nonebot-plugin-shiro-web-console 0.1.11__tar.gz → 0.1.13__tar.gz

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.

Potentially problematic release.


This version of nonebot-plugin-shiro-web-console might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-shiro-web-console
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: 一个用于 NoneBot2 的网页控制台插件,支持通过浏览器查看日志和发送消息
5
5
  Project-URL: Homepage, https://github.com/luojisama/nonebot-plugin-shiro-web-console
6
6
  Project-URL: Bug Tracker, https://github.com/luojisama/nonebot-plugin-shiro-web-console/issues
@@ -35,7 +35,7 @@ __plugin_meta__ = PluginMetadata(
35
35
  supported_adapters={"~onebot.v11"},
36
36
  extra={
37
37
  "author": "luojisama",
38
- "version": "0.1.11",
38
+ "version": "0.1.13",
39
39
  "pypi_test": "nonebot-plugin-shiro-web-console",
40
40
  },
41
41
  )
@@ -611,6 +611,7 @@ if app:
611
611
  @app.get("/web_console/api/plugins", dependencies=[Depends(check_auth)])
612
612
  async def get_plugins():
613
613
  from nonebot import get_loaded_plugins
614
+ from importlib.metadata import version, PackageNotFoundError
614
615
  import os
615
616
  plugins = []
616
617
  for p in get_loaded_plugins():
@@ -627,11 +628,26 @@ if app:
627
628
  elif module_name.startswith("nonebot_plugin_"):
628
629
  plugin_type = "store"
629
630
 
631
+ # 获取版本号
632
+ ver = "0.0.0"
633
+ # 优先尝试从 importlib 获取真实安装版本
634
+ try:
635
+ # 尝试将包名中的下划线替换为连字符(常见 PyPI 命名规范)
636
+ pkg_name = module_name.replace("_", "-")
637
+ ver = version(pkg_name)
638
+ except PackageNotFoundError:
639
+ try:
640
+ ver = version(module_name)
641
+ except PackageNotFoundError:
642
+ # 如果获取失败,回退到元数据中的版本
643
+ if metadata and metadata.extra and "version" in metadata.extra:
644
+ ver = metadata.extra.get("version", "0.0.0")
645
+
630
646
  plugins.append({
631
647
  "id": p.name,
632
648
  "name": metadata.name if metadata else p.name,
633
649
  "description": metadata.description if metadata else "暂无描述",
634
- "version": metadata.extra.get("version", "1.0.0") if metadata and metadata.extra else "1.0.0",
650
+ "version": ver,
635
651
  "type": plugin_type,
636
652
  "module": module_name,
637
653
  "homepage": metadata.homepage if metadata else None
@@ -514,6 +514,7 @@
514
514
  <div class="sub-nav">
515
515
  <div class="sub-nav-item active" id="tab-local" onclick="switchPluginTab('local')">已安装</div>
516
516
  <div class="sub-nav-item" id="tab-store" onclick="switchPluginTab('store')">插件商店</div>
517
+ <div class="sub-nav-item" id="tab-updates" onclick="switchPluginTab('updates')">检查更新</div>
517
518
  </div>
518
519
  </div>
519
520
  <div class="page-content" id="plugin-content" style="padding: 20px; background: var(--bg-main);">
@@ -533,6 +534,15 @@
533
534
  <span id="action-status" style="font-weight: bold; color: var(--primary-color);"></span>
534
535
  </div>
535
536
  </div>
537
+ <!-- 更新视图 -->
538
+ <div id="updates-view" style="display: none;">
539
+ <div id="updates-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px;">
540
+ <!-- 更新卡片 -->
541
+ </div>
542
+ <div id="updates-status-bar" style="margin-top: 20px; padding: 10px 0; font-size: 0.85em; color: var(--text-secondary); border-top: 1px solid var(--border-color);">
543
+ <span id="updates-count">正在检查更新...</span>
544
+ </div>
545
+ </div>
536
546
  </div>
537
547
  </div>
538
548
  </div>
@@ -1051,6 +1061,133 @@
1051
1061
  }
1052
1062
  }
1053
1063
 
1064
+ function switchPluginTab(tab) {
1065
+ // Update tabs
1066
+ document.querySelectorAll('.sub-nav-item').forEach(el => el.classList.remove('active'));
1067
+ document.getElementById(`tab-${tab}`).classList.add('active');
1068
+
1069
+ // Update views
1070
+ document.getElementById('local-plugins-view').style.display = 'none';
1071
+ document.getElementById('store-plugins-view').style.display = 'none';
1072
+ document.getElementById('updates-view').style.display = 'none';
1073
+
1074
+ // Show search bar only for local/store
1075
+ const searchContainer = document.getElementById('plugin-search-container');
1076
+ const localSearch = document.getElementById('local-plugin-search');
1077
+ const storeSearch = document.getElementById('store-search');
1078
+
1079
+ searchContainer.style.visibility = tab === 'updates' ? 'hidden' : 'visible';
1080
+ localSearch.style.display = tab === 'local' ? 'block' : 'none';
1081
+ storeSearch.style.display = tab === 'store' ? 'block' : 'none';
1082
+
1083
+ if (tab === 'local') {
1084
+ document.getElementById('local-plugins-view').style.display = 'block';
1085
+ fetchPlugins();
1086
+ } else if (tab === 'store') {
1087
+ document.getElementById('store-plugins-view').style.display = 'block';
1088
+ openStore();
1089
+ } else if (tab === 'updates') {
1090
+ document.getElementById('updates-view').style.display = 'block';
1091
+ openUpdates();
1092
+ }
1093
+ }
1094
+
1095
+ function compareVersions(v1, v2) {
1096
+ const parts1 = v1.split('.').map(p => parseInt(p, 10) || 0);
1097
+ const parts2 = v2.split('.').map(p => parseInt(p, 10) || 0);
1098
+
1099
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
1100
+ const n1 = parts1[i] || 0;
1101
+ const n2 = parts2[i] || 0;
1102
+ if (n1 > n2) return 1;
1103
+ if (n1 < n2) return -1;
1104
+ }
1105
+ return 0;
1106
+ }
1107
+
1108
+ async function openUpdates() {
1109
+ const listEl = document.getElementById('updates-list');
1110
+ const countEl = document.getElementById('updates-count');
1111
+
1112
+ listEl.innerHTML = '<div style="grid-column: 1/-1; text-align: center; color: #999;">正在检查更新...</div>';
1113
+ countEl.textContent = '正在获取数据...';
1114
+
1115
+ try {
1116
+ // 并行获取已安装插件和商店数据
1117
+ const [pluginsRes, storeRes] = await Promise.all([
1118
+ authorizedFetch('/web_console/api/plugins'),
1119
+ authorizedFetch('/web_console/api/store')
1120
+ ]);
1121
+
1122
+ const installedPlugins = await pluginsRes.json();
1123
+ const storeData = await storeRes.json();
1124
+
1125
+ if (storeData.error) {
1126
+ listEl.innerHTML = `<div style="grid-column: 1/-1; text-align: center; color: #dc3545;">${storeData.error}</div>`;
1127
+ return;
1128
+ }
1129
+
1130
+ // 筛选有更新的插件
1131
+ const updates = [];
1132
+
1133
+ installedPlugins.forEach(local => {
1134
+ // 通过 module_name 匹配
1135
+ const storePlugin = storeData.find(s => s.module_name === local.module || s.project_link === local.id);
1136
+
1137
+ if (storePlugin) {
1138
+ // 移除 'v' 前缀进行比较
1139
+ const v1 = (local.version || '0.0.0').replace(/^v/, '');
1140
+ const v2 = (storePlugin.version || '0.0.0').replace(/^v/, '');
1141
+
1142
+ // 只显示商店版本大于本地版本的情况
1143
+ if (compareVersions(v2, v1) > 0) {
1144
+ updates.push({
1145
+ local: local,
1146
+ store: storePlugin
1147
+ });
1148
+ }
1149
+ }
1150
+ });
1151
+
1152
+ if (updates.length === 0) {
1153
+ listEl.innerHTML = '<div style="grid-column: 1/-1; text-align: center; color: #999; padding: 40px;">所有插件已是最新版本 🎉</div>';
1154
+ countEl.textContent = '暂无更新';
1155
+ } else {
1156
+ renderUpdates(updates);
1157
+ countEl.textContent = `发现 ${updates.length} 个可更新插件`;
1158
+ }
1159
+
1160
+ } catch (e) {
1161
+ listEl.innerHTML = `<div style="grid-column: 1/-1; text-align: center; color: #dc3545;">检查更新失败: ${e.message}</div>`;
1162
+ }
1163
+ }
1164
+
1165
+ function renderUpdates(updates) {
1166
+ const listEl = document.getElementById('updates-list');
1167
+ listEl.innerHTML = updates.map(item => {
1168
+ const p = item.store;
1169
+ const local = item.local;
1170
+ return `
1171
+ <div class="store-card" style="border-left: 4px solid var(--primary-color);">
1172
+ <div style="display: flex; justify-content: space-between; align-items: center; gap: 10px; min-width: 0;">
1173
+ <a href="${p.homepage || '#'}" target="_blank" class="store-name" title="${p.name}">${p.name}</a>
1174
+ <span class="plugin-tag tag-store" style="font-size: 0.6em;">更新</span>
1175
+ </div>
1176
+ <div class="store-desc" title="${p.desc}">${p.desc}</div>
1177
+ <div class="store-meta" style="margin-top: 10px; display: grid; grid-template-columns: auto 1fr; gap: 5px 15px; font-size: 0.85em;">
1178
+ <span style="color: #999;">当前版本:</span>
1179
+ <span style="font-family: monospace;">${local.version}</span>
1180
+ <span style="color: var(--primary-color); font-weight: bold;">最新版本:</span>
1181
+ <span style="font-family: monospace; color: var(--primary-color); font-weight: bold;">${p.version}</span>
1182
+ </div>
1183
+ <div class="store-footer">
1184
+ <button onclick="handleStoreAction('update', '${p.project_link}')" class="store-btn store-btn-update" style="width: 100%;">立即更新</button>
1185
+ </div>
1186
+ </div>
1187
+ `;
1188
+ }).join('');
1189
+ }
1190
+
1054
1191
  function filterLocalPlugins() {
1055
1192
  const kw = document.getElementById('local-plugin-search').value.toLowerCase();
1056
1193
  const cards = document.querySelectorAll('#plugin-list .plugin-card');
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-shiro-web-console"
3
- version = "0.1.11"
3
+ version = "0.1.13"
4
4
  description = "一个用于 NoneBot2 的网页控制台插件,支持通过浏览器查看日志和发送消息"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"