762 lines
24 KiB
JavaScript
762 lines
24 KiB
JavaScript
#!/usr/bin/env -S node --no-warnings --loader ts-node/esm
|
||
import 'dotenv/config.js'
|
||
// import fs from 'fs'
|
||
import {
|
||
Contact,
|
||
Message,
|
||
ScanStatus,
|
||
log,
|
||
// Room,
|
||
types,
|
||
Wechaty,
|
||
WechatyBuilder,
|
||
} from 'wechaty'
|
||
|
||
import qrcodeTerminal from 'qrcode-terminal'
|
||
import { FileBox } from 'file-box'
|
||
import fs, { createWriteStream } from 'fs'
|
||
import XLSX from 'xlsx'
|
||
import csv from 'fast-csv'
|
||
import {
|
||
VikaBot,
|
||
configData,
|
||
sendMsg,
|
||
sendNotice,
|
||
getFormattedRideInfo,
|
||
imclient,
|
||
wxai,
|
||
ChatDevice,
|
||
propertyMessage,
|
||
eventMessage,
|
||
|
||
} from './plugins/index.js'
|
||
import type { types as configTypes } from './mods/mod.js'
|
||
import { baseConfig, config } from './config.js'
|
||
import {
|
||
waitForMs as wait,
|
||
formatSentMessage,
|
||
} from './util/tool.js'
|
||
import schedule from 'node-schedule'
|
||
import { db } from './db/tables.js'
|
||
|
||
log.info('db:', db)
|
||
log.info('config:', JSON.stringify(config))
|
||
// log.info('process.env', JSON.stringify(process.env))
|
||
|
||
enum Prompts {
|
||
a = '输入的信息错误或格式不符合要求,请输入如下格式"维格表token+空间名称",中间用加号分开,例如:\nuskxRhxxxxxxxx3UK959A8093+wechatbot',
|
||
b = '启动成功,请输入"维格表token+空间名称",中间用加号分开,例如:\nuskxRhxxxxxxxx3UK959A8093+wechatbot'
|
||
}
|
||
|
||
let bot: Wechaty
|
||
let puppet = baseConfig['puppetName'] || process.env['WECHATY_PUPPET']
|
||
let token = baseConfig['puppetToken'] || process.env['WECHATY_TOKEN']
|
||
const vikaConfig = {
|
||
spaceName: baseConfig['VIKA_SPACENAME'] || process.env['VIKA_SPACENAME'],
|
||
token: baseConfig['VIKA_TOKEN'] || process.env['VIKA_TOKEN'],
|
||
}
|
||
// log.info(vikaConfig)
|
||
let sysConfig: configTypes.SysConfig
|
||
let chatdev: any = {}
|
||
// let job: any
|
||
let jobs: any
|
||
let vika: any
|
||
let isVikaOk: boolean = false
|
||
let socket: any = {}
|
||
|
||
// log.info(baseConfig)
|
||
|
||
function updateBaseConfig (config: configTypes.SysConfig) {
|
||
puppet = config['puppetName'] || puppet
|
||
token = config['puppetToken'] || token
|
||
}
|
||
|
||
function updateConfig (config:any) {
|
||
fs.writeFileSync('src/config.json', JSON.stringify(config))
|
||
}
|
||
|
||
async function createVika () {
|
||
try {
|
||
vika = new VikaBot(vikaConfig)
|
||
await vika.init()
|
||
|
||
// 初始化获取配置信息
|
||
const initReady = await vika.checkInit('主程序载入系统配置成功,等待插件初始化...')
|
||
if (!initReady) {
|
||
return
|
||
}
|
||
|
||
// 获取系统配置信息
|
||
sysConfig = await vika.getConfig()
|
||
log.info('config:', JSON.stringify(config))
|
||
const configReady = checkConfig(config)
|
||
updateBaseConfig(config)
|
||
// 配置齐全,启动机器人
|
||
if (configReady) {
|
||
return vika
|
||
}
|
||
} catch {
|
||
return false
|
||
}
|
||
}
|
||
|
||
function getBot () {
|
||
const ops: any = {
|
||
name: 'qa-bot',
|
||
puppet,
|
||
puppetOptions: {
|
||
token,
|
||
},
|
||
}
|
||
|
||
log.info(ops)
|
||
|
||
if (puppet === 'wechaty-puppet-service') {
|
||
process.env['WECHATY_PUPPET_SERVICE_NO_TLS_INSECURE_CLIENT'] = 'true'
|
||
}
|
||
|
||
if ([ 'wechaty-puppet-wechat4u', 'wechaty-puppet-xp', 'wechaty-puppet-engine' ].includes(puppet)) {
|
||
delete ops.puppetOptions.token
|
||
}
|
||
|
||
if (puppet === 'wechaty-puppet-wechat') {
|
||
delete ops.puppetOptions.token
|
||
ops.puppetOptions.uos = true
|
||
}
|
||
|
||
log.info('bot ops:', JSON.stringify(ops))
|
||
|
||
const bot = WechatyBuilder.build(ops)
|
||
return bot
|
||
}
|
||
|
||
function getNow () {
|
||
return new Date().toLocaleString()
|
||
}
|
||
|
||
function checkConfig (config: { [key: string]: any }) {
|
||
const missingConfiguration = []
|
||
|
||
for (const key in config) {
|
||
if (!config[key] && ![ 'imOpen', 'DIFF_REPLY_ONOFF' ].includes(key)) {
|
||
missingConfiguration.push(key)
|
||
}
|
||
}
|
||
|
||
if (missingConfiguration.length > 0) {
|
||
// log.error('\n======================================\n\n', `错误提示:\n缺少${missingConfiguration.join()}配置参数,请检查config.js文件\n\n======================================`)
|
||
log.info('bot config:', config)
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
async function relpy (bot: Wechaty, vika: any, replyText: string, message: Message) {
|
||
await message.say(replyText)
|
||
vika.addRecord(await formatSentMessage(bot.currentUser, replyText, message.room() ? undefined : message.talker(), message.room()))
|
||
}
|
||
|
||
async function exportContactsAndRoomsToCSV () {
|
||
// 获取所有联系人和群聊
|
||
const contacts = await bot.Contact.findAll()
|
||
const rooms = await bot.Room.findAll()
|
||
|
||
// 准备CSV数据
|
||
const csvData = []
|
||
contacts.forEach((contact: Contact) => {
|
||
if (contact.friend()) {
|
||
csvData.push({ ID: contact.id, Name: Buffer.from(contact.name(), 'utf-8').toString() || '未知', Type: 'Contact' })
|
||
}
|
||
})
|
||
|
||
for (const room of rooms) {
|
||
csvData.push({ ID: room.id, Name: Buffer.from(await room.topic(), 'utf-8').toString() || '未知', Type: 'Room' })
|
||
}
|
||
|
||
log.info('通讯录原始数据:', csvData)
|
||
|
||
const fileName = './db/contacts_and_rooms.csv'
|
||
const writeStream = createWriteStream(fileName)
|
||
const csvStream = csv.format({ headers: true })
|
||
csvStream.pipe(writeStream).on('end', () => {
|
||
log.info('CSV file written successfully')
|
||
})
|
||
|
||
csvData.forEach((item) => {
|
||
csvStream.write(item)
|
||
})
|
||
|
||
csvStream.end()
|
||
|
||
// 返回FileBox对象
|
||
return FileBox.fromFile(fileName)
|
||
}
|
||
|
||
async function exportContactsAndRoomsToXLSX () {
|
||
// 获取所有联系人和群聊
|
||
const contacts = await bot.Contact.findAll()
|
||
const rooms = await bot.Room.findAll()
|
||
|
||
// 准备联系人和群聊数据
|
||
const contactsData = [ [ 'Name', 'ID' ] ]
|
||
const roomsData = [ [ 'Name', 'ID' ] ]
|
||
contacts.forEach((contact) => {
|
||
if (contact.friend()) {
|
||
contactsData.push([ contact.name(), contact.id ])
|
||
}
|
||
})
|
||
|
||
for (const room of rooms) {
|
||
roomsData.push([ await room.topic(), room.id ])
|
||
}
|
||
|
||
// 创建一个新的工作簿
|
||
const workbook = XLSX.utils.book_new()
|
||
|
||
// 将数据添加到工作簿的不同sheet中
|
||
const contactsSheet = XLSX.utils.aoa_to_sheet(contactsData)
|
||
const roomsSheet = XLSX.utils.aoa_to_sheet(roomsData)
|
||
XLSX.utils.book_append_sheet(workbook, contactsSheet, 'Contacts')
|
||
XLSX.utils.book_append_sheet(workbook, roomsSheet, 'Rooms')
|
||
|
||
// 将工作簿写入文件
|
||
const fileName = './db/contacts_and_rooms.xlsx'
|
||
XLSX.writeFile(workbook, fileName)
|
||
|
||
// 返回FileBox对象
|
||
return FileBox.fromFile(fileName)
|
||
}
|
||
|
||
async function updateJobs (bot: Wechaty, vika: any) {
|
||
try {
|
||
const tasks = await vika.getTimedTask()
|
||
schedule.gracefulShutdown()
|
||
jobs = {}
|
||
// log.info(tasks)
|
||
for (let i = 0; i < tasks.length; i++) {
|
||
const task: any = tasks[i]
|
||
if (task.active) {
|
||
const curTimeF = new Date(task.time)
|
||
// const curTimeF = new Date(task.time+8*60*60*1000)
|
||
let curRule = '* * * * * *'
|
||
let dayOfWeek: any = '*'
|
||
let month: any = '*'
|
||
let dayOfMonth: any = '*'
|
||
let hour: any = curTimeF.getHours()
|
||
let minute: any = curTimeF.getMinutes()
|
||
const second = 0
|
||
const addMonth = []
|
||
switch (task.cycle) {
|
||
case '每季度':
|
||
month = curTimeF.getMonth()
|
||
for (let i = 0; i < 4; i++) {
|
||
if (month + 3 <= 11) {
|
||
addMonth.push(month)
|
||
} else {
|
||
addMonth.push(month - 9)
|
||
}
|
||
month = month + 3
|
||
}
|
||
month = addMonth
|
||
break
|
||
case '每天':
|
||
break
|
||
case '每周':
|
||
dayOfWeek = curTimeF.getDay()
|
||
break
|
||
case '每月':
|
||
month = curTimeF.getMonth()
|
||
break
|
||
case '每小时':
|
||
hour = '*'
|
||
break
|
||
case '每30分钟':
|
||
hour = '*'
|
||
minute = [ 0, 30 ]
|
||
break
|
||
case '每15分钟':
|
||
hour = '*'
|
||
minute = [ 0, 15, 30, 45 ]
|
||
break
|
||
case '每10分钟':
|
||
hour = '*'
|
||
minute = [ 0, 10, 20, 30, 40, 50 ]
|
||
break
|
||
case '每5分钟':
|
||
hour = '*'
|
||
minute = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ]
|
||
break
|
||
case '每分钟':
|
||
hour = '*'
|
||
minute = '*'
|
||
break
|
||
default:
|
||
month = curTimeF.getMonth()
|
||
dayOfMonth = curTimeF.getDate()
|
||
break
|
||
|
||
}
|
||
curRule = `${second} ${minute} ${hour} ${dayOfMonth} ${month} ${dayOfWeek}`
|
||
log.info(curRule)
|
||
|
||
try {
|
||
schedule.scheduleJob(task.id, curRule, async () => {
|
||
try {
|
||
const curDate = new Date()
|
||
log.info('定时任务:', curTimeF, curRule, curDate, JSON.stringify(task))
|
||
// await user.say('心跳:' + curDate)
|
||
|
||
try {
|
||
if (task.contacts.length) {
|
||
const contact = await bot.Contact.find({ id: task.contacts[0] })
|
||
if (contact) {
|
||
await contact.say(task.msg)
|
||
vika.addRecord(await formatSentMessage(bot.currentUser, task.msg, contact, undefined))
|
||
await wait(200)
|
||
}
|
||
}
|
||
} catch (e) {
|
||
log.error('发送好友定时任务失败:', e)
|
||
}
|
||
|
||
try {
|
||
if (task.rooms.length) {
|
||
const room = await bot.Room.find({ id: task.rooms[0] })
|
||
if (room) {
|
||
await room.say(task.msg)
|
||
vika.addRecord(await formatSentMessage(bot.currentUser, task.msg, undefined, room))
|
||
await wait(200)
|
||
}
|
||
}
|
||
} catch (e) {
|
||
log.error('发送群定时任务失败:', e)
|
||
|
||
}
|
||
|
||
} catch (err) {
|
||
log.error('定时任务执行失败:', err)
|
||
}
|
||
})
|
||
jobs[task.id] = task
|
||
} catch (e) {
|
||
log.error('创建定时任务失败:', e)
|
||
}
|
||
}
|
||
}
|
||
log.info('通知提醒任务初始化完成,创建任务数量:', Object.keys(jobs).length)
|
||
|
||
} catch (err: any) {
|
||
log.error('更新通知提醒列表任务失败:', err)
|
||
}
|
||
}
|
||
|
||
async function onScan (qrcode: string, status: ScanStatus) {
|
||
// 上传二维码到维格表,可通过扫码维格表中二维码登录
|
||
if (isVikaOk) await vika.onScan(qrcode, status)
|
||
|
||
// 控制台显示二维码
|
||
if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
|
||
const qrcodeUrl = encodeURIComponent(qrcode)
|
||
const qrcodeImageUrl = [
|
||
'https://wechaty.js.org/qrcode/',
|
||
qrcodeUrl,
|
||
].join('')
|
||
log.info('StarterBot', 'onScan: %s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl)
|
||
qrcodeTerminal.generate(qrcode, { small: true }) // show qrcode on console
|
||
|
||
} else {
|
||
log.info('StarterBot', 'onScan: %s(%s)', ScanStatus[status], status)
|
||
}
|
||
}
|
||
|
||
async function onLogin (user: Contact) {
|
||
log.info('StarterBot', '%s login', user)
|
||
log.info('当前登录的账号信息:', JSON.stringify(user))
|
||
|
||
if (isVikaOk) {
|
||
const curDate = new Date().toLocaleString()
|
||
await user.say('上线:' + curDate)
|
||
// 启动MQTT通道
|
||
if (sysConfig.mqttPassword && (sysConfig.mqtt_SUB_ONOFF || sysConfig.mqtt_PUB_ONOFF)) {
|
||
chatdev = new ChatDevice(sysConfig.mqttUsername, sysConfig.mqttPassword, sysConfig.mqttEndpoint, sysConfig.mqttPort, user.id)
|
||
if (sysConfig.mqtt_SUB_ONOFF) {
|
||
chatdev.init(bot)
|
||
}
|
||
}
|
||
|
||
// 更新云端好友和群
|
||
await vika.updateRooms(bot)
|
||
await vika.updateContacts(bot)
|
||
|
||
// 如果开启了MQTT推送,心跳同步到MQTT,每30s一次
|
||
setInterval(() => {
|
||
try {
|
||
log.info(curDate)
|
||
if (chatdev && sysConfig.mqtt_PUB_ONOFF) {
|
||
chatdev.pub_property(propertyMessage('lastActive', curDate))
|
||
}
|
||
} catch (err) {
|
||
log.error('发送心跳失败:', err)
|
||
}
|
||
}, 300000)
|
||
|
||
// 启动用户定时通知提醒任务
|
||
await updateJobs(bot, vika)
|
||
log.info('================================================\n\n登录启动成功,程序准备就绪\n\n================================================\n')
|
||
} else {
|
||
log.info('================================================\n\n登录启动成功,但没有配置维格表\n\n================================================\n')
|
||
await user.say(Prompts.b)
|
||
}
|
||
}
|
||
|
||
async function onReady () {
|
||
const user: Contact = bot.currentUser
|
||
log.info('StarterBot', '%s ready', user)
|
||
log.info('当前登录的账号信息:', JSON.stringify(user))
|
||
|
||
if (isVikaOk) {
|
||
const curDate = new Date().toLocaleString()
|
||
await user.say('上线:' + curDate)
|
||
// 启动MQTT通道
|
||
if (sysConfig.mqttPassword && (sysConfig.mqtt_SUB_ONOFF || sysConfig.mqtt_PUB_ONOFF)) {
|
||
chatdev = new ChatDevice(sysConfig.mqttUsername, sysConfig.mqttPassword, sysConfig.mqttEndpoint, sysConfig.mqttPort, user.id)
|
||
if (sysConfig.mqtt_SUB_ONOFF) {
|
||
chatdev.init(bot)
|
||
}
|
||
}
|
||
|
||
// 更新云端好友和群
|
||
await vika.updateRooms(bot)
|
||
await vika.updateContacts(bot)
|
||
|
||
// 如果开启了MQTT推送,心跳同步到MQTT,每30s一次
|
||
setInterval(() => {
|
||
try {
|
||
log.info(curDate)
|
||
if (chatdev && sysConfig.mqtt_PUB_ONOFF) {
|
||
chatdev.pub_property(propertyMessage('lastActive', curDate))
|
||
}
|
||
} catch (err) {
|
||
log.error('发送心跳失败:', err)
|
||
}
|
||
}, 300000)
|
||
|
||
// 启动用户定时通知提醒任务
|
||
await updateJobs(bot, vika)
|
||
log.info('================================================\n\n登录启动成功,程序准备就绪\n\n================================================\n')
|
||
|
||
} else {
|
||
log.info('================================================\n\n登录启动成功,但没有配置维格表\n\n================================================\n')
|
||
await user.say(Prompts.b)
|
||
}
|
||
}
|
||
|
||
function onLogout (user: Contact) {
|
||
log.info('StarterBot', '%s logout', user)
|
||
// job.cancel()
|
||
}
|
||
|
||
async function onMessage (message: Message) {
|
||
log.info('onMessage', JSON.stringify(message))
|
||
const curDate = new Date().toLocaleString()
|
||
const talker = message.talker()
|
||
// const listener = message.listener()
|
||
const text = message.text()
|
||
const room = message.room()
|
||
const roomId = room?.id
|
||
const topic = await room?.topic()
|
||
const keyWord = bot.currentUser.name()
|
||
const isSelfMsg = message.self()
|
||
let isAdminRoom: boolean = false
|
||
log.info('keyWord is:', keyWord)
|
||
|
||
if (isVikaOk) {
|
||
await vika.onMessage(message)
|
||
// MQTT上报
|
||
if (chatdev && sysConfig.mqtt_PUB_ONOFF) {
|
||
/*
|
||
将消息通过mqtt通道上报到云端
|
||
*/
|
||
// chatdev.pub_message(message)
|
||
chatdev.pub_event(eventMessage('onMessage', { curDate }))
|
||
}
|
||
if (room || isSelfMsg) {
|
||
isAdminRoom = (topic !== undefined && topic === sysConfig.adminRoomTopic) || isSelfMsg
|
||
|
||
if (isAdminRoom) {
|
||
await sendNotice(bot, message)
|
||
}
|
||
|
||
let replyText: string = ''
|
||
if (isAdminRoom && (text === '#指令列表' || text === '#帮助')) {
|
||
replyText = `操作指令说明:
|
||
#更新配置 更新全部配置
|
||
#更新提醒 更新定时提醒任务
|
||
#更新通讯录 更新维格表通信录
|
||
#下载通讯录 下载通讯录xlsx表
|
||
#下载通知模板 下载通知模板`
|
||
|
||
await relpy(bot, vika, replyText, message)
|
||
}
|
||
|
||
if (isAdminRoom && text === '#更新配置') {
|
||
log.info('热更新系统配置~')
|
||
try {
|
||
sysConfig = await vika.getConfig()
|
||
// message.say('配置更新成功:' + JSON.stringify(newConfig))
|
||
log.info('newConfig', sysConfig)
|
||
replyText = '配置更新成功~'
|
||
} catch (e) {
|
||
replyText = '配置更新成功~'
|
||
}
|
||
|
||
await relpy(bot, vika, getNow() + replyText, message)
|
||
}
|
||
|
||
if (isAdminRoom && text === '#更新提醒') {
|
||
log.info('热更新通知任务~')
|
||
try {
|
||
await updateJobs(bot, vika)
|
||
replyText = '提醒任务更新成功~'
|
||
} catch (e) {
|
||
replyText = '提醒任务更新失败~'
|
||
}
|
||
|
||
await relpy(bot, vika, getNow() + replyText, message)
|
||
}
|
||
|
||
if (isAdminRoom && text === '#更新通讯录') {
|
||
log.info('热更新通讯录到维格表~')
|
||
try {
|
||
await vika.updateContacts(bot)
|
||
await vika.updateRooms(bot)
|
||
replyText = '通讯录更新成功~'
|
||
} catch (e) {
|
||
replyText = '通讯录更新失败~'
|
||
}
|
||
|
||
await relpy(bot, vika, getNow() + replyText, message)
|
||
}
|
||
|
||
if (isAdminRoom && text === '#下载csv通讯录') {
|
||
log.info('下载通讯录到csv表~')
|
||
try {
|
||
const fileBox = await exportContactsAndRoomsToCSV()
|
||
await message.say(fileBox)
|
||
} catch (err) {
|
||
log.error('exportContactsAndRoomsToCSV', err)
|
||
await message.say('下载失败~')
|
||
}
|
||
}
|
||
|
||
if (isAdminRoom && text === '#下载通讯录') {
|
||
log.info('下载通讯录到xlsx表~')
|
||
try {
|
||
const fileBox = await exportContactsAndRoomsToXLSX()
|
||
await message.say(fileBox)
|
||
} catch (err) {
|
||
log.error('exportContactsAndRoomsToXLSX', err)
|
||
}
|
||
}
|
||
|
||
if (isAdminRoom && text === '#下载通知模板') {
|
||
log.info('下载通知模板~')
|
||
try {
|
||
const fileBox = FileBox.fromFile('./src/templates/群发通知模板.xlsx')
|
||
await message.say(fileBox)
|
||
} catch (err) {
|
||
log.error('下载模板失败', err)
|
||
await message.say('下载失败,请重试~')
|
||
}
|
||
}
|
||
|
||
if (isAdminRoom && text === '#初始化') {
|
||
log.info('初始化系统~')
|
||
try {
|
||
await vika.init()
|
||
await message.say('初始化系统表完成~')
|
||
} catch (err) {
|
||
log.error('初始化系统失败', err)
|
||
await message.say('初始化系统失败,请重试~')
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
try {
|
||
|
||
if (room && roomId && !isSelfMsg) {
|
||
|
||
// 检测顺风车信息并格式化
|
||
// const KEYWORD_LIST = [ '人找车', '车找人' ]
|
||
// try {
|
||
// // 判断消息中是否包含关键字
|
||
// if (KEYWORD_LIST.some(keyword => message.text().includes(keyword))) {
|
||
// const replyMsg = await getFormattedRideInfo(message)
|
||
// if (replyMsg) {
|
||
// const replyText = replyMsg.choices[0].message.content.replace(/\r/g, '')
|
||
// log.info('回复内容:', replyText)
|
||
// await room.say(replyText)
|
||
// }
|
||
// }
|
||
// } catch (err) {
|
||
|
||
// }
|
||
|
||
// 智能问答开启时执行
|
||
if (sysConfig.WX_OPENAI_ONOFF && ((text.indexOf(keyWord) !== -1 && sysConfig.AT_AHEAD) || !sysConfig.AT_AHEAD)) {
|
||
if (sysConfig.roomWhiteListOpen) {
|
||
const isInRoomWhiteList = sysConfig.roomWhiteList.includes(roomId)
|
||
if (isInRoomWhiteList) {
|
||
log.info('当前群在白名单内,请求问答...')
|
||
await wxai(sysConfig, bot, talker, room, message)
|
||
} else {
|
||
log.info('当前群不在白名单内,流程结束')
|
||
}
|
||
}
|
||
|
||
if (!sysConfig.roomWhiteListOpen) {
|
||
log.info('系统未开启白名单,请求问答...')
|
||
await wxai(sysConfig, bot, talker, room, message)
|
||
}
|
||
}
|
||
|
||
// IM服务开启时执行
|
||
if (sysConfig.imOpen && types.Message.Text === message.type()) {
|
||
configData.clientChatEn.clientChatId = talker.id + ' ' + room.id
|
||
configData.clientChatEn.clientChatName = talker.name() + '@' + topic
|
||
// log.debug(configData)
|
||
socket.emit('CLIENT_ON', {
|
||
clientChatEn: configData.clientChatEn,
|
||
serverChatId: configData.serverChatEn.serverChatId,
|
||
})
|
||
const data = {
|
||
msg: {
|
||
avatarUrl: '/static/image/im_server_avatar.png',
|
||
content: text,
|
||
contentType: 'text',
|
||
role: 'client',
|
||
},
|
||
}
|
||
log.info(JSON.stringify(data))
|
||
sendMsg(data)
|
||
}
|
||
|
||
}
|
||
|
||
if ((!room || !room.id) && !isSelfMsg) {
|
||
// 智能问答开启时执行
|
||
if (sysConfig.WX_OPENAI_ONOFF && ((text.indexOf(keyWord) !== -1 && sysConfig.AT_AHEAD) || !sysConfig.AT_AHEAD)) {
|
||
if (sysConfig.contactWhiteListOpen) {
|
||
const isInContactWhiteList = sysConfig.contactWhiteList.includes(talker.id)
|
||
if (isInContactWhiteList) {
|
||
log.info('当前好友在白名单内,请求问答...')
|
||
await wxai(sysConfig, bot, talker, undefined, message)
|
||
} else {
|
||
log.info('当前好友不在白名单内,流程结束')
|
||
}
|
||
}
|
||
|
||
if (!sysConfig.contactWhiteListOpen) {
|
||
log.info('系统未开启好友白名单,对所有好友有效,请求问答...')
|
||
await wxai(sysConfig, bot, talker, undefined, message)
|
||
}
|
||
}
|
||
}
|
||
|
||
} catch (e) {
|
||
log.error('发起请求wxai失败', e)
|
||
}
|
||
} else {
|
||
if (message.self() && message.type() === types.Message.Text && text !== Prompts.a && text !== Prompts.b && text.includes('+')) {
|
||
try {
|
||
const textArr = text.split('+')
|
||
log.info(JSON.stringify(textArr))
|
||
if (text.length > 23 && text.length < 33 && textArr.length === 2) {
|
||
vikaConfig.spaceName = textArr[1]
|
||
vikaConfig.token = textArr[0]
|
||
await createVika()
|
||
isVikaOk = true
|
||
config.baseConfig.VIKA_TOKEN = vikaConfig.token
|
||
config.baseConfig.VIKA_SPACENAME = vikaConfig.spaceName
|
||
await updateConfig(config)
|
||
await talker.say('配置成功,初始化中,请稍后...')
|
||
log.info('初始化系统~')
|
||
try {
|
||
await vika.init()
|
||
await talker.say('初始化系统表完成~')
|
||
} catch (err) {
|
||
log.error('初始化系统失败', err)
|
||
await talker.say('初始化系统失败,请发送 #初始化 重试~')
|
||
}
|
||
} else {
|
||
await talker.say(Prompts.a)
|
||
}
|
||
} catch (err) {
|
||
log.error('解析失败:', err)
|
||
await talker.say(Prompts.a)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
async function roomJoin (room: { topic: () => any; id: any; say: (arg0: string, arg1: any) => any }, inviteeList: Contact[], inviter: any) {
|
||
const nameList = inviteeList.map(c => c.name()).join(',')
|
||
log.info(`Room ${await room.topic()} got new member ${nameList}, invited by ${inviter}`)
|
||
|
||
// 进群欢迎语,仅对开启了进群欢迎语白名单的群有效
|
||
if (isVikaOk && sysConfig.welcomeList.includes(room.id) && inviteeList.length) {
|
||
await room.say(`欢迎加入${await room.topic()},请阅读群公告~`, inviteeList)
|
||
}
|
||
}
|
||
|
||
async function onError (err: any) {
|
||
log.error('bot.onError:', JSON.stringify(err))
|
||
// try {
|
||
// // job.cancel()
|
||
// } catch (e) {
|
||
// log.error('销毁定时任务失败:', JSON.stringify(e))
|
||
// }
|
||
}
|
||
|
||
async function main (vika: any) {
|
||
|
||
// 检查维格表配置并启动
|
||
if (vikaConfig.spaceName && vikaConfig.token) {
|
||
try {
|
||
await createVika()
|
||
isVikaOk = true
|
||
} catch (err) {
|
||
log.info('初始化vika失败:', err)
|
||
}
|
||
|
||
} else {
|
||
log.error('\n================================================\n\nvikaConfig配置不全,请重新配置config.json文件中的token和spaceName之后重启,或者根据提示进行配置\n\n================================================\n')
|
||
}
|
||
|
||
bot = getBot()
|
||
bot.on('scan', onScan)
|
||
|
||
if (puppet === 'wechaty-puppet-xp') {
|
||
bot.on('login', onLogin)
|
||
}
|
||
if (puppet !== 'wechaty-puppet-xp') {
|
||
bot.on('ready', onReady)
|
||
}
|
||
|
||
bot.on('logout', onLogout)
|
||
bot.on('message', onMessage)
|
||
bot.on('room-join', roomJoin)
|
||
bot.on('error', onError)
|
||
|
||
bot.start()
|
||
.then(() => log.info('Starter Bot Started.'))
|
||
.catch((e: any) => log.error('bot运行异常:', JSON.stringify(e)))
|
||
|
||
if (isVikaOk && sysConfig.imOpen) {
|
||
socket = imclient(bot, vika, configData)
|
||
}
|
||
}
|
||
|
||
void main(vika)
|