New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: Message.forward() forward message #727

Merged
merged 17 commits into from Sep 1, 2017

Conversation

@binsee
Member

binsee commented Aug 13, 2017

You can directly forward files and multimedia, but limit the file size to 25Mb or less, otherwise it will fail because the server policy.

Issues: #726

add: Message.forward(id) forward message
You can directly forward files and multimedia, but limit the file size to 25Mb or less, otherwise it will fail because the server policy.
@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 13, 2017

Member

screenshot:

image
image
image

Member

binsee commented Aug 13, 2017

screenshot:

image
image
image

@binsee binsee referenced this pull request Aug 13, 2017

Closed

Add Transpond Message #726

@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 13, 2017

Member

demo code:

const QrcodeTerminal  = require('qrcode-terminal')
const finis           = require('finis')

/**
 * Change `import { ... } from '../'`
 * to     `import { ... } from 'wechaty'`
 * when you are runing with Docker or NPM instead of Git Source.
 */
import {
  config,
  Wechaty,
  log,
  MediaMessage,
  MsgType,
}               from './'

//const roomArr = { }

const welcome = `
| __        __        _           _
| \\ \\      / /__  ___| |__   __ _| |_ _   _
|  \\ \\ /\\ / / _ \\/ __| '_ \\ / _\` | __| | | |
|   \\ V  V /  __/ (__| | | | (_| | |_| |_| |
|    \\_/\\_/ \\___|\\___|_| |_|\\__,_|\\__|\\__, |
|                                     |___/

=============== Powered by Wechaty ===============
`

console.log(welcome)
const bot = Wechaty.instance({ profile: config.DEFAULT_PROFILE })

const forwards = <string[]>[]

