From e0506819b48b700832bb38b346d1c5643b991cf9 Mon Sep 17 00:00:00 2001 From: Pavel Egorov Date: Mon, 8 May 2017 15:22:04 +0100 Subject: [PATCH] Update skype.coffee --- src/skype.coffee | 173 +++++++++++++++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 58 deletions(-) diff --git a/src/skype.coffee b/src/skype.coffee index 096a5b5..ddd2789 100644 --- a/src/skype.coffee +++ b/src/skype.coffee @@ -1,82 +1,139 @@ {Robot, Adapter, TextMessage} = require "hubot" -skype = require "skype-sdk"; +builder = require "botbuilder"; # Microsoft botframework +# Skype adaptator class Skype extends Adapter constructor: (@robot) -> + # @robot is hubot super @robot - @botService = null + # @bot is botframework + @bot = null + @intents = null + + # Env vars to configure the botframework @appID = process.env.MICROSOFT_APP_ID - @appSecret = process.env.MICROSOFT_APP_SECRET - @botID = process.env.SKYPE_BOT_ID - @apiURL = "https://apis.skype.com" - @apiTimeout = 15000 - @robot.logger.info "hubot-skype-bot: Adapter loaded." + @appPassword = process.env.MICROSOFT_APP_PASSWORD - _nameFromId: (userId) -> - parts = userId.split(":") - parts[parts.length - 1] + @robot.logger.info "hubot-skype-bot: Adapter loaded." - _createUser: (userId, roomId = false, displayName = "") -> + _createUser: (userId, address) -> user = @robot.brain.userForId(userId) - user.room = roomId if roomId - user.name = displayName - if displayName.length < 1 - user.name = @_nameFromId(userId) - @robot.logger.info("hubot-skype-bot: new user : ", user) + if typeof address != 'undefined' + user.address = address + @robot.logger.debug("hubot-skype-bot: new user : ", user) user - _processMsg: (msg) -> - retun unless msg.from? and msg.content? - user = @_createUser msg.from, msg.to - _msg = msg.content.trim() - - # Format for PMs - _msg = @robot.name + " " + _msg if msg.to is @botID - - message = new TextMessage user, _msg, msg.messageId - @receive(message) if message? - - _sendMsg: (context, msg) -> - # TODO: add, and test support for rooms ... - target = context.user.id - target = context.user.room if context.user.room isnt @botID - @botService.send(target, msg, true, (err) => - @robot.logger.error("hubot-skype-bot: error sending message : ", err) if err? - ) - + _sendMsg: (address, text) => + @robot.logger.debug "Bot msg: #{text}" + msg = new builder.Message() + msg.textFormat("plain") # By default is markdown + msg.address(address) + msg.text(text) + @bot.send msg, (err) => + if typeof err == 'undefined' + @robot.logger.error "Sending msg to Skype #{err}" + else + @robot.logger.debug "Msg to Skype sended correctly" + return + + # Function used by Hubot to answer send: (envelope, strings...) -> - @_sendMsg envelope, strings.join "\n" + @robot.logger.debug "Send" + @_sendMsg envelope.user.address, strings.join "\n" reply: (envelope, strings...) -> - @_sendMsg envelope, envelope.user.name + ": " + strings.join "\n #{envelope.user.name}: " + @robot.logger.debug "Reply" + @_sendMsg envelope.user.address, strings.join "\n" + # Pass the msg to Hubot, appending the bot name at the beggining + _processMsg: (msg) -> + user = @_createUser msg.user.id, msg.address + # Remove name. This is received by the bot when called from a group + # Append robot name at the beggining + text = @robot.name + " " + msg.text.replace /.*<\/at>\s+(.*)$/, "$1" + message = new TextMessage user, text, msg.address.id + # @receive pass the message to Hubot internals + @receive(message) if message? + + # Adapter start run: -> unless @appID @emit "error", new Error "You must configure the MICROSOFT_APP_ID environment variable." - unless @appSecret - @emit "error", new Error "You must configure the MICROSOFT_APP_SECRET environment variable." - unless @botID - @emit "error", new Error "You must configure the SKYPE_BOT_ID environment variable." - - @botID = "28:#{@botID}" - @botService = new skype.BotService - messaging: - botId: @botID, - serverUrl: @apiURL, - requestTimeout: @apiTimeout, - appId: @appID, - appSecret: @appSecret - - @robot.router.post "/skype/", skype.messagingHandler(@botService) - - @botService.on("message", (bot, data) => - @_processMsg data - ) + unless @appPassword + @emit "error", new Error "You must configure the MICROSOFT_APP_PASSWORD environment variable." - @botService.on("contactAdded", (bot, data) => - @_createUser data.from, false, data.fromDisplayName + @connector = new (builder.ChatConnector)( + appId: @appID + appPassword: @appPassword ) + # Creating bot of botframework + @bot = new (builder.UniversalBot)(@connector) + + # HTTP POST to /skype/ are passed to botframework (by default port 8080) + @robot.router.post "/skype/", @connector.listen() + + # Anything received by the bot is parsed by the defined intents + # If nothing is matched, pass the msg to Hubot + @intents = new (builder.IntentDialog) + @bot.dialog '/', @intents + + # Intents regex starts with .* to also match callings from groups, that appends ... + # The matches function needs a regexp for the first arguments, then an array of anonymous funcs + # Those anonymous functions receive session param, which we could use to answer, store values, etc. + # https://docs.botframework.com/en-us/node/builder/chat-reference/classes/_botbuilder_d_.session.html + @intents.matches /.*example$/i, [ + (session) => + session.send "This bot is a mixture between BotFramwork de Microsoft y Hubot. +If you write 'example', this message is shown.\n\n +If you write 'chat', an example dialog is started.\n\n +Otherwise, the message is passed to hubot (write for example 'ping').\n\n\n\n +In group chats, bot only will receive messages send to it. Eg.: @botname example" + return + ] + + # This example intent has two anonymous funcs. First one start a dialog (botframework function) with the user. + # Second one is executed after and receive the values written by the user + @intents.matches /.*chat$/i, [ + (session) => + session.beginDialog '/chat' + return + (session, results) => + console.log "Dialog results: #{results}" + return + ] + + # Si ninguno de los otros intents ha matcheado, entra en este, que pasa el mensaje a Hubot + # Esta seria la conexion entre los mensajes de Skype y Hubot + @intents.onDefault [ + (session, args, next) => + @robot.logger.debug "Msg from the user: #{session.message.text}" + @_processMsg session.message + return + ] + + # If user wants to exit from any dialog at any moment it can write "goodbye" + @bot.endConversationAction('goodbye', 'Closing dialog', { matches: /.*goodbye/i }); + + # This dialog receives as first argument a name (to be called from intents) and an array of anonymous functions (as seen with intents) + # Normally you send answers and receive responses in the next func + @bot.dialog '/chat', [ + (session) -> + builder.Prompts.text session, "Tell me someting" + return + (session, results) -> + # This is to remove from the response of a user in case of group chats + resp = results.response.replace /.*<\/at>\s+(.*)$/, "$1" + session.send "You said: #{resp}" + + # We can use session.userData to store values + # Eg.: session.userData.channel_name = resp + + # To finish the dialog + session.endDialog() + return + ] + @robot.logger.info "hubot-skype-bot: Adapter running." @emit "connected"