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

merge

......@@ -29,6 +29,8 @@ Wechaty is a Bot Framework for Wechat **Personal** Account which can help you cr
> @shevyan: 简单的接口...和Docker化的封装,结合Docker绝对是一个不错的选择 [link](http://mp.weixin.qq.com/s/o-4VMcAMz0K8yJVdNaUXow)
> @lijiarui: [Chat实录|李佳芮:向前一步的程序媛](http://mp.weixin.qq.com/s/dWHAj8XtiKG-1fIS5Og79g)
# Example
The shortest wechat bot code in the world: 6 lines JavaScript
......@@ -60,11 +62,13 @@ We have two options to run wechaty:
[![Docker Pulls](https://img.shields.io/docker/pulls/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) [![Docker Stars](https://img.shields.io/docker/stars/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) [![Docker Layers](https://images.microbadger.com/badges/image/zixia/wechaty.svg)](https://microbadger.com/#/images/zixia/wechaty)
The **best practice** to use Wechaty is run by docker, becasue it's not only the most easy way to get start, but also protect you out of the troubles of dependencies problems.
```shell
$ docker run -ti --rm --volume="$(pwd)":/bot zixia/wechaty mybot.js
```
* Wechaty Docker has native support for TypeScript as well: just write in TypeScript and save to `mybot.ts`.
> Wechaty Docker support to run TypeScript directly as well: just write in TypeScript and save to `mybot.ts`.
Get to know more about Wechaty Docker at [Wiki:Docker](https://github.com/wechaty/wechaty/wiki/Docker).
......@@ -72,14 +76,14 @@ Get to know more about Wechaty Docker at [Wiki:Docker](https://github.com/wechat
[![NPM Version](https://badge.fury.io/js/wechaty.svg)](https://badge.fury.io/js/wechaty) [![Downloads][downloads-image]][downloads-url]
Using Wechaty from NPM is **NOT recommended**. Please use Docker(above) instead unless you are ready to deal with lots of unknown problems.
```shell
$ npm install --save wechaty
$ node mybot.js
```
You might be asked for install the `chromedriver`, depends on which platform you are.
Get to know more about NPM at [Wiki:NPM](https://github.com/wechaty/wechaty/wiki/NPM)
# API Reference
......@@ -204,11 +208,11 @@ You can directly submit pull requests for documentation changes.
## Join us
Scanning the following QR Code in WeChat, with secret code 'wechaty', you can join our **Wechaty Developers' Home**.
Scan the following QR Code in WeChat, with secret code _wechaty_, you can join our **Wechaty Developers' Home**.
![Wechaty Developers' Home](https://raw.githubusercontent.com/wechaty/wechaty/master/image/BotQrcode.png)
Scan now, then chat with other Wechaty developers!
Scan now, then you can chat with other Wechaty developers!
# See Also
......
#!/bin/bash
#!/usr/bin/env bash
#
# Wechaty - Connect ChatBots
#
......@@ -111,7 +111,7 @@ function wechaty::runBot() {
[ -f package.json ] && {
echo "Install dependencies modules ..."
yarn < /dev/null # yarn will close stdin??? cause `read` command fail after yarn
yarn < /dev/null || return $? # yarn will close stdin??? cause `read` command fail after yarn
}
# echo -n "Linking Wechaty module to bot ... "
......@@ -224,6 +224,8 @@ function main() {
# 2. Run a bot
#
*.ts | *.js)
# set -e will not work inside wechaty::runBot because of
# http://stackoverflow.com/a/4073372/1123955
wechaty::runBot "$@" || ret=$?
;;
......
......@@ -35,26 +35,25 @@ bot
console.log(`${url}\n[${code}] Scan QR Code in above url to login: `)
})
.on('login' , user => console.log(`${user} logined`))
.on('message', async function(this, m) {
console.log(`RECV: ${m}`)
.on('message', async function(this, msg) {
console.log(`RECV: ${msg}`)
if (m.type() !== MsgType.VOICE) {
if (msg.type() !== MsgType.VOICE) {
return // skip no-VOICE message
}
const mp3File = createWriteStream(m.filename())
const mp3Stream = await (msg as MediaMessage).readyStream()
const mp3Stream = await (m as MediaMessage).readyStream()
mp3Stream.pipe(mp3File)
const file = createWriteStream(msg.filename())
mp3Stream.pipe(file)
const text = await speechToText(mp3Stream)
console.log('VOICE TO TEXT: ' + text)
if (m.self()) {
if (msg.self()) {
this.say(text) // send text to 'filehelper'
} else {
m.say(text) // to original sender
msg.say(text) // to original sender
}
})
......
{
"name": "wechaty",
"version": "0.6.37",
"version": "0.6.40",
"description": "Wechat for Bot(Personal Account)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
......@@ -35,7 +35,7 @@
"test:chrome:fast": "cross-env LC_ALL=C WECHATY_HEAD=chrome ava --fail-fast --timeout=3m \"dist/{src,test}/**/*.spec.js\"",
"testdev": "cross-env LC_ALL=C WECHATY_LOG=silly ava --ext ts --serial --verbose --fail-fast --timeout=2m",
"testdist": "cross-env WECHATY_LOG=SILLY WECHATY_HEAD=chrome ava --ext ts --verbose --fail-fast --timeout=2m",
"ava": "cross-env LC_ALL=C WECHATY_LOG=verbose node_modules/.bin/ava",
"ava": "ava --extension ts",
"io-client": "ts-node bin/io-client",
"dev": "ts-node dev.ts",
"demo": "ts-node example/ding-dong-bot.ts",
......
......@@ -186,7 +186,7 @@ export class Contact implements Sayable {
}
log.verbose('Cotnact', 'findAll({ name: %s })', query.name)
const nameFilter = query.name
let nameFilter = query.name
if (!nameFilter) {
throw new Error('nameFilter not found')
......@@ -201,6 +201,7 @@ export class Contact implements Sayable {
if (nameFilter instanceof RegExp) {
filterFunction = `(function (c) { return ${nameFilter.toString()}.test(c) })`
} else if (typeof nameFilter === 'string') {
nameFilter = nameFilter.replace(/'/g, '\\\'')
filterFunction = `(function (c) { return c === '${nameFilter}' })`
} else {
throw new Error('unsupport name type')
......
......@@ -30,7 +30,7 @@ export abstract class FriendRequest {
}
}
public abstract send(contact: Contact, hello: string): Promise<void>
public abstract accept(): Promise<void>
public abstract send(contact: Contact, hello: string): Promise<boolean>
public abstract accept(): Promise<boolean>
}
......@@ -216,26 +216,26 @@ export class Bridge {
})
}
public verifyUserRequest(contactId, hello): Promise<void> {
public verifyUserRequest(contactId, hello): Promise<boolean> {
log.verbose('PuppetWebBridge', 'verifyUserRequest(%s, %s)', contactId, hello)
if (!contactId) {
throw new Error('no valid contactId')
}
return this.proxyWechaty('verifyUserRequest', contactId, hello)
return this.proxyWechaty('verifyUserRequestAsync', contactId, hello)
.catch(e => {
log.error('PuppetWebBridge', 'verifyUserRequest(%s, %s) exception: %s', contactId, hello, e.message)
throw e
})
}
public verifyUserOk(contactId, ticket): Promise<void> {
public verifyUserOk(contactId, ticket): Promise<boolean> {
log.verbose('PuppetWebBridge', 'verifyUserOk(%s, %s)', contactId, ticket)
if (!contactId || !ticket) {
throw new Error('no valid contactId or ticket')
}
return this.proxyWechaty('verifyUserOk', contactId, ticket)
return this.proxyWechaty('verifyUserOkAsync', contactId, ticket)
.catch(e => {
log.error('PuppetWebBridge', 'verifyUserOk(%s, %s) exception: %s', contactId, ticket, e.message)
throw e
......
......@@ -141,6 +141,11 @@ export class BrowserDriver {
}
} catch (e) {
if (/could not be found/.test(e.message)) {
// The ChromeDriver could not be found on the current PATH
log.error('PuppetWebBrowserDriver', 'initChromeDriver() Wechaty require `chrome-driver` to be installed.')
throw e
}
log.warn('PuppetWebBrowserDriver', 'initChromeDriver() exception: %s, retry: %d', e.message, retry)
driverError = e
}
......
......@@ -21,9 +21,9 @@ const retryPromise = require('retry-promise').default
import { Contact } from '../contact'
import {
Config
, RecommendInfo
, log
Config,
RecommendInfo,
log,
} from '../config'
import { FriendRequest } from '../friend-request'
......@@ -75,7 +75,7 @@ class PuppetWebFriendRequest extends FriendRequest {
this.type = 'confirm'
}
public async send(contact: Contact, hello = 'Hi'): Promise<void> {
public async send(contact: Contact, hello = 'Hi'): Promise<boolean> {
log.verbose('PuppetWebFriendRequest', 'send(%s)', contact)
if (!contact) {
......@@ -88,20 +88,19 @@ class PuppetWebFriendRequest extends FriendRequest {
this.hello = hello
}
await Config.puppetInstance()
return Config.puppetInstance()
.friendRequestSend(contact, hello)
return
}
public async accept(): Promise<void> {
public async accept(): Promise<boolean> {
log.verbose('FriendRequest', 'accept() %s', this.contact)
if (this.type !== 'receive') {
throw new Error('request on a ' + this.type + ' type')
throw new Error('request is not a `receive` type. it is a ' + this.type + ' type')
}
await Config.puppetInstance()
.friendRequestAccept(this.contact, this.ticket)
const ret = await Config.puppetInstance()
.friendRequestAccept(this.contact, this.ticket)
const max = 20
const backoff = 300
......@@ -127,7 +126,7 @@ class PuppetWebFriendRequest extends FriendRequest {
log.warn('PuppetWebFriendRequest', 'accept() rejected for contact %s because %s', this.contact, e && e.message || e)
})
return
return ret
}
}
......
......@@ -477,7 +477,7 @@ export class PuppetWeb extends Puppet {
/**
* FriendRequest
*/
public async friendRequestSend(contact: Contact, hello: string): Promise<any> {
public async friendRequestSend(contact: Contact, hello: string): Promise<boolean> {
if (!this.bridge) {
return Promise.reject(new Error('fail: no bridge(yet)!'))
}
......@@ -494,7 +494,7 @@ export class PuppetWeb extends Puppet {
}
}
public async friendRequestAccept(contact: Contact, ticket: string): Promise<any> {
public async friendRequestAccept(contact: Contact, ticket: string): Promise<boolean> {
if (!this.bridge) {
return Promise.reject(new Error('fail: no bridge(yet)!'))
}
......
......@@ -667,7 +667,13 @@
})
}
function verifyUserRequest(UserName, VerifyContent) {
function verifyUserRequestAsync(UserName, VerifyContent) {
var callback = arguments[arguments.length - 1]
if (typeof callback !== 'function') {
// here we should in sync mode, because there's no callback
throw new Error('async method need to be called via webdriver.executeAsyncScript')
}
VerifyContent = VerifyContent || '';
var contactFactory = WechatyBro.glue.contactFactory
......@@ -685,13 +691,21 @@
.then(function() { // succ
// alert('ok')
log('friendAdd(' + UserName + ', ' + VerifyContent + ') done')
callback(true)
}, function(t) { // fail
// alert('not ok')
log('friendAdd(' + UserName + ', ' + VerifyContent + ') fail: ' + t)
callback(false)
})
}
function verifyUserOk(UserName, Ticket) {
function verifyUserOkAsync(UserName, Ticket) {
var callback = arguments[arguments.length - 1]
if (typeof callback !== 'function') {
// here we should in sync mode, because there's no callback
throw new Error('async method need to be called via webdriver.executeAsyncScript')
}
var contactFactory = WechatyBro.glue.contactFactory
var confFactory = WechatyBro.glue.confFactory
......@@ -703,9 +717,11 @@
}).then(function() { // succ
// alert('ok')
log('friendVerify(' + UserName + ', ' + Ticket + ') done')
}, function() { // fail
callback(true)
}, function(err) { // fail
// alert('err')
log('friendVerify(' + UserName + ', ' + Ticket + ') fail')
callback(false)
})
}
......@@ -790,8 +806,8 @@
, roomModTopic: roomModTopic
// for Friend Request
, verifyUserRequest: verifyUserRequest
, verifyUserOk: verifyUserOk
, verifyUserRequestAsync: verifyUserRequestAsync
, verifyUserOkAsync: verifyUserOkAsync
// , friendAdd
// , friendVerify
......
......@@ -415,7 +415,7 @@ export class Room extends EventEmitter implements Sayable {
}
log.verbose('Room', 'findAll({ topic: %s })', query.topic)
const topicFilter = query.topic
let topicFilter = query.topic
if (!topicFilter) {
throw new Error('topicFilter not found')
......@@ -426,6 +426,7 @@ export class Room extends EventEmitter implements Sayable {
if (topicFilter instanceof RegExp) {
filterFunction = `(function (c) { return ${topicFilter.toString()}.test(c) })`
} else if (typeof topicFilter === 'string') {
topicFilter = topicFilter.replace(/'/g, '\\\'')
filterFunction = `(function (c) { return c === '${topicFilter}' })`
} else {
throw new Error('unsupport topic type')
......
......@@ -31,6 +31,5 @@ test('Puppet Web Event smoking test', async t => {
await pw.quit()
} catch (e) {
t.fail('exception: ' + e.message)
throw e
}
})
......@@ -18,7 +18,7 @@ import { Server } from '../../src/puppet-web/server'
// import { spy } from 'sinon'
process.on('unhandledRejection', (reason, p) => {
console.log('!!!!!!!')
console.log('!!!!!!! unhandledRejection in puppet-web.spec.ts')
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason)
console.log('!!!!!!!')
})
......
......@@ -21,7 +21,7 @@ import {
const PROFILE = 'unit-test-session.wechaty.json'
process.on('unhandledRejection', (reason, p) => {
console.log('!!!!!!!')
console.log('!!!!!!! unhandledRejection in watchdog.spec.ts')
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason)
console.log('!!!!!!!')
})
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册