Skip to content

Commit

Permalink
Update skype.coffee
Browse files Browse the repository at this point in the history
  • Loading branch information
egorovpavel authored May 8, 2017
1 parent 4cf4db3 commit e050681
Showing 1 changed file with 115 additions and 58 deletions.
173 changes: 115 additions & 58 deletions src/skype.coffee
Original file line number Diff line number Diff line change
@@ -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 <at id="28:...">name</at>. 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 <at id=...>...</at>
# 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 <at...> 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"

Expand Down

0 comments on commit e050681

Please sign in to comment.