nonebot-plugin-picmenu-next 0.1.0.dev1__tar.gz → 0.1.0.post1__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.
Files changed (92) hide show
  1. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/PKG-INFO +69 -18
  2. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/README.md +64 -16
  3. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/__init__.py +2 -6
  4. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/__main__.py +61 -41
  5. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/config.py +7 -0
  6. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/data_source/__init__.py +16 -0
  7. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/data_source/collect.py +126 -0
  8. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/data_source/mixin.py +225 -0
  9. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/data_source/models.py +93 -0
  10. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/data_source/pinyin.py +51 -0
  11. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/ft_parser.py +222 -0
  12. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/res/gan_shen_me.jpg +0 -0
  13. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/__init__.py +13 -3
  14. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/__init__.py +23 -44
  15. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/base.html.jinja +11 -4
  16. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/css/base.css +96 -3
  17. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/css/dark.css +2 -1
  18. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/css/index.css +0 -1
  19. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/detail.html.jinja +21 -19
  20. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/index.html.jinja +6 -2
  21. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/js/base.js +7 -0
  22. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/js/tsconfig.json +8 -0
  23. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/code-colorful.css +69 -0
  24. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/code-github-dark.css +81 -0
  25. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_AMS-Regular.ttf +0 -0
  26. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_AMS-Regular.woff +0 -0
  27. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  28. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  29. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  30. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  31. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  32. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  33. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  34. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  35. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  36. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  37. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  38. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  39. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  40. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Bold.ttf +0 -0
  41. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Bold.woff +0 -0
  42. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Bold.woff2 +0 -0
  43. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  44. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  45. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  46. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Italic.ttf +0 -0
  47. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Italic.woff +0 -0
  48. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Italic.woff2 +0 -0
  49. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Regular.ttf +0 -0
  50. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Regular.woff +0 -0
  51. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Main-Regular.woff2 +0 -0
  52. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  53. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  54. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  55. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-Italic.ttf +0 -0
  56. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-Italic.woff +0 -0
  57. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Math-Italic.woff2 +0 -0
  58. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  59. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  60. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  61. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  62. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  63. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  64. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  65. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  66. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  67. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Script-Regular.ttf +0 -0
  68. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Script-Regular.woff +0 -0
  69. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Script-Regular.woff2 +0 -0
  70. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size1-Regular.ttf +0 -0
  71. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size1-Regular.woff +0 -0
  72. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  73. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size2-Regular.ttf +0 -0
  74. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size2-Regular.woff +0 -0
  75. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  76. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size3-Regular.ttf +0 -0
  77. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size3-Regular.woff +0 -0
  78. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  79. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size4-Regular.ttf +0 -0
  80. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size4-Regular.woff +0 -0
  81. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  82. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  83. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  84. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  85. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/katex.min.css +1 -0
  86. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/default/res/third-party/katex.min.js +1 -0
  87. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/templates/pw_utils.py +82 -0
  88. nonebot_plugin_picmenu_next-0.1.0.post1/nonebot_plugin_picmenu_next/utils.py +18 -0
  89. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/pyproject.toml +5 -2
  90. nonebot_plugin_picmenu_next-0.1.0.dev1/nonebot_plugin_picmenu_next/data_source.py +0 -341
  91. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/LICENSE +0 -0
  92. {nonebot_plugin_picmenu_next-0.1.0.dev1 → nonebot_plugin_picmenu_next-0.1.0.post1}/nonebot_plugin_picmenu_next/templates/default/res/css/detail.css +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-picmenu-next
3
- Version: 0.1.0.dev1
3
+ Version: 0.1.0.post1
4
4
  Summary: Template plugin project
5
5
  Author-Email: LgCookie <lgc2333@126.com>
6
6
  License: MIT
@@ -8,10 +8,13 @@ Project-URL: homepage, https://github.com/lgc-NB2Dev/nonebot-plugin-picmenu-next
8
8
  Requires-Python: <4.0,>=3.9
