From 9b57615d94e2290f357936b7a8f87ddd2f921297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=8B=B1=E6=9D=B0?= <806895158@qq.com> Date: Fri, 14 Mar 2025 16:19:41 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=E4=BA=86=E5=85=B3?= =?UTF-8?q?=E4=BA=8Egewe=E5=8F=91=E9=80=81=E8=A7=86=E9=A2=91=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/platform/sources/gewechat/client.py | 17 +++++++ .../sources/gewechat/gewechat_event.py | 44 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/astrbot/core/platform/sources/gewechat/client.py b/astrbot/core/platform/sources/gewechat/client.py index f0e64e69..bce637d7 100644 --- a/astrbot/core/platform/sources/gewechat/client.py +++ b/astrbot/core/platform/sources/gewechat/client.py @@ -490,6 +490,23 @@ class SimpleGewechatClient: json_blob = await resp.json() logger.debug(f"发送图片结果: {json_blob}") + async def post_video( + self, to_wxid, video_url: str, thumb_url: str, video_duration: int + ): + payload = { + "appId": self.appid, + "toWxid": to_wxid, + "videoUrl": video_url, + "thumbUrl": thumb_url, + "videoDuration": video_duration, + } + async with aiohttp.ClientSession() as session: + async with session.post( + f"{self.base_url}/message/postVideo", headers=self.headers, json=payload + ) as resp: + json_blob = await resp.json() + logger.debug(f"发送视频结果: {json_blob}") + async def post_voice(self, to_wxid, voice_url: str, voice_duration: int): payload = { "appId": self.appid, diff --git a/astrbot/core/platform/sources/gewechat/gewechat_event.py b/astrbot/core/platform/sources/gewechat/gewechat_event.py index 7668663f..b43c0663 100644 --- a/astrbot/core/platform/sources/gewechat/gewechat_event.py +++ b/astrbot/core/platform/sources/gewechat/gewechat_event.py @@ -2,6 +2,8 @@ import wave import uuid import traceback import os + +from astrbot.core.message.components import Video from astrbot.core.utils.io import save_temp_img, download_image_by_url, download_file from astrbot.core.utils.tencent_record_helper import wav_to_tencent_silk from astrbot.api import logger @@ -90,6 +92,48 @@ class GewechatPlatformEvent(AstrMessageEvent): img_url = f"{client.file_server_url}/{file_id}" logger.debug(f"gewe callback img url: {img_url}") await client.post_image(to_wxid, img_url) + elif isinstance(comp, Video): + from pyffmpeg import FFmpeg + + video_url = comp.file + # 根据 url 下载视频 + video_filename = f"{uuid.uuid4()}.mp4" + video_path = f"data/temp/{video_filename}" + await download_file(video_url, video_path) + + # 获取视频第一帧 + thumb_path = f"data/temp/{uuid.uuid4()}.jpg" + try: + ff = FFmpeg() + command = f'-i "{video_path}" -ss 0 -vframes 1 "{thumb_path}"' + ff.options(command) + thumb_file_id = os.path.basename(thumb_path) + thumb_url = f"{client.file_server_url}/{thumb_file_id}" + except Exception as e: + logger.error(f"获取视频第一帧失败: {e}") + # 获取视频时长 + try: + from pyffmpeg import FFprobe + + # 创建 FFprobe 实例 + ffprobe = FFprobe(video_url) + # 获取时长字符串 + duration_str = ffprobe.duration + # 处理时长字符串 + video_duration = float(duration_str.replace(":", "")) + except Exception as e: + logger.error(f"获取时长失败: {e}") + video_duration = 10 + + file_id = os.path.basename(video_path) + video_url = f"{client.file_server_url}/{file_id}" + await client.post_video(to_wxid, video_url, thumb_url, video_duration) + + # 删除临时视频和缩略图文件 + if os.path.exists(video_path): + os.remove(video_path) + if os.path.exists(thumb_path): + os.remove(thumb_path) elif isinstance(comp, Record): # 默认已经存在 data/temp 中 record_url = comp.file From 02dee2d664bee083da1be7b0e28e8d8fa8b9bb39 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Fri, 21 Mar 2025 16:51:23 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=8E=88=20perf:=20add=20error=20handli?= =?UTF-8?q?ng=20for=20missing=20pyffmpeg=20library=20in=20video=20sending?= =?UTF-8?q?=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/platform/sources/gewechat/gewechat_event.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/astrbot/core/platform/sources/gewechat/gewechat_event.py b/astrbot/core/platform/sources/gewechat/gewechat_event.py index 160b7c8a..5b74a63e 100644 --- a/astrbot/core/platform/sources/gewechat/gewechat_event.py +++ b/astrbot/core/platform/sources/gewechat/gewechat_event.py @@ -84,7 +84,15 @@ class GewechatPlatformEvent(AstrMessageEvent): logger.debug(f"gewe callback img url: {img_url}") await client.post_image(to_wxid, img_url) elif isinstance(comp, Video): - from pyffmpeg import FFmpeg + try: + from pyffmpeg import FFmpeg + except (ImportError, ModuleNotFoundError): + logger.error( + "需要安装 pyffmpeg 库才能发送视频: pip install pyffmpeg" + ) + raise ModuleNotFoundError( + "需要安装 pyffmpeg 库才能发送视频: pip install pyffmpeg" + ) video_url = comp.file # 根据 url 下载视频 From e5828713cfc3a35ba4ed81ff480a40d118effb0f Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sun, 23 Mar 2025 22:57:02 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=8E=88=20perf:=20improve=20ChatPage?= =?UTF-8?q?=20and=20ConfigPage=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/AstrBotConfig.vue | 363 +++++++--- dashboard/src/views/ChatPage.vue | 646 ++++++++++++++---- 2 files changed, 794 insertions(+), 215 deletions(-) diff --git a/dashboard/src/components/shared/AstrBotConfig.vue b/dashboard/src/components/shared/AstrBotConfig.vue index 2796f95d..e9d8e667 100644 --- a/dashboard/src/components/shared/AstrBotConfig.vue +++ b/dashboard/src/components/shared/AstrBotConfig.vue @@ -1,141 +1,207 @@ @@ -153,4 +219,125 @@ export default { metadataKey: String } } - \ No newline at end of file + + + \ No newline at end of file diff --git a/dashboard/src/views/ChatPage.vue b/dashboard/src/views/ChatPage.vue index 8f412cec..346dde07 100644 --- a/dashboard/src/views/ChatPage.vue +++ b/dashboard/src/views/ChatPage.vue @@ -8,164 +8,181 @@ marked.setOptions({ + \ No newline at end of file From ade87f378adaf881c203f6463d38c40b09733e22 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Mon, 24 Mar 2025 00:32:40 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=8E=88=20perf:=20UI=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/dashboard/routes/stat.py | 28 +- .../src/components/shared/AstrBotConfig.vue | 363 ++++------------- .../dashboards/default/DefaultDashboard.vue | 251 ++++++++++-- .../default/components/MemoryUsage.vue | 140 +++++++ .../default/components/MessageStat.vue | 375 +++++++++++++++--- .../default/components/OnlinePlatform.vue | 101 +++-- .../default/components/OnlineTime.vue | 217 ++++++++-- .../default/components/PlatformStat.vue | 327 ++++++++++----- .../default/components/RunningTime.vue | 89 +++++ .../default/components/TotalMessage.vue | 109 +++-- 10 files changed, 1426 insertions(+), 574 deletions(-) create mode 100644 dashboard/src/views/dashboards/default/components/MemoryUsage.vue create mode 100644 dashboard/src/views/dashboards/default/components/RunningTime.vue diff --git a/astrbot/dashboard/routes/stat.py b/astrbot/dashboard/routes/stat.py index b20e9dca..04b2d21e 100644 --- a/astrbot/dashboard/routes/stat.py +++ b/astrbot/dashboard/routes/stat.py @@ -1,6 +1,7 @@ import traceback import psutil import time +import threading from .route import Route, Response, RouteContext from astrbot.core import logger from quart import request @@ -64,6 +65,25 @@ class StatRoute(Route): stat_dict = stat.__dict__ + # 获取CPU使用率 - 修复CPU始终为0的问题 + process = psutil.Process() + # 获取系统CPU使用率而不是进程CPU使用率 + cpu_percent = psutil.cpu_percent(interval=0.5) + + # 获取线程数 + thread_count = threading.active_count() + + # 获取插件信息 + plugins = self.core_lifecycle.star_context.get_all_stars() + plugin_info = [] + for plugin in plugins: + info = { + "name": getattr(plugin, "name", plugin.__class__.__name__), + "version": getattr(plugin, "version", "1.0.0"), + "is_enabled": True + } + plugin_info.append(info) + stat_dict.update( { "platform": self.db_helper.get_grouped_base_stats( @@ -73,9 +93,8 @@ class StatRoute(Route): "platform_count": len( self.core_lifecycle.platform_manager.get_insts() ), - "plugin_count": len( - self.core_lifecycle.star_context.get_all_stars() - ), + "plugin_count": len(plugins), + "plugins": plugin_info, "message_time_series": message_time_based_stats, "running": self.format_sec( int(time.time()) - self.core_lifecycle.start_time @@ -84,6 +103,9 @@ class StatRoute(Route): "process": psutil.Process().memory_info().rss >> 20, "system": psutil.virtual_memory().total >> 20, }, + "cpu_percent": round(cpu_percent, 1), + "thread_count": thread_count, + "start_time": self.core_lifecycle.start_time, } ) diff --git a/dashboard/src/components/shared/AstrBotConfig.vue b/dashboard/src/components/shared/AstrBotConfig.vue index e9d8e667..2796f95d 100644 --- a/dashboard/src/components/shared/AstrBotConfig.vue +++ b/dashboard/src/components/shared/AstrBotConfig.vue @@ -1,207 +1,141 @@ @@ -219,125 +153,4 @@ export default { metadataKey: String } } - - - \ No newline at end of file + \ No newline at end of file diff --git a/dashboard/src/views/dashboards/default/DefaultDashboard.vue b/dashboard/src/views/dashboards/default/DefaultDashboard.vue index e904bf3a..859d6226 100644 --- a/dashboard/src/views/dashboards/default/DefaultDashboard.vue +++ b/dashboard/src/views/dashboards/default/DefaultDashboard.vue @@ -1,37 +1,84 @@ + + diff --git a/dashboard/src/views/dashboards/default/components/MemoryUsage.vue b/dashboard/src/views/dashboards/default/components/MemoryUsage.vue new file mode 100644 index 00000000..79d0ecb2 --- /dev/null +++ b/dashboard/src/views/dashboards/default/components/MemoryUsage.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/dashboard/src/views/dashboards/default/components/MessageStat.vue b/dashboard/src/views/dashboards/default/components/MessageStat.vue index 98b56819..6856c302 100644 --- a/dashboard/src/views/dashboards/default/components/MessageStat.vue +++ b/dashboard/src/views/dashboards/default/components/MessageStat.vue @@ -1,65 +1,136 @@ - - \ No newline at end of file + methods: { + formatNumber(num) { + return new Intl.NumberFormat('zh-CN').format(num); + }, + + async fetchMessageSeries() { + this.loading = true; + + try { + const response = await axios.get(`/api/stat/get?offset_sec=${this.selectedTimeRange.value}`); + const data = response.data.data; + + if (data && data.message_time_series) { + this.messageTimeSeries = data.message_time_series; + this.processTimeSeriesData(); + } + } catch (error) { + console.error('获取消息趋势数据失败:', error); + } finally { + this.loading = false; + } + }, + + processTimeSeriesData() { + // 转换数据为图表格式 + this.chartSeries[0].data = this.messageTimeSeries.map((item) => { + return [new Date(item[0]*1000).getTime(), item[1]]; + }); + + // 计算总消息数 + let total = 0; + this.messageTimeSeries.forEach(item => { + total += item[1]; + }); + this.totalMessages = this.formatNumber(total); + + // 计算日平均 + if (this.messageTimeSeries.length > 0) { + const daysSpan = this.selectedTimeRange.value / 86400; // 将秒转换为天数 + this.dailyAverage = this.formatNumber(Math.round(total / daysSpan)); + } + + // 计算增长率 + this.calculateGrowthRate(); + }, + + calculateGrowthRate() { + if (this.messageTimeSeries.length < 4) { + this.growthRate = 0; + return; + } + + // 计算前半部分和后半部分的消息总数 + const halfIndex = Math.floor(this.messageTimeSeries.length / 2); + + const firstHalf = this.messageTimeSeries + .slice(0, halfIndex) + .reduce((sum, item) => sum + item[1], 0); + + const secondHalf = this.messageTimeSeries + .slice(halfIndex) + .reduce((sum, item) => sum + item[1], 0); + + // 计算增长率 + if (firstHalf > 0) { + this.growthRate = Math.round(((secondHalf - firstHalf) / firstHalf) * 100); + } else { + this.growthRate = secondHalf > 0 ? 100 : 0; + } + } + } +}; + + + \ No newline at end of file diff --git a/dashboard/src/views/dashboards/default/components/OnlinePlatform.vue b/dashboard/src/views/dashboards/default/components/OnlinePlatform.vue index 26fd6e8a..3eee6aaa 100644 --- a/dashboard/src/views/dashboards/default/components/OnlinePlatform.vue +++ b/dashboard/src/views/dashboards/default/components/OnlinePlatform.vue @@ -1,37 +1,84 @@ - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/dashboard/src/views/dashboards/default/components/OnlineTime.vue b/dashboard/src/views/dashboards/default/components/OnlineTime.vue index 4ba51a7d..3c869aa3 100644 --- a/dashboard/src/views/dashboards/default/components/OnlineTime.vue +++ b/dashboard/src/views/dashboards/default/components/OnlineTime.vue @@ -1,61 +1,190 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/dashboard/src/views/dashboards/default/components/PlatformStat.vue b/dashboard/src/views/dashboards/default/components/PlatformStat.vue index 243fd5b1..9235ff72 100644 --- a/dashboard/src/views/dashboards/default/components/PlatformStat.vue +++ b/dashboard/src/views/dashboards/default/components/PlatformStat.vue @@ -1,116 +1,253 @@ - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/dashboard/src/views/dashboards/default/components/RunningTime.vue b/dashboard/src/views/dashboards/default/components/RunningTime.vue new file mode 100644 index 00000000..139eaa6a --- /dev/null +++ b/dashboard/src/views/dashboards/default/components/RunningTime.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/dashboard/src/views/dashboards/default/components/TotalMessage.vue b/dashboard/src/views/dashboards/default/components/TotalMessage.vue index 8af94a75..6644a7b9 100644 --- a/dashboard/src/views/dashboards/default/components/TotalMessage.vue +++ b/dashboard/src/views/dashboards/default/components/TotalMessage.vue @@ -1,40 +1,97 @@ - - \ No newline at end of file + + + \ No newline at end of file From 89d51d2afc8ca565d12abdcdcd9c3c5993102e32 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Mon, 24 Mar 2025 11:36:34 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=8E=88=20perf:=20config=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/AstrBotConfig.vue | 500 +++++++++++++----- 1 file changed, 359 insertions(+), 141 deletions(-) diff --git a/dashboard/src/components/shared/AstrBotConfig.vue b/dashboard/src/components/shared/AstrBotConfig.vue index 2796f95d..2e24af80 100644 --- a/dashboard/src/components/shared/AstrBotConfig.vue +++ b/dashboard/src/components/shared/AstrBotConfig.vue @@ -1,156 +1,374 @@ \ No newline at end of file + + + \ No newline at end of file