Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wechaty
wechaty
提交
bf595dbb
W
wechaty
项目概览
wechaty
/
wechaty
上一次同步 3 年多
通知
307
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,发现更多精彩内容 >>
提交
bf595dbb
编写于
5月 28, 2016
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add npmignore
上级
cd24b2fe
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
287 addition
and
61 deletion
+287
-61
.npmignore
.npmignore
+5
-0
README.md
README.md
+29
-9
doc/webwxapp.js
doc/webwxapp.js
+19
-2
example/api-ai-bot.js
example/api-ai-bot.js
+169
-13
example/tuling123-bot.js
example/tuling123-bot.js
+16
-16
src/contact.js
src/contact.js
+12
-8
src/puppet-web-bridge.js
src/puppet-web-bridge.js
+8
-5
src/puppet-web-injectio.js
src/puppet-web-injectio.js
+11
-4
src/puppet-web-server.js
src/puppet-web-server.js
+3
-1
src/puppet-web.js
src/puppet-web.js
+2
-1
src/puppet.js
src/puppet.js
+2
-0
src/wechaty.js
src/wechaty.js
+7
-1
test/webdriver-spec.js
test/webdriver-spec.js
+4
-1
未找到文件。
.npmignore
0 → 100644
浏览文件 @
bf595dbb
doc
example
test
circle.yml
.travis.yml
README.md
浏览文件 @
bf595dbb
...
...
@@ -62,7 +62,7 @@ Plan to glue with Machine Learning/Deep Learning/Neural Network/Natural Language
# Installation
#
Use NPM - to Use in Production
#
Install from NPM
Use NPM is recommended to install a stable version of Wechaty published on NPM.com
```
shell
npm
install
--save
wechaty
...
...
@@ -70,8 +70,8 @@ npm install --save wechaty
Then you are set.
#
Start from source - to Hack / Development
In case that you want to dive
into Wechaty, then follow instructions would help you to run Wechaty bot on your machine, and easy to hack
.
#
Install from Github(for hack)
In case that you want to dive
deeper into Wechaty, fork & clone to run Wechaty bot on your machine, and start hacking
.
## 1. Install Node.js
Node.js Version 6.0 or above is required.
...
...
@@ -294,17 +294,37 @@ Know more about TAP: [Why I use Tape Instead of Mocha & So Should You](https://m
4.
...
## v0.0.5 (2016/5/11)
1.
Receive & send message
1.
Receive & send
text
message
1.
Show contacts info
1.
Show groups info
1.
1st usable version
1.
Start coding from May 1st 2016
# Todo List
[ ] Deal with friend request
[ ] Manage contacts(send friend request/delete contact etc.)
[ ] Create a new chat group, invite people to join
## v0.0.1 (2016/5/1)
1.
Start coding
2.
Publish the very first npm module
`wechaty`
# Todo List
[ ] Contact
[ ] Accept a friend request
[ ] Send a friend request
[ ] Delete a contact
[ ] Chat Group
[ ] Create a new chat group
[ ] Invite people to join a existing chat group
[ ] Rename a Chat Group
[ ] Events
[ ] Use EventEmitter2 to emit message events, so we can use wildcard
1.
`message`
2.
`message.recv`
3.
`message.sent`
4.
`message.recv.image`
5.
`message.sent.image`
6.
`message.recv.sys`
1.
`message.**.image`
1.
`message.recv.*`
[ ] Message
[ ] Send/Reply image message
Everybody is welcome to issue your needs.
# Known Issues & Support
...
...
doc/webwxapp.js
浏览文件 @
bf595dbb
...
...
@@ -1572,7 +1572,20 @@ angular.module("Controllers", []),
}(),
!
function
()
{
"
use strict
"
;
angular
.
module
(
"
Controllers
"
).
controller
(
"
contextMenuController
"
,
[
"
$rootScope
"
,
"
$scope
"
,
"
$state
"
,
"
contextMenuFactory
"
,
"
accountFactory
"
,
"
confFactory
"
,
"
contactFactory
"
,
"
ngDialog
"
,
"
chatroomFactory
"
,
"
emojiFactory
"
,
"
utilFactory
"
,
"
chatFactory
"
,
function
(
e
,
t
,
o
,
n
,
r
,
a
,
i
,
c
,
s
,
l
,
u
,
f
)
{
angular
.
module
(
"
Controllers
"
).
controller
(
"
contextMenuController
"
,
[
"
$rootScope
"
,
"
$scope
"
,
"
$state
"
,
"
contextMenuFactory
"
,
"
accountFactory
"
,
"
confFactory
"
,
"
contactFactory
"
,
"
ngDialog
"
,
"
chatroomFactory
"
,
"
emojiFactory
"
,
"
utilFactory
"
,
"
chatFactory
"
,
function
(
e
// $rootScope
,
t
// $scope
,
o
// $state
,
n
// contextMenuFactory
,
r
// accountFactory
,
a
// confFactory
,
i
// contactFactory
,
c
// ngDialog
,
s
// chatroomFactory
,
l
// emojiFactory
,
u
// utilFactory
,
f
// chatFactory
)
{
function
d
(
e
)
{
function
o
(
e
)
{
return
e
.
parentNode
!=
e
.
document
?
(
n
.
push
(
e
.
parentNode
),
...
...
@@ -3974,7 +3987,11 @@ angular.module("Services", []),
}(),
!
function
()
{
"
use strict
"
;
angular
.
module
(
"
Services
"
).
factory
(
"
utilFactory
"
,
[
"
$q
"
,
"
$rootScope
"
,
"
confFactory
"
,
function
(
e
,
t
,
o
)
{
angular
.
module
(
"
Services
"
).
factory
(
"
utilFactory
"
,
[
"
$q
"
,
"
$rootScope
"
,
"
confFactory
"
,
function
(
e
// $q
,
t
// $rootScope
,
o
// $confFactory
)
{
function
n
(
e
,
t
,
o
,
n
)
{
var
r
;
(
r
=
l
[
e
])
?
(
r
.
intervalSum
+=
o
,
...
...
example/api-ai-bot.js
浏览文件 @
bf595dbb
var
apiai
=
require
(
'
apiai
'
)
var
app
=
apiai
(
'
7217d7bce18c4bcfbe04ba7bdfaf9c08
'
)
var
request
=
app
.
textRequest
(
'
Hello
'
)
request
.
on
(
'
response
'
,
function
(
response
)
{
console
.
log
(
response
)
/**
*
* Wechaty bot use a ApiAi.com brain
*
* Apply your own tuling123.com API_KEY
* at: http://www.tuling123.com/html/doc/api.html
*
* Enjoy!
*
* Wechaty - https://github.com/zixia/wechaty
*
*/
const
log
=
require
(
'
npmlog
'
)
const
co
=
require
(
'
co
'
)
const
ApiAi
=
require
(
'
apiai
'
)
const
EventEmitter2
=
require
(
'
eventemitter2
'
)
const
Wechaty
=
require
(
'
../src/wechaty
'
)
//log.level = 'verbose'
// log.level = 'silly'
/**
*
* Apply Your Own ApiAi Developer API_KEY at:
* http://www.api.ai
*
* `7217d7bce18c4bcfbe04ba7bdfaf9c08` for Wechaty demo
*
*/
const
APIAI_API_KEY
=
'
7217d7bce18c4bcfbe04ba7bdfaf9c08
'
const
brainApiAi
=
ApiAi
(
APIAI_API_KEY
)
const
bot
=
new
Wechaty
({
head
:
false
})
console
.
log
(
`
Welcome to Tuling Wechaty Bot.
Api.AI Doc: https://docs.api.ai/v16/docs/get-started
Notice: This bot will only active in the group which name contains 'wechaty'.
/* if (m.group() && /Wechaty/i.test(m.group().name())) { */
Loading... please wait for QrCode Image Url and then scan to login.
`
)
bot
.
on
(
'
scan
'
,
({
url
,
code
})
=>
{
console
.
log
(
`[
${
code
}
]Scan qrcode in url to login:\n
${
url
}
`
)
})
request
.
on
(
'
error
'
,
function
(
error
)
{
console
.
log
(
error
)
.
on
(
'
login
'
,
user
=>
log
.
info
(
'
Bot
'
,
`bot login:
${
user
}
`
))
.
on
(
'
logout
'
,
e
=>
log
.
info
(
'
Bot
'
,
'
bot logout.
'
))
.
on
(
'
message
'
,
m
=>
{
co
(
function
*
()
{
const
msg
=
yield
m
.
ready
()
if
(
m
.
group
()
&&
/Wechaty/i
.
test
(
m
.
group
().
name
()))
{
log
.
info
(
'
Bot
'
,
'
talk: %s
'
,
msg
)
talk
(
m
)
}
else
{
log
.
info
(
'
Bot
'
,
'
recv: %s
'
,
msg
)
}
})
.
catch
(
e
=>
log
.
error
(
'
Bot
'
,
'
on message rejected: %s
'
,
e
))
})
request
.
end
()
bot
.
init
()
.
catch
(
e
=>
{
log
.
error
(
'
Bot
'
,
'
init() fail:
'
+
e
)
bot
.
quit
()
process
.
exit
(
-
1
)
})
class
Talker
extends
EventEmitter2
{
constructor
(
thinker
)
{
log
.
verbose
(
'
Talker()
'
)
super
()
this
.
thinker
=
thinker
this
.
obj
=
{
text
:
[]
,
time
:
[]
}
this
.
timer
=
null
}
save
(
text
)
{
log
.
verbose
(
'
Talker
'
,
'
save(%s)
'
,
text
)
this
.
obj
.
text
.
push
(
text
)
this
.
obj
.
time
.
push
(
Date
.
now
())
}
load
()
{
const
text
=
this
.
obj
.
text
.
join
(
'
,
'
)
log
.
verbose
(
'
Talker
'
,
'
load(%s)
'
,
text
)
this
.
obj
.
text
=
[]
this
.
obj
.
time
=
[]
return
text
}
updateTimer
(
delayTime
)
{
delayTime
=
delayTime
||
this
.
delayTime
()
log
.
verbose
(
'
Talker
'
,
'
updateTimer(%s)
'
,
delayTime
)
if
(
this
.
timer
)
{
clearTimeout
(
this
.
timer
)
}
this
.
timer
=
setTimeout
(
this
.
say
.
bind
(
this
),
delayTime
)
}
hear
(
text
)
{
log
.
verbose
(
'
Talker
'
,
`hear(
${
text
}
)`
)
this
.
save
(
text
)
this
.
updateTimer
()
}
say
()
{
log
.
verbose
(
'
Talker
'
,
'
say()
'
)
const
text
=
this
.
load
()
this
.
thinker
(
text
)
.
then
(
reply
=>
this
.
emit
(
'
say
'
,
reply
))
this
.
timer
=
null
}
delayTime
()
{
const
minDelayTime
=
5000
const
maxDelayTime
=
15000
const
delayTime
=
Math
.
floor
(
Math
.
random
()
*
(
maxDelayTime
-
minDelayTime
))
+
minDelayTime
return
delayTime
}
}
var
Talkers
=
[]
function
talk
(
m
)
{
const
fromId
=
m
.
from
().
id
const
groupId
=
m
.
group
().
id
const
content
=
m
.
content
()
const
talkerName
=
fromId
+
groupId
if
(
!
Talkers
[
talkerName
])
{
Talkers
[
talkerName
]
=
new
Talker
(
function
(
text
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
brainApiAi
.
textRequest
(
text
)
.
on
(
'
response
'
,
function
(
response
)
{
console
.
log
(
response
)
/*
{ id: 'a09381bb-8195-4139-b49c-a2d03ad5e014',
timestamp: '2016-05-27T17:22:46.597Z',
result:
{ source: 'domains',
resolvedQuery: 'hi',
action: 'smalltalk.greetings',
parameters: { simplified: 'hello' },
metadata: {},
fulfillment: { speech: 'Hi there.' },
score: 0 },
status: { code: 200, errorType: 'success' } }
*/
const
reply
=
response
.
result
.
fulfillment
.
speech
if
(
!
reply
)
{
log
.
info
(
'
ApiAi
'
,
`Talker do not want to talk for "
${
text
}
"`
)
return
reject
()
}
log
.
info
(
'
ApiAi
'
,
'
Talker reply:"%s" for "%s"
'
,
reply
,
text
)
return
resolve
(
reply
)
})
.
on
(
'
error
'
,
function
(
error
)
{
log
.
error
(
'
ApiAi
'
,
error
)
reject
(
error
)
})
.
end
()
})
})
Talkers
[
talkerName
].
on
(
'
say
'
,
reply
=>
bot
.
reply
(
m
,
reply
))
}
Talkers
[
talkerName
].
hear
(
content
)
}
example/tuling123-bot.js
浏览文件 @
bf595dbb
...
...
@@ -41,7 +41,7 @@ Loading...
`
)
bot
.
on
(
'
login
'
,
e
=>
log
.
info
(
'
Bot
'
,
'
bot login.
'
))
.
on
(
'
login
'
,
user
=>
log
.
info
(
'
Bot
'
,
`bot login:
${
user
}
`
))
.
on
(
'
logout
'
,
e
=>
log
.
info
(
'
Bot
'
,
'
bot logout.
'
))
.
on
(
'
scan
'
,
({
url
,
code
})
=>
{
console
.
log
(
`[
${
code
}
]Scan qrcode in url to login:\n
${
url
}
`
)
...
...
@@ -124,20 +124,20 @@ class Talker extends EventEmitter2 {
var
Talkers
=
[]
function
talk
(
m
)
{
const
fromId
=
m
.
from
().
id
const
groupId
=
m
.
group
().
id
const
content
=
m
.
content
()
const
talkerName
=
fromId
+
groupId
if
(
!
Talkers
[
talkerName
])
{
Talkers
[
talkerName
]
=
new
Talker
(
function
(
text
)
{
return
brain
.
ask
(
text
,
{
userid
:
talkerName
})
.
then
(
r
=>
{
log
.
info
(
'
Tuling123
'
,
'
Talker reply:"%s" for "%s"
'
,
r
.
text
,
text
)
return
r
.
text
})
const
fromId
=
m
.
from
().
id
const
groupId
=
m
.
group
().
id
const
content
=
m
.
content
()
const
talkerName
=
fromId
+
groupId
if
(
!
Talkers
[
talkerName
])
{
Talkers
[
talkerName
]
=
new
Talker
(
function
(
text
)
{
return
brain
.
ask
(
text
,
{
userid
:
talkerName
})
.
then
(
r
=>
{
log
.
info
(
'
Tuling123
'
,
'
Talker reply:"%s" for "%s"
'
,
r
.
text
,
text
)
return
r
.
text
})
Talkers
[
talkerName
].
on
(
'
say
'
,
reply
=>
bot
.
reply
(
m
,
reply
))
}
Talkers
[
talkerName
].
hear
(
content
)
})
Talkers
[
talkerName
].
on
(
'
say
'
,
reply
=>
bot
.
reply
(
m
,
reply
))
}
Talkers
[
talkerName
].
hear
(
content
)
}
src/contact.js
浏览文件 @
bf595dbb
...
...
@@ -30,6 +30,8 @@ class Contact {
,
province
:
rawObj
.
Province
,
city
:
rawObj
.
City
,
signature
:
rawObj
.
Signature
,
stranger
:
rawObj
.
stranger
// assign by injectio.js
}
}
name
()
{
return
this
.
obj
.
name
}
...
...
@@ -65,15 +67,17 @@ class Contact {
get
(
prop
)
{
return
this
.
obj
[
prop
]
}
send
(
message
)
{
}
static
find
()
{
}
static
findAll
()
{
send
(
message
)
{
const
msg
=
new
Contact
.
puppet
.
Message
()
// create a empty message
msg
.
set
(
'
from
'
,
this
)
msg
.
set
(
'
content
'
,
message
)
return
Contact
.
puppet
.
send
(
message
)
}
stranger
()
{
return
this
.
obj
.
stranger
}
static
find
()
{
}
static
findAll
()
{
}
}
Contact
.
init
=
function
()
{
Contact
.
pool
=
{}
}
...
...
src/puppet-web-bridge.js
浏览文件 @
bf595dbb
...
...
@@ -39,6 +39,7 @@ class Bridge {
getUserName
()
{
return
this
.
proxyWechaty
(
'
getUserName
'
)
}
getContact
(
id
)
{
// TODO: use retry-promise instead of waitData
return
this
.
waitData
(
r
=>
{
return
this
.
proxyWechaty
(
'
getContact
'
,
id
)
},
3000
)
...
...
@@ -49,6 +50,7 @@ class Bridge {
*
* @param {Function} pfunc
* @param {Number} timeout
*
* @TODO: change waitData to retry-promise
*/
waitData
(
pfunc
,
timeout
)
{
...
...
@@ -66,12 +68,10 @@ class Bridge {
}
else
if
(
totalTime
>
timeout
)
{
log
.
silly
(
'
Bridge
'
,
`waitData(
${
totalTime
}
/
${
timeout
}
) timeout`
)
return
resolve
()
}
else
{
log
.
silly
(
'
Bridge
'
,
`waitData(
${
totalTime
}
/
${
timeout
}
) retry`
)
totalTime
+=
waitTime
return
setTimeout
(
retry
,
waitTime
)
}
throw
new
Error
(
'
should not run to here
'
)
log
.
silly
(
'
Bridge
'
,
`waitData(
${
totalTime
}
/
${
timeout
}
) retry`
)
totalTime
+=
waitTime
return
setTimeout
(
retry
,
waitTime
)
})
}
catch
(
e
)
{
log
.
silly
(
'
Bridge
'
,
`waitData(
${
totalTime
}
/
${
timeout
}
) exception: %s`
,
e
)
...
...
@@ -148,5 +148,8 @@ ac = Wechaty.glue.contactFactory.getAllContacts();
Object.keys(ac).filter(function(k) { return /李/.test(ac[k].NickName) }).map(function(k) { var c = ac[k]; return {NickName: c.NickName, Alias: c.Alias, Uin: c.Uin, MMInChatRoom: c.MMInChatRoom} })
Object.keys(window._chatContent).filter(function (k) { return window._chatContent[k].length > 0 }).map(function (k) { return window._chatContent[k].map(function (v) {return v.MMDigestTime}) })
.web_wechat_tab_add
.web_wechat_tab_launch-chat
*
*/
\ No newline at end of file
src/puppet-web-injectio.js
浏览文件 @
bf595dbb
...
...
@@ -2,6 +2,8 @@
*
* Wechaty - Wechat for Bot, and human who talk to bot.
*
* Class PuppetWebInjectio
*
* Inject this js code to browser,
* in order to interactive with wechat web program.
*
...
...
@@ -9,6 +11,9 @@
* https://github.com/zixia/wechaty-lib
*
*/
/*global angular*/
if
(
typeof
Wechaty
!==
'
undefined
'
)
{
return
'
Wechaty already injected?
'
}
...
...
@@ -188,7 +193,9 @@ return (function(port) {
}
function
getContact
(
id
)
{
if
(
Wechaty
.
glue
.
contactFactory
)
{
return
Wechaty
.
glue
.
contactFactory
.
getContact
(
id
)
var
c
=
Wechaty
.
glue
.
contactFactory
.
getContact
(
id
)
c
.
stranger
=
!
(
c
.
isContact
())
return
c
}
log
(
'
contactFactory not inited
'
)
return
null
...
...
@@ -232,8 +239,8 @@ return (function(port) {
}
if
(
Wechaty
.
vars
.
eventsBuf
.
length
)
{
clog
(
'
Wechaty.vars.eventsBuf has
'
+
Wechaty
.
vars
.
eventsBuf
.
length
+
'
unsend events
'
)
var
eventData
while
(
eventData
=
Wechaty
.
vars
.
eventsBuf
.
pop
())
{
while
(
Wechaty
.
vars
.
eventsBuf
.
length
)
{
var
eventData
=
Wechaty
.
vars
.
eventsBuf
.
pop
()
Wechaty
.
vars
.
socket
.
emit
(
eventData
[
0
],
eventData
[
1
])
}
clog
(
'
Wechaty.vars.eventsBuf all sent
'
)
...
...
@@ -257,7 +264,7 @@ return (function(port) {
return
// wait to be called via script.onload()
}
// Wechaty global variable: socket
/
*global io*/
/
/ Wechaty global variable: socket
var
socket
=
Wechaty
.
vars
.
socket
=
io
.
connect
(
'
https://127.0.0.1:
'
+
port
)
// ding -> dong. for test & live check purpose
...
...
src/puppet-web-server.js
浏览文件 @
bf595dbb
/**
* Wechat for Bot. and for human who can talk with bot/robot
*
*
Interface
for puppet
*
Web Server
for puppet
*
* Class PuppetWebServer
*
* Licenst: ISC
* https://github.com/zixia/wechaty
*
...
...
src/puppet-web.js
浏览文件 @
bf595dbb
...
...
@@ -2,7 +2,8 @@
*
* wechaty: Wechat for Bot. and for human who talk to bot/robot
*
* Web Puppet
* Class PuppetWeb
*
* use to control wechat web.
*
* Licenst: ISC
...
...
src/puppet.js
浏览文件 @
bf595dbb
...
...
@@ -2,6 +2,8 @@
* Wechat for Bot. and for human who can talk with bot/robot
*
* Interface for puppet
*
* Class Puppet
*
* Licenst: ISC
* https://github.com/zixia/wechaty
...
...
src/wechaty.js
浏览文件 @
bf595dbb
...
...
@@ -2,10 +2,13 @@
*
* wechaty: Wechat for Bot. and for human who talk to bot/robot
*
* Class Wechaty
*
* Licenst: ISC
* https://github.com/zixia/wechaty
*
*/
const
log
=
require
(
'
npmlog
'
)
const
EventEmitter
=
require
(
'
events
'
)
...
...
@@ -87,4 +90,7 @@ Object.assign(Wechaty, {
,
Group
:
Group
})
module
.
exports
=
Wechaty
/**
* Expose `Wechaty`.
*/
module
.
exports
=
Wechaty
[
'
default
'
]
=
Wechaty
.
Wechaty
=
Wechaty
\ No newline at end of file
test/webdriver-spec.js
浏览文件 @
bf595dbb
'
use strict
'
const
path
=
require
(
'
path
'
)
const
co
=
require
(
'
co
'
)
const
test
=
require
(
'
tap
'
).
test
...
...
@@ -64,7 +66,7 @@ test('WebDriver process create & quit test', function(t) {
})
// XXX WTF with co module???
false
&&
test
(
'
WebDriver smoke testing
'
,
function
(
t
)
{
test
(
'
WebDriver smoke testing
'
,
function
(
t
)
{
const
wb
=
new
PuppetWebBrowser
()
t
.
ok
(
wb
,
'
Browser instnace
'
)
...
...
@@ -122,6 +124,7 @@ test('WebDriver WTF testing', function(t) {
t
.
ok
(
bridge
,
'
Bridge instnace
'
)
var
driver
// for help function `execute`
var
injectio
driverProcessNum
()
.
then
(
n
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录