Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
.Veneno.
wechaty
提交
0609eb8d
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,发现更多精彩内容 >>
提交
0609eb8d
编写于
5月 10, 2018
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix unit tests
上级
f7bf989d
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
265 addition
and
246 deletion
+265
-246
src/puppet-accessory.ts
src/puppet-accessory.ts
+1
-1
src/puppet-mock/mock-message.ts
src/puppet-mock/mock-message.ts
+7
-7
src/puppet-mock/puppet-mock.ts
src/puppet-mock/puppet-mock.ts
+9
-17
src/puppet-puppeteer/bridge.ts
src/puppet-puppeteer/bridge.ts
+6
-6
src/puppet-puppeteer/event.ts
src/puppet-puppeteer/event.ts
+13
-13
src/puppet-puppeteer/puppet-puppeteer.ts
src/puppet-puppeteer/puppet-puppeteer.ts
+66
-45
src/puppet-puppeteer/puppeteer-contact.spec.ts
src/puppet-puppeteer/puppeteer-contact.spec.ts
+12
-10
src/puppet-puppeteer/puppeteer-contact.ts
src/puppet-puppeteer/puppeteer-contact.ts
+5
-1
src/puppet-puppeteer/puppeteer-friend-request.ts
src/puppet-puppeteer/puppeteer-friend-request.ts
+3
-3
src/puppet-puppeteer/puppeteer-message.spec.ts
src/puppet-puppeteer/puppeteer-message.spec.ts
+15
-22
src/puppet-puppeteer/puppeteer-message.ts
src/puppet-puppeteer/puppeteer-message.ts
+42
-40
src/puppet-puppeteer/puppeteer-room.spec.ts
src/puppet-puppeteer/puppeteer-room.spec.ts
+28
-29
src/puppet-puppeteer/puppeteer-room.ts
src/puppet-puppeteer/puppeteer-room.ts
+23
-27
src/puppet-puppeteer/schema.ts
src/puppet-puppeteer/schema.ts
+11
-11
src/puppet/contact.ts
src/puppet/contact.ts
+1
-1
src/puppet/message.ts
src/puppet/message.ts
+10
-10
src/puppet/room.ts
src/puppet/room.ts
+11
-1
src/wechaty.ts
src/wechaty.ts
+2
-2
未找到文件。
src/puppet-accessory.ts
浏览文件 @
0609eb8d
...
...
@@ -80,7 +80,7 @@ export abstract class PuppetAccessory extends EventEmitter {
this
[
PUPPET_ACCESSORY_NAME
]
=
name
||
this
.
constructor
.
name
log
.
verbose
(
'
PuppetAccessory
'
,
'
<%s> constructor(%s)
'
,
log
.
silly
(
'
PuppetAccessory
'
,
'
<%s> constructor(%s)
'
,
this
[
PUPPET_ACCESSORY_NAME
],
name
||
''
,
)
...
...
src/puppet-mock/mock-message.ts
浏览文件 @
0609eb8d
...
...
@@ -30,7 +30,7 @@ import { MockContact } from './mock-contact'
import
{
MockRoom
}
from
'
./mock-room
'
import
{
MsgType
,
Web
MsgType
,
AppMsgType
,
}
from
'
../puppet-puppeteer/schema
'
...
...
@@ -41,7 +41,7 @@ export interface MockMessagePayload {
from
:
MockContact
,
to
?:
MockContact
,
room
?:
MockRoom
,
type
:
MsgType
,
type
:
Web
MsgType
,
}
export
class
MockMessage
extends
Message
{
...
...
@@ -137,8 +137,8 @@ export class MockMessage extends Message {
await
this
.
puppet
.
send
(
msg
)
}
public
type
():
MsgType
{
return
MsgType
.
TEXT
public
type
():
Web
MsgType
{
return
Web
MsgType
.
TEXT
}
public
self
():
boolean
{
...
...
@@ -184,7 +184,7 @@ export class MockMessage extends Message {
/**
* 1. Text message
*/
if
(
this
.
type
()
===
MsgType
.
TEXT
)
{
if
(
this
.
type
()
===
Web
MsgType
.
TEXT
)
{
await
to
.
say
(
this
.
text
())
return
}
...
...
@@ -200,8 +200,8 @@ export class MockMessage extends Message {
}
}
public
typeSub
():
MsgType
{
return
MsgType
.
TEXT
public
typeSub
():
Web
MsgType
{
return
Web
MsgType
.
TEXT
}
public
typeApp
():
AppMsgType
{
...
...
src/puppet-mock/puppet-mock.ts
浏览文件 @
0609eb8d
...
...
@@ -23,6 +23,7 @@ import {
ContactQueryFilter
,
Gender
,
ContactType
,
ContactPayload
,
Puppet
,
PuppetOptions
,
...
...
@@ -34,11 +35,8 @@ import {
import
{
log
,
}
from
'
../config
'
import
{
ContactPayload
,
}
from
'
../puppet/contact
'
import
Profile
from
'
../profile
'
import
Wechaty
from
'
../wechaty
'
// import Profile from '../profile'
// import Wechaty from '../wechaty'
import
{
MockContact
,
...
...
@@ -55,21 +53,15 @@ export class PuppetMock extends Puppet {
private
user
?:
MockContact
constructor
(
public
options
:
PuppetOptions
=
{}
as
any
,
public
options
:
PuppetOptions
,
)
{
super
(
options
.
profile
?
options
:
{
profile
:
new
Profile
(),
wechaty
:
new
Wechaty
(),
}
,
options
,
{
Contact
:
MockContact
,
FriendRequest
:
MockFriendRequest
,
Message
:
MockMessage
,
Room
:
MockRoom
,
Contact
:
MockContact
,
FriendRequest
:
MockFriendRequest
,
Message
:
MockMessage
,
Room
:
MockRoom
,
},
)
}
...
...
src/puppet-puppeteer/bridge.ts
浏览文件 @
0609eb8d
...
...
@@ -38,9 +38,9 @@ import Profile from '../profile'
import
Misc
from
'
../misc
'
import
{
Puppeteer
MessageMediaPayload
,
Puppeteer
MessageRawPayload
,
Puppeteer
ContactRawPayload
,
Web
MessageMediaPayload
,
Web
MessageRawPayload
,
Web
ContactRawPayload
,
}
from
'
./schema
'
import
{
PuppeteerRoomRawPayload
,
...
...
@@ -516,7 +516,7 @@ export class Bridge extends EventEmitter {
}
}
public
async
getContact
(
id
:
string
):
Promise
<
Puppeteer
ContactRawPayload
|
PuppeteerRoomRawPayload
>
{
public
async
getContact
(
id
:
string
):
Promise
<
Web
ContactRawPayload
|
PuppeteerRoomRawPayload
>
{
if
(
id
!==
id
)
{
// NaN
const
err
=
new
Error
(
'
NaN! where does it come from?
'
)
log
.
error
(
'
PuppetPuppeteerBridge
'
,
'
getContact(NaN): %s
'
,
err
)
...
...
@@ -597,7 +597,7 @@ export class Bridge extends EventEmitter {
}
}
public
async
sendMedia
(
mediaData
:
Puppeteer
MessageMediaPayload
):
Promise
<
boolean
>
{
public
async
sendMedia
(
mediaData
:
Web
MessageMediaPayload
):
Promise
<
boolean
>
{
log
.
verbose
(
'
PuppetPuppeteerBridge
'
,
'
sendMedia(mediaData)
'
)
if
(
!
mediaData
.
ToUserName
)
{
...
...
@@ -614,7 +614,7 @@ export class Bridge extends EventEmitter {
}
}
public
async
forward
(
baseData
:
PuppeteerMessageRawPayload
,
patchData
:
Puppeteer
MessageRawPayload
):
Promise
<
boolean
>
{
public
async
forward
(
baseData
:
WebMessageRawPayload
,
patchData
:
Web
MessageRawPayload
):
Promise
<
boolean
>
{
log
.
verbose
(
'
PuppetPuppeteerBridge
'
,
'
forward()
'
)
if
(
!
baseData
.
ToUserName
)
{
...
...
src/puppet-puppeteer/event.ts
浏览文件 @
0609eb8d
...
...
@@ -33,8 +33,8 @@ import PuppeteerMessage from './puppeteer-message'
import
Firer
from
'
./firer
'
import
PuppetPuppeteer
from
'
./puppet-puppeteer
'
import
{
MsgType
,
Puppeteer
MessageRawPayload
,
Web
MsgType
,
Web
MessageRawPayload
,
}
from
'
./schema
'
/* tslint:disable:variable-name */
...
...
@@ -189,7 +189,7 @@ async function onLogout(
async
function
onMessage
(
this
:
PuppetPuppeteer
,
obj
:
Puppeteer
MessageRawPayload
,
obj
:
Web
MessageRawPayload
,
):
Promise
<
void
>
{
let
m
=
new
PuppeteerMessage
(
obj
)
m
.
puppet
=
this
...
...
@@ -202,11 +202,11 @@ async function onMessage(
*/
switch
(
m
.
type
())
{
case
MsgType
.
VERIFYMSG
:
case
Web
MsgType
.
VERIFYMSG
:
Firer
.
checkFriendRequest
.
call
(
this
,
m
)
break
case
MsgType
.
SYS
:
case
Web
MsgType
.
SYS
:
if
(
m
.
room
())
{
const
joinResult
=
await
Firer
.
checkRoomJoin
.
call
(
this
,
m
)
const
leaveResult
=
await
Firer
.
checkRoomLeave
.
call
(
this
,
m
)
...
...
@@ -227,19 +227,19 @@ async function onMessage(
*/
switch
(
m
.
type
())
{
case
MsgType
.
EMOTICON
:
case
MsgType
.
IMAGE
:
case
MsgType
.
VIDEO
:
case
MsgType
.
VOICE
:
case
MsgType
.
MICROVIDEO
:
case
MsgType
.
APP
:
case
Web
MsgType
.
EMOTICON
:
case
Web
MsgType
.
IMAGE
:
case
Web
MsgType
.
VIDEO
:
case
Web
MsgType
.
VOICE
:
case
Web
MsgType
.
MICROVIDEO
:
case
Web
MsgType
.
APP
:
log
.
verbose
(
'
PuppetPuppeteerEvent
'
,
'
onMessage() EMOTICON/IMAGE/VIDEO/VOICE/MICROVIDEO message
'
)
m
=
new
PuppeteerMessage
(
obj
)
m
.
puppet
=
this
break
case
MsgType
.
TEXT
:
if
(
m
.
typeSub
()
===
MsgType
.
LOCATION
)
{
case
Web
MsgType
.
TEXT
:
if
(
m
.
typeSub
()
===
Web
MsgType
.
LOCATION
)
{
log
.
verbose
(
'
PuppetPuppeteerEvent
'
,
'
onMessage() (TEXT&LOCATION) message
'
)
m
=
new
PuppeteerMessage
(
obj
)
}
...
...
src/puppet-puppeteer/puppet-puppeteer.ts
浏览文件 @
0609eb8d
...
...
@@ -31,7 +31,7 @@ import {
import
{
ContactQueryFilter
,
ContactPayload
,
//
Gender,
Gender
,
Puppet
,
PuppetOptions
,
...
...
@@ -49,7 +49,7 @@ import Profile from '../profile'
import
Misc
from
'
../misc
'
import
{
Puppeteer
ContactRawPayload
,
Web
ContactRawPayload
,
}
from
'
./schema
'
import
{
Bridge
,
...
...
@@ -58,10 +58,10 @@ import {
import
Event
from
'
./event
'
import
{
Puppeteer
MessageMediaPayload
,
Puppeteer
MessageRawPayload
,
MediaType
,
MsgType
,
Web
MessageMediaPayload
,
Web
MessageRawPayload
,
Web
MediaType
,
Web
MsgType
,
}
from
'
./schema
'
import
{
...
...
@@ -342,7 +342,7 @@ export class PuppetPuppeteer extends Puppet {
}
}
private
async
uploadMedia
(
message
:
PuppeteerMessage
,
toUserName
:
string
):
Promise
<
Puppeteer
MessageMediaPayload
>
{
private
async
uploadMedia
(
message
:
PuppeteerMessage
,
toUserName
:
string
):
Promise
<
Web
MessageMediaPayload
>
{
if
(
message
.
type
()
===
PuppeteerMessage
.
Type
.
TEXT
)
{
throw
new
Error
(
'
require a Media Message
'
)
}
...
...
@@ -356,7 +356,7 @@ export class PuppetPuppeteer extends Puppet {
if
(
!
contentType
)
{
throw
new
Error
(
'
no MIME Type found on mediaMessage:
'
+
message
.
filename
())
}
let
mediatype
:
MediaType
let
mediatype
:
Web
MediaType
switch
(
ext
)
{
case
'
.bmp
'
:
...
...
@@ -364,13 +364,13 @@ export class PuppetPuppeteer extends Puppet {
case
'
.jpg
'
:
case
'
.png
'
:
case
'
.gif
'
:
mediatype
=
MediaType
.
IMAGE
mediatype
=
Web
MediaType
.
IMAGE
break
case
'
.mp4
'
:
mediatype
=
MediaType
.
VIDEO
mediatype
=
Web
MediaType
.
VIDEO
break
default
:
mediatype
=
MediaType
.
ATTACHMENT
mediatype
=
Web
MediaType
.
ATTACHMENT
}
const
readStream
=
await
message
.
readyStream
()
...
...
@@ -387,7 +387,7 @@ export class PuppetPuppeteer extends Puppet {
const
LARGE_FILE_SIZE
=
25
*
1024
*
1024
const
MAX_VIDEO_SIZE
=
20
*
1024
*
1024
if
(
mediatype
===
MediaType
.
VIDEO
&&
buffer
.
length
>
MAX_VIDEO_SIZE
)
if
(
mediatype
===
Web
MediaType
.
VIDEO
&&
buffer
.
length
>
MAX_VIDEO_SIZE
)
throw
new
Error
(
`Sending video files is not allowed to exceed
${
MAX_VIDEO_SIZE
/
1024
/
1024
}
MB`
)
if
(
buffer
.
length
>
MAX_FILE_SIZE
)
{
throw
new
Error
(
`Sending files is not allowed to exceed
${
MAX_FILE_SIZE
/
1024
/
1024
}
MB`
)
...
...
@@ -423,7 +423,7 @@ export class PuppetPuppeteer extends Puppet {
ToUserName
:
toUserName
,
UploadType
:
2
,
ClientMediaId
:
+
new
Date
,
MediaType
:
MediaType
.
ATTACHMENT
,
MediaType
:
Web
MediaType
.
ATTACHMENT
,
StartPos
:
0
,
DataLen
:
size
,
TotalLen
:
size
,
...
...
@@ -448,7 +448,7 @@ export class PuppetPuppeteer extends Puppet {
FileSize
:
size
,
FileMd5
:
md5
,
MMFileExt
:
ext
,
}
as
Puppeteer
MessageMediaPayload
}
as
Web
MessageMediaPayload
// If file size > 25M, must first call checkUpload to get Signature and AESKey, otherwise it will fail to upload
// https://github.com/Chatie/webwx-app-tracker/blob/7c59d35c6ea0cff38426a4c5c912a086c4c512b2/formatted/webwxApp.js#L1132 #1182
...
...
@@ -578,8 +578,8 @@ export class PuppetPuppeteer extends Puppet {
destinationId
=
to
.
id
}
let
mediaData
:
Puppeteer
MessageMediaPayload
const
rawObj
=
message
.
rawObj
||
{}
as
Puppeteer
MessageRawPayload
let
mediaData
:
Web
MessageMediaPayload
const
rawObj
=
message
.
rawObj
||
{}
as
Web
MessageRawPayload
if
(
!
rawObj
||
!
rawObj
.
MediaId
)
{
try
{
...
...
@@ -645,7 +645,7 @@ export class PuppetPuppeteer extends Puppet {
}
let
m
=
Object
.
assign
({},
message
.
rawObj
)
const
newMsg
=
<
Puppeteer
MessageRawPayload
>
{}
const
newMsg
=
<
Web
MessageRawPayload
>
{}
const
largeFileSize
=
25
*
1024
*
1024
// let ret = false
// if you know roomId or userId, you can use `Room.load(roomId)` or `Contact.load(userId)`
...
...
@@ -715,7 +715,7 @@ export class PuppetPuppeteer extends Puppet {
throw
new
Error
(
'
PuppetPuppeteer.send(): message with neither room nor to?
'
)
}
if
(
message
.
type
()
===
MsgType
.
TEXT
)
{
if
(
message
.
type
()
===
Web
MsgType
.
TEXT
)
{
log
.
silly
(
'
PuppetPuppeteer
'
,
'
send() TEXT message.
'
)
const
text
=
message
.
text
()
...
...
@@ -799,11 +799,17 @@ export class PuppetPuppeteer extends Puppet {
}
private
contactParseRawPayload
(
rawPayload
:
Puppeteer
ContactRawPayload
,
rawPayload
:
Web
ContactRawPayload
,
):
ContactPayload
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
contactParseRawPayload(%s)
'
,
rawPayload
)
if
(
!
rawPayload
.
UserName
)
{
throw
new
Error
(
'
contactParsePayload() got empty rawPayload!
'
)
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
contactParseRawPayload(Object.keys(payload).length=%d)
'
,
Object
.
keys
(
rawPayload
).
length
,
)
if
(
!
Object
.
keys
(
rawPayload
).
length
)
{
log
.
error
(
'
PuppetPuppeteer
'
,
'
contactParseRawPayload() got empty rawPayload!
'
)
return
{
gender
:
Gender
.
UNKNOWN
,
type
:
PuppeteerContact
.
Type
.
UNKNOWN
,
}
}
// this.id = rawPayload.UserName // MMActualSender??? MMPeerUserName??? `getUserContact(message.MMActualSender,message.MMPeerUserName).HeadImgUrl`
...
...
@@ -842,10 +848,10 @@ export class PuppetPuppeteer extends Puppet {
}
}
private
async
contactRawPayload
(
contact
:
PuppeteerContact
):
Promise
<
Puppeteer
ContactRawPayload
>
{
private
async
contactRawPayload
(
contact
:
PuppeteerContact
):
Promise
<
Web
ContactRawPayload
>
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
contactRawPayload(%s)
'
,
contact
)
try
{
const
rawPayload
=
await
this
.
bridge
.
getContact
(
contact
.
id
)
as
Puppeteer
ContactRawPayload
const
rawPayload
=
await
this
.
bridge
.
getContact
(
contact
.
id
)
as
Web
ContactRawPayload
return
rawPayload
}
catch
(
e
)
{
log
.
error
(
'
PuppetPuppeteer
'
,
'
contactRawPayload(%d) exception: %s
'
,
contact
,
e
.
message
)
...
...
@@ -984,8 +990,8 @@ export class PuppetPuppeteer extends Puppet {
}
}
p
ublic
async
roomPayload
(
room
:
PuppeteerRoom
):
Promise
<
Room
Payload
>
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
roomPayload(%s)
'
,
room
)
p
rivate
async
roomRawPayload
(
room
:
PuppeteerRoom
):
Promise
<
PuppeteerRoomRaw
Payload
>
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
room
Raw
Payload(%s)
'
,
room
)
try
{
let
rawPayload
:
PuppeteerRoomRawPayload
|
undefined
// = await this.bridge.getContact(room.id) as PuppeteerRoomRawPayload
...
...
@@ -1022,36 +1028,40 @@ export class PuppetPuppeteer extends Puppet {
throw
new
Error
(
'
no payload
'
)
}
const
payload
=
await
this
.
roomParseRawPayload
(
rawPayload
)
if
(
!
payload
)
{
throw
new
Error
(
'
no payload set after puppet.getContact
'
)
}
await
Promise
.
all
(
payload
.
memberList
.
map
(
c
=>
c
.
ready
()))
return
payload
return
rawPayload
}
catch
(
e
)
{
log
.
error
(
'
PuppetPuppeteer
'
,
'
room
Payload.getContact
(%s) exception: %s
'
,
room
.
id
,
e
.
message
)
log
.
error
(
'
PuppetPuppeteer
'
,
'
room
RawPayload
(%s) exception: %s
'
,
room
.
id
,
e
.
message
)
Raven
.
captureException
(
e
)
throw
e
}
}
public
async
roomPayload
(
room
:
PuppeteerRoom
):
Promise
<
RoomPayload
>
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
roomPayload(%s)
'
,
room
)
const
rawPayload
=
await
this
.
roomRawPayload
(
room
)
const
payload
=
await
this
.
roomParseRawPayload
(
rawPayload
)
return
payload
}
private
async
roomParseRawPayload
(
rawPayload
:
PuppeteerRoomRawPayload
):
Promise
<
RoomPayload
>
{
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
roomParseRawPayload(
)
'
)
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
roomParseRawPayload(
%s)
'
,
rawPayload
)
// console.log(rawPayload)
const
memberList
=
(
rawPayload
.
MemberList
||
[])
.
map
(
m
=>
{
const
c
=
PuppeteerContact
.
load
(
m
.
UserName
)
c
.
puppet
=
this
return
c
})
await
Promise
.
all
(
memberList
.
map
(
c
=>
c
.
ready
()))
const
nameMap
=
this
.
roomParseMap
(
'
name
'
,
rawPayload
.
MemberList
)
const
roomAliasMap
=
this
.
roomParseMap
(
'
roomAlias
'
,
rawPayload
.
MemberList
)
const
contactAliasMap
=
this
.
roomParseMap
(
'
contactAlias
'
,
rawPayload
.
MemberList
)
return
{
const
roomPayload
:
RoomPayload
=
{
// id: rawPayload.UserName,
// encryId: rawPayload.EncryChatRoomId, // ???
topic
:
rawPayload
.
NickName
,
...
...
@@ -1062,18 +1072,29 @@ export class PuppetPuppeteer extends Puppet {
roomAliasMap
,
contactAliasMap
,
}
// console.log(roomPayload)
return
roomPayload
}
private
roomParseMap
(
parseSection
:
keyof
RoomMemberQueryFilter
,
memberList
?:
PuppeteerRoomRawMember
[],
):
Map
<
string
,
string
>
{
const
mapList
:
Map
<
string
,
string
>
=
new
Map
<
string
,
string
>
()
log
.
verbose
(
'
PuppetPuppeteer
'
,
'
roomParseMap(%s, memberList.length=%d)
'
,
parseSection
,
memberList
&&
memberList
.
length
,
)
const
dict
:
Map
<
string
,
string
>
=
new
Map
<
string
,
string
>
()
if
(
memberList
&&
memberList
.
map
)
{
memberList
.
forEach
(
member
=>
{
let
tmpName
:
string
// console.log(member)
const
contact
=
PuppeteerContact
.
load
(
member
.
UserName
)
contact
.
puppet
=
this
// contact.ready().then(() => console.log('###############', contact.name()))
// console.log(contact)
// log.silly('PuppetPuppeteer', 'roomParseMap() memberList.forEach(contact=%s)', contact)
switch
(
parseSection
)
{
case
'
name
'
:
...
...
@@ -1095,10 +1116,10 @@ export class PuppetPuppeteer extends Puppet {
* @rui: webwx's NickName here return contactAlias, if not set contactAlias, return name
* @rui: 2017-7-2 webwx's NickName just ruturn name, no contactAlias
*/
mapLis
t
.
set
(
member
.
UserName
,
Misc
.
stripEmoji
(
tmpName
))
dic
t
.
set
(
member
.
UserName
,
Misc
.
stripEmoji
(
tmpName
))
})
}
return
mapLis
t
return
dic
t
}
public
async
roomFindAll
(
...
...
@@ -1301,19 +1322,19 @@ export class PuppetPuppeteer extends Puppet {
this
.
options
.
profile
.
save
()
}
public
extToType
(
ext
:
string
):
MsgType
{
public
extToType
(
ext
:
string
):
Web
MsgType
{
switch
(
ext
)
{
case
'
.bmp
'
:
case
'
.jpeg
'
:
case
'
.jpg
'
:
case
'
.png
'
:
return
MsgType
.
IMAGE
return
Web
MsgType
.
IMAGE
case
'
.gif
'
:
return
MsgType
.
EMOTICON
return
Web
MsgType
.
EMOTICON
case
'
.mp4
'
:
return
MsgType
.
VIDEO
return
Web
MsgType
.
VIDEO
default
:
return
MsgType
.
APP
return
Web
MsgType
.
APP
}
}
...
...
src/puppet-puppeteer/puppeteer-contact.spec.ts
浏览文件 @
0609eb8d
...
...
@@ -26,12 +26,11 @@ import cloneClass from 'clone-class'
import
{
log
,
}
from
'
../config
'
import
{
PuppetMock
,
}
from
'
../puppet-mock/puppet-mock
'
}
from
'
../config
'
import
Profile
from
'
../profile
'
import
Wechaty
from
'
../wechaty
'
import
PuppetPuppeteer
from
'
./puppet-puppeteer
'
import
PuppeteerContact
from
'
./puppeteer-contact
'
test
(
'
Contact smoke testing
'
,
async
t
=>
{
...
...
@@ -43,10 +42,10 @@ test('Contact smoke testing', async t => {
const
sandbox
=
sinon
.
createSandbox
()
function
mockContactPayload
(
id
:
string
)
{
log
.
verbose
(
'
PuppeteerContactTest
'
,
'
mockContactPayload(%s)
'
,
id
)
function
mockContactPayload
(
contact
:
PuppeteerContact
)
{
log
.
verbose
(
'
PuppeteerContactTest
'
,
'
mockContactPayload(%s)
'
,
contact
.
id
)
return
new
Promise
<
any
>
((
resolve
,
reject
)
=>
{
if
(
id
!==
UserName
)
return
resolve
({})
if
(
contact
.
id
!==
UserName
)
return
resolve
({})
setImmediate
(()
=>
resolve
({
UserName
:
UserName
,
NickName
:
NickName
,
...
...
@@ -55,8 +54,11 @@ test('Contact smoke testing', async t => {
})
}
const
puppet
=
new
PuppetMock
()
sandbox
.
stub
(
puppet
,
'
contactPayload
'
).
callsFake
(
mockContactPayload
)
const
puppet
=
new
PuppetPuppeteer
({
profile
:
new
Profile
(),
wechaty
:
new
Wechaty
(),
})
sandbox
.
stub
(
puppet
as
any
,
'
contactRawPayload
'
).
callsFake
(
mockContactPayload
)
// tslint:disable-next-line:variable-name
const
MyContact
=
cloneClass
(
PuppeteerContact
)
...
...
src/puppet-puppeteer/puppeteer-contact.ts
浏览文件 @
0609eb8d
...
...
@@ -90,7 +90,11 @@ export class PuppeteerContact extends Contact implements Sayable {
public
alias
(
empty
:
null
)
:
Promise
<
void
>
public
alias
(
newAlias
?:
null
|
string
):
null
|
string
|
Promise
<
void
>
{
log
.
verbose
(
'
PuppeteerContact
'
,
'
alias(%s)
'
,
newAlias
)
log
.
verbose
(
'
PuppeteerContact
'
,
'
alias(%s)
'
,
newAlias
===
undefined
?
''
:
newAlias
,
)
if
(
typeof
newAlias
===
'
undefined
'
)
{
return
this
.
payload
&&
this
.
payload
.
alias
||
null
...
...
src/puppet-puppeteer/puppeteer-friend-request.ts
浏览文件 @
0609eb8d
...
...
@@ -39,7 +39,7 @@ import {
}
from
'
../puppet/
'
import
{
RecommendPayload
,
Web
RecommendPayload
,
}
from
'
./schema
'
import
PuppeteerContact
from
'
./puppeteer-contact
'
...
...
@@ -48,7 +48,7 @@ import PuppeteerContact from './puppeteer-contact'
*/
export
class
PuppeteerFriendRequest
extends
FriendRequest
{
public
payload
:
RecommendPayload
public
payload
:
Web
RecommendPayload
private
ticket
:
string
private
_contact
:
PuppeteerContact
...
...
@@ -60,7 +60,7 @@ export class PuppeteerFriendRequest extends FriendRequest {
super
()
}
public
receive
(
payload
:
RecommendPayload
):
void
{
public
receive
(
payload
:
Web
RecommendPayload
):
void
{
log
.
verbose
(
'
PuppeteerFriendRequest
'
,
'
receive(%s)
'
,
payload
)
if
(
!
payload
||
!
payload
.
UserName
)
{
...
...
src/puppet-puppeteer/puppeteer-message.spec.ts
浏览文件 @
0609eb8d
...
...
@@ -31,7 +31,7 @@ import {
import
Profile
from
'
../profile
'
import
Wechaty
from
'
../wechaty
'
import
{
PuppetMock
}
from
'
../puppet-mock/
'
//
import { PuppetMock } from '../puppet-mock/'
import
PuppetPuppeteer
from
'
./puppet-puppeteer
'
import
PuppeteerContact
from
'
./puppeteer-contact
'
...
...
@@ -152,7 +152,7 @@ test('find()', async t => {
})
t
.
ok
(
m
,
'
Message found
'
)
t
.
ok
(
m
!
.
id
,
'
Message.
find
'
)
t
.
ok
(
m
!
.
id
,
'
Message.
id is ok
'
)
})
test
(
'
findAll()
'
,
async
t
=>
{
...
...
@@ -191,42 +191,35 @@ test('mentioned()', async t => {
const
rawObj32
=
JSON
.
parse
(
`{"MsgId":"3807714644369652210","FromUserName":"@@9cdc696e490bd76c57e7dd54792dc1408e27d65e312178b1943e88579b7939f4","ToUserName":"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2","MsgType":1,"Content":"@4c32c97337cbb325442c304d6a44e374:<br/>@_@ wow,@wuli舞哩客服 和@小桔同学 看起来很有默契","Status":3,"ImgStatus":1,"CreateTime":1489823764,"VoiceLength":0,"PlayLength":0,"FileName":"","FileSize":"","MediaId":"","Url":"","AppMsgType":0,"StatusNotifyCode":0,"StatusNotifyUserName":"","RecommendInfo":{"UserName":"","NickName":"","QQNum":0,"Province":"","City":"","Content":"","Signature":"","Alias":"","Scene":0,"VerifyFlag":0,"AttrStatus":0,"Sex":0,"Ticket":"","OpCode":0},"ForwardFlag":0,"AppInfo":{"AppID":"","Type":0},"HasProductId":0,"Ticket":"","ImgHeight":0,"ImgWidth":0,"SubMsgType":0,"NewMsgId":3807714644369652000,"OriContent":"","MMPeerUserName":"@@9cdc696e490bd76c57e7dd54792dc1408e27d65e312178b1943e88579b7939f4","MMDigest":"22acb030-ff09-11e6-8a73-cff62d9268c5:@_@ wow,@wuli舞哩客服 和@小桔同学 看起来很有默契","MMIsSend":false,"MMIsChatRoom":true,"MMUnread":true,"LocalID":"3807714644369652210","ClientMsgId":"3807714644369652210","MMActualContent":"@_@ wow,@wuli舞哩客服 和@小桔同学 看起来很有默契","MMActualSender":"@4c32c97337cbb325442c304d6a44e374","MMDigestTime":"15:56","MMDisplayTime":1489823598,"MMTime":""}`
)
const
R
AW_OBJ
=
JSON
.
parse
(
`{"RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","PYInitial":"","PYQuanPin":"","Uin":0,"UserName":"@@9cdc696e490bd76c57e7dd54792dc1408e27d65e312178b1943e88579b7939f4","NickName":"付费入群","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=670397504&username=@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278&skey=","ContactFlag":2,"MemberCount":146,"MemberList":[{"Alias":"ruirui_0914","AppAccountFlag":0,"AttrStatus":2147584103,"ChatRoomId":0,"City":"海淀","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=648035215&username=@4c32c97337cbb325442c304d6a44e374&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"qq5","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"李佳芮","OwnerUin":0,"PYInitial":"LJR","PYQuanPin":"lijiarui","Province":"北京","RemarkName":"22acb030-ff09-11e6-8a73-cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","Sex":2,"Signature":"出洞计划 | 向前一步","SnsFlag":49,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@4c32c97337cbb325442c304d6a44e374","VerifyFlag":0,"_h":50,"_index":16,"_offsetTop":696,"stranger":false},{"AppAccountFlag":0,"ContactFlag":0,"HeadImgFlag":1,"HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=665886775&username=@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"MMOrderSymbol":"~","NickName":"小桔同学","PYInitial":"","PYQuanPin":"","RemarkName":"","RemarkPYInitial":"","RemarkPYQuanPin":"","Sex":0,"Signature":"我是一个性感的机器人","SnsFlag":1,"StarFriend":0,"Uin":244009576,"UserName":"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2","VerifyFlag":0,"WebWxPluginSwitch":0,"stranger":false},{"$$hashKey":"01J","Alias":"dancewuli","AppAccountFlag":0,"AttrStatus":233509,"ChatRoomId":0,"City":"","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=635310858&username=@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"wuli舞哩客服","OwnerUin":0,"PYInitial":"WULIWLKF","PYQuanPin":"wuliwulikefu","Province":"","RemarkName":"50fb16c0-ff09-11e6-9fe5-dda97284d25b","RemarkPYInitial":"50FB16C0FF0911E69FE5DDA97284D25B","RemarkPYQuanPin":"50fb16c0ff0911e69fe5dda97284d25b","Sex":0,"Signature":"","SnsFlag":1,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855","VerifyFlag":0,"_h":50,"_index":10,"_offsetTop":396,"stranger":false}],"RemarkName":"","HideInputBarFlag":0,"Sex":0,"Signature":"","VerifyFlag":0,"OwnerUin":2351423900,"StarFriend":0,"AppAccountFlag":0,"Statues":0,"AttrStatus":0,"Province":"","City":"","Alias":"","SnsFlag":0,"UniFriend":0,"DisplayName":"","ChatRoomId":0,"KeyWord":"","MMFromBatchGet":true,"MMFromBatchget":true,"MMInChatroom":true}`
)
const
R
OOM_RAW_PAYLOAD
=
JSON
.
parse
(
`{"RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","PYInitial":"","PYQuanPin":"","Uin":0,"UserName":"@@9cdc696e490bd76c57e7dd54792dc1408e27d65e312178b1943e88579b7939f4","NickName":"付费入群","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=670397504&username=@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278&skey=","ContactFlag":2,"MemberCount":146,"MemberList":[{"Alias":"ruirui_0914","AppAccountFlag":0,"AttrStatus":2147584103,"ChatRoomId":0,"City":"海淀","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=648035215&username=@4c32c97337cbb325442c304d6a44e374&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"qq5","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"李佳芮","OwnerUin":0,"PYInitial":"LJR","PYQuanPin":"lijiarui","Province":"北京","RemarkName":"22acb030-ff09-11e6-8a73-cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","Sex":2,"Signature":"出洞计划 | 向前一步","SnsFlag":49,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@4c32c97337cbb325442c304d6a44e374","VerifyFlag":0,"_h":50,"_index":16,"_offsetTop":696,"stranger":false},{"AppAccountFlag":0,"ContactFlag":0,"HeadImgFlag":1,"HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=665886775&username=@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"MMOrderSymbol":"~","NickName":"小桔同学","PYInitial":"","PYQuanPin":"","RemarkName":"","RemarkPYInitial":"","RemarkPYQuanPin":"","Sex":0,"Signature":"我是一个性感的机器人","SnsFlag":1,"StarFriend":0,"Uin":244009576,"UserName":"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2","VerifyFlag":0,"WebWxPluginSwitch":0,"stranger":false},{"$$hashKey":"01J","Alias":"dancewuli","AppAccountFlag":0,"AttrStatus":233509,"ChatRoomId":0,"City":"","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=635310858&username=@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"wuli舞哩客服","OwnerUin":0,"PYInitial":"WULIWLKF","PYQuanPin":"wuliwulikefu","Province":"","RemarkName":"50fb16c0-ff09-11e6-9fe5-dda97284d25b","RemarkPYInitial":"50FB16C0FF0911E69FE5DDA97284D25B","RemarkPYQuanPin":"50fb16c0ff0911e69fe5dda97284d25b","Sex":0,"Signature":"","SnsFlag":1,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855","VerifyFlag":0,"_h":50,"_index":10,"_offsetTop":396,"stranger":false}],"RemarkName":"","HideInputBarFlag":0,"Sex":0,"Signature":"","VerifyFlag":0,"OwnerUin":2351423900,"StarFriend":0,"AppAccountFlag":0,"Statues":0,"AttrStatus":0,"Province":"","City":"","Alias":"","SnsFlag":0,"UniFriend":0,"DisplayName":"","ChatRoomId":0,"KeyWord":"","MMFromBatchGet":true,"MMFromBatchget":true,"MMInChatroom":true}`
)
const
CONTACT_
LIS
T
=
JSON
.
parse
(
`{"@4c32c97337cbb325442c304d6a44e374":{"Alias":"ruirui_0914","AppAccountFlag":0,"AttrStatus":2147584103,"ChatRoomId":0,"City":"海淀","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=648035215&username=@4c32c97337cbb325442c304d6a44e374&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"qq5","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"李佳芮","OwnerUin":0,"PYInitial":"LJR","PYQuanPin":"lijiarui","Province":"北京","RemarkName":"22acb030-ff09-11e6-8a73-cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","Sex":2,"Signature":"出洞计划 | 向前一步","SnsFlag":49,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@4c32c97337cbb325442c304d6a44e374","VerifyFlag":0,"_h":50,"_index":16,"_offsetTop":696,"stranger":false},"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2":{"AppAccountFlag":0,"ContactFlag":0,"HeadImgFlag":1,"HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=665886775&username=@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"MMOrderSymbol":"~","NickName":"小桔同学","PYInitial":"","PYQuanPin":"","RemarkName":"","RemarkPYInitial":"","RemarkPYQuanPin":"","Sex":0,"Signature":"我是一个性感的机器人","SnsFlag":1,"StarFriend":0,"Uin":244009576,"UserName":"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2","VerifyFlag":0,"WebWxPluginSwitch":0,"stranger":false},"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855":{"$$hashKey":"01J","Alias":"dancewuli","AppAccountFlag":0,"AttrStatus":233509,"ChatRoomId":0,"City":"","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=635310858&username=@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"wuli舞哩客服","OwnerUin":0,"PYInitial":"WULIWLKF","PYQuanPin":"wuliwulikefu","Province":"","RemarkName":"50fb16c0-ff09-11e6-9fe5-dda97284d25b","RemarkPYInitial":"50FB16C0FF0911E69FE5DDA97284D25B","RemarkPYQuanPin":"50fb16c0ff0911e69fe5dda97284d25b","Sex":0,"Signature":"","SnsFlag":1,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855","VerifyFlag":0,"_h":50,"_index":10,"_offsetTop":396,"stranger":false}}`
)
const
CONTACT_
RAW_PAYLOAD_DIC
T
=
JSON
.
parse
(
`{"@4c32c97337cbb325442c304d6a44e374":{"Alias":"ruirui_0914","AppAccountFlag":0,"AttrStatus":2147584103,"ChatRoomId":0,"City":"海淀","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=648035215&username=@4c32c97337cbb325442c304d6a44e374&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"qq5","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"李佳芮","OwnerUin":0,"PYInitial":"LJR","PYQuanPin":"lijiarui","Province":"北京","RemarkName":"22acb030-ff09-11e6-8a73-cff62d9268c5","RemarkPYInitial":"22ACB030FF0911E68A73CFF62D9268C5","RemarkPYQuanPin":"22acb030ff0911e68a73cff62d9268c5","Sex":2,"Signature":"出洞计划 | 向前一步","SnsFlag":49,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@4c32c97337cbb325442c304d6a44e374","VerifyFlag":0,"_h":50,"_index":16,"_offsetTop":696,"stranger":false},"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2":{"AppAccountFlag":0,"ContactFlag":0,"HeadImgFlag":1,"HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=665886775&username=@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"MMOrderSymbol":"~","NickName":"小桔同学","PYInitial":"","PYQuanPin":"","RemarkName":"","RemarkPYInitial":"","RemarkPYQuanPin":"","Sex":0,"Signature":"我是一个性感的机器人","SnsFlag":1,"StarFriend":0,"Uin":244009576,"UserName":"@cd7d467d7464e8ff6b0acd29364654f3666df5d04551f6082bfc875f90a6afd2","VerifyFlag":0,"WebWxPluginSwitch":0,"stranger":false},"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855":{"$$hashKey":"01J","Alias":"dancewuli","AppAccountFlag":0,"AttrStatus":233509,"ChatRoomId":0,"City":"","ContactFlag":3,"DisplayName":"","EncryChatRoomId":"","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=635310858&username=@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855&skey=@crypt_ee003aea_5265cdd0c2676aab3df86b0249ae90f7","HideInputBarFlag":0,"IsOwner":0,"KeyWord":"","MMOrderSymbol":"~","MemberCount":0,"MemberList":[],"NickName":"wuli舞哩客服","OwnerUin":0,"PYInitial":"WULIWLKF","PYQuanPin":"wuliwulikefu","Province":"","RemarkName":"50fb16c0-ff09-11e6-9fe5-dda97284d25b","RemarkPYInitial":"50FB16C0FF0911E69FE5DDA97284D25B","RemarkPYQuanPin":"50fb16c0ff0911e69fe5dda97284d25b","Sex":0,"Signature":"","SnsFlag":1,"StarFriend":0,"Statues":0,"Uin":0,"UniFriend":0,"UserName":"@36d55130f6a91bae4a2ed2cc5f19c56a9258c65ce3db9777f74f607223ef0855","VerifyFlag":0,"_h":50,"_index":10,"_offsetTop":396,"stranger":false}}`
)
const
ROOM_ID
=
'
@@9cdc696e490bd76c57e7dd54792dc1408e27d65e312178b1943e88579b7939f4
'
// Mock
const
contactPayloadMock
=
function
(
contact
:
PuppeteerContact
)
{
const
contactRawPayloadMock
=
function
(
contact
:
PuppeteerContact
|
PuppeteerRoom
)
{
log
.
silly
(
'
PuppeteerMessageTest
'
,
'
contactRawPayloadMock(%s)
'
,
contact
)
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
contact
.
id
!==
ROOM_ID
&&
!
(
contact
.
id
in
CONTACT_LIST
))
return
resolve
({})
if
(
contact
.
id
===
ROOM_ID
)
{
resolve
(
R
AW_OBJ
)
}
if
(
contact
.
id
in
CONTACT_LIST
)
{
setTimeout
(()
=>
{
return
resolve
(
CONTACT_LIST
[
contact
.
id
])
},
10
)
resolve
(
R
OOM_RAW_PAYLOAD
)
}
else
if
(
contact
.
id
in
CONTACT_RAW_PAYLOAD_DICT
)
{
const
contactRawPayload
=
CONTACT_RAW_PAYLOAD_DICT
[
contact
.
id
]
setTimeout
(()
=>
resolve
(
contactRawPayload
),
10
)
}
else
{
resolve
({}
)
}
})
}
// let puppet1
// try {
// puppet1 = config.puppetInstance()
// puppet1.getContact = mockContactGetter
// } catch (err) {
// puppet1 = { getContact: mockContactGetter }
// config.puppetInstance(puppet1)
// }
const
sandbox
=
sinon
.
createSandbox
()
const
puppet
=
new
Puppet
Mock
({
const
puppet
=
new
Puppet
Puppeteer
({
profile
:
new
Profile
(),
wechaty
:
new
Wechaty
(),
})
sandbox
.
stub
(
puppet
,
'
contactPayload
'
).
callsFake
(
contactPayloadMock
)
sandbox
.
stub
(
puppet
as
any
,
'
contactRawPayload
'
).
callsFake
(
contactRawPayloadMock
)
sandbox
.
stub
(
puppet
as
any
,
'
roomRawPayload
'
).
callsFake
(
contactRawPayloadMock
)
MyRoom
.
puppet
=
MyMessage
.
puppet
=
MyContact
.
puppet
=
puppet
...
...
src/puppet-puppeteer/puppeteer-message.ts
浏览文件 @
0609eb8d
...
...
@@ -39,9 +39,9 @@ import PuppeteerRoom from './puppeteer-room'
import
{
AppMsgType
,
MsgPayload
,
Puppeteer
MessageRawPayload
,
MsgType
,
Web
MsgPayload
,
Web
MessageRawPayload
,
Web
MsgType
,
}
from
'
./schema
'
// export type TypeName = 'attachment'
...
...
@@ -66,8 +66,8 @@ export class PuppeteerMessage extends Message {
/**
* @private
*/
private
payload
:
MsgPayload
public
rawObj
?:
Puppeteer
MessageRawPayload
private
payload
:
Web
MsgPayload
public
rawObj
?:
Web
MessageRawPayload
private
parsedPath
?:
ParsedPath
...
...
@@ -75,12 +75,12 @@ export class PuppeteerMessage extends Message {
* @private
*/
constructor
(
fileOrPayload
?:
string
|
Puppeteer
MessageRawPayload
,
fileOrPayload
?:
string
|
Web
MessageRawPayload
,
)
{
super
()
log
.
silly
(
'
PuppeteerMessage
'
,
'
constructor()
'
)
this
.
payload
=
{}
as
MsgPayload
this
.
payload
=
{}
as
Web
MsgPayload
// this.rawObj = {} as MsgRawObj
if
(
!
fileOrPayload
)
{
...
...
@@ -94,7 +94,7 @@ export class PuppeteerMessage extends Message {
this
.
payload
=
this
.
parse
(
this
.
rawObj
)
this
.
id
=
this
.
payload
.
id
}
else
{
throw
new
Error
(
'
not supported construct param
'
)
throw
new
Error
(
'
not supported construct param
:
'
+
typeof
fileOrPayload
)
}
}
...
...
@@ -102,8 +102,8 @@ export class PuppeteerMessage extends Message {
* @private
*/
// Transform rawObj to local obj
private
parse
(
rawObj
:
PuppeteerMessageRawPayload
):
MsgPayload
{
const
obj
:
MsgPayload
=
{
private
parse
(
rawObj
:
WebMessageRawPayload
):
Web
MsgPayload
{
const
obj
:
Web
MsgPayload
=
{
id
:
rawObj
.
MsgId
,
type
:
rawObj
.
MsgType
,
from
:
rawObj
.
MMActualSender
,
// MMPeerUserName
...
...
@@ -274,10 +274,10 @@ export class PuppeteerMessage extends Message {
*
* If type is equal to `MsgType.RECALLED`, {@link Message#id} is the msgId of the recalled message.
* @see {@link MsgType}
* @returns {MsgType}
* @returns {
Web
MsgType}
*/
public
type
():
MsgType
{
log
.
silly
(
'
PuppeteerMessage
'
,
'
type() = %s
'
,
MsgType
[
this
.
payload
.
type
])
public
type
():
Web
MsgType
{
log
.
silly
(
'
PuppeteerMessage
'
,
'
type() = %s
'
,
Web
MsgType
[
this
.
payload
.
type
])
/**
* 1. A message created with rawObj
...
...
@@ -291,7 +291,7 @@ export class PuppeteerMessage extends Message {
*/
const
ext
=
this
.
extFromFile
()
if
(
!
ext
)
{
return
MsgType
.
TEXT
return
Web
MsgType
.
TEXT
}
/**
...
...
@@ -302,16 +302,16 @@ export class PuppeteerMessage extends Message {
case
'
.jpg
'
:
case
'
.jpeg
'
:
case
'
.png
'
:
return
MsgType
.
IMAGE
return
Web
MsgType
.
IMAGE
case
'
.gif
'
:
return
MsgType
.
EMOTICON
return
Web
MsgType
.
EMOTICON
case
'
.mp4
'
:
return
MsgType
.
VIDEO
return
Web
MsgType
.
VIDEO
case
'
.mp3
'
:
return
MsgType
.
VOICE
return
Web
MsgType
.
VOICE
}
throw
new
Error
(
'
unknown type:
'
+
ext
)
...
...
@@ -323,9 +323,9 @@ export class PuppeteerMessage extends Message {
* If message is a location message: `m.type() === MsgType.TEXT && m.typeSub() === MsgType.LOCATION`
*
* @see {@link MsgType}
* @returns {MsgType}
* @returns {
Web
MsgType}
*/
public
typeSub
():
MsgType
{
public
typeSub
():
Web
MsgType
{
if
(
!
this
.
rawObj
)
{
throw
new
Error
(
'
no rawObj
'
)
}
...
...
@@ -393,9 +393,11 @@ export class PuppeteerMessage extends Message {
* console.log(contactList)
*/
public
mentioned
():
PuppeteerContact
[]
{
log
.
verbose
(
'
PuppeteerMessage
'
,
'
mentioned()
'
)
let
contactList
:
PuppeteerContact
[]
=
[]
const
room
=
this
.
room
()
if
(
this
.
type
()
!==
MsgType
.
TEXT
||
!
room
)
{
if
(
this
.
type
()
!==
Web
MsgType
.
TEXT
||
!
room
)
{
return
contactList
}
...
...
@@ -497,21 +499,21 @@ export class PuppeteerMessage extends Message {
let
url
:
string
|
undefined
switch
(
this
.
type
())
{
case
MsgType
.
EMOTICON
:
case
Web
MsgType
.
EMOTICON
:
url
=
await
puppet
.
bridge
.
getMsgEmoticon
(
this
.
id
)
break
case
MsgType
.
IMAGE
:
case
Web
MsgType
.
IMAGE
:
url
=
await
puppet
.
bridge
.
getMsgImg
(
this
.
id
)
break
case
MsgType
.
VIDEO
:
case
MsgType
.
MICROVIDEO
:
case
Web
MsgType
.
VIDEO
:
case
Web
MsgType
.
MICROVIDEO
:
url
=
await
puppet
.
bridge
.
getMsgVideo
(
this
.
id
)
break
case
MsgType
.
VOICE
:
case
Web
MsgType
.
VOICE
:
url
=
await
puppet
.
bridge
.
getMsgVoice
(
this
.
id
)
break
case
MsgType
.
APP
:
case
Web
MsgType
.
APP
:
if
(
!
this
.
rawObj
)
{
throw
new
Error
(
'
no rawObj
'
)
}
...
...
@@ -541,8 +543,8 @@ export class PuppeteerMessage extends Message {
}
break
case
MsgType
.
TEXT
:
if
(
this
.
typeSub
()
===
MsgType
.
LOCATION
)
{
case
Web
MsgType
.
TEXT
:
if
(
this
.
typeSub
()
===
Web
MsgType
.
LOCATION
)
{
url
=
await
puppet
.
bridge
.
getMsgPublicLinkImg
(
this
.
id
)
}
break
...
...
@@ -606,7 +608,7 @@ export class PuppeteerMessage extends Message {
*/
public
dump
()
{
console
.
error
(
'
======= dump message =======
'
)
Object
.
keys
(
this
.
payload
!
).
forEach
((
k
:
keyof
MsgPayload
)
=>
console
.
error
(
`
${
k
}
:
${
this
.
payload
!
[
k
]}
`
))
Object
.
keys
(
this
.
payload
!
).
forEach
((
k
:
keyof
Web
MsgPayload
)
=>
console
.
error
(
`
${
k
}
:
${
this
.
payload
!
[
k
]}
`
))
}
/**
...
...
@@ -617,7 +619,7 @@ export class PuppeteerMessage extends Message {
if
(
!
this
.
rawObj
)
{
throw
new
Error
(
'
no this.rawObj
'
)
}
Object
.
keys
(
this
.
rawObj
).
forEach
((
k
:
keyof
Puppeteer
MessageRawPayload
)
=>
console
.
error
(
`
${
k
}
:
${
this
.
rawObj
&&
this
.
rawObj
[
k
]}
`
))
Object
.
keys
(
this
.
rawObj
).
forEach
((
k
:
keyof
Web
MessageRawPayload
)
=>
console
.
error
(
`
${
k
}
:
${
this
.
rawObj
&&
this
.
rawObj
[
k
]}
`
))
}
// /**
...
...
@@ -764,24 +766,24 @@ export class PuppeteerMessage extends Message {
const
type
=
this
.
type
()
switch
(
type
)
{
case
MsgType
.
EMOTICON
:
case
Web
MsgType
.
EMOTICON
:
ext
=
'
.gif
'
break
case
MsgType
.
IMAGE
:
case
Web
MsgType
.
IMAGE
:
ext
=
'
.jpg
'
break
case
MsgType
.
VIDEO
:
case
MsgType
.
MICROVIDEO
:
case
Web
MsgType
.
VIDEO
:
case
Web
MsgType
.
MICROVIDEO
:
ext
=
'
.mp4
'
break
case
MsgType
.
VOICE
:
case
Web
MsgType
.
VOICE
:
ext
=
'
.mp3
'
break
case
MsgType
.
APP
:
case
Web
MsgType
.
APP
:
switch
(
this
.
typeApp
())
{
case
AppMsgType
.
URL
:
ext
=
'
.url
'
// XXX
...
...
@@ -792,8 +794,8 @@ export class PuppeteerMessage extends Message {
}
break
case
MsgType
.
TEXT
:
if
(
this
.
typeSub
()
===
MsgType
.
LOCATION
)
{
case
Web
MsgType
.
TEXT
:
if
(
this
.
typeSub
()
===
Web
MsgType
.
LOCATION
)
{
ext
=
'
.jpg
'
}
ext
=
'
.
'
+
this
.
type
()
...
...
@@ -904,7 +906,7 @@ export class PuppeteerMessage extends Message {
/**
* 1. Text message
*/
if
(
this
.
type
()
===
MsgType
.
TEXT
)
{
if
(
this
.
type
()
===
Web
MsgType
.
TEXT
)
{
await
to
.
say
(
this
.
text
())
return
}
...
...
src/puppet-puppeteer/puppeteer-room.spec.ts
浏览文件 @
0609eb8d
...
...
@@ -24,8 +24,9 @@ import * as sinon from 'sinon'
import
cloneClass
from
'
clone-class
'
import
{
log
}
from
'
../config
'
import
Profile
from
'
../profile
'
import
PuppetMock
from
'
../puppet-mock
'
import
Wechaty
from
'
../wechaty
'
import
PuppetPuppeteer
from
'
./puppet-puppeteer
'
...
...
@@ -40,7 +41,10 @@ const MyContact = cloneClass(PuppeteerContact)
// tslint:disable-next-line:variable-name
const
MyMessage
=
cloneClass
(
PuppeteerMessage
)
const
puppet
=
new
PuppetMock
()
const
puppet
=
new
PuppetPuppeteer
({
profile
:
new
Profile
(),
wechaty
:
new
Wechaty
(),
})
const
MOCK_USER_ID
=
'
TEST-USER-ID
'
puppet
.
emit
(
'
login
'
,
MyContact
.
load
(
MOCK_USER_ID
))
...
...
@@ -87,11 +91,11 @@ MyContact.puppet = MyMessage.puppet = MyRoom.puppet = puppet
test
(
'
Room smoking test
'
,
async
t
=>
{
/* tslint:disable:max-line-length */
const
R
AW_OBJ
=
JSON
.
parse
(
`{"RemarkPYQuanPin":"","RemarkPYInitial":"","PYInitial":"TZZGQNTSHGFJ","PYQuanPin":"tongzhizhongguoqingniantianshihuiguanfangjia","Uin":0,"UserName":"@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278","NickName":"(通知)中国青年天使会官方家","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=670397504&username=@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278&skey=","ContactFlag":2,"MemberCount":146,"MemberList":[{"Uin":0,"UserName":"@ecff4a7a86f23455dc42317269aa36ab","NickName":"童玮亮","AttrStatus":103423,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"dap","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ecff4a7a86f23455dc42317269aa36ab&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@eac4377ecfd59e4321262f892177169f","NickName":"麦刚","AttrStatus":33674247,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"mai","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@eac4377ecfd59e4321262f892177169f&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@ad85207730aa94e006ddce28f74e6878","NickName":"田美坤Maggie","AttrStatus":112679,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"田美坤","KeyWord":"tia","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ad85207730aa94e006ddce28f74e6878&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":2351423900,"UserName":"@33cc239d22b20d56395bbbd0967b28b9","NickName":"周宏光","AttrStatus":327869,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"周宏光","KeyWord":"acc","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@33cc239d22b20d56395bbbd0967b28b9&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@5e77381e1e3b5641ddcee44670b6e83a","NickName":"牛文文","AttrStatus":100349,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"niu","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@5e77381e1e3b5641ddcee44670b6e83a&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@56941ef97f3e9c70af88667fdd613b44","NickName":"羊东 东方红酒窖","AttrStatus":33675367,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"Yan","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@56941ef97f3e9c70af88667fdd613b44&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@72c4767ce32db488871fdd1c27173b81","NickName":"李竹~英诺天使(此号已满)","AttrStatus":235261,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"liz","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@72c4767ce32db488871fdd1c27173b81&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@0b0e2eb9501ab2d84f9f800f6a0b4216","NickName":"周静彤 杨宁助理","AttrStatus":230885,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"zlo","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@0b0e2eb9501ab2d84f9f800f6a0b4216&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@4bfa767be0cd3fb78409b9735d1dcc57","NickName":"周哲 Jeremy","AttrStatus":33791995,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"zho","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@4bfa767be0cd3fb78409b9735d1dcc57&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@ad954bf2159a572b7743a5bc134739f4","NickName":"vicky张","AttrStatus":100477,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"hua","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ad954bf2159a572b7743a5bc134739f4&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"}],"RemarkName":"","HideInputBarFlag":0,"Sex":0,"Signature":"","VerifyFlag":0,"OwnerUin":2351423900,"StarFriend":0,"AppAccountFlag":0,"Statues":0,"AttrStatus":0,"Province":"","City":"","Alias":"","SnsFlag":0,"UniFriend":0,"DisplayName":"","ChatRoomId":0,"KeyWord":"","EncryChatRoomId":"@4b8baa99bdfc354443711412126d2aaf","MMFromBatchGet":true,"MMOrderSymbol":"TONGZHIZHONGGUOQINGNIANTIANSHIHUIGUANFANGJIA","MMFromBatchget":true,"MMInChatroom":true}`
)
const
CONTACT_
LIST
=
JSON
.
parse
(
`{"@ad85207730aa94e006ddce28f74e6878":{ "UserName": "@ad85207730aa94e006ddce28f74e6878","NickName": "田美坤Maggie","RemarkName": "" },"@72c4767ce32db488871fdd1c27173b81":{ "UserName": "@72c4767ce32db488871fdd1c27173b81","NickName": "李竹~英诺天使(此号已满)","RemarkName": "" },"@ecff4a7a86f23455dc42317269aa36ab":{ "UserName": "@ecff4a7a86f23455dc42317269aa36ab","NickName": "童玮亮","RemarkName": "童玮亮备注" }}`
)
const
R
OOM_RAW_PAYLOAD
=
JSON
.
parse
(
`{"RemarkPYQuanPin":"","RemarkPYInitial":"","PYInitial":"TZZGQNTSHGFJ","PYQuanPin":"tongzhizhongguoqingniantianshihuiguanfangjia","Uin":0,"UserName":"@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278","NickName":"(通知)中国青年天使会官方家","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=670397504&username=@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278&skey=","ContactFlag":2,"MemberCount":146,"MemberList":[{"Uin":0,"UserName":"@ecff4a7a86f23455dc42317269aa36ab","NickName":"童玮亮","AttrStatus":103423,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"dap","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ecff4a7a86f23455dc42317269aa36ab&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@eac4377ecfd59e4321262f892177169f","NickName":"麦刚","AttrStatus":33674247,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"mai","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@eac4377ecfd59e4321262f892177169f&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@ad85207730aa94e006ddce28f74e6878","NickName":"田美坤Maggie","AttrStatus":112679,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"田美坤","KeyWord":"tia","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ad85207730aa94e006ddce28f74e6878&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":2351423900,"UserName":"@33cc239d22b20d56395bbbd0967b28b9","NickName":"周宏光","AttrStatus":327869,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"周宏光","KeyWord":"acc","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@33cc239d22b20d56395bbbd0967b28b9&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@5e77381e1e3b5641ddcee44670b6e83a","NickName":"牛文文","AttrStatus":100349,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"niu","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@5e77381e1e3b5641ddcee44670b6e83a&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@56941ef97f3e9c70af88667fdd613b44","NickName":"羊东 东方红酒窖","AttrStatus":33675367,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"Yan","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@56941ef97f3e9c70af88667fdd613b44&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@72c4767ce32db488871fdd1c27173b81","NickName":"李竹~英诺天使(此号已满)","AttrStatus":235261,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"liz","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@72c4767ce32db488871fdd1c27173b81&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@0b0e2eb9501ab2d84f9f800f6a0b4216","NickName":"周静彤 杨宁助理","AttrStatus":230885,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"zlo","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@0b0e2eb9501ab2d84f9f800f6a0b4216&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@4bfa767be0cd3fb78409b9735d1dcc57","NickName":"周哲 Jeremy","AttrStatus":33791995,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"zho","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@4bfa767be0cd3fb78409b9735d1dcc57&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"},{"Uin":0,"UserName":"@ad954bf2159a572b7743a5bc134739f4","NickName":"vicky张","AttrStatus":100477,"PYInitial":"","PYQuanPin":"","RemarkPYInitial":"","RemarkPYQuanPin":"","MemberStatus":0,"DisplayName":"","KeyWord":"hua","HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@ad954bf2159a572b7743a5bc134739f4&skey=@crypt_f9cec94b_f23a307a23231cfb5098faf91ff759ca&chatroomid=@4b8baa99bdfc354443711412126d2aaf"}],"RemarkName":"","HideInputBarFlag":0,"Sex":0,"Signature":"","VerifyFlag":0,"OwnerUin":2351423900,"StarFriend":0,"AppAccountFlag":0,"Statues":0,"AttrStatus":0,"Province":"","City":"","Alias":"","SnsFlag":0,"UniFriend":0,"DisplayName":"","ChatRoomId":0,"KeyWord":"","EncryChatRoomId":"@4b8baa99bdfc354443711412126d2aaf","MMFromBatchGet":true,"MMOrderSymbol":"TONGZHIZHONGGUOQINGNIANTIANSHIHUIGUANFANGJIA","MMFromBatchget":true,"MMInChatroom":true}`
)
const
CONTACT_
RAW_PAYLOAD_DICT
=
JSON
.
parse
(
`{"@ad85207730aa94e006ddce28f74e6878":{ "UserName": "@ad85207730aa94e006ddce28f74e6878","NickName": "田美坤Maggie","RemarkName": "" },"@72c4767ce32db488871fdd1c27173b81":{ "UserName": "@72c4767ce32db488871fdd1c27173b81","NickName": "李竹~英诺天使(此号已满)","RemarkName": "" },"@ecff4a7a86f23455dc42317269aa36ab":{ "UserName": "@ecff4a7a86f23455dc42317269aa36ab","NickName": "童玮亮","RemarkName": "童玮亮备注" }}`
)
const
EXPECTED
=
{
id
:
'
@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278
'
,
id
:
'
@@e2355db381dc46a77c0b95516d05e7486135cb6370d8a6af66925d89d50ec278
'
,
topic
:
'
(通知)中国青年天使会官方家
'
,
encryId
:
'
@4b8baa99bdfc354443711412126d2aaf
'
,
memberId1
:
'
@ad85207730aa94e006ddce28f74e6878
'
,
...
...
@@ -104,45 +108,38 @@ test('Room smoking test', async t => {
}
// Mock
const
mockContactPayload
=
function
(
id
:
string
)
{
const
mockRawPayload
=
function
(
contact
:
PuppeteerContact
)
{
log
.
verbose
(
'
PuppeteerRoomTest
'
,
'
mockContactRawPayload(%s)
'
,
contact
)
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
id
!==
EXPECTED
.
id
&&
!
(
id
in
CONTACT_LIST
))
return
resolve
({})
if
(
id
===
EXPECTED
.
id
)
{
setTimeout
(()
=>
{
return
resolve
(
RAW_OBJ
)
},
10
)
}
if
(
id
in
CONTACT_LIST
)
{
setTimeout
(()
=>
{
return
resolve
(
CONTACT_LIST
[
id
])
},
10
)
if
(
contact
.
id
===
EXPECTED
.
id
)
{
setImmediate
(()
=>
resolve
(
ROOM_RAW_PAYLOAD
))
}
else
if
(
contact
.
id
in
CONTACT_RAW_PAYLOAD_DICT
)
{
setImmediate
(()
=>
resolve
(
CONTACT_RAW_PAYLOAD_DICT
[
contact
.
id
]))
}
else
{
setImmediate
(()
=>
resolve
({}))
}
})
}
const
r
=
new
MyRoom
(
EXPECTED
.
id
)
const
r
=
MyRoom
.
load
(
EXPECTED
.
id
)
t
.
is
(
r
.
id
,
EXPECTED
.
id
,
'
should set id/UserName right
'
)
// let puppet
// try {
// puppet = config.puppetInstance()
// puppet.getContact = mockContactGetter
// } catch (err) {
// puppet = { getContact: mockContactGetter }
// config.puppetInstance(puppet)
// }
const
sandbox
=
sinon
.
createSandbox
()
const
puppet
=
new
PuppetMock
()
const
puppet
=
new
PuppetPuppeteer
({
profile
:
new
Profile
(),
wechaty
:
new
Wechaty
(),
})
sandbox
.
stub
(
puppet
,
'
contactPayload
'
).
callsFake
(
mockContactPayload
)
sandbox
.
stub
(
puppet
as
any
,
'
contactRawPayload
'
).
callsFake
(
mockRawPayload
)
sandbox
.
stub
(
puppet
as
any
,
'
roomRawPayload
'
).
callsFake
(
mockRawPayload
)
MyContact
.
puppet
=
MyMessage
.
puppet
=
MyRoom
.
puppet
=
puppet
await
r
.
ready
()
t
.
is
(
(
r
as
any
).
payload
[
'
id
'
]
,
EXPECTED
.
id
,
'
should set id/UserName
'
)
t
.
is
(
r
.
id
,
EXPECTED
.
id
,
'
should set id/UserName
'
)
// t.is((r as any).payload[.('encryId') , EXPECTED.encryId, 'should set EncryChatRoomId')
t
.
is
(
r
.
topic
()
,
EXPECTED
.
topic
,
'
should set topic/NickName
'
)
t
.
is
(
r
.
topic
(),
EXPECTED
.
topic
,
'
should set topic/NickName
'
)
const
contact1
=
new
MyContact
(
EXPECTED
.
memberId1
)
const
alias1
=
r
.
alias
(
contact1
)
...
...
@@ -191,6 +188,8 @@ test('Room smoking test', async t => {
const
s
=
r
.
toString
()
t
.
is
(
typeof
s
,
'
string
'
,
'
toString()
'
)
sandbox
.
restore
()
})
test
(
'
Room static method
'
,
async
t
=>
{
...
...
src/puppet-puppeteer/puppeteer-room.ts
浏览文件 @
0609eb8d
...
...
@@ -17,6 +17,8 @@
*
* @ignore
*/
import
*
as
util
from
'
util
'
import
{
Raven
,
log
,
...
...
@@ -82,15 +84,25 @@ export class PuppeteerRoom extends Room {
return
}
this
.
payload
=
await
this
.
puppet
.
roomPayload
(
this
)
const
payload
=
await
this
.
puppet
.
roomPayload
(
this
)
await
Promise
.
all
(
payload
.
memberList
.
map
(
contact
=>
contact
.
ready
(),
),
)
log
.
silly
(
'
PuppeteerRoom
'
,
'
ready() this.payload="%s"
'
,
util
.
inspect
(
payload
),
)
this
.
payload
=
payload
}
public
say
(
message
:
PuppeteerMessage
)
:
Promise
<
void
>
public
say
(
text
:
string
)
:
Promise
<
void
>
public
say
(
text
:
string
,
mention
:
PuppeteerContact
)
:
Promise
<
void
>
public
say
(
text
:
string
,
mention
:
PuppeteerContact
[])
:
Promise
<
void
>
public
say
(
text
:
never
,
...
args
:
never
[])
:
Promise
<
never
>
public
say
(
text
:
never
,
...
args
:
never
[]):
Promise
<
never
>
public
async
say
(
textOrMessage
:
string
|
PuppeteerMessage
,
mention
?
:
PuppeteerContact
|
PuppeteerContact
[],
...
...
@@ -184,7 +196,7 @@ export class PuppeteerRoom extends Room {
return
Misc
.
plainText
(
this
.
payload
?
this
.
payload
.
topic
:
''
)
}
this
.
puppet
// config.puppetInstance()
this
.
puppet
.
roomTopic
(
this
,
newTopic
)
.
catch
(
e
=>
{
log
.
warn
(
'
PuppeteerRoom
'
,
'
topic(newTopic=%s) exception: %s
'
,
...
...
@@ -196,7 +208,7 @@ export class PuppeteerRoom extends Room {
if
(
!
this
.
payload
)
{
this
.
payload
=
<
RoomPayload
>
{}
}
this
.
payload
[
'
topic
'
]
=
newTopic
this
.
payload
.
topic
=
newTopic
return
Promise
.
resolve
()
}
...
...
@@ -294,24 +306,7 @@ export class PuppeteerRoom extends Room {
*/
public
memberAll
(
queryArg
:
RoomMemberQueryFilter
|
string
):
PuppeteerContact
[]
{
if
(
typeof
queryArg
===
'
string
'
)
{
//
// use the following `return` statement to do this job.
//
// const nameList = this.memberAll({name: queryArg})
// const roomAliasList = this.memberAll({roomAlias: queryArg})
// const contactAliasList = this.memberAll({contactAlias: queryArg})
// if (nameList) {
// contactList = contactList.concat(nameList)
// }
// if (roomAliasList) {
// contactList = contactList.concat(roomAliasList)
// }
// if (contactAliasList) {
// contactList = contactList.concat(contactAliasList)
// }
// TODO: filter the duplicated result
return
([]
as
PuppeteerContact
[]).
concat
(
this
.
memberAll
({
name
:
queryArg
}),
this
.
memberAll
({
roomAlias
:
queryArg
}),
...
...
@@ -323,10 +318,11 @@ export class PuppeteerRoom extends Room {
* We got filter parameter
*/
log
.
silly
(
'
PuppeteerRoom
'
,
'
memberAll({ %s })
'
,
Object
.
keys
(
queryArg
)
.
map
((
k
:
keyof
RoomMemberQueryFilter
)
=>
`
${
k
}
:
${
queryArg
[
k
]}
`
)
.
join
(
'
,
'
),
)
JSON
.
stringify
(
queryArg
),
// Object.keys(queryArg)
// .map((k: keyof RoomMemberQueryFilter) => `${k}: ${queryArg[k]}`)
// .join(', '),
)
if
(
Object
.
keys
(
queryArg
).
length
!==
1
)
{
throw
new
Error
(
'
Room member find queryArg only support one key. multi key support is not availble now.
'
)
...
...
@@ -340,7 +336,7 @@ export class PuppeteerRoom extends Room {
/**
* ISSUE #64 emoji need to be striped
*/
const
filterValue
:
string
=
Misc
.
stripEmoji
(
Misc
.
plainText
(
queryArg
[
filterKey
]))
const
filterValue
:
string
=
Misc
.
stripEmoji
(
Misc
.
plainText
(
queryArg
[
filterKey
]))
const
keyMap
=
{
contactAlias
:
'
contactAliasMap
'
,
...
...
src/puppet-puppeteer/schema.ts
浏览文件 @
0609eb8d
...
...
@@ -20,7 +20,7 @@ import {
Gender
,
}
from
'
../puppet/
'
export
interface
Puppeteer
ContactRawPayload
{
export
interface
Web
ContactRawPayload
{
Alias
:
string
,
City
:
string
,
NickName
:
string
,
...
...
@@ -37,7 +37,7 @@ export interface PuppeteerContactRawPayload {
VerifyFlag
:
number
,
}
export
interface
Puppeteer
MessageMediaPayload
{
export
interface
Web
MessageMediaPayload
{
ToUserName
:
string
,
MsgType
:
number
,
MediaId
:
string
,
...
...
@@ -49,7 +49,7 @@ export interface PuppeteerMessageMediaPayload {
Signature
?:
string
,
}
export
interface
Puppeteer
MessageRawPayload
{
export
interface
Web
MessageRawPayload
{
MsgId
:
string
,
MMActualSender
:
string
,
// getUserContact(message.MMActualSender,message.MMPeerUserName).isContact()
...
...
@@ -108,7 +108,7 @@ export interface PuppeteerMessageRawPayload {
AppMsgType
:
AppMsgType
,
// message.MsgType == CONF.MSGTYPE_APP && message.AppMsgType == CONF.APPMSGTYPE_URL
// message.MsgType == CONF.MSGTYPE_TEXT && message.SubMsgType != CONF.MSGTYPE_LOCATION
SubMsgType
:
MsgType
,
// "msgType":"{{message.MsgType}}","subType":{{message.SubMsgType||0}},"msgId":"{{message.MsgId}}"
SubMsgType
:
Web
MsgType
,
// "msgType":"{{message.MsgType}}","subType":{{message.SubMsgType||0}},"msgId":"{{message.MsgId}}"
/**
* Status-es
...
...
@@ -148,7 +148,7 @@ export interface PuppeteerMessageRawPayload {
* MsgType == CONF.MSGTYPE_SHARECARD" ng-click="showProfile($event,message.RecommendInfo.UserName)
* MsgType == CONF.MSGTYPE_VERIFYMSG
*/
RecommendInfo
?:
RecommendPayload
,
RecommendInfo
?:
Web
RecommendPayload
,
/**
* Transpond Message
...
...
@@ -162,9 +162,9 @@ export interface PuppeteerMessageRawPayload {
}
export
interface
MsgPayload
{
export
interface
Web
MsgPayload
{
id
:
string
,
type
:
MsgType
,
type
:
Web
MsgType
,
from
:
string
,
to
?:
string
,
// if to is not set, then room must be set
room
?:
string
,
...
...
@@ -182,7 +182,7 @@ export interface MsgPayload {
// export type MessageTypeValue = 1 | 3 | 34 | 37 | 40 | 42 | 43 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 62 | 9999 | 10000 | 10002
export
interface
MsgTypeDict
{
export
interface
Web
MsgTypeDict
{
[
index
:
string
]:
string
|
number
,
// MessageTypeName: MessageTypeValue
// , MessageTypeValue: MessageTypeName
...
...
@@ -254,7 +254,7 @@ export enum AppMsgType {
* @property {number} SYS - MsgType.SYS (10000) for SYS
* @property {number} RECALLED - MsgType.RECALLED (10002) for RECALLED
*/
export
enum
MsgType
{
export
enum
Web
MsgType
{
TEXT
=
1
,
IMAGE
=
3
,
VOICE
=
34
,
...
...
@@ -278,7 +278,7 @@ export enum MsgType {
/**
* from Message
*/
export
interface
RecommendPayload
{
export
interface
Web
RecommendPayload
{
UserName
:
string
,
NickName
:
string
,
// display_name
Content
:
string
,
// request message
...
...
@@ -289,7 +289,7 @@ export interface RecommendPayload {
}
export
const
enum
MediaType
{
export
const
enum
Web
MediaType
{
IMAGE
=
1
,
VIDEO
=
2
,
AUDIO
=
3
,
...
...
src/puppet/contact.ts
浏览文件 @
0609eb8d
...
...
@@ -203,7 +203,7 @@ export abstract class Contact extends PuppetAccessory implements Sayable {
*/
public
toString
():
string
{
const
identity
=
this
.
alias
()
||
this
.
name
()
||
this
.
id
return
`
@
Contact<
${
identity
}
>`
return
`Contact<
${
identity
}
>`
}
/**
...
...
src/puppet/message.ts
浏览文件 @
0609eb8d
...
...
@@ -21,7 +21,7 @@ import {
}
from
'
stream
'
import
{
MsgType
,
Web
MsgType
,
AppMsgType
,
}
from
'
../puppet-puppeteer/schema
'
...
...
@@ -42,7 +42,7 @@ import Room from './room'
*/
export
abstract
class
Message
extends
PuppetAccessory
implements
Sayable
{
// tslint:disable-next-line:variable-name
public
static
readonly
Type
=
MsgType
public
static
readonly
Type
=
Web
MsgType
/**
* @todo add function
...
...
@@ -62,8 +62,8 @@ export abstract class Message extends PuppetAccessory implements Sayable {
query
:
any
,
):
Promise
<
T
[
'
prototype
'
][]
>
{
return
[
new
(
this
as
any
)(
1
),
new
(
this
as
any
)(
2
),
new
(
this
as
any
)(
{
MsgId
:
'
id1
'
}
),
new
(
this
as
any
)(
{
MsdId
:
'
id2
'
}
),
]
}
...
...
@@ -98,9 +98,9 @@ export abstract class Message extends PuppetAccessory implements Sayable {
*/
public
toString
()
{
if
(
this
.
type
()
===
Message
.
Type
.
TEXT
)
{
return
`Message#
${
MsgType
[
this
.
type
()]}
<
${
this
.
text
()}
>`
return
`Message#
${
Web
MsgType
[
this
.
type
()]}
<
${
this
.
text
()}
>`
}
else
{
return
`Message#
${
MsgType
[
this
.
type
()]}
<
${
this
.
filename
()}
>`
return
`Message#
${
Web
MsgType
[
this
.
type
()]}
<
${
this
.
filename
()}
>`
}
}
...
...
@@ -221,9 +221,9 @@ export abstract class Message extends PuppetAccessory implements Sayable {
*
* If type is equal to `MsgType.RECALLED`, {@link Message#id} is the msgId of the recalled message.
* @see {@link MsgType}
* @returns {MsgType}
* @returns {
Web
MsgType}
*/
public
abstract
type
():
MsgType
public
abstract
type
():
Web
MsgType
/**
* Get the typeSub from the message.
...
...
@@ -231,9 +231,9 @@ export abstract class Message extends PuppetAccessory implements Sayable {
* If message is a location message: `m.type() === MsgType.TEXT && m.typeSub() === MsgType.LOCATION`
*
* @see {@link MsgType}
* @returns {MsgType}
* @returns {
Web
MsgType}
*/
public
abstract
typeSub
():
MsgType
public
abstract
typeSub
():
Web
MsgType
/**
* Get the typeApp from the message.
...
...
src/puppet/room.ts
浏览文件 @
0609eb8d
...
...
@@ -176,6 +176,13 @@ export abstract class Room extends PuppetAccessory implements Sayable {
return
newRoom
}
/**
*
*
* Instance Properties
*
*
*/
protected
payload
?:
RoomPayload
/**
...
...
@@ -191,7 +198,10 @@ export abstract class Room extends PuppetAccessory implements Sayable {
/**
* @private
*/
public
toString
()
{
return
`@@Room<
${
this
.
topic
()}
>`
}
public
toString
()
{
const
identity
=
this
.
topic
()
||
this
.
id
return
`Room<
${
identity
}
>`
}
/**
* @private
...
...
src/wechaty.ts
浏览文件 @
0609eb8d
...
...
@@ -22,7 +22,7 @@ import * as os from 'os'
import
*
as
semver
from
'
semver
'
import
{
Constructor
,
//
Constructor,
cloneClass
,
instanceToClass
,
}
from
'
clone-class
'
...
...
@@ -373,7 +373,7 @@ export class Wechaty extends PuppetAccessory implements Sayable {
*/
if
(
typeof
this
.
options
.
puppet
===
'
string
'
)
{
// tslint:disable-next-line:variable-name
const
MyPuppet
=
PUPPET_DICT
[
this
.
options
.
puppet
]
as
typeof
Puppet
&
Constructor
<
Puppet
>
const
MyPuppet
=
PUPPET_DICT
[
this
.
options
.
puppet
]
const
options
=
{
profile
:
this
.
profile
,
wechaty
:
this
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录