Skip to content

Commit a7fea31

Browse files
authored
Merge pull request #19 from aoao-eth/app
Add robot status display
2 parents ed1cb8e + 17d33db commit a7fea31

File tree

6 files changed

+121
-33
lines changed

6 files changed

+121
-33
lines changed

app/main/background.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createWindow } from './helpers';
44
import { summarize } from './summarize';
55
import { getAllDirs } from './helpers/getAllDirs';
66
import { getConfig, setConfig } from './config';
7-
import { sendAudio, sendImage, sendText, startBot } from './startBot';
7+
import { botStatus, sendAudio, sendImage, sendText, startBot } from './startBot';
88
import path from 'path';
99
import { BASE_PATH, delay, PUBLIC_PATH, saveData } from './util';
1010
import fs from 'fs';
@@ -25,6 +25,7 @@ if (isProd) {
2525
height: 800,
2626
title: '群聊总结智囊',
2727
icon: path.join(__dirname, PUBLIC_PATH, 'logo.png'),
28+
backgroundColor: '#ffffff',
2829
});
2930

3031
if (isProd) {
@@ -34,7 +35,11 @@ if (isProd) {
3435
await mainWindow.loadURL(`http://localhost:${port}/home`);
3536
// mainWindow.webContents.openDevTools();
3637
}
37-
38+
ipcMain.on('get-bot-status', (event, title) => {
39+
mainWindow.webContents.send('bot-status-reply', {
40+
status: botStatus,
41+
});
42+
});
3843
ipcMain.on('summarize', (event, { dateDir, chatFileName }) => {
3944
const summarizeEvent = summarize(path.join(BASE_PATH, dateDir, chatFileName));
4045
summarizeEvent.addListener('update', (info) => {

app/main/startBot.ts

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
import { checkConfigIsOk, getConfig } from './config';
22
import { log, Message, ScanStatus, WechatyBuilder } from 'wechaty';
33
import { getMessagePayload, LOGPRE } from './helper';
4-
import { ipcMain } from 'electron';
5-
import { summarize } from './summarize';
6-
import { getAllDirs } from './helpers/getAllDirs';
74
import { PuppetPadlocal } from 'wechaty-puppet-padlocal-plus';
85
import { WechatyInterface } from 'wechaty/dist/esm/src/wechaty/wechaty-impl';
9-
import {FileBox} from 'file-box';
6+
import { FileBox } from 'file-box';
107
import { RoomInterface } from 'wechaty/dist/esm/src/user-modules/room';
118

12-
let bot:WechatyInterface
13-
export async function startBot(mainWindow: Electron.BrowserWindow) {
9+
let bot: WechatyInterface;
10+
11+
export let botStatus = '已停止';
1412

13+
export async function startBot(mainWindow: Electron.BrowserWindow) {
1514
if (!checkConfigIsOk()) {
1615
console.log('miss config');
1716
mainWindow.webContents.send('toast', `miss config`);
1817
mainWindow.webContents.send('show-config', getConfig());
1918
return;
2019
}
2120

22-
23-
if(bot){
21+
if (bot) {
2422
// 清理,重新启动 bot
2523
await bot.stop();
2624
bot = null;
@@ -29,35 +27,37 @@ export async function startBot(mainWindow: Electron.BrowserWindow) {
2927

3028
const puppet = new PuppetPadlocal({
3129
token: config.PADLOCAL_API_KEY,
32-
3330
});
3431
bot = WechatyBuilder.build({
3532
name: 'WXGroupSummary',
3633
puppet,
3734
});
38-
bot
39-
.on('message', async (message) => {
40-
log.info(LOGPRE, `on message: ${message.toString()}`);
35+
bot.on('message', async (message) => {
36+
log.info(LOGPRE, `on message: ${message.toString()}`);
4137

42-
await getMessagePayload(message);
38+
await getMessagePayload(message);
4339

44-
// await dingDongBot(message);
45-
});
40+
// await dingDongBot(message);
41+
botStatus = '运行中';
42+
});
4643
// 向 mainWindow 发送事件
4744
bot
4845
.on('error', (error) => {
4946
log.error(LOGPRE, `on error: ${error}`);
5047
mainWindow.webContents.send('toast', `错误: ${error}`);
48+
botStatus = '错误';
5149
})
5250
.on('login', (user) => {
5351
log.info(LOGPRE, `${user} login`);
5452
mainWindow.webContents.send('toast', `${user} login success`);
5553
mainWindow.webContents.send('login');
54+
botStatus = '登录成功';
5655
})
5756
.on('logout', (user, reason) => {
5857
log.info(LOGPRE, `${user} logout, reason: ${reason}`);
5958
mainWindow.webContents.send('toast', `${user} logout, reason: ${reason}`);
6059
mainWindow.webContents.send('logout');
60+
botStatus = '已退出';
6161
})
6262
.on('scan', (qrcode, status) => {
6363
if (status === ScanStatus.Waiting && qrcode) {
@@ -72,9 +72,11 @@ export async function startBot(mainWindow: Electron.BrowserWindow) {
7272
log.info(LOGPRE, `onScan: ${ScanStatus[status]}(${status})`);
7373
mainWindow.webContents.send('toast', `onScan: ${ScanStatus[status]}(${status})`);
7474
}
75+
botStatus = '已扫描';
7576
})
7677
.on('stop', () => {
7778
mainWindow.webContents.send('toast', `stop`);
79+
botStatus = '已停止';
7880
});
7981

8082
await bot.start();
@@ -84,44 +86,45 @@ export async function startBot(mainWindow: Electron.BrowserWindow) {
8486

8587
return bot;
8688
}
89+
8790
const roomCache = new Map<string, RoomInterface>();
8891
const getRoomByName = async (name: string) => {
89-
if(roomCache.has(name)){
90-
return roomCache.get(name)
92+
if (roomCache.has(name)) {
93+
return roomCache.get(name);
9194
}
9295
const roomList = await bot.Room.findAll();
9396
for (const room of roomList) {
9497
if (room.payload.topic === name) {
9598
console.log('找到了名为 [', name, '] 的群聊,其 ID 为:', room.id);
96-
roomCache.set(name,room)
99+
roomCache.set(name, room);
97100
return room;
98101
}
99102
}
100-
}
101-
const sendMessage = async (toRoomName:string, payload: any): Promise<Message> => {
103+
};
104+
const sendMessage = async (toRoomName: string, payload: any): Promise<Message> => {
102105
const room = await getRoomByName(toRoomName);
103-
const message = (await room.say(payload)) as Message;
104-
return message;
105-
106+
const message = (await room.say(payload)) as Message;
107+
return message;
106108
};
107109

108-
export async function sendText(toRoomName:string,text:string){
109-
console.log('sendText',toRoomName,text )
110+
export async function sendText(toRoomName: string, text: string) {
111+
console.log('sendText', toRoomName, text);
110112
const message = await sendMessage(toRoomName, text);
111113
return message;
112114
}
113-
export async function sendImage(toRoomName:string,imageFilePath:string){
114-
console.log('sendImage',toRoomName,imageFilePath )
115+
116+
export async function sendImage(toRoomName: string, imageFilePath: string) {
117+
console.log('sendImage', toRoomName, imageFilePath);
115118
// 图片大小建议不要超过 2 M
116119
const fileBox = FileBox.fromFile(imageFilePath);
117120

118121
const message = await sendMessage(toRoomName, fileBox);
119122
return message;
120123
}
121124

122-
export async function sendAudio(toRoomName:string,fileFilePath:string){
123-
console.log('sendAudio',toRoomName,fileFilePath )
125+
export async function sendAudio(toRoomName: string, fileFilePath: string) {
126+
console.log('sendAudio', toRoomName, fileFilePath);
124127
const fileBox = FileBox.fromFile(fileFilePath);
125128
const message = await sendMessage(toRoomName, fileBox);
126129
return message;
127-
}
130+
}

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"private": true,
33
"name": "wx-summarize-bot",
44
"description": "本项目是基于微信机器人的微信群聊总结助手,可以帮助群主或管理员自动收集群聊中的聊天记录,并使用 AI 进行总结,最终将其发送到指定的群聊中",
5-
"version": "1.0.1",
5+
"version": "1.0.2",
66
"author": "Yutou <xinyu198736@gmail.com>",
77
"main": "app/background.js",
88
"scripts": {

app/renderer/components/Header.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@ import Link from 'next/link';
33
import { ipcRenderer } from 'electron';
44
import Github from './icon/Github';
55
import Twitter from './icon/Twitter';
6+
import { useEffect, useState } from 'react';
7+
import { Chip } from '@nextui-org/react';
8+
import { SuccessIcon } from './icon/SuccessIcon';
9+
import { ErrorIcon } from './icon/ErrorIcon';
610

711
export function Header(props: { active: string }) {
12+
const [botStatus, setBotStatus] = useState('启动中');
13+
useEffect(() => {
14+
ipcRenderer.on('bot-status-reply', (event, args) => {
15+
setBotStatus(args.status);
16+
});
17+
setInterval(() => {
18+
ipcRenderer.send('get-bot-status');
19+
}, 3000);
20+
}, []);
21+
822
return (
923
<div className={styles['chat-header']}>
1024
<div className={styles['chat-header-inner']}>
@@ -97,6 +111,24 @@ export function Header(props: { active: string }) {
97111
</div>
98112
<div className={styles['chat-header-right']}>
99113
<div className={[styles['header-links'], 'hide_in_mobile'].join(' ')}>
114+
<Chip
115+
startContent={
116+
['错误', '已停止', '已退出'].includes(botStatus) ? <ErrorIcon size={14} /> : <SuccessIcon size={14} />
117+
}
118+
variant="flat"
119+
color={['错误', '已停止', '已退出'].includes(botStatus) ? 'danger' : 'success'}
120+
style={{
121+
paddingLeft: '10px',
122+
}}
123+
>
124+
<span
125+
style={{
126+
wordBreak: 'keep-all',
127+
}}
128+
>
129+
{botStatus}
130+
</span>
131+
</Chip>
100132
<a
101133
onClick={() => {
102134
ipcRenderer.send('open-url', 'https://twitter.com/aoao_eth');
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export function ErrorIcon(props: { size: number }) {
2+
return (
3+
<svg
4+
viewBox="0 0 1024 1024"
5+
version="1.1"
6+
xmlns="http://www.w3.org/2000/svg"
7+
width={props.size || 18}
8+
height={props.size || 18}
9+
style={{
10+
width: props.size || 18,
11+
height: props.size || 18,
12+
}}
13+
>
14+
<path
15+
d="M512 0a512 512 0 0 0-512 512 512 512 0 0 0 512 512 512 512 0 0 0 512-512 512 512 0 0 0-512-512z"
16+
fill="#FD6B6D"
17+
p-id="1179"
18+
></path>
19+
<path
20+
d="M513.755429 565.540571L359.277714 720.018286a39.058286 39.058286 0 0 1-55.296-0.073143 39.277714 39.277714 0 0 1 0.073143-55.442286l154.331429-154.331428-155.062857-155.136a36.571429 36.571429 0 0 1 51.712-51.785143l365.714285 365.714285a36.571429 36.571429 0 1 1-51.785143 51.785143L513.755429 565.540571z m157.549714-262.582857a35.254857 35.254857 0 1 1 49.737143 49.737143l-106.057143 108.982857a35.254857 35.254857 0 1 1-49.883429-49.810285l106.203429-108.982858z"
21+
fill="#FFFFFF"
22+
p-id="1180"
23+
></path>
24+
</svg>
25+
);
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export function SuccessIcon(props: { size: number }) {
2+
return (
3+
<svg
4+
viewBox="0 0 1024 1024"
5+
version="1.1"
6+
xmlns="http://www.w3.org/2000/svg"
7+
width={props.size || 18}
8+
height={props.size || 18}
9+
style={{
10+
width: props.size || 18,
11+
height: props.size || 18,
12+
}}
13+
>
14+
<path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#52C41A" p-id="1007"></path>
15+
<path
16+
d="M178.614857 557.860571a42.496 42.496 0 0 1 60.123429-60.050285l85.942857 87.625143a42.496 42.496 0 0 1-60.050286 60.123428L178.614857 557.860571z m561.005714-250.148571a42.496 42.496 0 1 1 65.097143 54.637714L394.459429 725.577143a42.496 42.496 0 0 1-65.097143-54.637714l410.112-363.373715z"
17+
fill="#FFFFFF"
18+
p-id="1008"
19+
></path>
20+
</svg>
21+
);
22+
}

0 commit comments

Comments
 (0)