nonebot-plugin-botui 0.1.0__tar.gz → 0.1.1__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 (347) hide show
  1. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/PKG-INFO +4 -1
  2. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/README.md +3 -0
  3. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/pyproject.toml +2 -2
  4. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/pyproject.toml.orig +2 -2
  5. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/api.py +14 -3
  6. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/config.py +2 -1
  7. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/segments.py +3 -1
  8. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/static/app.css +10 -0
  9. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/static/app.js +103 -1
  10. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/0.webp +0 -0
  11. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/1.webp +0 -0
  12. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/10.webp +0 -0
  13. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/100.webp +0 -0
  14. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/101.webp +0 -0
  15. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/102.webp +0 -0
  16. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/103.webp +0 -0
  17. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/104.webp +0 -0
  18. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/105.webp +0 -0
  19. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/106.webp +0 -0
  20. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/107.webp +0 -0
  21. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/108.webp +0 -0
  22. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/109.webp +0 -0
  23. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/11.webp +0 -0
  24. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/110.webp +0 -0
  25. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/111.webp +0 -0
  26. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/112.webp +0 -0
  27. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/114.webp +0 -0
  28. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/116.webp +0 -0
  29. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/118.webp +0 -0
  30. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/119.webp +0 -0
  31. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/12.webp +0 -0
  32. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/120.webp +0 -0
  33. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/121.webp +0 -0
  34. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/123.webp +0 -0
  35. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/124.webp +0 -0
  36. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/125.webp +0 -0
  37. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/129.webp +0 -0
  38. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/13.webp +0 -0
  39. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/137.webp +0 -0
  40. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/14.webp +0 -0
  41. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/144.webp +0 -0
  42. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/146.webp +0 -0
  43. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/147.webp +0 -0
  44. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/148.webp +0 -0
  45. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/15.webp +0 -0
  46. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/16.webp +0 -0
  47. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/169.webp +0 -0
  48. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/171.webp +0 -0
  49. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/172.webp +0 -0
  50. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/173.webp +0 -0
  51. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/174.webp +0 -0
  52. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/175.webp +0 -0
  53. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/176.webp +0 -0
  54. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/177.webp +0 -0
  55. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/178.webp +0 -0
  56. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/179.webp +0 -0
  57. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/18.webp +0 -0
  58. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/181.webp +0 -0
  59. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/182.webp +0 -0
  60. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/183.webp +0 -0
  61. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/185.webp +0 -0
  62. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/187.webp +0 -0
  63. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/19.webp +0 -0
  64. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/2.webp +0 -0
  65. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/20.webp +0 -0
  66. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/201.webp +0 -0
  67. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/21.webp +0 -0
  68. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/212.webp +0 -0
  69. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/22.webp +0 -0
  70. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/23.webp +0 -0
  71. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/24.webp +0 -0
  72. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/25.webp +0 -0
  73. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/26.webp +0 -0
  74. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/262.webp +0 -0
  75. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/263.webp +0 -0
  76. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/264.webp +0 -0
  77. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/265.webp +0 -0
  78. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/266.webp +0 -0
  79. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/267.webp +0 -0
  80. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/268.webp +0 -0
  81. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/269.webp +0 -0
  82. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/27.webp +0 -0
  83. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/270.webp +0 -0
  84. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/271.webp +0 -0
  85. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/272.webp +0 -0
  86. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/273.webp +0 -0
  87. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/277.webp +0 -0
  88. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/28.webp +0 -0
  89. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/281.webp +0 -0
  90. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/282.webp +0 -0
  91. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/283.webp +0 -0
  92. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/284.webp +0 -0
  93. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/285.webp +0 -0
  94. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/286.webp +0 -0
  95. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/287.webp +0 -0
  96. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/289.webp +0 -0
  97. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/29.webp +0 -0
  98. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/293.webp +0 -0
  99. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/294.webp +0 -0
  100. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/295.webp +0 -0
  101. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/297.webp +0 -0
  102. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/298.webp +0 -0
  103. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/299.webp +0 -0
  104. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/3.webp +0 -0
  105. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/30.webp +0 -0
  106. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/300.webp +0 -0
  107. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/302.webp +0 -0
  108. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/303.webp +0 -0
  109. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/305.webp +0 -0
  110. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/306.webp +0 -0
  111. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/307.webp +0 -0
  112. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/31.webp +0 -0
  113. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/311.webp +0 -0
  114. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/312.webp +0 -0
  115. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/314.webp +0 -0
  116. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/317.webp +0 -0
  117. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/318.webp +0 -0
  118. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/319.webp +0 -0
  119. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/32.webp +0 -0
  120. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/320.webp +0 -0
  121. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/323.webp +0 -0
  122. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/324.webp +0 -0
  123. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/325.webp +0 -0
  124. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/326.webp +0 -0
  125. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/33.webp +0 -0
  126. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/332.webp +0 -0
  127. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/333.webp +0 -0
  128. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/334.webp +0 -0
  129. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/336.webp +0 -0
  130. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/337.webp +0 -0
  131. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/338.webp +0 -0
  132. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/339.webp +0 -0
  133. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/34.webp +0 -0
  134. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/341.webp +0 -0
  135. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/342.webp +0 -0
  136. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/343.webp +0 -0
  137. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/344.webp +0 -0
  138. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/345.webp +0 -0
  139. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/346.webp +0 -0
  140. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/347.webp +0 -0
  141. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/349.webp +0 -0
  142. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/35.webp +0 -0
  143. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/350.webp +0 -0
  144. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/351.webp +0 -0
  145. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/352.webp +0 -0
  146. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/353.webp +0 -0
  147. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/354.webp +0 -0
  148. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/355.webp +0 -0
  149. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/356.webp +0 -0
  150. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/357.webp +0 -0
  151. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/358.webp +0 -0
  152. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/359.webp +0 -0
  153. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/36.webp +0 -0
  154. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/360.webp +0 -0
  155. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/361.webp +0 -0
  156. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/362.webp +0 -0
  157. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/363.webp +0 -0
  158. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/364.webp +0 -0
  159. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/365.webp +0 -0
  160. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/366.webp +0 -0
  161. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/367.webp +0 -0
  162. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/368.webp +0 -0
  163. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/369.webp +0 -0
  164. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/37.webp +0 -0
  165. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/370.webp +0 -0
  166. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/371.webp +0 -0
  167. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/372.webp +0 -0
  168. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/373.webp +0 -0
  169. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/374.webp +0 -0
  170. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/375.webp +0 -0
  171. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/376.webp +0 -0
  172. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/377.webp +0 -0
  173. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/378.webp +0 -0
  174. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/379.webp +0 -0
  175. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/38.webp +0 -0
  176. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/380.webp +0 -0
  177. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/381.webp +0 -0
  178. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/382.webp +0 -0
  179. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/383.webp +0 -0
  180. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/384.webp +0 -0
  181. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/385.webp +0 -0
  182. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/386.webp +0 -0
  183. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/387.webp +0 -0
  184. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/388.webp +0 -0
  185. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/389.webp +0 -0
  186. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/39.webp +0 -0
  187. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/390.webp +0 -0
  188. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/391.webp +0 -0
  189. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/392.webp +0 -0
  190. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/393.webp +0 -0
  191. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/394.webp +0 -0
  192. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/395.webp +0 -0
  193. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/396.webp +0 -0
  194. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/397.webp +0 -0
  195. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/398.webp +0 -0
  196. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/399.webp +0 -0
  197. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/4.webp +0 -0
  198. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/400.webp +0 -0
  199. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/401.webp +0 -0
  200. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/402.webp +0 -0
  201. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/403.webp +0 -0
  202. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/404.webp +0 -0
  203. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/405.webp +0 -0
  204. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/406.webp +0 -0
  205. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/407.webp +0 -0
  206. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/408.webp +0 -0
  207. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/409.webp +0 -0
  208. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/41.webp +0 -0
  209. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/410.webp +0 -0
  210. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/411.webp +0 -0
  211. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/412.webp +0 -0
  212. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/413.webp +0 -0
  213. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/415.webp +0 -0
  214. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/416.webp +0 -0
  215. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/417.webp +0 -0
  216. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/418.webp +0 -0
  217. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/419.webp +0 -0
  218. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/42.webp +0 -0
  219. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/420.webp +0 -0
  220. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/421.webp +0 -0
  221. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/422.webp +0 -0
  222. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/423.webp +0 -0
  223. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/424.webp +0 -0
  224. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/425.webp +0 -0
  225. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/426.webp +0 -0
  226. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/427.webp +0 -0
  227. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/428.webp +0 -0
  228. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/429.webp +0 -0
  229. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/43.webp +0 -0
  230. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/430.webp +0 -0
  231. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/431.webp +0 -0
  232. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/432.webp +0 -0
  233. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/433.webp +0 -0
  234. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/434.webp +0 -0
  235. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/435.webp +0 -0
  236. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/436.webp +0 -0
  237. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/437.webp +0 -0
  238. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/438.webp +0 -0
  239. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/439.webp +0 -0
  240. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/440.webp +0 -0
  241. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/441.webp +0 -0
  242. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/442.webp +0 -0
  243. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/443.webp +0 -0
  244. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/444.webp +0 -0
  245. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/445.webp +0 -0
  246. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/446.webp +0 -0
  247. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/447.webp +0 -0
  248. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/448.webp +0 -0
  249. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/449.webp +0 -0
  250. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/450.webp +0 -0
  251. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/451.webp +0 -0
  252. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/452.webp +0 -0
  253. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/453.webp +0 -0
  254. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/454.webp +0 -0
  255. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/455.webp +0 -0
  256. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/456.webp +0 -0
  257. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/457.webp +0 -0
  258. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/458.webp +0 -0
  259. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/459.webp +0 -0
  260. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/46.webp +0 -0
  261. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/460.webp +0 -0
  262. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/461.webp +0 -0
  263. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/462.webp +0 -0
  264. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/463.webp +0 -0
  265. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/464.webp +0 -0
  266. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/465.webp +0 -0
  267. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/466.webp +0 -0
  268. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/467.webp +0 -0
  269. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/468.webp +0 -0
  270. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/469.webp +0 -0
  271. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/470.webp +0 -0
  272. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/471.webp +0 -0
  273. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/472.webp +0 -0
  274. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/473.webp +0 -0
  275. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/474.webp +0 -0
  276. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/475.webp +0 -0
  277. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/476.webp +0 -0
  278. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/477.webp +0 -0
  279. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/478.webp +0 -0
  280. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/479.webp +0 -0
  281. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/480.webp +0 -0
  282. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/481.webp +0 -0
  283. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/482.webp +0 -0
  284. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/483.webp +0 -0
  285. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/484.webp +0 -0
  286. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/485.webp +0 -0
  287. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/486.webp +0 -0
  288. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/487.webp +0 -0
  289. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/488.webp +0 -0
  290. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/489.webp +0 -0
  291. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/49.webp +0 -0
  292. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/490.webp +0 -0
  293. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/491.webp +0 -0
  294. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/492.webp +0 -0
  295. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/493.webp +0 -0
  296. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/494.webp +0 -0
  297. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/495.webp +0 -0
  298. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/496.webp +0 -0
  299. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/497.webp +0 -0
  300. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/498.webp +0 -0
  301. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/499.webp +0 -0
  302. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/5.webp +0 -0
  303. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/500.webp +0 -0
  304. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/501.webp +0 -0
  305. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/502.webp +0 -0
  306. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/503.webp +0 -0
  307. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/504.webp +0 -0
  308. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/505.webp +0 -0
  309. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/506.webp +0 -0
  310. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/507.webp +0 -0
  311. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/53.webp +0 -0
  312. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/55.webp +0 -0
  313. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/56.webp +0 -0
  314. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/59.webp +0 -0
  315. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/6.webp +0 -0
  316. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/60.webp +0 -0
  317. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/63.webp +0 -0
  318. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/64.webp +0 -0
  319. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/66.webp +0 -0
  320. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/67.webp +0 -0
  321. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/7.webp +0 -0
  322. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/74.webp +0 -0
  323. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/75.webp +0 -0
  324. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/76.webp +0 -0
  325. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/77.webp +0 -0
  326. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/78.webp +0 -0
  327. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/79.webp +0 -0
  328. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/8.webp +0 -0
  329. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/85.webp +0 -0
  330. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/86.webp +0 -0
  331. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/89.webp +0 -0
  332. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/9.webp +0 -0
  333. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/96.webp +0 -0
  334. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/97.webp +0 -0
  335. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/98.webp +0 -0
  336. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/99.webp +0 -0
  337. nonebot_plugin_botui-0.1.1/src/nonebot_plugin_botui/static/face/names.json +1 -0
  338. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/__init__.py +0 -0
  339. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/capture.py +0 -0
  340. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/ingest.py +0 -0
  341. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/media.py +0 -0
  342. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/mediastore.py +0 -0
  343. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/models.py +0 -0
  344. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/paths.py +0 -0
  345. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/static/index.html +0 -0
  346. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/store.py +0 -0
  347. {nonebot_plugin_botui-0.1.0 → nonebot_plugin_botui-0.1.1}/src/nonebot_plugin_botui/webui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nonebot-plugin-botui
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: 一个 QQ 风格的 WebUI 控制台:查看机器人收发的全部消息,并以机器人的身份发消息。
5
5
  Author: Lonely-Sails
6
6
  Requires-Dist: aiosqlite>=0.20.0,<1.0.0
@@ -215,6 +215,7 @@ LOCALSTORE_PLUGIN_DATA_DIR={"nonebot_plugin_botui": "/srv/botui/data"}
215
215
  - **多机器人**:每个机器人(`self_id`)的会话彼此独立 —— 会话 key 采用 `self_id:kind_id` 的形式内嵌机器人 ID,同名群在 A、B 两个机器人下就是两条不同的会话;每条消息都带上产生它的适配器名与 `self_id`。WebUI 的发送只会用**会话自己的机器人**,它不在线时返回 503 而不会改用别的机器人。
216
216
  - 只要适配器支持对应的能力就能用:私聊/群聊识别、消息段解析、以及通过 alconna 的 exporter 发送消息。召回(撤回)需要该适配器在 alconna 里实现了对应的 exporter,不支持时网页会提示「适配器 xxx 不支持撤回」。
217
217
  - `BOTUI_EXCLUDE_ADAPTERS` 可以按适配器名(如 `["OneBot V12"]`)排除某些平台的记录。
218
+ - **QQ 表情**:官方 QQ 适配器的 `emoji` 段只给一个编号(`data.id`,即 QQNT 的 emojiId),网页按这个编号显示表情图并带上中文名(如 `67 → 心碎`、`179 → doge`),图缺失时退回「[中文名]」文字标签。表情图与名称表随插件分发在 `static/face/`(327 张 64×64 WebP,约 600 KB + 运行时惰性加载的 `names.json`),素材取自 [QFace](https://koishi.js.org/QFace/)(MIT),按 QQNT 索引同步,与旧 QZone 编号不通用。
218
219
 
219
220
  ## 🧪 开发 / 测试
220
221
 
@@ -229,3 +230,5 @@ uv run poe bump patch # 版本号变更(bump-my-version)
229
230
  ## 📄 协议
230
231
 
231
232
  MIT © 2026 Lonely-Sails
233
+
234
+ 内置的 QQ 表情素材(`static/face/`)来自 [QFace](https://koishi.js.org/QFace/),遵循其 MIT 协议;表情形象版权归腾讯所有,仅用于本地展示消息中的表情。
@@ -196,6 +196,7 @@ LOCALSTORE_PLUGIN_DATA_DIR={"nonebot_plugin_botui": "/srv/botui/data"}
196
196
  - **多机器人**:每个机器人(`self_id`)的会话彼此独立 —— 会话 key 采用 `self_id:kind_id` 的形式内嵌机器人 ID,同名群在 A、B 两个机器人下就是两条不同的会话;每条消息都带上产生它的适配器名与 `self_id`。WebUI 的发送只会用**会话自己的机器人**,它不在线时返回 503 而不会改用别的机器人。
197
197
  - 只要适配器支持对应的能力就能用:私聊/群聊识别、消息段解析、以及通过 alconna 的 exporter 发送消息。召回(撤回)需要该适配器在 alconna 里实现了对应的 exporter,不支持时网页会提示「适配器 xxx 不支持撤回」。
198
198
  - `BOTUI_EXCLUDE_ADAPTERS` 可以按适配器名(如 `["OneBot V12"]`)排除某些平台的记录。
199
+ - **QQ 表情**:官方 QQ 适配器的 `emoji` 段只给一个编号(`data.id`,即 QQNT 的 emojiId),网页按这个编号显示表情图并带上中文名(如 `67 → 心碎`、`179 → doge`),图缺失时退回「[中文名]」文字标签。表情图与名称表随插件分发在 `static/face/`(327 张 64×64 WebP,约 600 KB + 运行时惰性加载的 `names.json`),素材取自 [QFace](https://koishi.js.org/QFace/)(MIT),按 QQNT 索引同步,与旧 QZone 编号不通用。
199
200
 
200
201
  ## 🧪 开发 / 测试
201
202
 
@@ -210,3 +211,5 @@ uv run poe bump patch # 版本号变更(bump-my-version)
210
211
  ## 📄 协议
211
212
 
212
213
  MIT © 2026 Lonely-Sails
214
+
215
+ 内置的 QQ 表情素材(`static/face/`)来自 [QFace](https://koishi.js.org/QFace/),遵循其 MIT 协议;表情形象版权归腾讯所有,仅用于本地展示消息中的表情。
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-botui"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "一个 QQ 风格的 WebUI 控制台:查看机器人收发的全部消息,并以机器人的身份发消息。"
5
5
  readme = "README.md"
6
6
  requires-python = ">= 3.10, < 4.0"
@@ -48,7 +48,7 @@ requires = ["uv_build >= 0.9.0,<0.11.0"]
48
48
  build-backend = "uv_build"
49
49
 
50
50
  [tool.bumpversion]
51
- current_version = "0.1.0"
51
+ current_version = "0.1.1"
52
52
  commit = true
53
53
  message = "release: bump version from {current_version} to {new_version}"
54
54
  tag = true
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-botui"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "一个 QQ 风格的 WebUI 控制台:查看机器人收发的全部消息,并以机器人的身份发消息。"
5
5
  readme = "README.md"
6
6
  requires-python = ">= 3.10, < 4.0"
@@ -50,7 +50,7 @@ requires = ["uv_build >= 0.9.0,<0.11.0"]
50
50
  build-backend = "uv_build"
51
51
 
52
52
  [tool.bumpversion]
53
- current_version = "0.1.0"
53
+ current_version = "0.1.1"
54
54
  commit = true
55
55
  message = "release: bump version from {current_version} to {new_version}"
56
56
  tag = true
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
41
41
  from .webui import WebUIServer
42
42
  from .mediastore import MediaRecord
43
43
 
44
- VERSION = '0.1.0'
44
+ VERSION = '0.1.1'
45
45
 
46
46
  # WebSocket 空闲心跳间隔(秒):两层作用,一是挡掉反向代理的空闲断连,
47
47
  # 二是让服务端在下一次发送时发现已经断掉的连接。
@@ -1209,9 +1209,17 @@ async def post_recall(request: Request) -> dict[str, Any]:
1209
1209
 
1210
1210
 
1211
1211
  # ── 页面资源 ────────────────────────────────────────────────────────────
1212
- @router.get('/static/{filename}')
1212
+ @router.get('/static/{filename:path}')
1213
1213
  async def get_static(filename: str) -> FileResponse:
1214
- if not filename or '/' in filename or '\\' in filename or filename.startswith('.'):
1214
+ """静态资源。
1215
+
1216
+ 允许子目录(表情图在 ``static/face/`` 下),但仍然只接受插件自己的
1217
+ 静态目录内的文件:``..``、绝对路径、``.`` 开头的隐藏文件一律拒绝。
1218
+ """
1219
+ parts = filename.replace('\\', '/').split('/')
1220
+ if not parts or any(
1221
+ part in ('', '.', '..') or part.startswith('.') for part in parts
1222
+ ):
1215
1223
  raise HTTPException(status_code=400, detail='非法的资源名')
1216
1224
  path = (_static_dir / filename).resolve()
1217
1225
  if _static_dir.resolve() not in path.parents or not path.is_file():
@@ -1220,8 +1228,11 @@ async def get_static(filename: str) -> FileResponse:
1220
1228
  '.css': 'text/css; charset=utf-8',
1221
1229
  '.js': 'application/javascript; charset=utf-8',
1222
1230
  '.html': 'text/html; charset=utf-8',
1231
+ '.json': 'application/json; charset=utf-8',
1223
1232
  '.svg': 'image/svg+xml',
1224
1233
  '.png': 'image/png',
1234
+ '.webp': 'image/webp',
1235
+ '.gif': 'image/gif',
1225
1236
  '.ico': 'image/x-icon',
1226
1237
  }.get(path.suffix.lower(), 'application/octet-stream')
1227
1238
  return FileResponse(path, media_type=media)
@@ -3,7 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from nonebot import get_driver, get_plugin_config
6
- from pydantic import BaseModel, field_validator
6
+ from pydantic import BaseModel
7
+ from nonebot.compat import field_validator
7
8
 
8
9
  # 机器人发送消息时可能调用的 API 名称(用于区分“发出”的消息)
9
10
  SEND_APIS: frozenset[str] = frozenset(
@@ -726,7 +726,9 @@ def _fallback_segments(message: Any) -> list[dict[str, Any]]:
726
726
  )
727
727
  else:
728
728
  out.append(_seg_media_dict(kind, url))
729
- elif rtype == 'face':
729
+ elif rtype in ('face', 'emoji'):
730
+ # 官方 QQ 适配器把表情段叫作 emoji(data 里只有一个 id,就是小黄脸
731
+ # 编号);OneBot V11 叫 face,两边用的是同一套编号,统一成 face。
730
732
  out.append(
731
733
  {
732
734
  'type': 'face',
@@ -735,6 +735,16 @@ html[data-theme="light"] .hit-text mark.hit { background: rgba(255, 200, 0, 0.42
735
735
  .msg.out .chip.seg-unknown { color: rgba(255, 255, 255, 0.72); }
736
736
  .chip.seg-reply::before { content: "↩"; font-size: 11px; opacity: 0.85; }
737
737
  .chip.seg-face::before { content: "☺"; font-size: 11px; opacity: 0.85; }
738
+ /* QQ 小黄脸:内联小图,跟着文字基线走,不把气泡撑成图片块 */
739
+ .seg-face-img {
740
+ width: 20px;
741
+ height: 20px;
742
+ margin: 0 1px;
743
+ vertical-align: -4px;
744
+ object-fit: contain;
745
+ }
746
+ /* 段里直接给的是 emoji 字符(非 QQ 编号)时原样显示 */
747
+ .seg-emoji-char { font-size: 18px; line-height: 1; vertical-align: -2px; }
738
748
  .chip .chip-link { color: var(--accent); text-decoration: none; }
739
749
  .msg.out .chip .chip-link { color: #fff; text-decoration: underline; }
740
750
  .chip .chip-link:hover { text-decoration: underline; }
@@ -1793,7 +1793,7 @@ function buildBubble(segments) {
1793
1793
  bubble.appendChild(buildImage(seg));
1794
1794
  return;
1795
1795
  case 'face':
1796
- bubble.appendChild(h('span', 'chip seg-face', '[表情 ' + (hasText(seg.id) ? seg.id : '?') + ']'));
1796
+ bubble.appendChild(buildFace(seg));
1797
1797
  return;
1798
1798
  case 'reply': {
1799
1799
  bubble.appendChild(buildQuote(seg));
@@ -2212,6 +2212,108 @@ function externalLink(href, text) {
2212
2212
  return a;
2213
2213
  }
2214
2214
 
2215
+ /* ---------- QQ 表情 ----------
2216
+ *
2217
+ * 官方 QQ 适配器的 emoji 段只给一个编号(data.id),这个编号就是 QQNT 的
2218
+ * emojiId。表情图与中文名随插件一起分发(static/face/),数据取自
2219
+ * koishi.js.org/QFace(QQNT 索引,由 QQ 服务端定义同步而来),所以
2220
+ * 「67 → 心碎」「179 → doge」这类映射是准的。
2221
+ *
2222
+ * 注意别再用旧的 QZone 表情地址(按 qzoneCode 拼出来的 gif 链接):那套用的是
2223
+ * QZone 编号(QFace 里的 qzoneCode),和适配器给的 emojiId 差了一整套映射,
2224
+ * 直接拼会显示成完全不相干的表情。
2225
+ */
2226
+ const FACE_DIR = ROOT_BASE + '/static/face/';
2227
+ const FACE_NAMES_URL = FACE_DIR + 'names.json';
2228
+
2229
+ // id -> 中文名,从 names.json 惰性加载一次
2230
+ let faceNames = null;
2231
+ let faceNamesLoading = null;
2232
+
2233
+ function loadFaceNames() {
2234
+ if (faceNames) return Promise.resolve(faceNames);
2235
+ if (faceNamesLoading) return faceNamesLoading;
2236
+ faceNamesLoading = fetch(FACE_NAMES_URL, { cache: 'force-cache' })
2237
+ .then((resp) => (resp.ok ? resp.json() : {}))
2238
+ .then((data) => {
2239
+ faceNames = data && typeof data === 'object' ? data : {};
2240
+ return faceNames;
2241
+ })
2242
+ .catch(() => {
2243
+ faceNames = {};
2244
+ return faceNames;
2245
+ });
2246
+ return faceNamesLoading;
2247
+ }
2248
+
2249
+ /** 表情的显示名(拿不到名称表时退回编号) */
2250
+ function faceLabel(seg) {
2251
+ const id = hasText(seg && seg.id) ? String(seg.id).trim() : '';
2252
+ // 适配器有时把编号塞进 name,那种 name 不是可读名
2253
+ const raw = hasText(seg && seg.name) ? String(seg.name).trim() : '';
2254
+ if (raw && !/^\d+$/.test(raw)) return raw;
2255
+ if (id && faceNames && hasText(faceNames[id])) return String(faceNames[id]);
2256
+ return id ? '表情 ' + id : '表情';
2257
+ }
2258
+
2259
+ /**
2260
+ * 表情图片地址。
2261
+ *
2262
+ * 优先用段里自带的 url(部分适配器直接把表情图放进来),其次就是本插件
2263
+ * 随包分发的 static/face/<id>.webp。编号不像表情时返回空串。
2264
+ */
2265
+ function faceImageUrl(seg) {
2266
+ const own = safeUrl(seg && seg.url);
2267
+ if (own) return own;
2268
+ const id = hasText(seg && seg.id) ? String(seg.id).trim() : '';
2269
+ if (!/^\d{1,4}$/.test(id)) return '';
2270
+ return FACE_DIR + Number(id) + '.webp';
2271
+ }
2272
+
2273
+ /**
2274
+ * 表情段。
2275
+ *
2276
+ * 早先这里直接渲染成「[表情 67]」——官方适配器只给编号,界面上就只剩一串数字。
2277
+ * 现在按编号显示本地表情图;图片缺失(新表情 / 老编号)或加载失败时,退回
2278
+ * 「[中文名]」文字标签,至少能看出是哪个表情。
2279
+ */
2280
+ function buildFace(seg) {
2281
+ const id = hasText(seg && seg.id) ? String(seg.id).trim() : '';
2282
+ const numeric = /^\d+$/.test(id);
2283
+ const label = faceLabel(seg);
2284
+ const textFallback = () => h('span', 'chip seg-face', '[' + label + ']');
2285
+
2286
+ // 编号本身就是字符(部分平台直接把 emoji 字符放进 id)时原样显示,
2287
+ // 但段里若另外给了图片,仍以图片为准
2288
+ if (id && !numeric && !safeUrl(seg.url)) return h('span', 'seg-emoji-char', id);
2289
+
2290
+ const url = faceImageUrl(seg);
2291
+ if (!url) return textFallback();
2292
+
2293
+ const img = document.createElement('img');
2294
+ img.className = 'seg-face-img';
2295
+ img.loading = 'lazy';
2296
+ img.decoding = 'async';
2297
+ img.referrerPolicy = 'no-referrer';
2298
+ img.alt = label;
2299
+ img.title = label;
2300
+ img.src = url;
2301
+ img.addEventListener('error', () => {
2302
+ if (!img.parentNode) return;
2303
+ // 图没下载到就先看一眼名称表,拿到中文名再退化,比直接显示编号友好
2304
+ const swap = () => {
2305
+ if (!img.parentNode) return;
2306
+ img.parentNode.replaceChild(
2307
+ id && !numeric ? h('span', 'seg-emoji-char', id) : textFallback(),
2308
+ img
2309
+ );
2310
+ };
2311
+ if (faceNames) swap();
2312
+ else loadFaceNames().then(swap);
2313
+ });
2314
+ return img;
2315
+ }
2316
+
2215
2317
  function buildImage(seg) {
2216
2318
  const wrap = h('span', 'seg-block');
2217
2319
  const source = safeUrl(seg.url);