From 632b1f42954b65a15664d6188dc32b877aeff9a8 Mon Sep 17 00:00:00 2001 From: "Zhuohuan LI (CARPE DIEM)" Date: Fri, 6 May 2016 00:26:29 +0800 Subject: [PATCH] half work, for echo bot --- .gitignore | 1 + lib/contact.js | 15 +- lib/message.js | 40 +++- lib/puppet-web-browser.js | 86 ++++++++ lib/puppet-web-injectio.js | 87 +++++--- lib/puppet-web-server.js | 217 +++++++++++++++++++ lib/puppet-web.js | 336 ++++-------------------------- lib/puppet.js | 60 ++++-- lib/wechaty.js | 50 ++--- tests/message-tests.js | 37 ++++ tests/puppet-web-browser-tests.js | 13 +- tests/puppet-web-server-tests.js | 59 +++--- 12 files changed, 579 insertions(+), 422 deletions(-) create mode 100755 lib/puppet-web-browser.js create mode 100755 lib/puppet-web-server.js create mode 100644 tests/message-tests.js diff --git a/.gitignore b/.gitignore index 8a995cd89..2b288c2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ t.js t socket.io.min.js +.*.swp diff --git a/lib/contact.js b/lib/contact.js index 2c7b40936..55725cba7 100644 --- a/lib/contact.js +++ b/lib/contact.js @@ -1,12 +1,21 @@ class Contact { - constructor() { + constructor(id) { + this.id = id + + + } + + getId() { return this.id } + + send(message) { + } - find() { + static find() { } - findAll() { + static findAll() { } } diff --git a/lib/message.js b/lib/message.js index c7175d0bc..9f2ef92a7 100644 --- a/lib/message.js +++ b/lib/message.js @@ -1,14 +1,42 @@ -const EventEmitter = require('events') +//const EventEmitter = require('events') -class Message extends EventEmitter { - constructor() { - super() +class Message { + constructor(rawObj) { + 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'}) + ] } } diff --git a/lib/puppet-web-browser.js b/lib/puppet-web-browser.js new file mode 100755 index 000000000..9b31c02ab --- /dev/null +++ b/lib/puppet-web-browser.js @@ -0,0 +1,86 @@ +/**************************************** + * + * 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 diff --git a/lib/puppet-web-injectio.js b/lib/puppet-web-injectio.js index a11f54f1a..4931608c3 100644 --- a/lib/puppet-web-injectio.js +++ b/lib/puppet-web-injectio.js @@ -22,54 +22,73 @@ ;(function (port) { 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 confFactory = injector.get("confFactory") + var Wechaty = { + // 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() zlog('wechaty port ' + port) - /** - * socket might be destroyed(reconnected) - */ - var socket - - initSocket() + initSocket() // save to socket - hookUnload() + hookUnload() hookMessage() zlog('Wechaty injected!. ;-D') } 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() { var enable = true if (enable) { - if (console) - delete console.log - delete console + if (!console.memory && console.time) { // wechat debuger exist + delete console + } console.zlog = window.console.log window.zlog = function (s) { return console.zlog(s) } console.log = function () {} @@ -93,11 +112,11 @@ function initSocket() { // 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) - socket.on('connect', function() { + Wechaty.socket.on('connect', function() { zlog('on connect entried') rootScope.$on("message:add:success", function (event, data) { @@ -106,11 +125,17 @@ socket.on('disconnect', function(e) { zlog('event: socket disconnect') - socket.emit('disconnect', e) + // socket.emit('disconnect', e) // Reconnect... 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') + }) }) } diff --git a/lib/puppet-web-server.js b/lib/puppet-web-server.js new file mode 100755 index 000000000..06cca1c1b --- /dev/null +++ b/lib/puppet-web-server.js @@ -0,0 +1,217 @@ +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 diff --git a/lib/puppet-web.js b/lib/puppet-web.js index 108ac0920..aa4d2dd40 100644 --- a/lib/puppet-web.js +++ b/lib/puppet-web.js @@ -1,6 +1,6 @@ /** * - * wechaty-lib - Robot API/SDK Library for Personal WeChat(微信) Account + * wechaty-lib: Wechat for Bot. and for human who can talk with bot/robot * * Web Soul of Puppet * use to control wechat web. @@ -16,15 +16,18 @@ * 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) { 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 - const server = this.server = new WebServer(this.port) + init() { + this.server = new WebServer(this.port) const EVENTS_IN = [ 'message' @@ -32,17 +35,37 @@ class PuppetWeb extends EventEmitter { , 'logout' ] 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 = [ - 'sent' - ] - EVENTS_OUT.map( event => - this.on(event, data => server.emit(event, data) ) - ) + return p } + 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 @@ -65,291 +88,4 @@ class PuppetWeb extends EventEmitter { 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 diff --git a/lib/puppet.js b/lib/puppet.js index 75ac6cac4..9ad42a879 100644 --- a/lib/puppet.js +++ b/lib/puppet.js @@ -1,3 +1,10 @@ +/** +* Wechat for Bot. and for human who can talk with bot/robot +* +* Interface for puppet +* +*/ + const EventEmitter = require('events') class Puppet extends EventEmitter { @@ -5,28 +12,41 @@ class Puppet extends EventEmitter { super() } - currentUser() { - return 'zixia' - } - - attach(soul) { - if (this.soul) throw new Error('already a soul inside, detach it first!') - if (!soul.alive()) throw new Error('soul is not alive!') - - this.soul = soul - this.soul.on('message', data => { this.emit('message', data) }) + /** + * Get current logined user + * @return + */ + currentUser() { throw new Error('To Be Implemented') } + + /** + * let puppet send message + * + * @param message - the message to be sent + * @return + */ + 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 diff --git a/lib/wechaty.js b/lib/wechaty.js index d42495e21..822ca2c53 100644 --- a/lib/wechaty.js +++ b/lib/wechaty.js @@ -1,22 +1,24 @@ -'use strict' -/* jshint node:true, unused:true */ +const EventEmitter = require('events') +//const Util = require('util'); -const EventEmitter = require('events'); -const Util = require('util'); -var Puppet = require('./puppet') -var Contact = require('./contact') -var Group = require('./group') -var Message = require('./message') +const Puppet = require('./puppet') +const PuppetWeb = require('./puppet-web') + +const Message = require('./message') +const Contact = require('./contact') +const Group = require('./group') class Wechaty extends EventEmitter { // cookie,Uin, Sid,SKey - constructor(opts) { + constructor() { super() - this.puppet = new Puppet(opts) + this.puppet = new Puppet.Web() + /* this.contact = new Contact(this.puppet) this.group = new Group(this.puppet) this.message = new Message(this.puppet) + */ this.puppet.on('message', (e) => { this.emit('message', e) @@ -29,27 +31,19 @@ class Wechaty extends EventEmitter { }) } - currentUser() { - return this.puppet.currentUser() - } + init() { return this.puppet.init() } + currentUser() { return this.puppet.currentUser() } + send(message) { return this.puppet.send(message) } - test1() { - console.log('inst echo...') - } - - static test() { - console.log('stat echo...') - } } - /* -header cookie +Puppet.Web = PuppetWeb -BaseRequest -Uin -Sid -Skey -DeviceId -*/ +Object.assign(Wechaty, { + Puppet: Puppet + , Message: Message + , Contact: Contact + , Group: Group +}) module.exports = Wechaty diff --git a/tests/message-tests.js b/tests/message-tests.js new file mode 100644 index 000000000..0f68afb92 --- /dev/null +++ b/tests/message-tests.js @@ -0,0 +1,37 @@ +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() +}) diff --git a/tests/puppet-web-browser-tests.js b/tests/puppet-web-browser-tests.js index c7f93988d..fb06d519a 100644 --- a/tests/puppet-web-browser-tests.js +++ b/tests/puppet-web-browser-tests.js @@ -1,12 +1,10 @@ const test = require('tape') -const PuppetWeb = require('../lib/puppet-web') +const Browser = require('../lib/puppet-web-browser') -const WebBrowser = PuppetWeb.WebBrowser - -test('WebBrowser class tests', function (t) { +test('Browser class smoking tests', function (t) { //t.plan(5) - const b = new WebBrowser({browser: 'chrome'}) - t.ok(b, 'WebBrowser instance created') + const b = new Browser() + t.ok(b, 'Browser instance created') b.open() .then(() => { @@ -25,10 +23,9 @@ test('WebBrowser class tests', function (t) { b.execute('return Wechaty && Wechaty.isReady()') .then(r => t.notEqual(typeof r, 'bool', 'Wechaty.isReady() returns bool')) + b.quit() t.end() }) }) - b.quit() - }) diff --git a/tests/puppet-web-server-tests.js b/tests/puppet-web-server-tests.js index 14bc16a20..860d7e73b 100644 --- a/tests/puppet-web-server-tests.js +++ b/tests/puppet-web-server-tests.js @@ -1,29 +1,27 @@ const https = require('https') const test = require('tape') -const PuppetWeb = require('../lib/puppet-web') +const Server = require('../lib/puppet-web-server') -const WebServer = PuppetWeb.WebServer - -test('WebServer basic tests', function (t) { +test('Server basic tests', function (t) { t.plan(9) const PORT = 58788 - const s = new WebServer() - t.equal(typeof s , 'object', 'WebServer instance created') + const s = new Server(PORT) + t.equal(typeof s , 'object', 'Server instance created') - const express = s.initExpress() - t.equal(typeof express, 'function', 'init express') + const express = s.createExpress() + t.equal(typeof express, 'function', 'create express') delete express - const server = s.initHttpsServer(express, PORT) - t.equal(typeof server, 'object', 'init server') + const server = s.createHttpsServer(express, PORT) + t.equal(typeof server, 'object', 'create server') server.on('close', () => t.ok(true, 'HttpsServer quited')) server.close(() => t.ok(true, 'HttpsServer closed')) delete server - const socketio = s.initSocketIo() - t.equal(typeof socketio, 'object', 'init socket io') + const socketio = s.createSocketIo() + t.equal(typeof socketio, 'object', 'create socket io') delete socketio t.equal(s.isLogined() , false , 'instance not logined') @@ -37,25 +35,34 @@ test('WebServer basic tests', function (t) { //t.end() }) -test('WebServer smoking tests', function (t) { +test('Server smoking tests', function (t) { const PORT = 58788 - const s = new WebServer() + const s = new Server(PORT) t.plan(1) - console.log(`s.init(${PORT})`) - s.init(PORT) + console.log(`s.init()`) + 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`) - Object.assign(options, {rejectUnauthorized: false}) // permit self-signed CA + https.get(options, (res) => { + console.error('server inited') - https.get(options, (res) => { - res.on('data', chunk => { - t.equal(chunk.toString(), 'pong', 'https get /ping return pong') + res.on('data', chunk => { + 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') + }) +}) -- GitLab