Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wechaty
wechaty
提交
632b1f42
W
wechaty
项目概览
wechaty
/
wechaty
上一次同步 3 年多
通知
306
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,发现更多精彩内容 >>
提交
632b1f42
编写于
5月 06, 2016
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
half work, for echo bot
上级
a272e85c
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
579 addition
and
422 deletion
+579
-422
.gitignore
.gitignore
+1
-0
lib/contact.js
lib/contact.js
+12
-3
lib/message.js
lib/message.js
+34
-6
lib/puppet-web-browser.js
lib/puppet-web-browser.js
+86
-0
lib/puppet-web-injectio.js
lib/puppet-web-injectio.js
+56
-31
lib/puppet-web-server.js
lib/puppet-web-server.js
+217
-0
lib/puppet-web.js
lib/puppet-web.js
+36
-300
lib/puppet.js
lib/puppet.js
+40
-20
lib/wechaty.js
lib/wechaty.js
+22
-28
tests/message-tests.js
tests/message-tests.js
+37
-0
tests/puppet-web-browser-tests.js
tests/puppet-web-browser-tests.js
+5
-8
tests/puppet-web-server-tests.js
tests/puppet-web-server-tests.js
+33
-26
未找到文件。
.gitignore
浏览文件 @
632b1f42
...
@@ -38,3 +38,4 @@ t.js
...
@@ -38,3 +38,4 @@ t.js
t
t
socket.io.min.js
socket.io.min.js
.*.swp
lib/contact.js
浏览文件 @
632b1f42
class
Contact
{
class
Contact
{
constructor
()
{
constructor
(
id
)
{
this
.
id
=
id
}
getId
()
{
return
this
.
id
}
send
(
message
)
{
}
}
find
()
{
static
find
()
{
}
}
findAll
()
{
static
findAll
()
{
}
}
}
}
...
...
lib/message.js
浏览文件 @
632b1f42
const
EventEmitter
=
require
(
'
events
'
)
//
const EventEmitter = require('events')
class
Message
extends
EventEmitter
{
class
Message
{
constructor
()
{
constructor
(
rawObj
)
{
super
()
this
.
rawObj
=
rawObj
// Transform rawObj to local m
this
.
m
=
{
id
:
rawObj
.
MsgId
,
from
:
rawObj
.
FromUserName
,
type
:
rawObj
.
MsgType
,
content
:
rawObj
.
Content
,
status
:
rawObj
.
Status
,
digest
:
rawObj
.
MMDigest
,
to
:
rawObj
.
MMPeerUserName
,
actual_content
:
rawObj
.
MMActualContent
,
group
:
rawObj
.
MMIsChatRoom
?
rawObj
.
ToUserName
:
null
,
date
:
new
Date
(
rawObj
.
MMDisplayTime
*
1000
)
}
}
get
(
prop
)
{
if
(
!
prop
||
!
(
prop
in
this
.
m
))
{
const
s
=
'
[
'
+
Object
.
keys
(
this
.
m
).
join
(
'
,
'
)
+
'
]
'
throw
new
Error
(
`Message.get(
${
prop
}
) must be in:
${
s
}
`
)
}
return
this
.
m
[
prop
]
}
}
find
()
{
static
find
(
selector
,
option
)
{
return
new
Message
({
MsgId
:
'
-1
'
})
}
}
findAll
()
{
static
findAll
(
selector
,
option
)
{
return
[
new
Message
({
MsgId
:
'
-2
'
})
,
new
Message
({
MsgId
:
'
-3
'
})
]
}
}
}
}
...
...
lib/puppet-web-browser.js
0 → 100755
浏览文件 @
632b1f42
/****************************************
*
* Class Browser
*
header cookie
BaseRequest
Uin
Sid
Skey
DeviceId
***************************************/
const
fs
=
require
(
'
fs
'
)
const
path
=
require
(
'
path
'
)
const
WebDriver
=
require
(
'
selenium-webdriver
'
)
class
Browser
{
constructor
(
browser
,
port
)
{
this
.
browser
=
browser
||
'
chrome
'
this
.
port
=
port
||
8788
}
toString
()
{
return
`Class Wechaty.Puppet.Browser(
${
this
.
browser
}
,
${
this
.
port
}
)`
}
init
()
{
return
this
.
open
()
.
then
(
this
.
inject
.
bind
(
this
))
}
open
()
{
const
WX_URL
=
'
https://wx.qq.com
'
console
.
error
(
`browser init
${
this
.
browser
}
:
${
this
.
port
}
`
)
this
.
driver
=
new
WebDriver
.
Builder
().
forBrowser
(
this
.
browser
).
build
()
return
this
.
driver
.
get
(
WX_URL
)
}
inject
()
{
const
injectio
=
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
puppet-web-injectio.js
'
)
,
'
utf8
'
)
const
socketio
=
fs
.
readFileSync
(
// 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js'
path
.
join
(
path
.
dirname
(
__filename
),
'
/socket.io.min.js
'
)
,
'
utf8
'
)
console
.
error
(
'
injecting
'
)
return
this
.
execute
(
socketio
)
.
then
(()
=>
{
console
.
error
(
'
injected socketio
'
)
this
.
execute
(
injectio
,
this
.
port
)
})
.
then
(()
=>
{
console
.
error
(
'
injected injectio
'
)
return
this
.
execute
(
'
return Wechaty()
'
)
})
.
then
(()
=>
{
console
.
error
(
'
injected Wechaty()
'
)
return
new
Promise
((
resolve
,
reject
)
=>
resolve
())
})
}
quit
()
{
// console.error('Browser.quit')
if
(
this
.
driver
)
{
console
.
error
(
'
Browser.driver.quit
'
)
// this.driver.quit()
delete
this
.
driver
}
}
execute
(
script
,
...
args
)
{
// console.error(`Browser.execute(${script})`)
if
(
!
this
.
driver
)
throw
new
Error
(
'
driver not found
'
)
// a promise
return
this
.
driver
.
executeScript
(
script
,
args
)
}
}
module
.
exports
=
Browser
\ No newline at end of file
lib/puppet-web-injectio.js
浏览文件 @
632b1f42
...
@@ -22,54 +22,73 @@
...
@@ -22,54 +22,73 @@
;(
function
(
port
)
{
;(
function
(
port
)
{
port
=
port
||
8788
port
=
port
||
8788
/**
*
* Get All I Need from Browser
*
*/
var
injector
=
angular
.
element
(
document
).
injector
()
var
rootScope
=
injector
.
get
(
"
$rootScope
"
)
var
http
=
injector
.
get
(
"
$http
"
)
var
chatFactory
=
injector
.
get
(
"
chatFactory
"
)
var
Wechaty
=
{
var
confFactory
=
injector
.
get
(
"
confFactory
"
)
// get all we need from browser(angularjs)
glue
:
{
injector
:
angular
.
element
(
document
).
injector
()
,
rootScope
:
injector
.
get
(
"
$rootScope
"
)
,
http
:
injector
.
get
(
"
$http
"
)
,
chatFactory
:
injector
.
get
(
"
chatFactory
"
)
,
confFactory
:
injector
.
get
(
"
confFactory
"
)
,
loginScope
:
angular
.
element
(
"
.login_box
"
).
scope
()
}
// variables
,
var
{
socket
:
socket
}
// methods
,
func
{
,
init
:
init
,
send
:
send
,
zlog
:
zlog
,
log
:
log
var
loginScope
=
angular
.
element
(
"
.login_box
"
).
scope
()
,
log
:
function
(
msg
)
{
socket
&&
socket
.
emit
(
'
log
'
,
msg
)
}
,
ping
:
function
()
{
return
'
pong
'
}
,
getLoginStatusCode
:
function
()
{
return
loginScope
.
code
}
,
getLoginQrImgUrl
:
function
()
{
return
loginScope
.
qrcodeUrl
}
,
isLogined
:
function
()
{
return
200
===
loginScope
.
code
}
,
isReady
:
function
()
{
return
!!
(
angular
&&
angular
.
element
&&
angular
.
element
(
"
body
"
))
}
,
initSocket
:
initSocket
}
}
var
Wechaty
=
function
()
{
function
send
(
ToUserName
,
Content
)
{
var
m
=
chatFactory
.
createMessage
({
ToUserName
:
ToUserName
,
Content
:
Content
})
chatFactory
.
appendMessage
(
m
)
return
chatFactory
.
sendMessage
(
m
)
}
function
init
()
{
initZlog
()
initZlog
()
zlog
(
'
wechaty port
'
+
port
)
zlog
(
'
wechaty port
'
+
port
)
/**
initSocket
()
// save to socket
* socket might be destroyed(reconnected)
*/
var
socket
initSocket
()
hookUnload
()
hookUnload
()
hookMessage
()
hookMessage
()
zlog
(
'
Wechaty injected!. ;-D
'
)
zlog
(
'
Wechaty injected!. ;-D
'
)
}
}
angular
.
extend
(
Wechaty
,
{
angular
.
extend
(
Wechaty
,
{
getLoginStatusCode
:
function
()
{
return
loginScope
.
code
}
,
getLoginQrImgUrl
:
function
()
{
return
loginScope
.
qrcodeUrl
}
,
isLogined
:
function
()
{
return
200
===
loginScope
.
code
}
,
isReady
:
function
()
{
return
!!
(
angular
&&
angular
.
element
&&
angular
.
element
(
"
body
"
))
}
,
log
:
function
(
msg
)
{
SOCKET
&&
SOCKET
.
emit
(
'
log
'
,
msg
)
}
,
ping
:
function
()
{
return
'
pong
'
}
})
})
function
initZlog
()
{
function
initZlog
()
{
var
enable
=
true
var
enable
=
true
if
(
enable
)
{
if
(
enable
)
{
if
(
console
)
if
(
!
console
.
memory
&&
console
.
time
)
{
// wechat debuger exist
delete
console
.
log
delete
console
delete
console
}
console
.
zlog
=
window
.
console
.
log
console
.
zlog
=
window
.
console
.
log
window
.
zlog
=
function
(
s
)
{
return
console
.
zlog
(
s
)
}
window
.
zlog
=
function
(
s
)
{
return
console
.
zlog
(
s
)
}
console
.
log
=
function
()
{}
console
.
log
=
function
()
{}
...
@@ -93,11 +112,11 @@
...
@@ -93,11 +112,11 @@
function
initSocket
()
{
function
initSocket
()
{
// Wechaty global variable: socket
// Wechaty global variable: socket
socket
=
io
.
connect
(
'
https://127.0.0.1:
'
+
port
)
Wechaty
.
socket
=
io
.
connect
(
'
https://127.0.0.1:
'
+
port
)
zlog
(
'
socket:
'
+
socket
)
zlog
(
'
socket:
'
+
socket
)
socket
.
on
(
'
connect
'
,
function
()
{
Wechaty
.
socket
.
on
(
'
connect
'
,
function
()
{
zlog
(
'
on connect entried
'
)
zlog
(
'
on connect entried
'
)
rootScope
.
$on
(
"
message:add:success
"
,
function
(
event
,
data
)
{
rootScope
.
$on
(
"
message:add:success
"
,
function
(
event
,
data
)
{
...
@@ -106,11 +125,17 @@
...
@@ -106,11 +125,17 @@
socket
.
on
(
'
disconnect
'
,
function
(
e
)
{
socket
.
on
(
'
disconnect
'
,
function
(
e
)
{
zlog
(
'
event: socket disconnect
'
)
zlog
(
'
event: socket disconnect
'
)
socket
.
emit
(
'
disconnect
'
,
e
)
//
socket.emit('disconnect', e)
// Reconnect...
// Reconnect...
setTimeout
(
initSocket
,
1000
)
setTimeout
(
initSocket
,
1000
)
})
})
// for test & live check purpose: ping -> pong
socket
.
on
(
'
ping
'
,
function
(
e
)
{
zlog
(
'
received socket io event: ping. emit pong...
'
)
socket
.
emit
(
'
pong
'
,
'
pong
'
)
})
})
})
}
}
...
...
lib/puppet-web-server.js
0 → 100755
浏览文件 @
632b1f42
const
Browser
=
require
(
'
./puppet-web-browser
'
)
/****************************************
*
* Class Server
*
***************************************/
const
fs
=
require
(
'
fs
'
)
const
io
=
require
(
'
socket.io
'
)
const
path
=
require
(
'
path
'
)
const
https
=
require
(
'
https
'
)
const
bodyParser
=
require
(
'
body-parser
'
)
const
Express
=
require
(
'
express
'
)
const
EventEmitter
=
require
(
'
events
'
)
class
Server
extends
EventEmitter
{
constructor
(
port
)
{
super
()
this
.
port
=
port
||
8788
// W(87) X(88), ascii char code ;-]
this
.
logined
=
false
this
.
on
(
'
login
'
,
()
=>
this
.
logined
=
true
)
this
.
on
(
'
logout
'
,
()
=>
this
.
logined
=
false
)
}
init
()
{
this
.
express
=
this
.
createExpress
()
this
.
server
=
this
.
createHttpsServer
(
this
.
express
,
this
.
port
)
this
.
socketio
=
this
.
createSocketIo
(
this
.
server
)
this
.
browser
=
this
.
createBrowser
()
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
browser
.
init
()
.
then
(()
=>
{
console
.
error
(
'
browser init finished with port:
'
+
this
.
port
+
'
.
'
)
resolve
()
// after init success
})
})
}
createBrowser
()
{
const
b
=
new
Browser
(
'
chrome
'
,
this
.
port
)
/**
* `unload` event is sent from js@browser to webserver via socketio
* after received `unload`, we re-inject the Wechaty js code into browser.
*/
this
.
on
(
'
unload
'
,
()
=>
{
console
.
error
(
'
server received unload event
'
)
this
.
browser
.
inject
()
.
then
(()
=>
console
.
error
(
'
re-injected
'
))
})
return
b
}
/**
*
* Https Server
*
*/
createHttpsServer
(
express
,
port
)
{
port
=
port
||
this
.
port
// http://blog.mgechev.com/2014/02/19/create-https-tls-ssl-application-with-express-nodejs/
// openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
// openssl rsa -in key.pem -out newkey.pem && mv newkey.pem key.pem
return
https
.
createServer
({
key
:
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
key.pem
'
)),
cert
:
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
cert.pem
'
))
},
express
).
listen
(
port
,
()
=>
{
console
.
error
(
`createHttpsServer listening on port
${
port
}
!`
)
})
}
/**
*
* Express Middleware
*
*/
createExpress
()
{
const
app
=
new
Express
()
app
.
use
(
bodyParser
.
json
())
app
.
use
(
function
(
req
,
res
,
next
)
{
res
.
header
(
"
Access-Control-Allow-Origin
"
,
"
*
"
)
res
.
header
(
"
Access-Control-Allow-Headers
"
,
"
Origin, X-Requested-With, Content-Type, Accept
"
)
next
()
})
app
.
get
(
'
/ping
'
,
function
(
req
,
res
)
{
console
.
error
(
new
Date
()
+
'
GET /ping
'
)
res
.
send
(
'
pong
'
)
})
// app.post('/', function (req, res) {
// console.log('post ' + new Date())
// console.log(req.body)
// res.send(req.body)
// })
return
app
}
/**
*
* Socket IO
*
*/
createSocketIo
(
server
)
{
const
socketServer
=
io
.
listen
(
server
,
{
log
:
true
})
socketServer
.
sockets
.
on
(
'
connection
'
,
(
s
)
=>
{
console
.
log
(
'
socket.on connection entried
'
)
// save to instance: socketClient
this
.
socketClient
=
s
s
.
on
(
'
disconnect
'
,
function
()
{
console
.
error
(
'
socket.io disconnected
'
)
/**
* Possible conditions:
* 1. Browser reload
* 2. Lost connection(Bad network
* 3.
*/
this
.
socketClient
=
null
})
// Events from Wechaty@Broswer --to--> Server
const
events
=
[
'
message
'
,
'
login
'
,
'
logout
'
,
'
unload
'
]
events
.
map
(
e
=>
{
s
.
on
(
e
,
data
=>
{
console
.
log
(
`recv event[
${
e
}
] from browser`
)
this
.
emit
(
e
,
data
)
})
})
/**
* prevent lost event: buffer new event received when socket disconnected
while (buff.length) {
let e = buff.shift()
socket.emit(e.event, e.data)
}
*/
})
return
socketServer
}
isLogined
()
{
return
this
.
logined
}
quit
()
{
if
(
this
.
browser
)
{
this
.
browser
.
quit
()
delete
this
.
browser
}
if
(
this
.
socketClient
)
{
this
.
socketClient
.
disconnect
(
0
)
delete
this
.
socketClient
}
if
(
this
.
socketServer
)
{
socketServer
.
httpsServer
.
close
()
socketServer
.
close
()
delete
this
.
socketServer
}
if
(
this
.
server
)
{
this
.
server
.
close
()
delete
this
.
server
}
}
/**
*
* Proxy Call to Wechaty in Browser
*
*/
browserExecute
(
script
)
{
if
(
!
this
.
browser
)
throw
new
Error
(
'
no browser!
'
)
return
this
.
browser
.
execute
(
script
)
}
proxyWechaty
(
wechatyFunc
)
{
const
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
)
const
argsJson
=
JSON
.
stringify
(
args
)
const
wechatyScript
=
`return (Wechaty && Wechaty.
${
wechatyFunc
}
.apply(undefined, JSON.parse('
${
argsJson
}
')))`
console
.
error
(
'
proxyWechaty:
'
+
wechatyScript
)
return
this
.
browserExecute
(
wechatyScript
)
}
Wechaty_getLoginStatusCode
()
{
return
this
.
proxyWechaty
(
'
getLoginStatusCode
'
)
}
Wechaty_getLoginQrImgUrl
()
{
return
this
.
proxyWechaty
(
'
getLoginQrImgUrl
'
)
}
// Wechaty_CARPEDIEM() { return this.proxyWechaty('call') }
debugLoop
()
{
this
.
Wechaty_getLoginStatusCode
().
then
((
c
)
=>
{
console
.
error
(
`login status code:
${
c
}
`
)
setTimeout
(
this
.
debugLoop
.
bind
(
this
),
3000
)
})
}
}
module
.
exports
=
Server
lib/puppet-web.js
浏览文件 @
632b1f42
/**
/**
*
*
* wechaty-lib
- Robot API/SDK Library for Personal WeChat(微信) Accoun
t
* wechaty-lib
: Wechat for Bot. and for human who can talk with bot/robo
t
*
*
* Web Soul of Puppet
* Web Soul of Puppet
* use to control wechat web.
* use to control wechat web.
...
@@ -16,15 +16,18 @@
...
@@ -16,15 +16,18 @@
* Class PuppetWeb
* Class PuppetWeb
*
*
***************************************/
***************************************/
const
EventEmitter
=
require
(
'
events
'
)
const
Puppet
=
require
(
'
./puppet
'
)
class
PuppetWeb
extends
EventEmitter
{
const
WebServer
=
require
(
'
./puppet-web-server
'
)
class
PuppetWeb
extends
Puppet
{
constructor
(
port
)
{
constructor
(
port
)
{
super
()
super
()
const
PORT
=
8788
// W(87) X(88), ascii char code ;-]
this
.
port
=
port
||
8788
// W(87) X(88), ascii char code ;-]
}
this
.
port
=
port
||
PORT
init
()
{
const
server
=
this
.
server
=
new
WebServer
(
this
.
port
)
this
.
server
=
new
WebServer
(
this
.
port
)
const
EVENTS_IN
=
[
const
EVENTS_IN
=
[
'
message
'
'
message
'
...
@@ -32,17 +35,37 @@ class PuppetWeb extends EventEmitter {
...
@@ -32,17 +35,37 @@ class PuppetWeb extends EventEmitter {
,
'
logout
'
,
'
logout
'
]
]
EVENTS_IN
.
map
(
event
=>
EVENTS_IN
.
map
(
event
=>
server
.
on
(
event
,
data
=>
this
.
emit
(
event
,
data
)
)
this
.
server
.
on
(
event
,
data
=>
this
.
emit
(
event
,
data
)
)
)
)
const
p
=
new
Promise
((
resolve
,
reject
)
=>
{
this
.
server
.
init
(
this
.
port
)
})
const
EVENTS_OUT
=
[
return
p
'
sent
'
]
EVENTS_OUT
.
map
(
event
=>
this
.
on
(
event
,
data
=>
server
.
emit
(
event
,
data
)
)
)
}
}
send
(
message
)
{
if
(
!
this
.
browser
)
throw
new
Error
(
'
browser not exist!
'
);
const
ToUserName
=
message
.
get
(
'
to
'
)
const
Content
=
message
.
get
(
'
content
'
)
const
script
=
`return Wechaty.send('
${
ToUserName
}
', '
${
Content
}
')`
return
this
.
browser
.
execte
(
script
)
}
logout
()
{
if
(
!
this
.
browser
)
throw
new
Error
(
'
browser not exist!
'
);
return
this
.
browser
.
execte
(
'
return Wechaty.logout()
'
)
}
/*
sendByServer(message) {
this.server.send(message)
}
*/
/**
/**
*
*
* Interface Methods
* Interface Methods
...
@@ -65,291 +88,4 @@ class PuppetWeb extends EventEmitter {
...
@@ -65,291 +88,4 @@ class PuppetWeb extends EventEmitter {
getLoginStatusCode
()
{
return
this
.
server
.
Wechaty_getLoginStatusCode
()
}
getLoginStatusCode
()
{
return
this
.
server
.
Wechaty_getLoginStatusCode
()
}
}
}
/****************************************
*
* Class WebServer
*
*
*
*
*
*
*
***************************************/
const
fs
=
require
(
'
fs
'
)
const
io
=
require
(
'
socket.io
'
)
const
https
=
require
(
'
https
'
)
const
bodyParser
=
require
(
'
body-parser
'
)
const
Express
=
require
(
'
express
'
)
class
WebServer
extends
EventEmitter
{
constructor
()
{
super
()
/**
* io events proxy between server & browser
*/
this
.
EVENTS_IN
=
[
'
message
'
,
'
login
'
,
'
logout
'
,
'
unload
'
]
this
.
EVENTS_OUT
=
[
'
send
'
,
'
logout
'
]
this
.
logined
=
false
this
.
on
(
'
login
'
,
()
=>
this
.
logined
=
true
)
this
.
on
(
'
logout
'
,
()
=>
this
.
logined
=
false
)
}
init
(
port
)
{
this
.
port
=
port
||
8788
this
.
express
=
this
.
initExpress
()
this
.
server
=
this
.
initHttpsServer
(
this
.
express
,
this
.
port
)
this
.
socketio
=
this
.
initSocketIo
(
this
.
server
)
this
.
browser
=
new
WebBrowser
()
this
.
browser
.
init
(
this
.
port
)
.
then
(()
=>
{
console
.
error
(
'
browser init finished with port:
'
+
this
.
port
+
'
.
'
)
this
.
on
(
'
unload
'
,
()
=>
{
console
.
error
(
'
webserver received unload event
'
)
this
.
browser
.
inject
()
.
then
(()
=>
console
.
error
(
'
re-injected
'
))
})
})
// this.debugLoop()
}
/**
*
* Https Server
*
*/
initHttpsServer
(
express
,
port
)
{
port
=
port
||
this
.
port
// http://blog.mgechev.com/2014/02/19/create-https-tls-ssl-application-with-express-nodejs/
// openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
// openssl rsa -in key.pem -out newkey.pem && mv newkey.pem key.pem
return
https
.
createServer
({
key
:
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
key.pem
'
)),
cert
:
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
cert.pem
'
))
},
express
).
listen
(
port
,
()
=>
{
console
.
error
(
`initHttpsServer listening on port
${
port
}
!`
)
})
}
/**
*
* Express Middleware
*
*/
initExpress
()
{
const
app
=
new
Express
()
app
.
use
(
bodyParser
.
json
())
app
.
use
(
function
(
req
,
res
,
next
)
{
res
.
header
(
"
Access-Control-Allow-Origin
"
,
"
*
"
)
res
.
header
(
"
Access-Control-Allow-Headers
"
,
"
Origin, X-Requested-With, Content-Type, Accept
"
)
next
()
})
app
.
get
(
'
/ping
'
,
function
(
req
,
res
)
{
console
.
error
(
new
Date
()
+
'
GET /ping
'
)
res
.
send
(
'
pong
'
)
})
// app.post('/', function (req, res) {
// console.log('post ' + new Date())
// console.log(req.body)
// res.send(req.body)
// })
return
app
}
/**
*
* Socket IO
*
*/
initSocketIo
(
server
)
{
const
ioServer
=
io
.
listen
(
server
,
{
log
:
true
})
ioServer
.
sockets
.
on
(
'
connection
'
,
(
s
)
=>
{
console
.
log
(
'
socket.on connection entried
'
)
let
socket
=
s
socket
.
on
(
'
disconnect
'
,
function
()
{
console
.
error
(
'
socket.io disconnected
'
)
/**
* Possible conditions:
* 1. Browser reload
* 2. Lost connection(Bad network
* 3.
*/
socket
=
null
})
this
.
EVENTS_IN
.
map
(
event
=>
{
// Events from Wechaty@Broswer --to--> Server
socket
.
on
(
event
,
data
=>
{
console
.
log
(
`recv event[
${
event
}
] from browser`
)
this
.
emit
(
event
,
data
)
})
})
this
.
EVENTS_OUT
.
map
(
event
=>
{
// Event from Server --to--> Wechaty@Browser
this
.
on
(
event
,
data
=>
{
console
.
log
(
`sent even[
${
event
}
] to browser`
)
socket
.
emit
(
event
,
data
)
})
})
/**
* prevent lost event: buffer new event received when socket disconnected
while (buff.length) {
let e = buff.shift()
socket.emit(e.event, e.data)
}
*/
})
return
ioServer
}
isLogined
()
{
return
this
.
logined
}
quit
()
{
if
(
this
.
browser
)
{
this
.
browser
.
quit
()
delete
this
.
browser
}
if
(
this
.
server
)
{
// TODO: close server
console
.
log
(
'
todo: close & quite server
'
)
}
}
/**
*
* Proxy Call to Wechaty in Browser
*
*/
browserExecute
(
script
)
{
if
(
!
this
.
browser
)
throw
new
Error
(
'
no browser!
'
)
return
this
.
browser
.
execute
(
script
)
}
proxyWechaty
(
wechatyFunc
)
{
const
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
)
const
argsJson
=
JSON
.
stringify
(
args
)
const
wechatyScript
=
`return (Wechaty && Wechaty.
${
wechatyFunc
}
.apply(undefined, JSON.parse('
${
argsJson
}
')))`
console
.
error
(
'
proxyWechaty:
'
+
wechatyScript
)
return
this
.
browserExecute
(
wechatyScript
)
}
Wechaty_getLoginStatusCode
()
{
return
this
.
proxyWechaty
(
'
getLoginStatusCode
'
)
}
Wechaty_getLoginQrImgUrl
()
{
return
this
.
proxyWechaty
(
'
getLoginQrImgUrl
'
)
}
// Wechaty_CARPEDIEM() { return this.proxyWechaty('call') }
debugLoop
()
{
this
.
Wechaty_getLoginStatusCode
().
then
((
c
)
=>
{
console
.
error
(
`login status code:
${
c
}
`
)
setTimeout
(
this
.
debugLoop
.
bind
(
this
),
3000
)
})
}
}
/*
*/
/****************************************
*
* Class WebBrowser
*
***************************************/
const
path
=
require
(
'
path
'
)
const
WebDriver
=
require
(
'
selenium-webdriver
'
)
class
WebBrowser
{
constructor
(
browser
)
{
const
BROWSER
=
this
.
BROWSER
=
browser
||
'
chrome
'
const
driver
=
this
.
driver
=
new
WebDriver
.
Builder
().
forBrowser
(
BROWSER
).
build
()
}
init
(
port
)
{
console
.
log
(
`browser inititializing... port:
${
port
}
`
)
this
.
port
=
port
||
8788
return
this
.
open
().
then
(
this
.
inject
.
bind
(
this
))
}
open
()
{
const
WX_URL
=
'
https://wx.qq.com
'
return
this
.
driver
.
get
(
WX_URL
)
// open wechat web page
// return this.driver.wait(() => {
// return this.driver.isElementPresent(WebDriver.By.css('div.login_box'))
// }, 60*1000, '\nFailed to wait div.login_box')
}
inject
()
{
const
injectio
=
fs
.
readFileSync
(
path
.
join
(
path
.
dirname
(
__filename
),
'
puppet-web-injectio.js
'
)
,
'
utf8
'
)
const
socketio
=
fs
.
readFileSync
(
// 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js'
path
.
join
(
path
.
dirname
(
__filename
),
'
/socket.io.min.js
'
)
,
'
utf8
'
)
console
.
error
(
'
injecting
'
)
return
this
.
execute
(
socketio
)
.
then
(()
=>
this
.
execute
(
injectio
,
this
.
port
))
.
then
(()
=>
this
.
execute
(
'
Wechaty()
'
))
.
then
(()
=>
console
.
error
(
'
injected
'
))
}
quit
()
{
if
(
this
.
driver
)
{
this
.
driver
.
quit
()
delete
this
.
driver
}
}
execute
(
script
,
...
args
)
{
if
(
!
this
.
driver
)
throw
new
Error
(
'
driver not found
'
)
// a promise
return
this
.
driver
.
executeScript
(
script
,
args
)
}
}
PuppetWeb
.
WebServer
=
WebServer
PuppetWeb
.
WebBrowser
=
WebBrowser
module
.
exports
=
PuppetWeb
module
.
exports
=
PuppetWeb
lib/puppet.js
浏览文件 @
632b1f42
/**
* Wechat for Bot. and for human who can talk with bot/robot
*
* Interface for puppet
*
*/
const
EventEmitter
=
require
(
'
events
'
)
const
EventEmitter
=
require
(
'
events
'
)
class
Puppet
extends
EventEmitter
{
class
Puppet
extends
EventEmitter
{
...
@@ -5,28 +12,41 @@ class Puppet extends EventEmitter {
...
@@ -5,28 +12,41 @@ class Puppet extends EventEmitter {
super
()
super
()
}
}
currentUser
()
{
/**
return
'
zixia
'
* Get current logined user
}
* @return <Contact>
*/
attach
(
soul
)
{
currentUser
()
{
throw
new
Error
(
'
To Be Implemented
'
)
}
if
(
this
.
soul
)
throw
new
Error
(
'
already a soul inside, detach it first!
'
)
if
(
!
soul
.
alive
())
throw
new
Error
(
'
soul is not alive!
'
)
/**
* let puppet send message
this
.
soul
=
soul
*
this
.
soul
.
on
(
'
message
'
,
data
=>
{
this
.
emit
(
'
message
'
,
data
)
})
* @param <Message> message - the message to be sent
* @return <Promise>
*/
send
(
message
)
{
throw
new
Error
(
'
To Be Implemented
'
)
}
logout
()
{
throw
new
Error
(
'
To Be Implementsd
'
)
}
alive
()
{
throw
new
Error
(
'
To Be Implementsd
'
)
}
// () { throw new Error('To Be Implemented') }
/**
*
* Events .on(...)
*
* login -
* logout -
*
*
*/
debug
(
cb
)
{
// List of all events
[
'
message
'
// event data should carry a instance of Message
,
'
login
'
,
'
logout
'
].
map
(
e
=>
{
this
.
on
(
e
,
cb
)
})
}
}
detach
()
{
if
(
!
this
.
soul
)
throw
new
Error
(
'
there is no soul inside to detach!
'
)
this
.
soul
.
destroy
()
delete
this
.
soul
}
}
Puppet
.
Soul
=
{
Web
:
require
(
'
./puppet-web
'
)
}
}
module
.
exports
=
Puppet
module
.
exports
=
Puppet
...
...
lib/wechaty.js
浏览文件 @
632b1f42
'
use strict
'
const
EventEmitter
=
require
(
'
events
'
)
/
* jshint node:true, unused:true */
/
/const Util = require('util');
const
EventEmitter
=
require
(
'
events
'
);
const
Util
=
require
(
'
util
'
);
var
Puppet
=
require
(
'
./puppet
'
)
const
Puppet
=
require
(
'
./puppet
'
)
var
Contact
=
require
(
'
./contact
'
)
const
PuppetWeb
=
require
(
'
./puppet-web
'
)
var
Group
=
require
(
'
./group
'
)
var
Message
=
require
(
'
./message
'
)
const
Message
=
require
(
'
./message
'
)
const
Contact
=
require
(
'
./contact
'
)
const
Group
=
require
(
'
./group
'
)
class
Wechaty
extends
EventEmitter
{
class
Wechaty
extends
EventEmitter
{
// cookie,Uin, Sid,SKey
// cookie,Uin, Sid,SKey
constructor
(
opts
)
{
constructor
()
{
super
()
super
()
this
.
puppet
=
new
Puppet
(
opts
)
this
.
puppet
=
new
Puppet
.
Web
()
/*
this.contact = new Contact(this.puppet)
this.contact = new Contact(this.puppet)
this.group = new Group(this.puppet)
this.group = new Group(this.puppet)
this.message = new Message(this.puppet)
this.message = new Message(this.puppet)
*/
this
.
puppet
.
on
(
'
message
'
,
(
e
)
=>
{
this
.
puppet
.
on
(
'
message
'
,
(
e
)
=>
{
this
.
emit
(
'
message
'
,
e
)
this
.
emit
(
'
message
'
,
e
)
...
@@ -29,27 +31,19 @@ class Wechaty extends EventEmitter {
...
@@ -29,27 +31,19 @@ class Wechaty extends EventEmitter {
})
})
}
}
currentUser
()
{
init
()
{
return
this
.
puppet
.
init
()
}
return
this
.
puppet
.
currentUser
()
currentUser
()
{
return
this
.
puppet
.
currentUser
()
}
}
send
(
message
)
{
return
this
.
puppet
.
send
(
message
)
}
test1
()
{
console
.
log
(
'
inst echo...
'
)
}
static
test
()
{
console
.
log
(
'
stat echo...
'
)
}
}
}
/*
Puppet
.
Web
=
PuppetWeb
header cookie
BaseRequest
Object
.
assign
(
Wechaty
,
{
Uin
Puppet
:
Puppet
Sid
,
Message
:
Message
Skey
,
Contact
:
Contact
DeviceId
,
Group
:
Group
*/
})
module
.
exports
=
Wechaty
module
.
exports
=
Wechaty
tests/message-tests.js
0 → 100644
浏览文件 @
632b1f42
const
test
=
require
(
'
tape
'
)
const
Message
=
require
(
'
../lib/message
'
)
test
(
'
Message constructor parser test
'
,
t
=>
{
const
rawData
=
JSON
.
parse
(
'
{"MsgId":"179242112323992762","FromUserName":"@0bb3e4dd746fdbd4a80546aef66f4085","ToUserName":"@16d20edf23a3bf3bc71bb4140e91619f3ff33b4e33f7fcd25e65c1b02c7861ab","MsgType":1,"Content":"test123","Status":3,"ImgStatus":1,"CreateTime":1461652670,"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":179242112323992770,"MMPeerUserName":"@0bb3e4dd746fdbd4a80546aef66f4085","MMDigest":"test123","MMIsSend":false,"MMIsChatRoom":false,"MMUnread":true,"LocalID":"179242112323992762","ClientMsgId":"179242112323992762","MMActualContent":"test123","MMActualSender":"@0bb3e4dd746fdbd4a80546aef66f4085","MMDigestTime":"14:37","MMDisplayTime":1461652670,"MMTime":"14:37"}
'
)
const
EXPECTED
=
{
id
:
'
179242112323992762
'
,
from
:
'
@0bb3e4dd746fdbd4a80546aef66f4085
'
}
const
m
=
new
Message
(
rawData
)
t
.
equal
(
m
.
get
(
'
id
'
)
,
EXPECTED
.
id
,
'
id right
'
)
t
.
equal
(
m
.
get
(
'
from
'
)
,
EXPECTED
.
from
,
'
from right
'
)
t
.
end
()
})
test
(
'
TBW: Message static method
'
,
t
=>
{
const
m
=
Message
.
find
({
id
:
'
xxx
'
},
{
limit
:
1
})
t
.
ok
(
m
.
get
(
'
id
'
),
'
Message.find
'
)
const
ms
=
Message
.
findAll
({
from
:
'
yyy
'
},
{
limit
:
2
})
t
.
equal
(
ms
.
length
,
2
,
'
Message.findAll with limit 2
'
)
t
.
end
()
})
tests/puppet-web-browser-tests.js
浏览文件 @
632b1f42
const
test
=
require
(
'
tape
'
)
const
test
=
require
(
'
tape
'
)
const
PuppetWeb
=
require
(
'
../lib/puppet-web
'
)
const
Browser
=
require
(
'
../lib/puppet-web-browser
'
)
const
WebBrowser
=
PuppetWeb
.
WebBrowser
test
(
'
Browser class smoking tests
'
,
function
(
t
)
{
test
(
'
WebBrowser class tests
'
,
function
(
t
)
{
//t.plan(5)
//t.plan(5)
const
b
=
new
WebBrowser
({
browser
:
'
chrome
'
}
)
const
b
=
new
Browser
(
)
t
.
ok
(
b
,
'
Web
Browser instance created
'
)
t
.
ok
(
b
,
'
Browser instance created
'
)
b
.
open
()
b
.
open
()
.
then
(()
=>
{
.
then
(()
=>
{
...
@@ -25,10 +23,9 @@ test('WebBrowser class tests', function (t) {
...
@@ -25,10 +23,9 @@ test('WebBrowser class tests', function (t) {
b
.
execute
(
'
return Wechaty && Wechaty.isReady()
'
)
b
.
execute
(
'
return Wechaty && Wechaty.isReady()
'
)
.
then
(
r
=>
t
.
notEqual
(
typeof
r
,
'
bool
'
,
'
Wechaty.isReady() returns bool
'
))
.
then
(
r
=>
t
.
notEqual
(
typeof
r
,
'
bool
'
,
'
Wechaty.isReady() returns bool
'
))
b
.
quit
()
t
.
end
()
t
.
end
()
})
})
})
})
b
.
quit
()
})
})
tests/puppet-web-server-tests.js
浏览文件 @
632b1f42
const
https
=
require
(
'
https
'
)
const
https
=
require
(
'
https
'
)
const
test
=
require
(
'
tape
'
)
const
test
=
require
(
'
tape
'
)
const
PuppetWeb
=
require
(
'
../lib/puppet-web
'
)
const
Server
=
require
(
'
../lib/puppet-web-server
'
)
const
WebServer
=
PuppetWeb
.
WebServer
test
(
'
Server basic tests
'
,
function
(
t
)
{
test
(
'
WebServer basic tests
'
,
function
(
t
)
{
t
.
plan
(
9
)
t
.
plan
(
9
)
const
PORT
=
58788
const
PORT
=
58788
const
s
=
new
WebServer
(
)
const
s
=
new
Server
(
PORT
)
t
.
equal
(
typeof
s
,
'
object
'
,
'
Web
Server instance created
'
)
t
.
equal
(
typeof
s
,
'
object
'
,
'
Server instance created
'
)
const
express
=
s
.
init
Express
()
const
express
=
s
.
create
Express
()
t
.
equal
(
typeof
express
,
'
function
'
,
'
init
express
'
)
t
.
equal
(
typeof
express
,
'
function
'
,
'
create
express
'
)
delete
express
delete
express
const
server
=
s
.
init
HttpsServer
(
express
,
PORT
)
const
server
=
s
.
create
HttpsServer
(
express
,
PORT
)
t
.
equal
(
typeof
server
,
'
object
'
,
'
init
server
'
)
t
.
equal
(
typeof
server
,
'
object
'
,
'
create
server
'
)
server
.
on
(
'
close
'
,
()
=>
t
.
ok
(
true
,
'
HttpsServer quited
'
))
server
.
on
(
'
close
'
,
()
=>
t
.
ok
(
true
,
'
HttpsServer quited
'
))
server
.
close
(()
=>
t
.
ok
(
true
,
'
HttpsServer closed
'
))
server
.
close
(()
=>
t
.
ok
(
true
,
'
HttpsServer closed
'
))
delete
server
delete
server
const
socketio
=
s
.
init
SocketIo
()
const
socketio
=
s
.
create
SocketIo
()
t
.
equal
(
typeof
socketio
,
'
object
'
,
'
init
socket io
'
)
t
.
equal
(
typeof
socketio
,
'
object
'
,
'
create
socket io
'
)
delete
socketio
delete
socketio
t
.
equal
(
s
.
isLogined
()
,
false
,
'
instance not logined
'
)
t
.
equal
(
s
.
isLogined
()
,
false
,
'
instance not logined
'
)
...
@@ -37,25 +35,34 @@ test('WebServer basic tests', function (t) {
...
@@ -37,25 +35,34 @@ test('WebServer basic tests', function (t) {
//t.end()
//t.end()
})
})
test
(
'
Web
Server smoking tests
'
,
function
(
t
)
{
test
(
'
Server smoking tests
'
,
function
(
t
)
{
const
PORT
=
58788
const
PORT
=
58788
const
s
=
new
WebServer
(
)
const
s
=
new
Server
(
PORT
)
t
.
plan
(
1
)
t
.
plan
(
1
)
console
.
log
(
`s.init(
${
PORT
}
)`
)
console
.
log
(
`s.init()`
)
s
.
init
(
PORT
)
s
.
init
().
then
(()
=>
{
console
.
error
(
'
s.inited
'
)
const
options
=
require
(
'
url
'
).
parse
(
`https://localhost:
${
PORT
}
/ping`
)
options
.
rejectUnauthorized
=
false
// permit self-signed CA
const
options
=
require
(
'
url
'
).
parse
(
`https://localhost:
${
PORT
}
/ping`
)
https
.
get
(
options
,
(
res
)
=>
{
Object
.
assign
(
options
,
{
rejectUnauthorized
:
false
})
// permit self-signed CA
console
.
error
(
'
server inited
'
)
https
.
get
(
options
,
(
res
)
=>
{
res
.
on
(
'
data
'
,
chunk
=>
{
res
.
on
(
'
data
'
,
chunk
=>
{
t
.
equal
(
chunk
.
toString
(),
'
pong
'
,
'
https get /ping return pong
'
)
t
.
equal
(
chunk
.
toString
(),
'
pong
'
,
'
https get /ping return pong
'
)
})
}).
on
(
'
error
'
,
e
=>
{
console
.
error
(
e
)
t
.
ok
(
false
,
'
https get error
'
)
})
})
}).
on
(
'
error
'
,
e
=>
{
console
.
error
(
e
)
t
.
ok
(
false
,
'
https get fail
'
)
})
})
s
.
socketClient
.
on
(
'
pong
'
,
(
data
)
=>
{
console
.
error
(
'
received event pong from socket:
'
+
data
)
t
.
equal
(
data
,
'
pong
'
,
'
socket io sent ping got pong
'
)
})
s
.
socketClient
.
emit
(
'
ping
'
)
})
})
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录