提交 de556b95 编写于 作者: Huan (李卓桓)'s avatar Huan (李卓桓)

directory re-structure

上级 fac30910
......@@ -8,7 +8,7 @@
, "pretest": "npm run lint"
, "start": "node bin/io-bot.js"
, "demo": "node example/ding-dong-bot.js"
, "test": "cross-env TAP_TIMEOUT=600 tap --reporter=tap test/*.spec.js"
, "test": "cross-env TAP_TIMEOUT=600 tap --reporter=tap test/**/*.spec.js"
}
, "repository": {
"type": "git"
......
......@@ -101,7 +101,7 @@ class Bridge {
const fs = require('fs')
const path = require('path')
return fs.readFileSync(
path.join(path.dirname(__filename), 'puppet-web-injectio.js')
path.join(path.dirname(__filename), 'injectio.js')
, 'utf8'
)
}
......
module.exports = require('./puppet-web')
/**
*
* wechaty: Wechat for Bot. and for human who talk to bot/robot
*
* Class PuppetWeb
*
* use to control wechat in web browser.
*
* Licenst: ISC
* https://github.com/zixia/wechaty
*
*/
/**************************************
*
* Class PuppetWeb
*
***************************************/
const util = require('util')
const fs = require('fs')
const co = require('co')
const log = require('../npmlog-env')
const Puppet = require('../puppet')
const Contact = require('../contact')
const Room = require('../room')
const Message = require('../message')
const Server = require('./server')
const Browser = require('./browser')
const Bridge = require('./bridge')
const Event = require('./event')
const Watchdog = require('./watchdog')
class PuppetWeb extends Puppet {
constructor({
port = 8788 // W(87) X(88), ascii char code ;-]
, profile // if not set profile, then dont store session.
, head
} = {}) {
super()
this.port = port
this.head = head
this.profile = profile
this.userId = null // user id
this.user = null // <Contact> of user self
}
toString() { return `Class PuppetWeb({browser:${this.browser},port:${this.port}})` }
init() {
log.verbose('PuppetWeb', `init() with port:${this.port}, head:${this.head}, profile:${this.profile}`)
this.on('watchdog', Watchdog.onFeed.bind(this))
return co.call(this, function* () {
yield this.initAttach(this)
log.verbose('PuppetWeb', 'initAttach() done')
this.server = yield this.initServer()
log.verbose('PuppetWeb', 'initServer() done')
this.browser = yield this.initBrowser()
log.verbose('PuppetWeb', 'initBrowser() done')
this.bridge = yield this.initBridge()
log.verbose('PuppetWeb', 'initBridge() done')
// this.watchDog('inited') // start watchdog
this.emit('watchdog', { data: 'inited' })
})
.catch(e => { // Reject
log.error('PuppetWeb', 'init exception: %s', e.message)
throw e
})
.then(() => { // Finally
log.verbose('PuppetWeb', 'init() done')
return this // for Chaining
})
}
quit() {
log.verbose('PuppetWeb', 'quit()')
// this.clearWatchDogTimer()
this.emit('watchdog', {
data: 'PuppetWeb.quit()',
type: 'POISON'
})
return co.call(this, function* () {
if (this.bridge) {
yield this.bridge.quit().catch(e => { // fail safe
log.warn('PuppetWeb', 'quit() bridge.quit() exception: %s', e.message)
})
this.bridge = null
} else { log.warn('PuppetWeb', 'quit() without a bridge') }
if (this.server) {
yield this.server.quit()
this.server = null
} else { log.verbose('PuppetWeb', 'quit() without a server') }
if (this.browser) {
yield this.browser.quit()
.catch(e => { // fail safe
log.warn('PuppetWeb', 'quit() browser.quit() exception: %s', e.message)
})
this.browser = null
} else { log.warn('PuppetWeb', 'quit() without a browser') }
yield this.initAttach(null)
})
.catch(e => { // Reject
log.error('PuppetWeb', 'quit() exception: %s', e.message)
throw e
})
.then(() => { // Finally, Fail Safe
log.verbose('PuppetWeb', 'quit() done')
return this // for Chaining
})
}
initAttach(puppet) {
log.verbose('PuppetWeb', 'initAttach()')
Contact.attach(puppet)
Room.attach(puppet)
Message.attach(puppet)
return Promise.resolve(!!puppet)
}
initBrowser() {
log.verbose('PuppetWeb', 'initBrowser()')
const browser = new Browser({
head: this.head
, sessionFile: this.profile
})
browser.on('dead', Event.onBrowserDead.bind(this))
// fastUrl is used to open in browser for we can set cookies.
// backup: 'https://res.wx.qq.com/zh_CN/htmledition/v2/images/icon/ico_loading28a2f7.gif'
const fastUrl = 'https://wx.qq.com/zh_CN/htmledition/v2/images/webwxgeticon.jpg'
return co.call(this, function* () {
yield browser.init()
yield browser.open(fastUrl)
yield browser.loadSession()
.catch(e => { // fail safe
log.verbose('PuppetWeb', 'browser.loadSession(%s) exception: %s', this.profile, e.message || e)
})
yield browser.open()
return browser // follow func name meaning
}).catch(e => {
log.error('PuppetWeb', 'initBrowser() exception: %s', e.message)
throw e
})
}
initBridge() {
log.verbose('PuppetWeb', 'initBridge()')
const bridge = new Bridge({
puppet: this // use puppet instead of browser, is because browser might change(die) duaring run time
, port: this.port
})
return bridge.init()
.catch(e => {
if (this.browser.dead()) {
log.warn('PuppetWeb', 'initBridge() found browser dead, wait it to restore')
} else {
log.error('PuppetWeb', 'initBridge() exception: %s', e.message)
throw e
}
})
}
initServer() {
log.verbose('PuppetWeb', 'initServer()')
const server = new Server({port: this.port})
server.on('scan' , Event.onServerScan.bind(this))
server.on('login' , Event.onServerLogin.bind(this))
server.on('logout' , Event.onServerLogout.bind(this))
server.on('message' , Event.onServerMessage.bind(this))
server.on('unload' , Event.onServerUnload.bind(this))
server.on('connection', Event.onServerConnection.bind(this))
server.on('disconnect', Event.onServerDisconnect.bind(this))
server.on('log' , Event.onServerLog.bind(this))
server.on('ding' , Event.onServerDing.bind(this))
return server.init()
.catch(e => {
log.error('PuppetWeb', 'initServer() exception: %s', e.message)
throw e
})
}
self(message) {
if (!this.userId) {
log.verbose('PuppetWeb', 'self() got no this.userId')
return false
}
if (!message || !message.get('from')) {
log.verbose('PuppetWeb', 'self() got no message')
return false
}
return this.userId == message.get('from')
}
send(message) {
const to = message.get('to')
const room = message.get('room')
let content = message.get('content')
let destination = to
if (room) {
destination = room
// if (to && to!==room) {
// content = `@[${to}] ${content}`
// }
}
log.silly('PuppetWeb', `send(${destination}, ${content})`)
return this.bridge.send(destination, content)
.catch(e => {
log.error('PuppetWeb', 'send() exception: %s', e.message)
throw e
})
}
reply(message, replyContent) {
if (this.self(message)) {
return Promise.reject(new Error('will not to reply message of myself'))
}
const m = new Message()
.set('content' , replyContent)
.set('from' , message.obj.to)
.set('to' , message.obj.from)
.set('room' , message.obj.room)
// log.verbose('PuppetWeb', 'reply() by message: %s', util.inspect(m))
return this.send(m)
.catch(e => {
log.error('PuppetWeb', 'reply() exception: %s', e.message)
throw e
})
}
/**
* logout from browser, then server will emit `logout` event
*/
logout() {
return this.bridge.logout()
.catch(e => {
log.error('PuppetWeb', 'logout() exception: %s', e.message)
throw e
})
}
getContact(id) {
return this.bridge.getContact(id)
.catch(e => {
log.error('PuppetWeb', 'getContact(%d) exception: %s', id, e.message)
throw e
})
}
logined() { return !!(this.user) }
ding(data) {
if (!this.bridge) {
return Promise.reject(new Error('ding fail: no bridge(yet)!'))
}
return this.bridge.ding(data)
.catch(e => {
log.warn('PuppetWeb', 'ding(%s) rejected: %s', data, e.message)
throw e
})
}
}
module.exports = PuppetWeb
/**
*
* wechaty: Wechat for Bot. and for human who talk to bot/robot
*
* Class PuppetWeb
*
* use to control wechat in web browser.
*
* Licenst: ISC
* https://github.com/zixia/wechaty
*
*/
/**************************************
*
* Class PuppetWeb
*
***************************************/
const util = require('util')
const fs = require('fs')
const co = require('co')
const log = require('../npmlog-env')
const Puppet = require('../puppet')
const Contact = require('../contact')
const Room = require('../room')
const Message = require('../message')
const Server = require('./puppet-web-server')
const Browser = require('./puppet-web-browser')
const Bridge = require('./puppet-web-bridge')
const Event = require('./puppet-web-event')
const Watchdog = require('./puppet-web-watchdog')
class PuppetWeb extends Puppet {
constructor({
port = 8788 // W(87) X(88), ascii char code ;-]
, profile // if not set profile, then dont store session.
, head
} = {}) {
super()
this.port = port
this.head = head
this.profile = profile
this.userId = null // user id
this.user = null // <Contact> of user self
}
toString() { return `Class PuppetWeb({browser:${this.browser},port:${this.port}})` }
init() {
log.verbose('PuppetWeb', `init() with port:${this.port}, head:${this.head}, profile:${this.profile}`)
this.on('watchdog', Watchdog.onFeed.bind(this))
return co.call(this, function* () {
yield this.initAttach(this)
log.verbose('PuppetWeb', 'initAttach() done')
this.server = yield this.initServer()
log.verbose('PuppetWeb', 'initServer() done')
this.browser = yield this.initBrowser()
log.verbose('PuppetWeb', 'initBrowser() done')
this.bridge = yield this.initBridge()
log.verbose('PuppetWeb', 'initBridge() done')
// this.watchDog('inited') // start watchdog
this.emit('watchdog', { data: 'inited' })
})
.catch(e => { // Reject
log.error('PuppetWeb', 'init exception: %s', e.message)
throw e
})
.then(() => { // Finally
log.verbose('PuppetWeb', 'init() done')
return this // for Chaining
})
}
quit() {
log.verbose('PuppetWeb', 'quit()')
// this.clearWatchDogTimer()
this.emit('watchdog', {
data: 'PuppetWeb.quit()',
type: 'POISON'
})
return co.call(this, function* () {
if (this.bridge) {
yield this.bridge.quit().catch(e => { // fail safe
log.warn('PuppetWeb', 'quit() bridge.quit() exception: %s', e.message)
})
this.bridge = null
} else { log.warn('PuppetWeb', 'quit() without a bridge') }
if (this.server) {
yield this.server.quit()
this.server = null
} else { log.verbose('PuppetWeb', 'quit() without a server') }
if (this.browser) {
yield this.browser.quit()
.catch(e => { // fail safe
log.warn('PuppetWeb', 'quit() browser.quit() exception: %s', e.message)
})
this.browser = null
} else { log.warn('PuppetWeb', 'quit() without a browser') }
yield this.initAttach(null)
})
.catch(e => { // Reject
log.error('PuppetWeb', 'quit() exception: %s', e.message)
throw e
})
.then(() => { // Finally, Fail Safe
log.verbose('PuppetWeb', 'quit() done')
return this // for Chaining
})
}
initAttach(puppet) {
log.verbose('PuppetWeb', 'initAttach()')
Contact.attach(puppet)
Room.attach(puppet)
Message.attach(puppet)
return Promise.resolve(!!puppet)
}
initBrowser() {
log.verbose('PuppetWeb', 'initBrowser()')
const browser = new Browser({
head: this.head
, sessionFile: this.profile
})
browser.on('dead', Event.onBrowserDead.bind(this))
// fastUrl is used to open in browser for we can set cookies.
// backup: 'https://res.wx.qq.com/zh_CN/htmledition/v2/images/icon/ico_loading28a2f7.gif'
const fastUrl = 'https://wx.qq.com/zh_CN/htmledition/v2/images/webwxgeticon.jpg'
return co.call(this, function* () {
yield browser.init()
yield browser.open(fastUrl)
yield browser.loadSession()
.catch(e => { // fail safe
log.verbose('PuppetWeb', 'browser.loadSession(%s) exception: %s', this.profile, e.message || e)
})
yield browser.open()
return browser // follow func name meaning
}).catch(e => {
log.error('PuppetWeb', 'initBrowser() exception: %s', e.message)
throw e
})
}
initBridge() {
log.verbose('PuppetWeb', 'initBridge()')
const bridge = new Bridge({
puppet: this // use puppet instead of browser, is because browser might change(die) duaring run time
, port: this.port
})
return bridge.init()
.catch(e => {
if (this.browser.dead()) {
log.warn('PuppetWeb', 'initBridge() found browser dead, wait it to restore')
} else {
log.error('PuppetWeb', 'initBridge() exception: %s', e.message)
throw e
}
})
}
initServer() {
log.verbose('PuppetWeb', 'initServer()')
const server = new Server({port: this.port})
server.on('scan' , Event.onServerScan.bind(this))
server.on('login' , Event.onServerLogin.bind(this))
server.on('logout' , Event.onServerLogout.bind(this))
server.on('message' , Event.onServerMessage.bind(this))
server.on('unload' , Event.onServerUnload.bind(this))
server.on('connection', Event.onServerConnection.bind(this))
server.on('disconnect', Event.onServerDisconnect.bind(this))
server.on('log' , Event.onServerLog.bind(this))
server.on('ding' , Event.onServerDing.bind(this))
return server.init()
.catch(e => {
log.error('PuppetWeb', 'initServer() exception: %s', e.message)
throw e
})
}
self(message) {
if (!this.userId) {
log.verbose('PuppetWeb', 'self() got no this.userId')
return false
}
if (!message || !message.get('from')) {
log.verbose('PuppetWeb', 'self() got no message')
return false
}
return this.userId == message.get('from')
}
send(message) {
const to = message.get('to')
const room = message.get('room')
let content = message.get('content')
let destination = to
if (room) {
destination = room
// if (to && to!==room) {
// content = `@[${to}] ${content}`
// }
}
log.silly('PuppetWeb', `send(${destination}, ${content})`)
return this.bridge.send(destination, content)
.catch(e => {
log.error('PuppetWeb', 'send() exception: %s', e.message)
throw e
})
}
reply(message, replyContent) {
if (this.self(message)) {
return Promise.reject(new Error('will not to reply message of myself'))
}
const m = new Message()
.set('content' , replyContent)
.set('from' , message.obj.to)
.set('to' , message.obj.from)
.set('room' , message.obj.room)
// log.verbose('PuppetWeb', 'reply() by message: %s', util.inspect(m))
return this.send(m)
.catch(e => {
log.error('PuppetWeb', 'reply() exception: %s', e.message)
throw e
})
}
/**
* logout from browser, then server will emit `logout` event
*/
logout() {
return this.bridge.logout()
.catch(e => {
log.error('PuppetWeb', 'logout() exception: %s', e.message)
throw e
})
}
getContact(id) {
return this.bridge.getContact(id)
.catch(e => {
log.error('PuppetWeb', 'getContact(%d) exception: %s', id, e.message)
throw e
})
}
logined() { return !!(this.user) }
ding(data) {
if (!this.bridge) {
return Promise.reject(new Error('ding fail: no bridge(yet)!'))
}
return this.bridge.ding(data)
.catch(e => {
log.warn('PuppetWeb', 'ding(%s) rejected: %s', data, e.message)
throw e
})
}
}
module.exports = PuppetWeb
......@@ -19,7 +19,7 @@
const co = require('co')
const log = require('../npmlog-env')
const Event = require('./puppet-web-event')
const Event = require('./event')
const Watchdog = {
onFeed
......@@ -32,6 +32,16 @@ function onFeed({
, timeout = 60000 // 60s default. can be override in options but be careful about the number zero(0)
} = {}) {
if (!this) {
throw new Error('onFeed() must has `this`')
}
// console.log('#################')
// console.log(typeof this)
// console.log(this.constructor.name)
// console.log(this)
// throw new Error('faint')
process.nextTick(_ => {
log.verbose('PuppetWebWatchdog', 'onFeed: %s, %d, [%s]', type, timeout, data)
......
const co = require('co')
const test = require('tap').test
const Browser = require('../src/puppet-web/puppet-web-browser')
const Bridge = require('../src/puppet-web/puppet-web-bridge')
const Browser = require('../../src/puppet-web/browser')
const Bridge = require('../../src/puppet-web/bridge')
const PORT = 58788
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
test('Bridge retry-promise testing', function(t) {
co(function* () {
......
const co = require('co')
const test = require('tap').test
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
const Browser = require('../src/puppet-web/puppet-web-browser')
const Browser = require('../../src/puppet-web/browser')
const PORT = process.env.WECHATY_PORT || 58788
const HEAD = process.env.WECHATY_HEAD || false
const PROFILE = 'unit-test-session.wechaty.json'
......
......@@ -3,14 +3,14 @@ const util = require('util')
const test = require('tap').test
const retryPromise = require('retry-promise').default
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
const PORT = process.env.WECHATY_PORT || 58788
const HEAD = process.env.WECHATY_HEAD || false
const PROFILE = 'unit-test-session.wechaty.json'
const PuppetWeb = require('../src/puppet-web')
const PuppetWebEvent = require('../src/puppet-web/puppet-web-event')
const PuppetWeb = require('../../src/puppet-web')
const PuppetWebEvent = require('../../src/puppet-web/event')
test('Puppet Web Event smoking test', function(t) {
let pw = new PuppetWeb({port: PORT, head: HEAD, profile: PROFILE})
......
......@@ -3,14 +3,14 @@ const util = require('util')
const test = require('tap').test
const retryPromise = require('retry-promise').default
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
const PORT = process.env.WECHATY_PORT || 58788
const HEAD = process.env.WECHATY_HEAD || false
const PROFILE = 'unit-test-session.wechaty.json'
const PuppetWeb = require('../src/puppet-web')
const Message = require('../src/message')
const PuppetWeb = require('../../src/puppet-web')
const Message = require('../../src/message')
test('PuppetWeb smoke testing', function(t) {
let pw = new PuppetWeb({port: PORT, head: HEAD, profile: PROFILE})
......
......@@ -2,9 +2,9 @@ const https = require('https')
const test = require('tap').test
const co = require('co')
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
const PuppetWebServer = require('../src/puppet-web/puppet-web-server')
const PuppetWebServer = require('../../src/puppet-web/server')
const PORT = 58788
test('PuppetWebServer basic tests', function(t) {
......
......@@ -3,20 +3,20 @@ const util = require('util')
const test = require('tap').test
const retryPromise = require('retry-promise').default
const log = require('../src/npmlog-env')
const log = require('../../src/npmlog-env')
const PORT = process.env.WECHATY_PORT || 58788
const HEAD = process.env.WECHATY_HEAD || false
const PROFILE = 'unit-test-session.wechaty.json'
const PuppetWeb = require('../src/puppet-web')
const Watchdog = require('../src/puppet-web/puppet-web-watchdog.js')
const PuppetWeb = require('../../src/puppet-web')
const Watchdog = require('../../src/puppet-web/watchdog.js')
test('Puppet Web watchdog timer', function(t) {
const pw = new PuppetWeb({port: PORT, head: HEAD, profile: PROFILE})
t.ok(pw, 'should instantiate a PuppetWeb')
Watchdog.onFeed.call({}, { data: 'initing directly' })
Watchdog.onFeed.call(pw, { data: 'initing directly' })
t.pass('should ok with default food type')
co(function* () {
......@@ -31,7 +31,7 @@ test('Puppet Web watchdog timer', function(t) {
let errorCounter = 0
pw.once('error', e => errorCounter = 1)
pw.emit('watchdog', {
data: 'feed_and_active_it'
data: 'active_for_timeout_1ms'
, timeout: 1
})
yield new Promise((resolve) => setTimeout(_ => resolve(), 10)) // wait untill reset
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册