Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions examples/mqtt-gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Wechaty - https://github.com/wechaty/wechaty
*
* @copyright 2016-now Huan LI <zixia@zixia.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { WechatyBuilder } from 'wechaty'

import {
QRCodeTerminal,
MqttGateway,
MqttGatewayConfig,
// getKeyByBasicString,
} from '../src/mod.js' // from 'wechaty-plugin-contrib'

const bot = WechatyBuilder.build({
name : 'ding-dong-bot',
puppet: 'wechaty-puppet-xp',
})
const config: MqttGatewayConfig = {
events: [
'login',
'logout',
'reset',
'ready',
'dirty',
'dong',
'error',
// 'heartbeat',
'friendship',
'message', 'post',
'room-invite', 'room-join',
'room-leave', 'room-topic',
'scan',
],
// mqtt: {
// clientId: 'wechaty-mqtt-gateway',
// host: 'broker.emqx.io',
// password: '',
// port: 1883,
// username: '',
// },
mqtt: {
clientId: 'wechaty-mqtt-gateway',
host: 'atfenbu.iot.gz.baidubce.com',
password: 'nVdvJODJdIkYCsLf',
port: 1883,
username: 'atfenbu/admin',
},
options:{
secrectKey: '',
simple: false,
},
token: '',
}

bot.use(
MqttGateway(config),
QRCodeTerminal(),
)

