Skip to content

Commit

Permalink
add new UI
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhangWei-KUMO committed Dec 11, 2024
1 parent bf79ec5 commit e38e44f
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 37 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
logger
script
yarn.lock
xuyue.memory-card.json
xuyue.memory-card.json
*.db
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ This is an open-source WeChat robot project based on WechatY, Dify API services,
| USGC | 纽约黄金价格 ||
| Inpainting | 机器人集群启动 ||
| Websocket监听通信 | Websocket监听通信 ||
| SQLite | 支持SQLite数据库 ||
| Group Chat Export | 群聊天记录的导出 ||



## Workflow

Expand All @@ -45,7 +49,9 @@ This is an open-source WeChat robot project based on WechatY, Dify API services,
```bash
# e.g. Ubuntu 22
sudo apt update
# 启动语音识别功能需要安装ffmpeg
sudo apt install ffmpeg
# redis记录临时ID
sudo apt install redis-server
npm install -g pm2
```
Expand Down Expand Up @@ -101,3 +107,4 @@ [email protected]
https://tubex.chat



1 change: 0 additions & 1 deletion __tests__/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
};

ws.onmessage = (event) => {
console.log("Received QR code:", event.data);
// Display the QR code (assuming it's a string)
document.getElementById('qrcode').innerText = event.data;
};
Expand Down
65 changes: 65 additions & 0 deletions db/chats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import sqlite3 from 'sqlite3';
import moment from 'moment-timezone'; // Import moment-timezone for timezones

// Set the default timezone to Beijing
moment.tz.setDefault("Asia/Shanghai");


// 数据库文件名
const dbFile = 'chats.db';

// 创建数据库连接
let db = new sqlite3.Database(dbFile, (err) => {
if (err) {
console.error(err.message);
} else {
console.log('连接聊天记录数据库');
db.run(`
CREATE TABLE IF NOT EXISTS chats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), -- Use STRFTIME for timestamps
name TEXT,
message TEXT
)
`);
}
});



// 日志记录函数
export function chat(name, message) {

// Limit message length to 200 characters
// if(!message) return
// const truncatedMessage = message.substring(0, 200);

const timestamp = moment().format("YYYY-MM-DD HH:mm"); // Format timestamp with Beijing time
db.run(`INSERT INTO chats (timestamp, name, message) VALUES (?, ?, ?)`, [timestamp, name, message], function (err) {
if (err) {
console.error(err.message);
}
});


// Keep only the latest 200 log entries
db.run(`DELETE FROM chats WHERE id NOT IN (SELECT id FROM logs ORDER BY id DESC LIMIT 200)`);


}



// 查询日志
export function getChats() {
return new Promise((resolve, reject) => {
db.all(`SELECT * FROM chats ORDER BY timestamp DESC`, [], (err, rows) => {
if (err) {
console.error(err.message);
reject(err);
} else {
resolve(rows);
}
});
});
}
66 changes: 66 additions & 0 deletions db/logs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import sqlite3 from 'sqlite3';
import moment from 'moment-timezone'; // Import moment-timezone for timezones

// Set the default timezone to Beijing
moment.tz.setDefault("Asia/Shanghai");


// 数据库文件名
const dbFile = 'logs.db';

// 创建数据库连接
let db = new sqlite3.Database(dbFile, (err) => {
if (err) {
console.error(err.message);
} else {
console.log('连接日志数据库');
// 创建日志表(如果不存在)
db.run(`
CREATE TABLE IF NOT EXISTS logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), -- Use STRFTIME for timestamps
level TEXT,
message TEXT
)
`);
}
});



// 日志记录函数
export function log(level, message) {

// Limit message length to 200 characters
// if(!message) return
// const truncatedMessage = message.substring(0, 200);

const timestamp = moment().format("YYYY-MM-DD HH:mm"); // Format timestamp with Beijing time
db.run(`INSERT INTO logs (timestamp, level, message) VALUES (?, ?, ?)`, [timestamp, level, message], function (err) {
if (err) {
console.error(err.message);
}
});


// Keep only the latest 200 log entries
db.run(`DELETE FROM logs WHERE id NOT IN (SELECT id FROM logs ORDER BY id DESC LIMIT 200)`);


}



// 查询日志
export function getLogs() {
return new Promise((resolve, reject) => {
db.all(`SELECT * FROM logs ORDER BY timestamp DESC`, [], (err, rows) => { // Order by timestamp descending
if (err) {
console.error(err.message);
reject(err);
} else {
resolve(rows);
}
});
});
}
72 changes: 40 additions & 32 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@ import {sendMessage,convertSilkToWav,readSheet,readTxt,
import {recognizeSpeech} from './util/azure.js'
import { config } from 'dotenv';
import {splitTextIntoArray} from './util/reply-filter.js'
// import qrcode from 'qrcode-terminal';
import {transporter,mailOptions} from './util/mailer.js';
import schedule from 'node-schedule';
import {getNews} from './util/group.js'
import { WebSocketServer } from "ws"
import express from 'express';
import path from 'path';
import open from 'open';
import {log,getLogs} from './db/logs.js'
import {chat,getChats} from './db/chats.js'
import { fileURLToPath } from 'url'; // Import fileURLToPath
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);


