Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wechaty
wechaty
提交
50d9be58
W
wechaty
项目概览
wechaty
/
wechaty
上一次同步 大约 3 年
通知
304
Star
10499
Fork
6
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
152
列表
看板
标记
里程碑
合并请求
1
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
W
wechaty
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
152
Issue
152
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
50d9be58
编写于
3月 30, 2019
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of github.com:Chatie/wechaty
上级
e06a358f
382cedff
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
179 addition
and
34 deletion
+179
-34
package.json
package.json
+1
-1
src/user/room.spec.ts
src/user/room.spec.ts
+91
-2
src/user/room.ts
src/user/room.ts
+87
-31
未找到文件。
package.json
浏览文件 @
50d9be58
{
"name"
:
"wechaty"
,
"version"
:
"0.2
3.40
"
,
"version"
:
"0.2
5.1
"
,
"description"
:
"Wechaty is a Bot SDK for Wechat Personal Account"
,
"main"
:
"dist/src/index.js"
,
"typings"
:
"dist/src/index.d.ts"
,
...
...
src/user/room.spec.ts
浏览文件 @
50d9be58
...
...
@@ -23,10 +23,14 @@
import
test
from
'
blue-tape
'
import
sinon
from
'
sinon
'
import
{
RoomPayload
}
from
'
wechaty-puppet
'
import
{
ContactPayload
,
RoomMemberPayload
,
RoomPayload
}
from
'
wechaty-puppet
'
import
{
PuppetMock
}
from
'
wechaty-puppet-mock
'
import
{
Wechaty
}
from
'
../wechaty
'
import
{
Wechaty
}
from
'
../wechaty
'
test
(
'
findAll()
'
,
async
t
=>
{
const
EXPECTED_ROOM_ID
=
'
test-id
'
...
...
@@ -54,3 +58,88 @@ test('findAll()', async t => {
await
wechaty
.
stop
()
})
test
(
'
say()
'
,
async
_
=>
{
const
sandbox
=
sinon
.
createSandbox
()
const
callback
=
sinon
.
spy
()
const
puppet
=
new
PuppetMock
()
const
wechaty
=
new
Wechaty
({
puppet
})
await
wechaty
.
start
()
const
EXPECTED_ROOM_ID
=
'
roomId
'
const
EXPECTED_ROOM_TOPIC
=
'
test-topic
'
const
EXPECTED_CONTACT_1_ID
=
'
contact1
'
const
EXPECTED_CONTACT_1_ALIAS
=
'
little1
'
const
EXPECTED_CONTACT_2_ID
=
'
contact2
'
const
EXPECTED_CONTACT_2_ALIAS
=
'
big2
'
const
CONTACT_MAP
:
{
[
contactId
:
string
]:
string
}
=
{}
CONTACT_MAP
[
EXPECTED_CONTACT_1_ID
]
=
EXPECTED_CONTACT_1_ALIAS
CONTACT_MAP
[
EXPECTED_CONTACT_2_ID
]
=
EXPECTED_CONTACT_2_ALIAS
sandbox
.
stub
(
puppet
,
'
roomMemberPayload
'
).
callsFake
(
async
(
_
,
contactId
)
=>
{
await
new
Promise
(
r
=>
setImmediate
(
r
))
return
{
id
:
contactId
,
roomAlias
:
CONTACT_MAP
[
contactId
],
}
as
RoomMemberPayload
})
sandbox
.
stub
(
puppet
,
'
roomPayload
'
).
callsFake
(
async
()
=>
{
await
new
Promise
(
r
=>
setImmediate
(
r
))
return
{
topic
:
EXPECTED_ROOM_TOPIC
,
}
as
RoomPayload
})
sandbox
.
stub
(
puppet
,
'
contactPayload
'
).
callsFake
(
async
(
contactId
)
=>
{
await
new
Promise
(
r
=>
setImmediate
(
r
))
return
{
id
:
contactId
,
}
as
ContactPayload
})
// sandbox.spy(puppet, 'messageSendText')
sandbox
.
stub
(
puppet
,
'
messageSendText
'
).
callsFake
(
callback
)
const
room
=
wechaty
.
Room
.
load
(
EXPECTED_ROOM_ID
)
const
contact1
=
wechaty
.
Contact
.
load
(
EXPECTED_CONTACT_1_ID
)
const
contact2
=
wechaty
.
Contact
.
load
(
EXPECTED_CONTACT_2_ID
)
await
contact1
.
sync
()
await
contact2
.
sync
()
await
room
.
sync
()
test
(
'
say with Tagged Template
'
,
async
t
=>
{
callback
.
resetHistory
()
await
room
.
say
`To be
${
contact1
}
or not to be
${
contact2
}
`
t
.
deepEqual
(
callback
.
getCall
(
0
).
args
,
[
{
contactId
:
EXPECTED_CONTACT_1_ID
,
roomId
:
EXPECTED_ROOM_ID
},
'
To be @little1 or not to be @big2
'
,
[
EXPECTED_CONTACT_1_ID
,
EXPECTED_CONTACT_2_ID
],
],
'
Tagged Template say should be matched
'
)
})
test
(
'
say with regular mention contact
'
,
async
t
=>
{
callback
.
resetHistory
()
await
room
.
say
(
'
Yo
'
,
contact1
)
t
.
deepEqual
(
callback
.
getCall
(
0
).
args
,
[
{
contactId
:
EXPECTED_CONTACT_1_ID
,
roomId
:
EXPECTED_ROOM_ID
},
'
@little1 Yo
'
,
[
EXPECTED_CONTACT_1_ID
],
],
'
Single mention should work with old ways
'
)
})
test
(
'
say with multiple mention contact
'
,
async
t
=>
{
callback
.
resetHistory
()
await
room
.
say
(
'
hey buddies, let
\'
s party
'
,
contact1
,
contact2
)
t
.
deepEqual
(
callback
.
getCall
(
0
).
args
,
[
{
contactId
:
EXPECTED_CONTACT_1_ID
,
roomId
:
EXPECTED_ROOM_ID
},
'
@little1 @big2 hey buddies, let
\'
s party
'
,
[
EXPECTED_CONTACT_1_ID
,
EXPECTED_CONTACT_2_ID
],
],
'
Multiple mention should work with new way
'
)
})
await
wechaty
.
stop
()
})
src/user/room.ts
浏览文件 @
50d9be58
...
...
@@ -382,10 +382,10 @@ export class Room extends Accessory implements Sayable {
}
public
say
(
text
:
string
)
:
Promise
<
void
>
public
say
(
text
:
string
,
mention
:
Contact
)
:
Promise
<
void
>
public
say
(
text
:
string
,
mention
:
Contact
[])
:
Promise
<
void
>
public
say
(
text
:
string
,
...
mentionList
:
Contact
[])
:
Promise
<
void
>
public
say
(
file
:
FileBox
)
:
Promise
<
void
>
public
say
(
url
:
UrlLink
)
:
Promise
<
void
>
public
say
(
textList
:
TemplateStringsArray
,
...
mentionList
:
Contact
[]):
Promise
<
void
>
public
say
(...
args
:
never
[]):
never
...
...
@@ -423,65 +423,121 @@ export class Room extends Accessory implements Sayable {
* // 4. Send text inside room and mention @mention contact
* const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of the room member
* await room.say('Hello world!', contact)
*
* // 5. Send text inside room and mention someone with Tagged Template
* const contact2 = await bot.Contact.find({name: 'zixia'}) // change 'zixia' to any of the room member
* await room.say`Hello ${contact}, here is the world ${contact2}`
*/
public
async
say
(
textOr
ContactOrFileOrUrl
:
string
|
Contact
|
FileBox
|
UrlLink
,
mention
?
:
Contact
|
Contact
[],
textOr
ListOrContactOrFileOrUrl
:
string
|
Contact
|
FileBox
|
UrlLink
|
TemplateStringsArray
,
...
mentionList
:
Contact
[]
):
Promise
<
void
>
{
let
replyToList
:
Contact
[]
=
[]
replyToList
=
replyToList
.
concat
(
mention
||
[])
const
mentionAliasList
=
await
Promise
.
all
(
replyToList
.
map
(
async
c
=>
await
this
.
alias
(
c
)
||
c
.
name
()
)
)
log
.
verbose
(
'
Room
'
,
'
say(%s, %s)
'
,
textOrContactOrFileOrUrl
,
mention
Alias
List
.
join
(
'
,
'
),
textOr
ListOr
ContactOrFileOrUrl
,
mentionList
.
join
(
'
,
'
),
)
let
text
:
string
if
(
typeof
textOrContactOrFileOrUrl
===
'
string
'
)
{
if
(
typeof
textOr
ListOr
ContactOrFileOrUrl
===
'
string
'
)
{
if
(
mentionAliasList
.
length
>
0
)
{
// const AT_SEPRATOR = String.fromCharCode(8197)
const
AT_SEPRATOR
=
FOUR_PER_EM_SPACE
const
mentionList
=
mentionAliasList
.
map
(
roomAlias
=>
'
@
'
+
roomAlias
).
join
(
AT_SEPRATOR
)
if
(
mentionList
.
length
>
0
)
{
const
AT_SEPARATOR
=
FOUR_PER_EM_SPACE
const
mentionAlias
=
await
Promise
.
all
(
mentionList
.
map
(
async
contact
=>
'
@
'
+
(
await
this
.
alias
(
contact
)
||
contact
.
name
())
))
const
mentionText
=
mentionAlias
.
join
(
AT_SEPARATOR
)
text
=
mention
List
+
'
'
+
tex
tOrContactOrFileOrUrl
text
=
mention
Text
+
'
'
+
textOrLis
tOrContactOrFileOrUrl
}
else
{
text
=
textOrContactOrFileOrUrl
text
=
textOr
ListOr
ContactOrFileOrUrl
}
const
receiver
=
{
contactId
:
replyToList
.
length
&&
replyTo
List
[
0
].
id
||
undefined
,
contactId
:
mentionList
.
length
&&
mention
List
[
0
].
id
||
undefined
,
roomId
:
this
.
id
,
}
await
this
.
puppet
.
messageSendText
(
receiver
,
text
,
replyTo
List
.
map
(
c
=>
c
.
id
),
mention
List
.
map
(
c
=>
c
.
id
),
)
}
else
if
(
textOrContactOrFileOrUrl
instanceof
FileBox
)
{
}
else
if
(
textOrListOrContactOrFileOrUrl
instanceof
FileBox
)
{
/**
* 2. File Message
*/
await
this
.
puppet
.
messageSendFile
({
roomId
:
this
.
id
,
},
textOrContactOrFileOrUrl
)
}
else
if
(
textOrContactOrFileOrUrl
instanceof
Contact
)
{
},
textOrListOrContactOrFileOrUrl
)
}
else
if
(
textOrListOrContactOrFileOrUrl
instanceof
Contact
)
{
/**
* 3. Contact Card
*/
await
this
.
puppet
.
messageSendContact
({
roomId
:
this
.
id
,
},
textOrContactOrFileOrUrl
.
id
)
}
else
if
(
textOrContactOrFileOrUrl
instanceof
UrlLink
)
{
},
textOr
ListOr
ContactOrFileOrUrl
.
id
)
}
else
if
(
textOr
ListOr
ContactOrFileOrUrl
instanceof
UrlLink
)
{
/**
* 4. Link Message
*/
await
this
.
puppet
.
messageSendUrl
({
contactId
:
this
.
id
},
textOrContactOrFileOrUrl
.
payload
)
},
textOrListOrContactOrFileOrUrl
.
payload
)
}
else
if
(
textOrListOrContactOrFileOrUrl
instanceof
Array
)
{
await
this
.
sayTemplateStringsArray
(
textOrListOrContactOrFileOrUrl
,
...
mentionList
,
)
}
else
{
throw
new
Error
(
'
arg unsupported:
'
+
textOrContactOrFileOrUrl
)
throw
new
Error
(
'
arg unsupported:
'
+
textOrListOrContactOrFileOrUrl
)
}
}
private
async
sayTemplateStringsArray
(
textList
:
TemplateStringsArray
,
...
mentionList
:
Contact
[]
)
{
const
receiver
=
{
contactId
:
mentionList
.
length
&&
mentionList
[
0
].
id
||
undefined
,
roomId
:
this
.
id
,
}
if
(
mentionList
.
length
===
0
)
{
/**
* No mention in the string
*/
await
this
.
puppet
.
messageSendText
(
receiver
,
textList
[
0
],
)
}
else
if
(
textList
.
length
===
1
)
{
/**
* Constructed mention string, skip inserting @ signs
*/
await
this
.
puppet
.
messageSendText
(
receiver
,
textList
[
0
],
mentionList
.
map
(
c
=>
c
.
id
),
)
}
else
{
/**
* Mention in the string
*/
const
strLength
=
textList
.
length
const
mentionLength
=
mentionList
.
length
if
(
strLength
-
mentionLength
!==
1
)
{
throw
new
Error
(
`Can not say message, invalid Tagged Template.`
)
}
let
constructedString
=
''
let
i
=
0
for
(;
i
<
mentionLength
;
i
++
)
{
constructedString
+=
textList
[
i
]
+
'
@
'
+
(
await
this
.
alias
(
mentionList
[
i
])
||
mentionList
[
i
].
name
())
}
constructedString
+=
textList
[
i
]
await
this
.
puppet
.
messageSendText
(
receiver
,
constructedString
,
mentionList
.
map
(
c
=>
c
.
id
),
)
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录