Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
.Veneno.
wechaty
提交
7d7fa0d9
W
wechaty
项目概览
.Veneno.
/
wechaty
与 Fork 源项目一致
Fork自
wechaty / wechaty
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
W
wechaty
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7d7fa0d9
编写于
5月 30, 2018
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
implement some pad functions
上级
62422547
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
187 addition
and
70 deletion
+187
-70
src/puppet-padchat/bridge.ts
src/puppet-padchat/bridge.ts
+21
-2
src/puppet-padchat/event.ts
src/puppet-padchat/event.ts
+1
-1
src/puppet-padchat/firer.ts
src/puppet-padchat/firer.ts
+12
-12
src/puppet-padchat/puppet-padchat.ts
src/puppet-padchat/puppet-padchat.ts
+153
-55
未找到文件。
src/puppet-padchat/bridge.ts
浏览文件 @
7d7fa0d9
...
...
@@ -11,6 +11,10 @@ import {
PadchatRoomMemberRawPayload
,
}
from
'
./padchat-schemas
'
import
{
ADDRESS
,
}
from
'
./config
'
export
const
resolverDict
:
{
[
idx
:
string
]:
Function
,
}
=
{}
...
...
@@ -19,7 +23,7 @@ export interface BridgeOptions {
// head? : boolean,
userId
:
string
,
// profile: Profile,
botWs
:
WebSocket
,
//
botWs: WebSocket,
// desperate in the future
autoData
:
AutoDataType
,
}
...
...
@@ -141,7 +145,9 @@ export class Bridge extends EventEmitter {
log
.
verbose
(
'
PuppetPadchatBridge
'
,
'
constructor()
'
)
this
.
userId
=
options
.
userId
this
.
botWs
=
options
.
botWs
this
.
botWs
=
new
WebSocket
(
ADDRESS
,
{
perMessageDeflate
:
true
})
this
.
autoData
=
options
.
autoData
||
{}
// this.state = new StateSwitch('PuppetPadchatBridge', log)
}
...
...
@@ -175,6 +181,19 @@ export class Bridge extends EventEmitter {
})
}
public
async
initWs
():
Promise
<
void
>
{
this
.
botWs
.
on
(
'
message
'
,
wsMsg
=>
{
this
.
emit
(
'
ws
'
,
wsMsg
)
})
this
.
botWs
.
on
(
'
open
'
,
()
=>
{
this
.
emit
(
'
open
'
)
})
}
public
closeWs
():
void
{
this
.
botWs
.
close
()
}
/**
* Init with WebSocket Server
*/
...
...
src/puppet-padchat/event.ts
浏览文件 @
7d7fa0d9
...
...
@@ -69,7 +69,7 @@ async function onMessage(
}
await
msg
.
ready
()
this
.
emit
(
'
message
'
,
msg
)
this
.
emit
(
'
message
'
,
msg
.
id
)
}
catch
(
e
)
{
log
.
error
(
'
PuppetPadchatEvent
'
,
'
onMessage() exception: %s
'
,
e
.
stack
)
...
...
src/puppet-padchat/firer.ts
浏览文件 @
7d7fa0d9
...
...
@@ -227,7 +227,7 @@ async function checkRoomJoin(
try
{
if
(
inviter
===
'
You
'
||
inviter
===
'
你
'
||
inviter
===
'
you
'
)
{
inviterContact
=
this
.
userSelf
(
)
inviterContact
=
this
.
Contact
.
load
(
this
.
selfId
()
)
}
const
max
=
20
...
...
@@ -318,7 +318,7 @@ async function checkRoomJoin(
await
inviterContact
.
ready
()
await
room
.
ready
()
this
.
emit
(
'
room-join
'
,
room
,
inviteeContactList
,
inviterContact
)
this
.
emit
(
'
room-join
'
,
room
.
id
,
inviteeContactList
.
map
(
c
=>
c
.
id
),
inviterContact
.
id
)
room
.
emit
(
'
join
'
,
inviteeContactList
,
inviterContact
)
return
true
...
...
@@ -342,7 +342,7 @@ function parseRoomLeave(
if
((
!
foundByBot
||
!
foundByBot
.
length
)
&&
(
!
foundByOther
||
!
foundByOther
.
length
))
{
throw
new
Error
(
'
checkRoomLeave() no matched re for
'
+
content
)
}
const
[
leaver
,
remover
]
=
foundByBot
?
[
foundByBot
[
1
],
this
.
userSelf
().
id
]
:
[
this
.
userSelf
().
id
,
foundByOther
[
1
]
]
const
[
leaver
,
remover
]
=
foundByBot
?
[
foundByBot
[
1
],
this
.
selfId
()
]
:
[
this
.
selfId
()
,
foundByOther
[
1
]
]
return
[
leaver
,
remover
]
}
...
...
@@ -373,8 +373,8 @@ async function checkRoomLeave(
* @lijiarui: I have checked, leaver will never be a list. If the bot remove 2 leavers at the same time, it will be 2 sys message, instead of 1 sys message contains 2 leavers.
*/
let
leaverContact
:
Contact
|
null
,
removerContact
:
Contact
|
null
if
(
leaver
===
this
.
userSelf
().
id
)
{
leaverContact
=
this
.
userSelf
(
)
if
(
leaver
===
this
.
selfId
()
)
{
leaverContact
=
this
.
Contact
.
load
(
this
.
selfId
()
)
// not sure which is better
// removerContact = room.member({contactAlias: remover}) || room.member({name: remover})
...
...
@@ -385,7 +385,7 @@ async function checkRoomLeave(
// }
}
else
{
removerContact
=
this
.
userSelf
(
)
removerContact
=
this
.
Contact
.
load
(
this
.
selfId
()
)
// not sure which is better
// leaverContact = room.member({contactAlias: remover}) || room.member({name: leaver})
...
...
@@ -408,7 +408,7 @@ async function checkRoomLeave(
* it will be 2 sys message, instead of 1 sys message contains 2 leavers.
* @huan 2018 May: we need to generilize the pattern for future usage.
*/
this
.
emit
(
'
room-leave
'
,
room
,
[
leaverContact
]
/* , [removerContact] */
)
this
.
emit
(
'
room-leave
'
,
room
.
id
,
[
leaverContact
.
id
]
/* , [removerContact] */
)
room
.
emit
(
'
leave
'
,
[
leaverContact
],
removerContact
||
undefined
)
setTimeout
(
_
=>
{
room
.
refresh
()
},
10000
)
// reload the room data, especially for memberList
...
...
@@ -450,7 +450,7 @@ async function checkRoomTopic(
let
changerContact
:
Contact
|
null
if
(
/^You$/
.
test
(
changer
)
||
/^你$/
.
test
(
changer
))
{
changerContact
=
this
.
userSelf
(
)
changerContact
=
this
.
Contact
.
load
(
this
.
selfId
()
)
}
else
{
changerContact
=
room
.
member
(
changer
)
}
...
...
@@ -463,7 +463,7 @@ async function checkRoomTopic(
try
{
await
changerContact
.
ready
()
await
room
.
ready
()
this
.
emit
(
'
room-topic
'
,
room
,
topic
,
oldTopic
,
changerContact
)
this
.
emit
(
'
room-topic
'
,
room
.
id
,
topic
,
oldTopic
,
changerContact
.
id
)
room
.
emit
(
'
topic
'
,
topic
,
oldTopic
,
changerContact
)
room
.
refresh
()
return
true
...
...
src/puppet-padchat/puppet-padchat.ts
浏览文件 @
7d7fa0d9
...
...
@@ -18,7 +18,8 @@
*/
import
*
as
path
from
'
path
'
// import * as fs from 'fs'
import
*
as
fs
from
'
fs
'
import
*
as
cuid
from
'
cuid
'
import
{
FileBox
,
...
...
@@ -64,10 +65,6 @@ import {
// Profile,
// } from '../profile'
import
{
ADDRESS
,
}
from
'
./config
'
import
{
Bridge
,
resolverDict
,
...
...
@@ -101,23 +98,20 @@ const TOKEN = 'padchattest'
export
class
PuppetPadchat
extends
Puppet
{
public
bridge
:
Bridge
public
botWs
:
WebSocket
//
public botWs: WebSocket
constructor
(
public
options
:
PuppetOptions
,
)
{
super
(
options
)
this
.
botWs
=
new
WebSocket
(
ADDRESS
,
{
perMessageDeflate
:
true
})
this
.
bridge
=
new
Bridge
({
userId
:
TOKEN
,
botWs
:
this
.
botWs
,
autoData
:
{},
// profile: profile, // should be profile in the future
})
this
.
b
otWs
.
on
(
'
message
'
,
data
=>
this
.
wsOnMessage
(
data
))
this
.
b
ridge
.
on
(
'
ws
'
,
data
=>
this
.
wsOnMessage
(
data
))
}
...
...
@@ -129,49 +123,74 @@ export class PuppetPadchat extends Puppet {
return
data
}
//
public initWatchdog(): void {
//
log.verbose('PuppetPadchat', 'initWatchdogForPuppet()')
public
initWatchdog
():
void
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
initWatchdogForPuppet()
'
)
//
const puppet = this
const
puppet
=
this
//
// clean the dog because this could be re-inited
//
this.watchdog.removeAllListeners()
// clean the dog because this could be re-inited
this
.
watchdog
.
removeAllListeners
()
// puppet.on('watchdog', food => this.watchdog.feed(food))
// this.watchdog.on('feed', food => {
// log.silly('PuppetPadchat', 'initWatchdogForPuppet() dog.on(feed, food={type=%s, data=%s})', food.type, food.data)
// // feed the dog, heartbeat the puppet.
// puppet.emit('heartbeat', food.data)
// })
puppet
.
on
(
'
watchdog
'
,
food
=>
this
.
watchdog
.
feed
(
food
))
this
.
watchdog
.
on
(
'
feed
'
,
async
food
=>
{
log
.
silly
(
'
PuppetPadchat
'
,
'
initWatchdogForPuppet() dog.on(feed, food={type=%s, data=%s})
'
,
food
.
type
,
food
.
data
)
// feed the dog, heartbeat the puppet.
puppet
.
emit
(
'
heartbeat
'
,
food
.
data
)
// this.watchdog.on('reset', async (food, timeout) => {
// log.warn('PuppetPadchat', 'initWatchdogForPuppet() dog.on(reset) last food:%s, timeout:%s',
// food.data, timeout)
// try {
// await this.stop()
// await this.start()
// } catch (e) {
// puppet.emit('error', e)
// }
// })
// }
const
feedAfterTenSeconds
=
async
()
=>
{
this
.
bridge
.
WXHeartBeat
()
.
then
(()
=>
{
this
.
emit
(
'
watchdog
'
,
{
data
:
'
WXHeartBeat()
'
,
})
})
.
catch
(
e
=>
{
log
.
warn
(
'
PuppetPadchat
'
,
'
initWatchdogForPuppet() feedAfterTenSeconds rejected: %s
'
,
e
&&
e
.
message
||
''
)
})
}
setTimeout
(
feedAfterTenSeconds
,
15
*
1000
)
})
this
.
watchdog
.
on
(
'
reset
'
,
async
(
food
,
timeout
)
=>
{
log
.
warn
(
'
PuppetPadchat
'
,
'
initWatchdogForPuppet() dog.on(reset) last food:%s, timeout:%s
'
,
food
.
data
,
timeout
)
try
{
await
this
.
stop
()
await
this
.
start
()
}
catch
(
e
)
{
puppet
.
emit
(
'
error
'
,
e
)
}
})
}
public
async
start
():
Promise
<
void
>
{
// Connect with websocket server
const
botWs
=
this
.
botWs
const
bridge
=
this
.
bridge
=
await
this
.
initBridge
()
if
(
!
this
.
bridge
)
{
throw
Error
(
'
cannot init bridge successfully!
'
)
}
/**
* state has two main state: ON / OFF
* ON (pending)
* OFF (pending)
*/
this
.
state
.
on
(
'
pending
'
)
const
bridge
=
this
.
bridge
=
await
this
.
initBridge
()
this
.
bridge
.
loginSucceed
=
false
log
.
verbose
(
'
PuppetPadchat
'
,
`start() with
${
this
.
options
.
profile
}
`
)
this
.
state
.
on
(
'
pending
'
)
botWs
.
on
(
'
open
'
,
async
()
=>
{
this
.
bridge
.
once
(
'
open
'
,
async
()
=>
{
this
.
emit
(
'
watchdog
'
,
{
data
:
'
start
'
,
})
// await some tasks...
await
bridge
.
init
()
await
bridge
.
WXInitialize
()
...
...
@@ -219,11 +238,14 @@ export class PuppetPadchat extends Puppet {
public
async
initBridge
():
Promise
<
Bridge
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
initBridge()
'
)
// if (this.state.off()) {
// const e = new Error('initBridge() found targetState != live, no init anymore')
// log.warn('PuppetPadchat', e.message)
// throw e
// }
if
(
this
.
state
.
off
())
{
const
e
=
new
Error
(
'
initBridge() found targetState != live, no init anymore
'
)
log
.
warn
(
'
PuppetPadchat
'
,
e
.
message
)
throw
e
}
await
this
.
bridge
.
initWs
()
const
autoData
:
AutoDataType
=
await
this
.
options
.
profile
.
get
(
'
autoData
'
)
log
.
silly
(
'
PuppetPadchat
'
,
'
initBridge, get autoData: %s
'
,
JSON
.
stringify
(
autoData
))
...
...
@@ -277,14 +299,14 @@ export class PuppetPadchat extends Puppet {
const
msg
=
this
.
Message
.
create
(
msgRawPayload
[
'
msg_id
'
],
await
this
.
messageRawPayloadParser
(
msgRawPayload
))
await
msg
.
ready
()
this
.
emit
(
'
message
'
,
msg
)
this
.
emit
(
'
message
'
,
msg
.
id
)
})
// Data Return From WebSocket Client
}
else
{
// check logout:
if
(
rawWebSocketData
.
type
===
-
1
)
{
this
.
emit
(
'
logout
'
,
this
.
userSelf
())
this
.
emit
(
'
logout
'
,
this
.
selfId
())
}
log
.
silly
(
'
PuppetPadchat
'
,
'
return apiName: %s, msgId: %s
'
,
rawWebSocketData
.
apiName
,
rawWebSocketData
.
msgId
)
...
...
@@ -362,12 +384,15 @@ export class PuppetPadchat extends Puppet {
this
.
userId
=
this
.
bridge
.
autoData
.
user_name
// Puppet userId different with WebSocket userId
const
user
=
this
.
Contact
.
load
(
this
.
userId
)
await
user
.
ready
()
this
.
emit
(
'
login
'
,
user
)
this
.
emit
(
'
login
'
,
this
.
userId
)
log
.
verbose
(
'
PuppetPadchatBridge
'
,
'
loginSucceed: Send login to the bot, user_name: %s
'
,
this
.
bridge
.
username
)
await
this
.
bridge
.
WXSendMsg
(
this
.
bridge
.
autoData
.
user_name
,
'
Bot on line!
'
)
this
.
state
.
on
(
true
)
this
.
emit
(
'
start
'
)
this
.
initWatchdog
()
return
}
else
{
log
.
verbose
(
'
PuppetPadchatBridge
'
,
'
no enough data, save again, %s
'
,
JSON
.
stringify
(
this
.
bridge
.
autoData
))
...
...
@@ -388,21 +413,30 @@ export class PuppetPadchat extends Puppet {
}
this
.
state
.
off
(
'
pending
'
)
this
.
watchdog
.
sleep
()
setImmediate
(()
=>
this
.
bridge
.
removeAllListeners
())
await
this
.
logout
()
this
.
bridge
.
closeWs
()
// await some tasks...
this
.
state
.
off
(
true
)
this
.
emit
(
'
stop
'
)
}
public
async
logout
():
Promise
<
void
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
logout()
'
)
if
(
!
this
.
logonoff
()
)
{
if
(
!
this
.
userId
)
{
throw
new
Error
(
'
logout before login?
'
)
}
// this.emit('logout', this.user!
) // becore we will throw above by logonoff() when this.user===undefined
// this.user
= undefined
this
.
emit
(
'
logout
'
,
this
.
userId
)
// becore we will throw above by logonoff() when this.user===undefined
this
.
userId
=
undefined
// TODO:
do the logout job
// TODO:
this.bridge.logout
}
/**
...
...
@@ -416,24 +450,36 @@ export class PuppetPadchat extends Puppet {
public
async
contactAlias
(
contactId
:
string
,
alias
?:
string
|
null
):
Promise
<
void
|
string
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
contactAlias(%s, %s)
'
,
contactId
,
alias
)
const
payload
=
await
this
.
contactPayload
(
contactId
)
if
(
typeof
alias
===
'
undefined
'
)
{
return
'
padchat alias
'
return
payload
.
alias
||
'
'
}
// TODO: modify alias in bridge
return
}
public
async
contactFindAll
(
query
:
ContactQueryFilter
):
Promise
<
string
[]
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
contactFindAll(%s)
'
,
query
)
// this.bridge.WX
return
[]
}
public
async
contactAvatar
(
contactId
:
string
):
Promise
<
FileBox
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
contactAvatar(%s)
'
,
contactId
)
const
WECHATY_ICON_PNG
=
path
.
resolve
(
'
../../docs/images/wechaty-icon.png
'
)
// TODO
return
FileBox
.
packBase64
(
''
,
WECHATY_ICON_PNG
)
const
rawPayload
=
await
this
.
contactRawPayload
(
contactId
)
const
payload
=
await
this
.
contactRawPayloadParser
(
rawPayload
)
if
(
!
payload
.
avatar
)
{
throw
new
Error
(
'
no avatar
'
)
}
const
file
=
FileBox
.
packRemote
(
payload
.
avatar
)
return
file
}
public
async
contactRawPayload
(
id
:
string
):
Promise
<
PadchatContactRawPayload
>
{
...
...
@@ -484,6 +530,21 @@ export class PuppetPadchat extends Puppet {
* Message
*
*/
public
async
messageFile
(
id
:
string
):
Promise
<
FileBox
>
{
// const rawPayload = await this.messageRawPayload(id)
const
base64
=
'
cRH9qeL3XyVnaXJkppBuH20tf5JlcG9uFX1lL2IvdHRRRS9kMMQxOPLKNYIzQQ==
'
const
filename
=
'
test.txt
'
const
file
=
FileBox
.
packBase64
(
base64
,
filename
,
)
return
file
}
public
async
messageRawPayload
(
id
:
string
):
Promise
<
PadchatMessageRawPayload
>
{
throw
Error
(
'
should not call messageRawPayload
'
)
// log.verbose('PuppetPadchat', 'messageRawPayload(%s)', id)
...
...
@@ -536,7 +597,7 @@ export class PuppetPadchat extends Puppet {
}
const
payload
:
MessagePayload
=
{
date
:
new
Date
(),
timestamp
:
Date
.
now
(),
fromId
:
rawPayload
.
from_user
,
text
:
rawPayload
.
content
,
toId
:
rawPayload
.
to_user
,
...
...
@@ -584,6 +645,22 @@ export class PuppetPadchat extends Puppet {
file
:
FileBox
,
):
Promise
<
void
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
messageSend(%s, %s)
'
,
receiver
,
file
)
const
id
=
receiver
.
contactId
||
receiver
.
roomId
if
(
!
id
)
{
throw
new
Error
(
'
no id!
'
)
}
const
xxx
=
cuid
()
const
tmpFile
=
path
.
join
(
'
/tmp/
'
+
xxx
)
file
.
save
(
tmpFile
)
const
bitmap
=
fs
.
readFileSync
(
tmpFile
)
const
base64
=
new
Buffer
(
bitmap
).
toString
(
'
base64
'
)
fs
.
unlinkSync
(
tmpFile
)
await
this
.
bridge
.
WXSendImage
(
id
,
base64
)
}
public
async
messageForward
(
...
...
@@ -594,6 +671,21 @@ export class PuppetPadchat extends Puppet {
receiver
,
messageId
,
)
const
msg
=
this
.
Message
.
create
(
messageId
)
await
msg
.
ready
()
if
(
msg
.
type
()
===
this
.
Message
.
Type
.
Text
)
{
await
this
.
messageSendText
(
receiver
,
msg
.
text
(),
)
}
else
{
await
this
.
messageSendFile
(
receiver
,
await
msg
.
file
(),
)
}
}
/**
...
...
@@ -680,6 +772,7 @@ export class PuppetPadchat extends Puppet {
contactId
:
string
,
):
Promise
<
void
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
roomDel(%s, %s)
'
,
roomId
,
contactId
)
}
public
async
roomAdd
(
...
...
@@ -695,9 +788,14 @@ export class PuppetPadchat extends Puppet {
):
Promise
<
void
|
string
>
{
log
.
verbose
(
'
PuppetPadchat
'
,
'
roomTopic(%s, %s)
'
,
roomId
,
topic
)
const
payload
=
await
this
.
roomPayload
(
roomId
)
if
(
typeof
topic
===
'
undefined
'
)
{
return
'
padchat room topic
'
return
payload
.
topic
}
// TODO: modify
return
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录