const wss = new WebSocketServer({ port: 1982 })
const app = express();
const port = 3000;

config();
console.log("微信机器人启动,版本号:",bot.version());
// function qrcodeToTerminal(url) {
// qrcode.generate(url, { small: true });
// }

export async function prepareBot() {
bot.on("message", async (message) => {
Expand All @@ -36,6 +37,9 @@ export async function prepareBot() {
// 属于群聊的聊天信息
if (message.room()) {
let roomMsg = message.room()
let {payload} = roomMsg;
// 群名称
let {topic} = payload;
// 获取当前群聊名称
let mentionText = await message.mentionText();
if (await message.mentionSelf()) {
Expand Down Expand Up @@ -109,7 +113,7 @@ export async function prepareBot() {
}
break;
case 7:
console.log(message)
chat(topic, message.payload.text);
break;
default:
return
Expand All @@ -132,6 +136,8 @@ export async function prepareBot() {
const locationText = `我的地址是:${lines[0]}`;
saveInLongMemory(locationText,talkerId)
}else{

chat(talkerId, text);
let answer = await difyChat(talkerId,text)
if(answer){
answer = answer.replace(/\*/g, '');
Expand All @@ -155,6 +161,7 @@ export async function prepareBot() {
break;
// 图片消息
case 6:
chat(talkerId, '图片消息');
break;
case 11:
{ const xmlstr = payload.text;
Expand Down Expand Up @@ -269,38 +276,29 @@ export async function prepareBot() {
});

bot.on('scan', (qrcode) => {
// 生成微信登录二维码
// qrcodeToTerminal(qrcode);
wss.on('connection', function connection(ws) {
// 发送二维码给前端
ws.send(qrcode);
})
})

bot.on("login", (user) => {
let {payload} = user;
let {name} = payload;
console.log("机器人登录成功,账号名:", name);
log('info', "机器人登录成功,账号名:"+name);
})

bot.on("logout", async () => {
transporter.sendMail(mailOptions, (error) => {
if (error) {
return console.error(error);
}
});
wss.clients.forEach((client) => {
client.close(); // Important: Close client after login
});
bot.on("logout", async (user) => {
let {payload} = user;
let {name} = payload;
log('info', name+"退出登录");
})

bot.on("error", (e) => {
console.error(e);
log('error', e);
})
// 启动的时间会比较久
bot.on("ready",async ()=>{
let rooms = await bot.Room.findAll()
// 过滤rooms中payload.topic是否有匹配
let id = ""
rooms.filter(room=>{
if(process.env.MANAGE_ROOMS.includes(room.payload.topic)){
Expand Down Expand Up @@ -332,30 +330,40 @@ export async function prepareBot() {
}

async function startBot() {
// Serve static files from the 'public' directory
app.use(express.static(path.join(process.cwd(), 'public'))); // Assuming your HTML is in 'public'
console.log("---")
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, './public/index.html')); // or wherever your index.html is
});

app.listen(port, async () => {

app.get('/api/logs', (req, res) => {
getLogs().then((data) => {
res.json(data);
});
});
app.get('/api/chats', (req, res) => {
getChats().then((data) => {
res.json(data);
});
});
app.get('/settings', (req, res) => {
res.sendFile(path.join(__dirname, './public/settings.html'));
});
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, './public/index.html'));
});
app.listen(port, async () => {
console.log(`Web server listening at http://localhost:${port}`);
// Open the browser automatically
await open(`http://localhost:${port}`);
});
});
await prepareBot();

}

startBot().catch(console.error);

process.on('exit', async(code) => {
console.log(`WechatY程序中断: ${code}`);
log('warning', "程序退出"+code);
});

process.on('SIGINT', async () => {
console.log(`WechatY程序中断:SIGINT`);
log('warning', "程序退出");
await bot.logout();
process.exit();
});
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"mammoth": "^1.6.0",
"microsoft-cognitiveservices-speech-sdk": "^1.35.0",
"moment": "^2.30.1",
"moment-timezone": "^0.5.46",
"node-schedule": "^2.1.1",
"nodemailer": "^6.9.15",
"open": "^10.1.0",
Expand All @@ -28,6 +29,7 @@
"qrcode-terminal": "^0.12.0",
"replicate": "^0.34.0",
"sensitive-words-js": "^1.0.4",
"sqlite3": "^5.1.7",
"talib": "^1.1.6",
"technicalindicators": "^3.1.0",
"wechaty": "^1.20.2",
Expand Down
Loading

0 comments on commit e38e44f

Please sign in to comment.