bot.start()
.catch(console.error)
20 changes: 12 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wechaty-plugin-contrib",
"version": "1.12.1",
"version": "1.13.0",
"description": "Wechaty Plugin Ecosystem Contrib Package",
"type": "module",
"exports": {
Expand All @@ -15,16 +15,23 @@
"npm": ">=7"
},
"dependencies": {
"crypto-js": "^4.2.0",
"language-monitor": "^1.0.3",
"moment": "^2.30.1",
"mqtt": "^4.3.8",
"mustache": "^4.2.0",
"qrcode-terminal": "^0.12.0"
"qrcode-terminal": "^0.12.0",
"uuid": "^9.0.1",
"winston": "^3.11.0"
},
"devDependencies": {
"@chatie/eslint-config": "^1.0.4",
"@chatie/git-scripts": "^0.6.2",
"@chatie/semver": "^0.4.7",
"@chatie/tsconfig": "^4.6.2",
"@types/crypto-js": "^4.1.3",
"@types/mustache": "^4.1.2",
"@types/uuid": "^9.0.7",
"wechaty": "^1.11.22",
"wechaty-mocker": "^1.10.2",
"wechaty-puppet-mock": "^1.11.2"
Expand All @@ -37,12 +44,14 @@
"lint": "npm-run-all lint:es lint:ts lint:md",
"lint:md": "markdownlint README.md",
"lint:ts": "tsc --isolatedModules --noEmit",
"lint:fix": "npm-run-all lint:es lint:ts lint:md",
"example": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" node examples/ding-dong-bot.ts",
"start": "npm run example",
"start:mg": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" node examples/mqtt-gateway.ts",
"test": "npm-run-all lint test:unit",
"test:pack": "bash -x scripts/npm-pack-testing.sh",
"test:unit": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" tap \"src/**/*.spec.ts\" \"tests/**/*.spec.ts\"",
"lint:es": "eslint --ignore-pattern tests/fixtures/ '{bin,examples,scripts,src,tests}/**/*.ts'"
"lint:es": "eslint --fix --ignore-pattern tests/fixtures/ '{bin,examples,scripts,src,tests}/**/*.ts'"
},
"repository": {
"type": "git",
Expand All @@ -59,11 +68,6 @@
"url": "https://github.com/wechaty/plugin-contrib/issues"
},
"homepage": "https://github.com/wechaty/plugin-contrib#readme",
"git": {
"scripts": {
"pre-push": "npx git-scripts-pre-push"
}
},
"files": [
"bin/",
"dist/",
Expand Down
4 changes: 2 additions & 2 deletions src/contrib/ding-dong/ding-dong.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test('isMatchConfig {mention: true}', async t => {

const mentionMessage = await new Promise<Message>(resolve => {
room.once('message', resolve)
fixture.mocker.player.say('ding', [fixture.mocker.bot]).to(fixture.mocker.room)
fixture.mocker.player.say('ding', [ fixture.mocker.bot ]).to(fixture.mocker.room)
})
let result: boolean = await isMatch(mentionMessage)
t.equal(result, true, 'should match for room mention self message')
Expand All @@ -54,7 +54,7 @@ test('isMatchConfig {mention: false}', async t => {

const mentionMessage = await new Promise<Message>(resolve => {
room.once('message', resolve)
fixture.mocker.player.say('ding', [fixture.mocker.bot]).to(fixture.mocker.room)
fixture.mocker.player.say('ding', [ fixture.mocker.bot ]).to(fixture.mocker.room)
})
let result: boolean = await isMatch(mentionMessage)
t.equal(result, true, 'should match for room mention self message')
Expand Down
123 changes: 123 additions & 0 deletions src/contrib/mqtt-gateway/command/contact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/* eslint-disable sort-keys */
import { Wechaty, log, Contact, Message } from 'wechaty'
import type MqttProxy from '../mqtt-proxy'
import { CommandInfo, getResponseTemplate, ResponseInfo } from '../utils.js'

async function getAllContact (bot: Wechaty) {
const contactList: Contact[] = await bot.Contact.findAll()
const friends = []
for (const i in contactList) {
const contact = contactList[i]
// const avatar = ''
// let alias = ''
// try {
// avatar = JSON.parse(JSON.stringify(await contact?.avatar())).url
// } catch (err) {
// log.error('获取头像失败:', err)
// }
// try {
// alias = await contact?.alias() || ''
// } catch (err) {
// log.error('获取备注失败:', err)
// }
// const contactInfo = {
// alias,
// avatar,
// gender: contact?.gender() || '',
// id: contact?.id,
// name: contact?.name() || '',
// type: contact?.type(),
// }
// if (contact.friend()) {
// friends.push(contactInfo)
// }
if (contact?.friend()) {
friends.push(contact)
}
}
log.info('friends count:', friends.length)
return friends
}
export const handleContact = async (bot: Wechaty, mqttProxy: MqttProxy, commandInfo: CommandInfo) => {
log.info('handleContact', bot, mqttProxy, commandInfo)
const { reqId, name, params } = commandInfo
log.info('handleContact', reqId, name, params)
const payload: ResponseInfo = getResponseTemplate()
payload.name = name
payload.reqId = reqId
const responseTopic = mqttProxy.responseApi + `/${reqId}`

switch (name) {
case 'contactAliasGet': { // 获取好友备注
log.info('cmd name:' + name)
break
}
case 'contactAliasSet': { // 设置好友备注
log.info('cmd name:' + name)
break
}
case 'contactAdd': { // 添加好友
log.info('cmd name:' + name)

break
}
case 'contactFindAll': { // 获取好友列表
const friends = await getAllContact(bot)
// 每50条发送一次
const len = friends.length
const bacthNum = params.size || 100
const count = Math.ceil(len / bacthNum)
for (let i = 0; i < count; i++) {
const start = i * bacthNum
const end = (i + 1) * bacthNum
const arr = friends.slice(start, end)
payload.params = {
page: i + 1,
size: bacthNum,
total: len,
items: arr,
}
log.info('page:', i + 1, 'size:', bacthNum, 'count:', len, 'items:', arr)
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
// 延时0.3s
await new Promise((resolve) => setTimeout(resolve, 300))
}
break
}
case 'contactFind': { // 获取好友信息
if (!params.id && !params.name && !params.alias) {
payload.code = 400
payload.message = 'params error'
payload.params = {}
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
} else {
const info = params.id ? { id: params.id } : params.name ? { name: params.name } : { alias: params.alias }
const contact = await bot.Contact.find(info)
payload.params = contact || {}
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
}
break
}
case 'contactSay': { // 发送消息
if (params.contacts && params.contacts.length > 0 && params.messageType && params.messagePayload) {
for (let i = 0; i < params.contacts.length; i++) {
try {
const contact = await bot.Contact.find({ id: params.contacts[i] })
if (contact) {
const message: Message | void = await contact.say(params.messagePayload)
payload.params = message || {}
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
// 延迟0.5s
await new Promise((resolve) => setTimeout(resolve, 500))
}
} catch (err) {
log.error('获取联系人失败:', err)
}
}
}
break
}
default:
log.error('Unknown command:', name)
}
}
18 changes: 18 additions & 0 deletions src/contrib/mqtt-gateway/command/friendship.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Wechaty, log } from 'wechaty'
import type MqttProxy from '../mqtt-proxy'
import type { CommandInfo } from '../utils.js'

export const handleCommandFriendship = async (bot:Wechaty, mqttProxy:MqttProxy, commandInfo:CommandInfo) => {
log.info('handleCommandFriendship', bot, mqttProxy, commandInfo)
const { reqId, name, params } = commandInfo
log.info('handleCommandFriendship', reqId, name, params)
switch (name) {
case 'friendshipAccept':
case 'friendshipSearch':
case 'friendshipAdd':
log.info('cmd name:' + name)
break
default:
log.error('Unknown command:', name)
}
}
51 changes: 51 additions & 0 deletions src/contrib/mqtt-gateway/command/message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Wechaty, log, Message } from 'wechaty'
import type MqttProxy from '../mqtt-proxy'
import { CommandInfo, getResponseTemplate, ResponseInfo } from '../utils.js'

export const handleMessage = async (bot:Wechaty, mqttProxy:MqttProxy, commandInfo:CommandInfo) => {
log.info('handleMessage', bot, mqttProxy, commandInfo)
const { reqId, name, params } = commandInfo
log.info('handleMessage', reqId, name, params)
const payload: ResponseInfo = getResponseTemplate()
payload.name = name
payload.reqId = reqId
const responseTopic = mqttProxy.responseApi + `/${reqId}`
switch (name) {
case 'messageFind':
case 'messageFindAll':
case 'messageSay':{
if (params.id && params.messageType && params.messagePayload) {
const id = params.id
const messageSay = await bot.Message.find({ id })
if (messageSay) {
try {
const message: Message | void = await messageSay.say(params.messagePayload)
payload.params = message || { id }
await mqttProxy.publish(responseTopic, JSON.stringify(payload))

} catch (err) {
payload.params = {}
payload.message = '发送失败'
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
}
} else {
payload.params = {}
payload.message = '消息不存在'
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
}

} else {
payload.params = {}
payload.message = '参数错误'
await mqttProxy.publish(responseTopic, JSON.stringify(payload))
}
break
}

case 'messageToRecalled':
log.info('cmd name:' + name)
break
default:
log.error('Unknown command:', name)
}
}
12 changes: 12 additions & 0 deletions src/contrib/mqtt-gateway/command/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { handleCommandFriendship } from './friendship.js'
import { handleWechaty } from './wechaty.js'
import { handleMessage } from './message.js'
import { handleContact } from './contact.js'
import { handleRoom } from './room.js'
export {
handleCommandFriendship,
handleWechaty,
handleMessage,
handleContact,
handleRoom,
}
Loading