In a previous tutorial, we looked at how to interactively log in and send an instant message. It occurred to me that it would be remarkably simple to automate the process, so that a single JavaScript file could be used to simply send a message.
With error handling, and a basic logging functions, the whole process is less than 100 lines of code. Without comments and logging, it's less than 50 lines!
Important Prerequisites
The Skype Web SDK requires that the UCWA framework is installed and enabled on your Front-End, Edge and Director servers. Click here to view instructions for how to install UCWA. The Skype Web SDK simply won't function without these steps.
Application Flow
The application performs a the following basic steps, the same as my previous tutorial, but without any interaction. These are outlined below.
- Initialize the SDK
- Authenticate with user credentials
- Start the conversation using chatService
- Add one or more participants to the conversation
- Send the actual Instant Message
- Stop the conversation using chatService
- Logout
Interesting Observation
It appears that whilst the Skype Web SDK uses JavaScript promises, some functions return a success function before the request has actually finished. As such, I've found it a little more reliable to introduce a few small pauses at key steps in the process, which you can see in code below.
Once I discover why this is the case, when Promises should stop this from being necessary, I'll provide a further update. This issue may also be resolved in future versions of the Skype Web SDK.
Logic processing using JavaScript Promises
In this tutorial, I've chained JavaScript Promises to create a logical application flow - ensuring that each subsequent step only executes if the previous step was successful.
You can use promises in a number of different ways. You can chain promise operations by calling then or done on the promise that is returned by the previous then function, which is what I have created below.
As each function is processed, JavaScript moves to the next logical step if it is successful, by implementing the then operator.
Below is a conceptual view of the code and how the promise logic works. Once we have actually sent the message using the sendMessage function, I then call the chatService.stop() method and the signOut method. Neither of these are chained, as I'm not worrying about error checking at this stage - our message has been sent, which is the objective of this tutorial.
Microsoft have a great collection of samples and explanations of JavaScript Promises on MSDN.
Skype.initialize({....}, function (api)
{
client.signInManager.signIn({...}).then(function ()
{
conversation.chatService.start().then(function ()
{
conversation.addParticipant(...).then(function ()
{
conversation.chatService.sendMessage(...).then(function ()
{
conversation.chatService.stop()
client.signInManager.signOut().then()
}
}
}
}
}
For a more detailed explanation of each function, see the first part of this tutorial.
The Full Code
<!doctype html>
<html>
<head>
<title>Send IM using the Skype Web SDK - Quick Method</title>
<!-- SkypeWeb library requires IE compatible mode turned off -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- the jQuery library written by John Resig (MIT license) -->
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
<!-- SkypeWebSDK Bootstrap Libray -->
<script src="https://swx.cdn.skype.com/shared/v/1.1.23.0/SkypeBootstrap.min.js"></script>
<!-- Javascript used in this demonstration -->
<script src="index.js"></script>
</head>
<body>
<h2>Send IM using the Skype Web SDK - Quick Method</h2>
<b>Event Logs</b><br />
<div id="logging_box" contenteditable="false" class="code"></div>
</body>
</html>
// replace this with the credentials of the Lync or Skype for Business account
// that will be used to send the Instant Message.
var skype_username = "[email protected]";
var skype_password = "password123";
// this is the recipient to whom we'll send a message
var recipient = "[email protected]";
// and this is the actual message :-)
var the_message = "Hello World!";
function pause(howlongfor){
log("Pausing for " + howlongfor + "ms");
var currentTime = new Date().getTime();
while (currentTime + howlongfor >= new Date().getTime()) { }
}
function nicetime() {
var d = new Date();
return padLeft(d.getHours(), 2) + ":" + padLeft(d.getMinutes(), 2) + ":" + padLeft(d.getSeconds(), 2) + ":" + padLeft(d.getMilliseconds(), 3);
}
function log(texttolog) {
$('#logging_box').prepend(nicetime() + ": " + texttolog + "<br>");
}
function padLeft(nr, n, str) { return Array(n - String(nr).length + 1).join(str || '0') + nr; }
$(function () {
'use strict';
var Application
var client;
var conversation;
Skype.initialize({
apiKey: 'SWX-BUILD-SDK',
}, function (api) {
Application = api.application;
client = new Application();
log("Client Created");
log('Signing in ' + $('#address').text());
client.signInManager.signIn({
username: skype_username,skype_password
}).then(function () {
log('Logged In Successfully');
//create a new conversation
log("Creating a new Conversation");
conversation = client.conversationsManager.createConversation();
log("Starting chatService");
conversation.chatService.start().then(function () {
log('chatService started!');
conversation.addParticipant("sip:" + recipient).then(function () {
log(recipient + "added!");
pause(1000);
log('Sending message: ' + the_message);
conversation.chatService.sendMessage(the_message).then(function () {
log('Message sent.');
pause(1000);
conversation.chatService.stop().then(function () {
log('chatService stopped.');
}).then(null, function (error) {
log('Error Stopping chatService:' + error);
});
log("Signing Out");
client.signInManager.signOut().then(
function () {
log('Signed out');
},
function (error) {
log('Error signing out:' + error);
});
}).then(null, function (error) {
log('Error Sending Message:' + error);
});
}).then(null, function (error) {
log('Error adding participant:' + error);
});
}).then(null, function (error) {
log('Error starting chatService' + error);
});
}).then(null, function (error) {
// if either of the operations above fails, tell the user about the problem
log("Error signing in: "+error );
});
}, function (err) {
log('some error occurred: ' + err);
});
});
Miscellaneous Functions
Throughout this tutorial, I’m reporting status and updates via a log() function, instead of using the alert() function. Aside from being annoying when it
pops up a message, alert() is not overly flexible. Instead, my log() function simply prepends the text message to a DIV, with the current time stamp – very
useful for debugging and seeing activities in real time.
function log(texttolog) {
var d = new Date();
var time = padLeft(d.getHours(), 2) + ":" + padLeft(d.getMinutes(), 2) + ":" + padLeft(d.getSeconds(), 2) + ":" +
padLeft(d.getMilliseconds(), 3);
$('#logging_box').prepend(time + ": " + texttolog + "<br>");
}
function padLeft(nr, n, str) {
return Array(n - String(nr).length + 1).join(str || '0') + nr;
}
There’s also a simple padLeft() function that pads time references with 0’s where they are less than 2 digits long, to make them nice and consistent.
I've also implemented a pause() function, which is passed a value representing the number of milliseconds to wait. As mentioned above, this is used to briefly pause between SDK calls to improve reliability.
function pause(howlongfor){
var currentTime = new Date().getTime();
while (currentTime + howlongfor >= new Date().getTime()) { }
}
Very Important Considerations
The code examples here require the framework to be logged in as you (or using an account that has your contacts/groups configured as well) – so be careful
with your credentials.
We recommend running this code on a site protected by SSL, and under no circumstances hard-coding your credentials into the code. If you do, it’s at your
own peril!
Tags
Skype,
Skype Web SDK,
UCJA,
JLync,
CodeProject,
UCWA
CodeProject