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"