9
9
  Requires-Dist: nonebot2>=2.4.1
10
10
  Requires-Dist: nonebot-plugin-alconna>=0.54.2
11
- Requires-Dist: cookit[jinja,loguru,nonebot-alconna,nonebot-localstore,pw,pyd]>=0.11.2
11
+ Requires-Dist: cookit[jinja,loguru,nonebot-alconna,pw,pyd]>=0.11.6
12
12
  Requires-Dist: pypinyin>=0.54.0
13
13
  Requires-Dist: jieba>=0.42.1
14
14
  Requires-Dist: thefuzz>=0.22.1
15
+ Requires-Dist: markdown-it-py[plugins]>=3.0.0
16
+ Requires-Dist: pygments>=2.19.1
17
+ Requires-Dist: nonebot-plugin-htmlrender>=0.6.5
15
18
  Description-Content-Type: text/markdown
16
19
 
17
20
  <!-- markdownlint-disable MD031 MD033 MD036 MD041 -->
@@ -28,7 +31,7 @@ Description-Content-Type: text/markdown
28
31
 
29
32
  # NoneBot-Plugin-PicMenu-Next
30
33
 
31
- _✨ NoneBot 插件简单描述 ✨_
34
+ _✨ 新一代的图片帮助插件 ✨_
32
35
 
33
36
  <img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
34
37
  <a href="https://pdm.fming.dev">
@@ -66,7 +69,56 @@ _✨ NoneBot 插件简单描述 ✨_
66
69
 
67
70
  ## 📖 介绍
68
71
 
69
- 这里是插件的详细介绍部分
72
+ - ✨ **美观的图片界面**:直观友好的图片界面
73
+ - 🛠️ **PicMenu 兼容**:本插件使用 PicMenu 插件格式的三级菜单(功能详情),兼容 PicMenu 的 `<ft>` 富文本标签(但不太推荐使用)
74
+ - 🔍 **支持模糊搜索**:支持通过序号或名称查找插件及功能,并提供插件名称的模糊匹配
75
+ - 🔤 **拼音支持**:插件排序与模糊搜索时考虑拼音,提高中文环境下的使用体验
76
+ - 📜 **Markdown 支持**:支持 Markdown 格式的帮助信息展示(需要插件开发者主动适配)
77
+ - 🔒 **隐藏控制**:默认状态下类型为 `library` 的插件会对普通用户隐藏
78
+ - 🎨 **自定义模板**:提供模板开发者注册模板的接口,提供插件开发者自定义某插件使用的详细信息模板的方式,提供配置供用户自定义想要使用的模板
79
+ - 🔌 **插件扩展机制**:提供强大的 mixin 支持,允许插件通过中间件方式自定义帮助菜单展示和行为
80
+
81
+ ### 展示图
82
+
83
+ <details>
84
+ <summary>主页面</summary>
85
+
86
+ ![亮色主页](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_main.jpg)
87
+ ![暗色主页](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_main.jpg)
88
+
89
+ </details>
90
+
91
+ <details>
92
+ <summary>插件详情</summary>
93
+
94
+ ![亮色插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_detail.jpg)
95
+ ![暗色插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_detail.jpg)
96
+
97
+ </details>
98
+
99
+ <details>
100
+ <summary>插件详情(带功能详情三级菜单)</summary>
101
+
102
+ ![亮色带三级菜单插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_with_func.jpg)
103
+ ![暗色带三级菜单插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_with_func.jpg)
104
+
105
+ </details>
106
+
107
+ <details>
108
+ <summary>功能详情</summary>
109
+
110
+ ![亮色功能详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_func_detail.jpg)
111
+ ![暗色功能详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_func_detail.jpg)
112
+
113
+ </details>
114
+
115
+ <details>
116
+ <summary>Markdown 测试</summary>
117
+
118
+ ![亮色 Markdown 测试](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_markdown.jpg)
119
+ ![暗色 Markdown 测试](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_markdown.jpg)
120
+
121
+ </details>
70
122
 
71
123
  ## 💿 安装
72
124
 
@@ -133,25 +185,22 @@ plugins = [
133
185
 
134
186
  ## ⚙️ 配置
135
187
 
136
- nonebot2 项目的 `.env` 文件中添加下表中的必填配置
188
+ NoneBot2 项目的 `.env` 文件中添加下表中的配置
137
189
 
138
- | 配置项 | 必填 | 默认值 | 说明 |
139
- | :------: | :--: | :----: | :------: |
140
- | 配置项 1 | | 无 | 配置说明 |
141
- | 配置项 2 | 否 | 无 | 配置说明 |
190
+ | 配置项 | 必填 | 默认值 | 说明 |
191
+ | :-----------------------------: | :--: | :-------: | :----------------------------: |
192
+ | `PMN_INDEX_TEMPLATE` | | `default` | 首页展示模板的名称 |
193
+ | `PMN_DETAIL_TEMPLATE` | 否 | `default` | 插件详情模板的名称 |
194
+ | `PMN_FUNC_DETAIL_TEMPLATE` | 否 | `default` | 插件功能详情模板的名称 |
195
+ | `PMN_ONLY_SUPERUSER_SEE_HIDDEN` | 否 | `False` | 是否仅超级用户可以查看隐藏内容 |
142
196
 
143
197
  ## 🎉 使用
144
198
 
145
- ### 指令表
146
-
147
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
148
- | :----: | :--: | :---: | :--: | :------: |
149
- | 指令 1 | 主人 | 否 | 私聊 | 指令说明 |
150
- | 指令 2 | 群员 | 是 | 群聊 | 指令说明 |
199
+ 发送 `帮助` 指令试试吧!
151
200
 
152
- ### 效果图
201
+ ## 🔧 开发
153
202
 
154
- 如果有效果图的话
203
+ 文档待补充
155
204
 
156
205
  ## 📞 联系
157
206
 
@@ -162,7 +211,9 @@ Telegram:[@lgc2333](https://t.me/lgc2333)
162
211
 
163
212
  ## 💡 鸣谢
164
213
 
165
- 如果有要鸣谢的人的话
214
+ ### [hamo-reid/nonebot_plugin_PicMenu](https://github.com/hamo-reid/nonebot_plugin_PicMenu)
215
+
216
+ - 灵感来源(?)
166
217
 
167
218
  ## 💰 赞助
168
219
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  # NoneBot-Plugin-PicMenu-Next
14
14
 
15
- _✨ NoneBot 插件简单描述 ✨_
15
+ _✨ 新一代的图片帮助插件 ✨_
16
16
 
17
17
  <img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
18
18
  <a href="https://pdm.fming.dev">
@@ -50,7 +50,56 @@ _✨ NoneBot 插件简单描述 ✨_
50
50
 
51
51
  ## 📖 介绍
52
52
 
53
- 这里是插件的详细介绍部分
53
+ - ✨ **美观的图片界面**:直观友好的图片界面
54
+ - 🛠️ **PicMenu 兼容**:本插件使用 PicMenu 插件格式的三级菜单(功能详情),兼容 PicMenu 的 `<ft>` 富文本标签(但不太推荐使用)
55
+ - 🔍 **支持模糊搜索**:支持通过序号或名称查找插件及功能,并提供插件名称的模糊匹配
56
+ - 🔤 **拼音支持**:插件排序与模糊搜索时考虑拼音,提高中文环境下的使用体验
57
+ - 📜 **Markdown 支持**:支持 Markdown 格式的帮助信息展示(需要插件开发者主动适配)
58
+ - 🔒 **隐藏控制**:默认状态下类型为 `library` 的插件会对普通用户隐藏
59
+ - 🎨 **自定义模板**:提供模板开发者注册模板的接口,提供插件开发者自定义某插件使用的详细信息模板的方式,提供配置供用户自定义想要使用的模板
60
+ - 🔌 **插件扩展机制**:提供强大的 mixin 支持,允许插件通过中间件方式自定义帮助菜单展示和行为
61
+
62
+ ### 展示图
63
+
64
+ <details>
65
+ <summary>主页面</summary>
66
+
67
+ ![亮色主页](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_main.jpg)
68
+ ![暗色主页](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_main.jpg)
69
+
70
+ </details>
71
+
72
+ <details>
73
+ <summary>插件详情</summary>
74
+
75
+ ![亮色插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_detail.jpg)
76
+ ![暗色插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_detail.jpg)
77
+
78
+ </details>
79
+
80
+ <details>
81
+ <summary>插件详情(带功能详情三级菜单)</summary>
82
+
83
+ ![亮色带三级菜单插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_with_func.jpg)
84
+ ![暗色带三级菜单插件详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_with_func.jpg)
85
+
86
+ </details>
87
+
88
+ <details>
89
+ <summary>功能详情</summary>
90
+
91
+ ![亮色功能详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_func_detail.jpg)
92
+ ![暗色功能详情](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_func_detail.jpg)
93
+
94
+ </details>
95
+
96
+ <details>
97
+ <summary>Markdown 测试</summary>
98
+
99
+ ![亮色 Markdown 测试](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/light_markdown.jpg)
100
+ ![暗色 Markdown 测试](https://raw.githubusercontent.com/lgc-NB2Dev/readme/main/picmenu-next/dark_markdown.jpg)
101
+
102
+ </details>
54
103
 
55
104
  ## 💿 安装
56
105
 
@@ -117,25 +166,22 @@ plugins = [
117
166
 
118
167
  ## ⚙️ 配置
119
168
 
120
- nonebot2 项目的 `.env` 文件中添加下表中的必填配置
169
+ NoneBot2 项目的 `.env` 文件中添加下表中的配置
121
170
 
122
- | 配置项 | 必填 | 默认值 | 说明 |
123
- | :------: | :--: | :----: | :------: |
124
- | 配置项 1 | | 无 | 配置说明 |
125
- | 配置项 2 | 否 | 无 | 配置说明 |
171
+ | 配置项 | 必填 | 默认值 | 说明 |
172
+ | :-----------------------------: | :--: | :-------: | :----------------------------: |
173
+ | `PMN_INDEX_TEMPLATE` | | `default` | 首页展示模板的名称 |
174
+ | `PMN_DETAIL_TEMPLATE` | 否 | `default` | 插件详情模板的名称 |
175
+ | `PMN_FUNC_DETAIL_TEMPLATE` | 否 | `default` | 插件功能详情模板的名称 |
176
+ | `PMN_ONLY_SUPERUSER_SEE_HIDDEN` | 否 | `False` | 是否仅超级用户可以查看隐藏内容 |
126
177
 
127
178
  ## 🎉 使用
128
179
 
129
- ### 指令表
130
-
131
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
132
- | :----: | :--: | :---: | :--: | :------: |
133
- | 指令 1 | 主人 | 否 | 私聊 | 指令说明 |
134
- | 指令 2 | 群员 | 是 | 群聊 | 指令说明 |
180
+ 发送 `帮助` 指令试试吧!
135
181
 
136
- ### 效果图
182
+ ## 🔧 开发
137
183
 
138
- 如果有效果图的话
184
+ 文档待补充
139
185
 
140
186
  ## 📞 联系
141
187
 
@@ -146,7 +192,9 @@ Telegram:[@lgc2333](https://t.me/lgc2333)
146
192
 
147
193
  ## 💡 鸣谢
148
194
 
149
- 如果有要鸣谢的人的话
195
+ ### [hamo-reid/nonebot_plugin_PicMenu](https://github.com/hamo-reid/nonebot_plugin_PicMenu)
196
+
197
+ - 灵感来源(?)
150
198
 
151
199
  ## 💰 赞助
152
200
 
@@ -4,7 +4,6 @@ from nonebot import get_driver
4
4
  from nonebot.plugin import PluginMetadata, inherit_supported_adapters, require
5
5
 
6
6
  require("nonebot_plugin_alconna")
7
- require("nonebot_plugin_waiter")
8
7
  require("nonebot_plugin_htmlrender")
9
8
 
10
9
  from . import __main__ as __main__
@@ -12,7 +11,7 @@ from .config import ConfigModel
12
11
  from .data_source import refresh_infos
13
12
  from .templates import load_builtin_templates
14
13
 
15
- __version__ = "0.1.0.dev1"
14
+ __version__ = "0.1.0.post1"
16
15
  __plugin_meta__ = PluginMetadata(
17
16
  name="PicMenu Next",
18
17
  description="新一代的图片帮助插件",
@@ -20,10 +19,7 @@ __plugin_meta__ = PluginMetadata(
20
19
  type="application",
21
20
  homepage="https://github.com/lgc-NB2Dev/nonebot-plugin-picmenu-next",
22
21
  config=ConfigModel,
23
- supported_adapters=inherit_supported_adapters(
24
- "nonebot_plugin_alconna",
25
- "nonebot_plugin_waiter",
26
- ),
22
+ supported_adapters=inherit_supported_adapters("nonebot_plugin_alconna"),
27
23
  extra={"License": "MIT", "Author": "LgCookie"},
28
24
  )
29
25
 
@@ -1,21 +1,24 @@
1
1
  from collections.abc import Sequence
2
- from contextlib import suppress
2
+ from pathlib import Path
3
3
  from typing import Optional, TypeVar
4
4
 
5
5
  from arclet.alconna import Alconna, Arg, Args, CommandMeta, Option, store_true
6
6
  from loguru import logger
7
+ from nonebot.adapters import Bot as BaseBot, Event as BaseEvent
8
+ from nonebot.permission import SUPERUSER
7
9
  from nonebot_plugin_alconna import Query, on_alconna
8
10
  from nonebot_plugin_alconna.uniseg import UniMessage
9
11
  from thefuzz import process
10
12
 
11
- from .data_source import (
12
- PMDataItem,
13
- PMNPluginInfo,
14
- get_resolved_infos,
15
- transform_to_pinyin,
16
- )
13
+ from .config import config
14
+ from .data_source import get_infos
15
+ from .data_source.mixin import resolve_detail_mixin, resolve_main_mixin
16
+ from .data_source.models import PinyinChunkSequence, PMDataItem, PMNPluginInfo
17
17
  from .templates import detail_templates, func_detail_templates, index_templates
18
18
 
19
+ RES_DIR = Path(__file__).parent / "res"
20
+ TIP_IMG_PATH = RES_DIR / "gan_shen_me.jpg"
21
+
19
22
  alc = Alconna(
20
23
  "help",
21
24
  Args(
@@ -49,21 +52,24 @@ def get_name_similarities(
49
52
  raw_weight: float = 0.6,
50
53
  pinyin_weight: float = 0.4,
51
54
  ) -> list[float]:
52
- similarities: list[float] = []
53
- raw_iter = process.extractWithoutOrder(query, choices)
54
- pinyin_iter = process.extractWithoutOrder(query_pinyin, choices_pinyin)
55
- with suppress(StopIteration):
56
- while True:
57
- raw_score = next(raw_iter)[1]
58
- pinyin_score = next(pinyin_iter)[1]
59
- similarities.append(raw_weight * raw_score + pinyin_weight * pinyin_score)
55
+ raw_scores = [x[1] for x in process.extractWithoutOrder(query, choices)]
56
+ pinyin_scores = [
57
+ x[1] for x in process.extractWithoutOrder(query_pinyin, choices_pinyin)
58
+ ]
59
+ similarities = [
60
+ raw_weight * raw + pinyin_weight * pinyin
61
+ for raw, pinyin in zip(raw_scores, pinyin_scores)
62
+ ]
60
63
  logger.opt(lazy=True).debug(
61
- "Query: {}, similarities: {}",
62
- lambda: query,
63
- lambda: "; ".join(
64
- f"{choices[i]}: {s}"
65
- for i, s in sorted(
66
- enumerate(similarities),
64
+ "Query: {}, similarities:\n{}",
65
+ lambda: f"{query} ({query_pinyin})",
66
+ lambda: ";\n".join(
67
+ (
68
+ f"{choices[i]} ({choices_pinyin[i]})"
69
+ f": ({raw} * {raw_weight}) + ({pin} * {pinyin_weight}) = {sim}"
70
+ )
71
+ for i, (raw, pin, sim) in sorted(
72
+ enumerate(zip(raw_scores, pinyin_scores, similarities)),
67
73
  key=lambda x: x[1],
68
74
  reverse=True,
69
75
  )
@@ -96,12 +102,12 @@ async def query_plugin(
96
102
  choices: list[str] = []
97
103
  choices_pinyin: list[str] = []
98
104
  for info in infos:
99
- choices.append(info.name.casefold())
100
- choices_pinyin.append(info.name_pinyin.casefold())
105
+ choices.append(info.casefold_name)
106
+ choices_pinyin.append(info.name_pinyin.casefold_str)
101
107
 
102
108
  similarities = get_name_similarities(
103
109
  query.casefold(),
104
- transform_to_pinyin(query).casefold(),
110
+ PinyinChunkSequence.from_raw(query).casefold_str,
105
111
  choices,
106
112
  choices_pinyin,
107
113
  )
@@ -122,12 +128,12 @@ async def query_func_detail(
122
128
  choices: list[str] = []
123
129
  choices_pinyin: list[str] = []
124
130
  for data in pm_data:
125
- choices.append(data.func.casefold())
126
- choices_pinyin.append(data.func_pinyin.casefold())
131
+ choices.append(data.casefold_func)
132
+ choices_pinyin.append(data.func_pinyin.casefold_str)
127
133
 
128
134
  similarities = get_name_similarities(
129
135
  query.casefold(),
130
- transform_to_pinyin(query).casefold(),
136
+ PinyinChunkSequence.from_raw(query).casefold_str,
131
137
  choices,
132
138
  choices_pinyin,
133
139
  )
@@ -139,16 +145,30 @@ async def query_func_detail(
139
145
 
140
146
  @m_cls.handle()
141
147
  async def _(
148
+ bot: BaseBot,
149
+ ev: BaseEvent,
142
150
  q_plugin: Query[Optional[str]] = Query("~plugin", None),
143
151
  q_function: Query[Optional[str]] = Query("~function", None),
144
152
  q_show_hidden: Query[bool] = Query("~show-hidden.value", default=False),
145
153
  ):
146
- infos = await get_resolved_infos()
147
- if not q_show_hidden.result:
148
- infos = [x for x in infos if not x.pmn_v.hidden]
154
+ show_hidden = q_show_hidden.result
155
+ if (
156
+ show_hidden
157
+ and config.only_superuser_see_hidden
158
+ and (not await SUPERUSER(bot, ev))
159
+ ):
160
+ await (
161
+ UniMessage.image(raw=TIP_IMG_PATH.read_bytes())
162
+ .text("别想看咱藏起来的东西!")
163
+ .finish(reply_to=True)
164
+ )
165
+
166
+ infos = await resolve_main_mixin(get_infos())
167
+ if not show_hidden:
168
+ infos = [x for x in infos if not x.pmn.hidden]
149
169
 
150
170
  if not q_plugin.result:
151
- m = await index_templates.get()(infos)
171
+ m = await index_templates.get()(infos, show_hidden)
152
172
  await m.finish()
153
173
 
154
174
  r = await query_plugin(infos, q_plugin.result)
@@ -156,21 +176,21 @@ async def _(
156
176
  await UniMessage.text("好像没有找到对应插件呢……").finish(reply_to=True)
157
177
  info_index, info = r
158
178
  if not q_function.result:
159
- m = await detail_templates.get(info.pmn.template)(info, info_index)
179
+ m = await detail_templates.get(
180
+ info.pmn.template,
181
+ )(info, info_index, show_hidden)
160
182
  await m.finish()
161
183
 
162
- if not info.pm_data:
184
+ info = await resolve_detail_mixin(info)
185
+ pm_data = info.pm_data
186
+ if pm_data and (not show_hidden):
187
+ pm_data = [x for x in pm_data if not x.hidden]
188
+
189
+ if not pm_data:
163
190
  await UniMessage.text(
164
191
  f"插件 `{info.name}` 没有详细功能介绍哦",
165
192
  ).finish(reply_to=True)
166
193
 
167
- if (not (plugin := info.plugin)) or (
168
- not (pm_data := await info.resolve_pm_data(plugin))
169
- ):
170
- await UniMessage.text("啊哦,遇到了意外情况……").finish(reply_to=True)
171
-
172
- if not q_show_hidden.result:
173
- pm_data = [x for x in pm_data if not x.hidden]
174
194
  r = await query_func_detail(pm_data, q_function.result)
175
195
  if not r:
176
196
  await UniMessage.text(
@@ -179,5 +199,5 @@ async def _(
179
199
  func_index, func = r
180
200
  m = await func_detail_templates.get(
181
201
  func.template,
182
- )(info, info_index, func, func_index)
202
+ )(info, info_index, func, func_index, show_hidden)
183
203
  await m.finish()
@@ -8,6 +8,13 @@ class ConfigModel(BaseModel):
8
8
  index_template: str = "default"
9
9
  detail_template: str = "default"
10
10
  func_detail_template: str = "default"
11
+ only_superuser_see_hidden: bool = False
11
12
 
12
13
 
13
14
  config: ConfigModel = get_plugin_config(ConfigModel)
15
+
16
+
17
+ def version():
18
+ from . import __version__
19
+
20
+ return __version__
@@ -0,0 +1,16 @@
1
+ from nonebot import get_loaded_plugins as _get_loaded_plugins
2
+
3
+ from .collect import collect_plugin_infos as _collect_plugin_infos
4
+ from .models import PMNPluginInfo as _PMNPluginInfoRaw
5
+
6
+ _infos: list[_PMNPluginInfoRaw] = []
7
+
8
+
9
+ def get_infos() -> list[_PMNPluginInfoRaw]:
10
+ return _infos
11
+
12
+
13
+ async def refresh_infos() -> list[_PMNPluginInfoRaw]:
14
+ global _infos
15
+ _infos = await _collect_plugin_infos(_get_loaded_plugins())
16
+ return _infos
@@ -0,0 +1,126 @@
1
+ import asyncio
2
+ import importlib
3
+ from collections.abc import Iterable
4
+ from contextlib import suppress
5
+ from functools import lru_cache
6
+ from importlib.metadata import Distribution, PackageNotFoundError, distribution
7
+ from typing import Optional
8
+
9
+ from cookit.loguru import warning_suppress
10
+ from cookit.pyd import type_validate_python
11
+ from nonebot import logger
12
+ from nonebot.plugin import Plugin
13
+
14
+ from ..utils import normalize_plugin_name
15
+ from .mixin import chain_mixins, plugin_collect_mixins
16
+ from .models import PMNData, PMNPluginExtra, PMNPluginInfo
17
+
18
+
19
+ def normalize_metadata_user(info: str, allow_multi: bool = False) -> str:
20
+ infos = info.split(",")
21
+ if not allow_multi:
22
+ infos = infos[:1]
23
+ return " & ".join(x.split("<")[0].strip().strip("'\"") for x in infos)
24
+
25
+
26
+ @lru_cache
27
+ def get_dist(module_name: str) -> Optional[Distribution]:
28
+ with warning_suppress(f"Unexpected error happened when getting info of package {module_name}"),\
29
+ suppress(PackageNotFoundError): # fmt: skip
30
+ return distribution(module_name)
31
+ if "." not in module_name:
32
+ return None
33
+ module_name = module_name.rsplit(".", 1)[0]
34
+ return get_dist(module_name)
35
+
36
+
37
+ @lru_cache
38
+ def get_version_attr(module_name: str) -> Optional[str]:
39
+ with warning_suppress(f"Unexpected error happened when importing {module_name}"),\
40
+ suppress(ImportError): # fmt: skip
41
+ m = importlib.import_module(module_name)
42
+ if ver := getattr(m, "__version__", None):
43
+ return ver
44
+ if "." not in module_name:
45
+ return None
46
+ module_name = module_name.rsplit(".", 1)[0]
47
+ return get_version_attr(module_name)
48
+
49
+
50
+ async def get_info_from_plugin(plugin: Plugin) -> PMNPluginInfo:
51
+ meta = plugin.metadata
52
+ extra: Optional[PMNPluginExtra] = None
53
+ if meta:
54
+ with warning_suppress(f"Failed to parse plugin metadata of {plugin.id_}"):
55
+ extra = type_validate_python(PMNPluginExtra, meta.extra)
56
+
57
+ name = normalize_plugin_name(meta.name if meta else plugin.id_)
58
+
59
+ ver = extra.version if extra else None
60
+ if not ver:
61
+ ver = get_version_attr(plugin.module_name)
62
+ if not ver and (dist := get_dist(plugin.module_name)):
63
+ ver = dist.version
64
+
65
+ author = (
66
+ (" & ".join(extra.author) if isinstance(extra.author, list) else extra.author)
67
+ if extra
68
+ else None
69
+ )
70
+ if not author and (dist := get_dist(plugin.module_name)):
71
+ if author := dist.metadata.get("Author") or dist.metadata.get("Maintainer"):
72
+ author = normalize_metadata_user(author)
73
+ elif author := dist.metadata.get("Author-Email") or dist.metadata.get(
74
+ "Maintainer-Email",
75
+ ):
76
+ author = normalize_metadata_user(author, allow_multi=True)
77
+
78
+ description = (
79
+ meta.description
80
+ if meta
81
+ else (
82
+ dist.metadata.get("Summary")
83
+ if (dist := get_dist(plugin.module_name))
84
+ else None
85
+ )
86
+ )
87
+
88
+ pmn = (extra.pmn if extra else None) or PMNData()
89
+ if ("hidden" not in pmn.model_fields_set) and meta and meta.type == "library":
90
+ pmn = PMNData(hidden=True)
91
+
92
+ logger.debug(f"Completed to get info of plugin {plugin.id_}")
93
+ return PMNPluginInfo(
94
+ plugin_id=plugin.id_,
95
+ name=name,
96
+ author=author,
97
+ version=ver,
98
+ description=description,
99
+ usage=meta.usage if meta else None,
100
+ pm_data=extra.menu_data if extra else None,
101
+ pmn=pmn,
102
+ )
103
+
104
+
105
+ async def collect_plugin_infos(plugins: Iterable[Plugin]):
106
+ async def _get(p: Plugin):
107
+ with warning_suppress(f"Failed to get plugin info of {p.id_}"):
108
+ return await get_info_from_plugin(p)
109
+
110
+ infos = await asyncio.gather(
111
+ *(_get(plugin) for plugin in plugins),
112
+ )
113
+ infos = [x for x in infos if x]
114
+
115
+ async def final_mixin(infos: list[PMNPluginInfo]):
116
+ return infos
117
+
118
+ mixin_chain = chain_mixins(plugin_collect_mixins.data, final_mixin)
119
+ infos = await mixin_chain(infos)
120
+
121
+ infos.sort(key=lambda x: x.name_pinyin)
122
+ logger.success(f"Collected {len(infos)} plugin infos")
123
+
124
+ get_dist.cache_clear()
125
+ get_version_attr.cache_clear()
126
+ return infos