bot
.on('logout'	, user => log.info('Bot', `${user.name()} logouted`))
.on('login'	  , user => {
  log.info('Bot', `${user.name()} logined`)
  bot.say('Wechaty login')
})
.on('error'   , e => {
  log.info('Bot', 'error: %s', e)
  bot.say('Wechaty error: ' + e.message)
})
.on('scan', (url, code) => {
  if (!/201|200/.test(String(code))) {
    const loginUrl = url.replace(/\/qrcode\//, '/l/')
    QrcodeTerminal.generate(loginUrl)
  }
  console.log(`${url}\n[${code}] Scan QR Code in above url to login: `)
})
.on('message', async m => {
  try {
    const room = m.room()
    const forwardId = room ? m.obj.room as string : m.obj.from as string
    const name = room ? room.topic() as string : m.from().name() as string
    let doForward = false
    console.log((room ? '[' + room.topic() + ']' : '')
                + '<' + m.from().name() + '>'
                + ':' + m.toStringDigest(),
    )
    if (!m.self()) {
      if (/^(ding|ping|bing|code)$/i.test(m.toString())) {
        doForward = true
        m.say('dong')
        log.info('Bot', 'REPLY: dong')
        await m.say(new MediaMessage(__dirname + '/../image/BotQrcode.png'))
        await m.say('Scan now, because other Wechaty developers want to talk with you too!\n\n(secret code: wechaty)')
        log.info('Bot', 'REPLY: Image')
      } else if (/^(forward|f)$/i.test(m.toString())) {
        if (forwards.indexOf(forwardId) < 0) {
          forwards.push(forwardId)
          await m.say(`你为${room ? '群[' + name + ']' : '自己'}订阅了信息转发,稍后接收到的信息将转发给${room ? '' : ''}`)
        } else {
          await m.say(`${room ? '群[' + name + ']' : '自己'} 已经订阅了信息转发`)
        }
      } else if (/^(unforward|unf)$/i.test(m.toString())) {
        if (forwards.indexOf(forwardId) >= 0) {
          forwards.splice(forwards.indexOf(forwardId), 1)
          await m.say(`你为${room ? '群[' + name + ']' : '自己'}取消了信息转发,稍后接收到的信息将转发给${room ? '' : ''}`)
        } else {
          await m.say(`${room ? '群[' + name + ']' : '自己'} 已经取消了信息转发`)
        }
      } else if (/^(list)$/i.test(m.toString())) {
        await m.say(`当前订阅列表数量为${forwards.length}\n列表如下:\n${forwards.join(',\n')}`)
      } else if (/^(帮助|help|h|使用)$/i.test(m.toString())) {
          await m.say(`你可以在任意聊天界面发送指令订阅/取消订阅信息同步\n'forward' 或 'f' 指令订阅,\n'unforward' 或 'unf' 指令取消订阅\n'list'查看订阅列表\n'help'查看帮助`)
      } else {
        doForward = true
        // 有效消息,且当前聊天未参与同步转发
        if (m.toString().length > 0 && forwards.indexOf(forwardId) < 0) {
          await m.say(`你发的消息内容为: '${m.toString()}'`)
          await m.say(`你可以在任意聊天界面发送指令订阅/取消订阅信息同步\n'forward' 或 'f' 指令订阅,\n'unforward' 或 'unf' 指令取消订阅\n'list'查看订阅列表\n'help'查看帮助`)
        }
      }

      //过滤系统信息
      if (m.type() === MsgType.SYSNOTICE || m.type() === MsgType.SYS) {
        log.info('Bot', '系统信息,不转发')
        doForward = false
      }
      // 过滤 桔小子 bot的 转发信息
      if (/(消息来自)/i.test(m.toString())) {
        doForward = false
        log.info('Bot', '检测到疑似其他Bot信息,不转发')
      }
    }
    if (doForward) {
      forwards.forEach(id => {
        if (id !== forwardId) { // 避免转发到当前会话
          m.forward(id)
        } else {
          log.info('forwards.forEach()', `id=${id},forwardId=${forwardId}`)
        }
      });
    } else {
      log.info('Bot', 'doForward=false')
    }
    } catch (e) {
      log.error('Bot', 'on(message) exception: %s', e)
    }
  })

bot.init()
.catch(e => {
  log.error('Bot', 'init() fail: %s', e)
  bot.quit()
  process.exit(-1)
})

finis((code, signal) => {
  const exitMsg = `Wechaty exit ${code} because of ${signal} `
  console.log(exitMsg)
  bot.say(exitMsg)
})
Member

binsee commented Aug 13, 2017

demo code:

const QrcodeTerminal  = require('qrcode-terminal')
const finis           = require('finis')

/**
 * Change `import { ... } from '../'`
 * to     `import { ... } from 'wechaty'`
 * when you are runing with Docker or NPM instead of Git Source.
 */
import {
  config,
  Wechaty,
  log,
  MediaMessage,
  MsgType,
}               from './'

//const roomArr = { }

const welcome = `
| __        __        _           _
| \\ \\      / /__  ___| |__   __ _| |_ _   _
|  \\ \\ /\\ / / _ \\/ __| '_ \\ / _\` | __| | | |
|   \\ V  V /  __/ (__| | | | (_| | |_| |_| |
|    \\_/\\_/ \\___|\\___|_| |_|\\__,_|\\__|\\__, |
|                                     |___/

=============== Powered by Wechaty ===============
`

console.log(welcome)
const bot = Wechaty.instance({ profile: config.DEFAULT_PROFILE })

const forwards = <string[]>[]

bot
.on('logout'	, user => log.info('Bot', `${user.name()} logouted`))
.on('login'	  , user => {
  log.info('Bot', `${user.name()} logined`)
  bot.say('Wechaty login')
})
.on('error'   , e => {
  log.info('Bot', 'error: %s', e)
  bot.say('Wechaty error: ' + e.message)
})
.on('scan', (url, code) => {
  if (!/201|200/.test(String(code))) {
    const loginUrl = url.replace(/\/qrcode\//, '/l/')
    QrcodeTerminal.generate(loginUrl)
  }
  console.log(`${url}\n[${code}] Scan QR Code in above url to login: `)
})
.on('message', async m => {
  try {
    const room = m.room()
    const forwardId = room ? m.obj.room as string : m.obj.from as string
    const name = room ? room.topic() as string : m.from().name() as string
    let doForward = false
    console.log((room ? '[' + room.topic() + ']' : '')
                + '<' + m.from().name() + '>'
                + ':' + m.toStringDigest(),
    )
    if (!m.self()) {
      if (/^(ding|ping|bing|code)$/i.test(m.toString())) {
        doForward = true
        m.say('dong')
        log.info('Bot', 'REPLY: dong')
        await m.say(new MediaMessage(__dirname + '/../image/BotQrcode.png'))
        await m.say('Scan now, because other Wechaty developers want to talk with you too!\n\n(secret code: wechaty)')
        log.info('Bot', 'REPLY: Image')
      } else if (/^(forward|f)$/i.test(m.toString())) {
        if (forwards.indexOf(forwardId) < 0) {
          forwards.push(forwardId)
          await m.say(`你为${room ? '群[' + name + ']' : '自己'}订阅了信息转发,稍后接收到的信息将转发给${room ? '' : ''}`)
        } else {
          await m.say(`${room ? '群[' + name + ']' : '自己'} 已经订阅了信息转发`)
        }
      } else if (/^(unforward|unf)$/i.test(m.toString())) {
        if (forwards.indexOf(forwardId) >= 0) {
          forwards.splice(forwards.indexOf(forwardId), 1)
          await m.say(`你为${room ? '群[' + name + ']' : '自己'}取消了信息转发,稍后接收到的信息将转发给${room ? '' : ''}`)
        } else {
          await m.say(`${room ? '群[' + name + ']' : '自己'} 已经取消了信息转发`)
        }
      } else if (/^(list)$/i.test(m.toString())) {
        await m.say(`当前订阅列表数量为${forwards.length}\n列表如下:\n${forwards.join(',\n')}`)
      } else if (/^(帮助|help|h|使用)$/i.test(m.toString())) {
          await m.say(`你可以在任意聊天界面发送指令订阅/取消订阅信息同步\n'forward' 或 'f' 指令订阅,\n'unforward' 或 'unf' 指令取消订阅\n'list'查看订阅列表\n'help'查看帮助`)
      } else {
        doForward = true
        // 有效消息,且当前聊天未参与同步转发
        if (m.toString().length > 0 && forwards.indexOf(forwardId) < 0) {
          await m.say(`你发的消息内容为: '${m.toString()}'`)
          await m.say(`你可以在任意聊天界面发送指令订阅/取消订阅信息同步\n'forward' 或 'f' 指令订阅,\n'unforward' 或 'unf' 指令取消订阅\n'list'查看订阅列表\n'help'查看帮助`)
        }
      }

      //过滤系统信息
      if (m.type() === MsgType.SYSNOTICE || m.type() === MsgType.SYS) {
        log.info('Bot', '系统信息,不转发')
        doForward = false
      }
      // 过滤 桔小子 bot的 转发信息
      if (/(消息来自)/i.test(m.toString())) {
        doForward = false
        log.info('Bot', '检测到疑似其他Bot信息,不转发')
      }
    }
    if (doForward) {
      forwards.forEach(id => {
        if (id !== forwardId) { // 避免转发到当前会话
          m.forward(id)
        } else {
          log.info('forwards.forEach()', `id=${id},forwardId=${forwardId}`)
        }
      });
    } else {
      log.info('Bot', 'doForward=false')
    }
    } catch (e) {
      log.error('Bot', 'on(message) exception: %s', e)
    }
  })

bot.init()
.catch(e => {
  log.error('Bot', 'init() fail: %s', e)
  bot.quit()
  process.exit(-1)
})

finis((code, signal) => {
  const exitMsg = `Wechaty exit ${code} because of ${signal} `
  console.log(exitMsg)
  bot.say(exitMsg)
})
@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 13, 2017

Member

Thanks for @lijiarui !

parameter support Room/Contact/roomId/ContactId

  public forward(room: Room): Promise<any>
  public forward(contact: Contact): Promise<any>
  public forward(id: string): Promise<any>
  public forward(sendTo: string|Room|Contact): Promise<any> {}
Member

binsee commented Aug 13, 2017

Thanks for @lijiarui !

parameter support Room/Contact/roomId/ContactId

  public forward(room: Room): Promise<any>
  public forward(contact: Contact): Promise<any>
  public forward(id: string): Promise<any>
  public forward(sendTo: string|Room|Contact): Promise<any> {}
@zixia

Hi @binsee, your forward implementation is awesome!

This will help the wechaty user very much when we are dealing with many attachments.

I have some questions and suggestions for your PR, please read my review, and let me know if you have any question/suggestion.

Looking forward to merge your new PR, thanks!

@@ -42,7 +42,9 @@ export interface MsgRawObj {
MMActualSender: string, // getUserContact(message.MMActualSender,message.MMPeerUserName).isContact()
MMPeerUserName: string, // message.MsgType == CONF.MSGTYPE_TEXT && message.MMPeerUserName == 'newsapp'
ToUserName: string,
FromUserName: string,

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

MsgRawObj is the object from the WebWxApp.

Does FromUserName and Content exist in the structure?

Just want to confirm that.

@zixia

zixia Aug 13, 2017

Member

MsgRawObj is the object from the WebWxApp.

Does FromUserName and Content exist in the structure?

Just want to confirm that.

This comment has been minimized.

@binsee

binsee Aug 13, 2017

Member

When MsgType in [1,3,43,47,49],FromUserName and Content exist..
Other unconfirmed.

@binsee

binsee Aug 13, 2017

Member

When MsgType in [1,3,43,47,49],FromUserName and Content exist..
Other unconfirmed.

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Then I think it's enough for us to believe that they always exist.

@zixia

zixia Aug 13, 2017

Member

Then I think it's enough for us to believe that they always exist.

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

@@ -132,6 +134,16 @@ export interface MsgRawObj {
* MsgType == CONF.MSGTYPE_VERIFYMSG
*/
RecommendInfo?: RecommendInfo,
/**
* Transpond Message

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Do those attributes all exist in the WebWxApp data structure?

Need to confirm them too.

@zixia

zixia Aug 13, 2017

Member

Do those attributes all exist in the WebWxApp data structure?

Need to confirm them too.

This comment has been minimized.

@binsee

binsee Aug 13, 2017

Member

Not exist.
I will fix it.

@binsee

binsee Aug 13, 2017

Member

Not exist.
I will fix it.

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Thanks. Let's make the MsgRawObj reflect and only reflect the WebWxApp data struct.

@zixia

zixia Aug 13, 2017

Member

Thanks. Let's make the MsgRawObj reflect and only reflect the WebWxApp data struct.

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

Show outdated Hide outdated src/message.ts
Show outdated Hide outdated src/message.ts
Show outdated Hide outdated src/message.ts
@@ -422,6 +423,20 @@ export class Bridge {
})
}
public forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> {

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

As I asked before: could we just use forward(rawObj: MsgRawObj) at here?

@zixia

zixia Aug 13, 2017

Member

As I asked before: could we just use forward(rawObj: MsgRawObj) at here?

This comment has been minimized.

@binsee

binsee Aug 13, 2017

Member

After thinking, I can only do this design.

@binsee

binsee Aug 13, 2017

Member

After thinking, I can only do this design.

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Ok, I understood after reading the code you provided. Thanks.

@zixia

zixia Aug 13, 2017

Member

Ok, I understood after reading the code you provided. Thanks.

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

Show outdated Hide outdated src/puppet-web/bridge.ts
@@ -490,6 +491,26 @@ export class PuppetWeb extends Puppet {
return ret
}
public async forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> {

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

forwrd(rawObj: MsgRawObj)

@zixia

zixia Aug 13, 2017

Member

forwrd(rawObj: MsgRawObj)

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

@@ -505,6 +505,32 @@
return true
}
function forward(baseData, patchData) {

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

One parameter please

@zixia

zixia Aug 13, 2017

Member

One parameter please

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

@@ -54,6 +55,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract self(): Contact
public abstract send(message: Message | MediaMessage): Promise<boolean>
public abstract forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean>

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

One parameter.

@zixia

zixia Aug 13, 2017

Member

One parameter.

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 13, 2017

Member

About baseData and patchData: This design is needed

transpondDialogController in WxApp:

  angular.module("Controllers").controller("transpondDialogController", ["$rootScope", "$scope", "$timeout", "$state", "$log", "$document", "chatFactory", "contactFactory", "appFactory", "chatroomFactory", "confFactory", "mmpop", "ngDialog", "utilFactory", "stateManageService", "accountFactory",
    function(e, t, a, n, i, o, chatFactory, c, s, l, confFactory, f, u, m, g, accountFactory) {
      function h(msg, userName) {
        if (e.MsgType != confFactory.MSGTYPE_SYS) {
          var newMsg = angular.copy(msg);
          newMsg.ToUserName = userName;
          newMsg.FromUserName = accountFactory.getUserName();
          newMsg.isTranspond = !0;
          newMsg.MsgIdBeforeTranspond = msg.MsgIdBeforeTranspond || msg.MsgId;
          newMsg._h = void 0;
          newMsg._offsetTop = void 0;
          newMsg.MMSourceMsgId = msg.MsgId;
          newMsg.Scene = 2;
          newMsg = chatFactory.createMessage(newMsg); // call createMessage()

          // The following parameters need to be overridden after calling createMessage()
          newMsg.sendByLocal = !1;
          newMsg.Content = m.htmlDecode(newMsg.Content.replace(/^@\w+:<br\/>/, ""));
          newMsg.MMActualSender = accountFactory.getUserName();
          newMsg.MMSendContent && (newMsg.MMSendContent = newMsg.MMSendContent.replace(/^@\w+:\s/, ""));
          newMsg.MMDigest && (newMsg.MMDigest = newMsg.MMDigest.replace(/^@\w+:/, ""));
          newMsg.MMActualContent && (newMsg.MMActualContent = m.clearHtmlStr(newMsg.MMActualContent.replace(/^@\w+:<br\/>/, "")));

          // append and send message
          chatFactory.appendMessage(newMsg);
          chatFactory.sendMessage(newMsg)
        }
      }

chatFactory.createMessage() in WxApp:

createMessage: function(e) { // 创建消息体
  switch (e.FromUserName || (e.FromUserName = accountFactory.getUserName()),
    e.ToUserName || (e.ToUserName = this.getCurrentUserName()), //
    e.ClientMsgId = e.LocalID = e.MsgId = (utilFactory.now() + Math.random().toFixed(3)).replace(".", ""), //生成本地消息id
    e.CreateTime = Math.round(utilFactory.now() / 1e3),
    e.MMStatus = confFactory.MSG_SEND_STATUS_READY, //标记消息的状态为准备状态
    e.sendByLocal = !0, // 是否是本地信息,如果需要转发文件,必须为 false
    e.MsgType) { //判断消息类型

    case confFactory.MSGTYPE_TEXT:
      var t = [];
      e.Content = e.Content.replace(/<input.*?un="(.*?)".*?value="(.*?)".*?>/g,
          function(e, a, n) {
            return t.push(a), n
          }),
        e.MMAtContacts = t.join(","),
        e.MMSendContent = utilFactory.htmlDecode(utilFactory.clearHtmlStr(e.Content.replace(/<(?:img|IMG).*?text="(.*?)".*?>/g,
          function(e, t) {
            return t.replace(confFactory.MM_EMOTICON_WEB, "")
          }).replace(/<(?:br|BR)\/?>/g, "\n"))).replace(/<(.*?)>/g, function(e) {
          return emojiFactory.EmojiCodeMap[emojiFactory.QQFaceMap[e]] || e
        }),
        e.Content = e.Content.replace(/<(?!(img|IMG|br|BR))[^>]*>/g, "").replace(/\n/g, "<br>");
      break;

    case confFactory.MSGTYPE_APP:
      if (e.AppMsgType == confFactory.APPMSGTYPE_URL) break;
      e.AppMsgType = confFactory.APPMSGTYPE_ATTACH,
        e.Content = "<msg><appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>" + e.FileName + "</title><des></des><action></action><type>" + confFactory.APPMSGTYPE_ATTACH + "</type><content></content><url></url><lowurl></lowurl><appattach><totallen>" + e.FileSize + "</totallen><attachid>#MediaId#</attachid><fileext>" + (e.MMFileExt || e.MMAppMsgFileExt) + "</fileext></appattach><extinfo></extinfo></appmsg></msg>"
  }
  return e
},

foraward() in wechaty-bro

  function forward(baseData, patchData) {
    var chatFactory = WechatyBro.glue.chatFactory
    var confFactory = WechatyBro.glue.confFactory

    if (!chatFactory || !confFactory) {
      log('forward() chatFactory or confFactory not exist.')
      return false
    }

    try {
      var m = chatFactory.createMessage(baseData)

      // Need to override the parametes after called createMessage()
      m = Object.assign(m, patchData)

      chatFactory.appendMessage(m)
      chatFactory.sendMessage(m)
    } catch (e) {
      log('forward() exception: ' + e.message)
      return false
    }
    return true
  }
Member

binsee commented Aug 13, 2017

About baseData and patchData: This design is needed

transpondDialogController in WxApp:

  angular.module("Controllers").controller("transpondDialogController", ["$rootScope", "$scope", "$timeout", "$state", "$log", "$document", "chatFactory", "contactFactory", "appFactory", "chatroomFactory", "confFactory", "mmpop", "ngDialog", "utilFactory", "stateManageService", "accountFactory",
    function(e, t, a, n, i, o, chatFactory, c, s, l, confFactory, f, u, m, g, accountFactory) {
      function h(msg, userName) {
        if (e.MsgType != confFactory.MSGTYPE_SYS) {
          var newMsg = angular.copy(msg);
          newMsg.ToUserName = userName;
          newMsg.FromUserName = accountFactory.getUserName();
          newMsg.isTranspond = !0;
          newMsg.MsgIdBeforeTranspond = msg.MsgIdBeforeTranspond || msg.MsgId;
          newMsg._h = void 0;
          newMsg._offsetTop = void 0;
          newMsg.MMSourceMsgId = msg.MsgId;
          newMsg.Scene = 2;
          newMsg = chatFactory.createMessage(newMsg); // call createMessage()

          // The following parameters need to be overridden after calling createMessage()
          newMsg.sendByLocal = !1;
          newMsg.Content = m.htmlDecode(newMsg.Content.replace(/^@\w+:<br\/>/, ""));
          newMsg.MMActualSender = accountFactory.getUserName();
          newMsg.MMSendContent && (newMsg.MMSendContent = newMsg.MMSendContent.replace(/^@\w+:\s/, ""));
          newMsg.MMDigest && (newMsg.MMDigest = newMsg.MMDigest.replace(/^@\w+:/, ""));
          newMsg.MMActualContent && (newMsg.MMActualContent = m.clearHtmlStr(newMsg.MMActualContent.replace(/^@\w+:<br\/>/, "")));

          // append and send message
          chatFactory.appendMessage(newMsg);
          chatFactory.sendMessage(newMsg)
        }
      }

chatFactory.createMessage() in WxApp:

createMessage: function(e) { // 创建消息体
  switch (e.FromUserName || (e.FromUserName = accountFactory.getUserName()),
    e.ToUserName || (e.ToUserName = this.getCurrentUserName()), //
    e.ClientMsgId = e.LocalID = e.MsgId = (utilFactory.now() + Math.random().toFixed(3)).replace(".", ""), //生成本地消息id
    e.CreateTime = Math.round(utilFactory.now() / 1e3),
    e.MMStatus = confFactory.MSG_SEND_STATUS_READY, //标记消息的状态为准备状态
    e.sendByLocal = !0, // 是否是本地信息,如果需要转发文件,必须为 false
    e.MsgType) { //判断消息类型

    case confFactory.MSGTYPE_TEXT:
      var t = [];
      e.Content = e.Content.replace(/<input.*?un="(.*?)".*?value="(.*?)".*?>/g,
          function(e, a, n) {
            return t.push(a), n
          }),
        e.MMAtContacts = t.join(","),
        e.MMSendContent = utilFactory.htmlDecode(utilFactory.clearHtmlStr(e.Content.replace(/<(?:img|IMG).*?text="(.*?)".*?>/g,
          function(e, t) {
            return t.replace(confFactory.MM_EMOTICON_WEB, "")
          }).replace(/<(?:br|BR)\/?>/g, "\n"))).replace(/<(.*?)>/g, function(e) {
          return emojiFactory.EmojiCodeMap[emojiFactory.QQFaceMap[e]] || e
        }),
        e.Content = e.Content.replace(/<(?!(img|IMG|br|BR))[^>]*>/g, "").replace(/\n/g, "<br>");
      break;

    case confFactory.MSGTYPE_APP:
      if (e.AppMsgType == confFactory.APPMSGTYPE_URL) break;
      e.AppMsgType = confFactory.APPMSGTYPE_ATTACH,
        e.Content = "<msg><appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>" + e.FileName + "</title><des></des><action></action><type>" + confFactory.APPMSGTYPE_ATTACH + "</type><content></content><url></url><lowurl></lowurl><appattach><totallen>" + e.FileSize + "</totallen><attachid>#MediaId#</attachid><fileext>" + (e.MMFileExt || e.MMAppMsgFileExt) + "</fileext></appattach><extinfo></extinfo></appmsg></msg>"
  }
  return e
},

foraward() in wechaty-bro

  function forward(baseData, patchData) {
    var chatFactory = WechatyBro.glue.chatFactory
    var confFactory = WechatyBro.glue.confFactory

    if (!chatFactory || !confFactory) {
      log('forward() chatFactory or confFactory not exist.')
      return false
    }

    try {
      var m = chatFactory.createMessage(baseData)

      // Need to override the parametes after called createMessage()
      m = Object.assign(m, patchData)

      chatFactory.appendMessage(m)
      chatFactory.sendMessage(m)
    } catch (e) {
      log('forward() exception: ' + e.message)
      return false
    }
    return true
  }
fix(message): fix forward return Promise<boolean>
In addition, some notes are added.
@zixia

Thank you for update the PR and let me know the pattern of WebWxApp of forwarding messages.

This PR will LGTM after you follow my reviews and mark all of them to be resolved.

Show outdated Hide outdated src/message.ts
// The following parameters need to be overridden after calling createMessage()
// If you want to forward the file, would like to skip the duplicate upload, sendByLocal must be false.
// But need to pay attention to file.size> 25Mb, due to the server policy restrictions, need to re-upload

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Could we reuse the MediaId instead of re-upload it?

Because some projects use the MediaId directly, which means it might be valid across sessions and accounts.

See: #422 (comment)

I think the solution should be not to upload the same media file twice by caching the MediaId of the Uploaded File and reuse it in the future.

There also has a very interesting project that we could have a look: 微信表情轰炸器

It can send emoticon by MediaId directly, no need to upload anything.

@zixia

zixia Aug 13, 2017

Member

Could we reuse the MediaId instead of re-upload it?

Because some projects use the MediaId directly, which means it might be valid across sessions and accounts.

See: #422 (comment)

I think the solution should be not to upload the same media file twice by caching the MediaId of the Uploaded File and reuse it in the future.

There also has a very interesting project that we could have a look: 微信表情轰炸器

It can send emoticon by MediaId directly, no need to upload anything.

This comment has been minimized.

@zixia

zixia Aug 16, 2017

Member

The project 微信表情轰炸器 is worth having a look! :)

It only stores the MediaId, and reuse it for sending the emoticons.

@zixia

zixia Aug 16, 2017

Member

The project 微信表情轰炸器 is worth having a look! :)

It only stores the MediaId, and reuse it for sending the emoticons.

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

By using fiddler to intercept data, testing found files larger than 25mb in webwx can not use mediaId for multiplexing, the server will return processing failure.
I think this problem needs to be shelved and later resolved. Need to refactor the upload file flow.

"BaseResponse": {
"Ret": 1,
"ErrMsg": ""
}
@binsee

binsee Aug 18, 2017

Member

By using fiddler to intercept data, testing found files larger than 25mb in webwx can not use mediaId for multiplexing, the server will return processing failure.
I think this problem needs to be shelved and later resolved. Need to refactor the upload file flow.

"BaseResponse": {
"Ret": 1,
"ErrMsg": ""
}

This comment has been minimized.

@binsee

binsee Aug 18, 2017

Member

resolved

@binsee

binsee Aug 18, 2017

Member

resolved

Show outdated Hide outdated src/message.ts
@@ -422,6 +423,20 @@ export class Bridge {
})
}
public forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> {

This comment has been minimized.

@zixia

zixia Aug 13, 2017

Member

Ok, I understood after reading the code you provided. Thanks.

@zixia

zixia Aug 13, 2017

Member

Ok, I understood after reading the code you provided. Thanks.

@zixia zixia requested a review from lijiarui Aug 16, 2017

@zixia

Thanks for the update.

I'll approve it after you follow my latest reviews.

Nice job!

Show outdated Hide outdated src/message.ts
@zixia

Update the outdated reviews for the MsgRawObj undefined problem.

Show outdated Hide outdated src/message.ts

binsee added some commits Aug 16, 2017

fix(message): fix msg content error of forward group message
fix: When forwarding a message within a group, the content is prefixed with @userid.
@zixia

zixia approved these changes Aug 16, 2017

Thanks for your great job!

LGTM now.

I'll merge this PR after it getting total three approvements, and I'd like to tag a new version of v0.9 after we confirmed the code can work without any problem.

Looking forward to the new version, Cheers!

// The following parameters need to be overridden after calling createMessage()
// If you want to forward the file, would like to skip the duplicate upload, sendByLocal must be false.
// But need to pay attention to file.size> 25Mb, due to the server policy restrictions, need to re-upload

This comment has been minimized.

@zixia

zixia Aug 16, 2017

Member

The project 微信表情轰炸器 is worth having a look! :)

It only stores the MediaId, and reuse it for sending the emoticons.

@zixia

zixia Aug 16, 2017

Member

The project 微信表情轰炸器 is worth having a look! :)

It only stores the MediaId, and reuse it for sending the emoticons.

@zixia zixia removed the request for review from imWildCat Aug 16, 2017

binsee added some commits Aug 16, 2017

add(message): Add the Forward Message Source Settings option
```
m.forward(Room.load(id), { user: '$USER', room: 'Room[$ROOM]', custom: 'forward from $ROOM$USER' })

// source message: 'test msg'
// from room: 'testRoom'
// from user: 'Bot'
// forward message: `forward from Room[testRoom]Bot:\ntest msg`
```
@zixia

I think the forward methods should be moved from the class Message to MediaMessage.

Show outdated Hide outdated src/message.ts

binsee added some commits Aug 17, 2017

fix(message): fix the error of forward room video
In room msg, the content prefix sender:, need to be removed, otherwise the forwarded sender will display the source message sender, causing self () to determine the error
Show outdated Hide outdated src/message.ts
@zixia

This comment has been minimized.

Show comment
Hide comment
@zixia

zixia Aug 18, 2017

Member

@binsee Could you please mark all the reviews from me as resolved?

Because I'm ok with all of them. After marked as resolved, the outdated reviews will be hidden in the "Files Change" UI.

Thanks!

Member

zixia commented Aug 18, 2017

@binsee Could you please mark all the reviews from me as resolved?

Because I'm ok with all of them. After marked as resolved, the outdated reviews will be hidden in the "Files Change" UI.

Thanks!

@zixia

This comment has been minimized.

Show comment
Hide comment
@zixia

zixia Aug 18, 2017

Member

Thanks for the reply the "resolved" to my reviews.

But I remember that there has a [resolved] button under each review, which you could click that button to make the review as resolved state. Could you find it?

Member

zixia commented Aug 18, 2017

Thanks for the reply the "resolved" to my reviews.

But I remember that there has a [resolved] button under each review, which you could click that button to make the review as resolved state. Could you find it?

@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 18, 2017

Member

@zixia Sorry,I can't find it.
And I search 'resolved' in github help,still not found.

Member

binsee commented Aug 18, 2017

@zixia Sorry,I can't find it.
And I search 'resolved' in github help,still not found.

@coveralls

This comment has been minimized.

Show comment
Hide comment
@coveralls

coveralls Aug 18, 2017

Coverage Status

Changes Unknown when pulling 0a76682 on binsee:add-transpond-msg into ** on Chatie:master**.

coveralls commented Aug 18, 2017

Coverage Status

Changes Unknown when pulling 0a76682 on binsee:add-transpond-msg into ** on Chatie:master**.

@zixia zixia changed the title from add: Message.forward(id) forward message to add: Message.forward() forward message Aug 19, 2017

@lijiarui

looks good to me, Thanks!

@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Aug 31, 2017

Member

@hczhcz
Can I invite you to take the time to review this pr?
I hope this enhancement can be open to everyone to use, thanks!

Member

binsee commented Aug 31, 2017

@hczhcz
Can I invite you to take the time to review this pr?
I hope this enhancement can be open to everyone to use, thanks!

@hczhcz

hczhcz suggested changes Aug 31, 2017 edited

This Message.forward implementation is great!

Please run jsdoc (npm run doc) so that the new API will take effect in the documentation.

@binsee

This comment has been minimized.

Show comment
Hide comment
@binsee

binsee Sep 1, 2017

Member

@hczhcz
This development branch is at an earlier time, and the implementation of npm run doc 's index.md does not contain the contents ofmessage.js. The latest master branch has fixed the problem, and if I execute this command, I need to create a development branch based on the latest master branch and submit it.
I think that by @zixia merge this branch, the implementation of this order is more time-saving.

Or I can submit a new development branch that invites more than three members to review.

Please tell me which way to choose? Thanks!

Member

binsee commented Sep 1, 2017

@hczhcz
This development branch is at an earlier time, and the implementation of npm run doc 's index.md does not contain the contents ofmessage.js. The latest master branch has fixed the problem, and if I execute this command, I need to create a development branch based on the latest master branch and submit it.
I think that by @zixia merge this branch, the implementation of this order is more time-saving.

Or I can submit a new development branch that invites more than three members to review.

Please tell me which way to choose? Thanks!

@hczhcz

hczhcz approved these changes Sep 1, 2017 edited

Ok. Please go ahead. It is not necessary to create another PR, just take care when merging. (Since the code has changed much when this PR is pending, there probably be a lot of things to do in the merging process...) Anyway, do not worry about that :D Thank you for your contribution!

@zixia

This comment has been minimized.

Show comment
Hide comment
@zixia

zixia Sep 1, 2017

Member

Great! Thanks all for the time of reviewing the code, appreciate it!

Member

zixia commented Sep 1, 2017

Great! Thanks all for the time of reviewing the code, appreciate it!

@zixia zixia merged commit 4957489 into Chatie:master Sep 1, 2017

1 of 6 checks passed

ci/circleci CircleCI is running your tests
Details
codacy/pr Hang in there, Codacy is reviewing your Pull request.
Details
codeclimate Code Climate is analyzing this code.
Details
continuous-integration/appveyor/pr Waiting for AppVeyor build to complete
Details
continuous-integration/travis-ci/pr The Travis CI build is in progress
Details
security/snyk No new issues
Details

@binsee binsee deleted the binsee:add-transpond-msg branch Sep 2, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment