As I already posted in my previous post, I am busy developing Bots for Messenger. My first Bot, the Gwaam Bot, has been online since a month, and it is quite popular at the moment. It was "finished" when I submitted it to the Robot Invaders gallery, but in the meanwhile I've changed several things to make it nicer and better! When you play in August you can win a nice price, so make sure you try it! But I'm not blogging to advertize for my bot.
In the Bot Contest you can choose between 3 SDK's: Akonix L7 Builder, the Incesoft Bot Platform and the Colloquis Buddyscript SDK (previously called Conversagent Buddyscript SDK). I have tried them all, and I will give a review together with some hints and code samples for all the SDK's.
Akonix L7 Builder
The Akonix platform is a large platform, with some interesting features. You can choose between Java, C++ and C# to develop your bots. I've used C# (one of my favorite languages) to develop bots, but I assume the other 2 languages have the same features.
When I tried to set up the first "Echo Bot" example, I miserably failed. I spent a lot of hours trying to get my bot online, but it just didn't work. I didn't try it, untill I read the review on Messenger-Blog about this platform. You need a license file to be able to run this platform! I sent an e-mail and got my license the next day. The text in the e-mail was a bit weird, I couldn't really understand it, but I got my license file and it worked.
The Akonix platform supports welcome messages, responses to incoming messages, sending messages and activity's. The last one is nice, I'm not sure if it is also supported in Java / C++. The weird thing (this platform has a lot of weird things) is that the platform can send an invite for an application, but it cannot respond to one! But when the bot sends the invite, the users accepts, you can send messages between the bot and the activity.
As I promised, I will give a code sample for this platform. First the code for a welcome message (the first message in the conversation). I'm adding functionality to the EchoBot sample, so the variable names etc are all the same. The code:
/// <summary>
/// Called when the application provider has been invited to join a session.
/// </summary>
/// <param name="sCurrent">The session.</param>
/// <param name="pInvitor">The participant who initiated the invite.</param>
public void SessionInvite(Session sCurrent, Participant pInvitor)
{
// Accept all sessions
try
{
this.m_apiBot.AcceptSession(sCurrent);
// Send a welcome message to all the participants in this session
this.m_apiBot.SendMessageToAllParticipants(sCurrent, "Hi, I am the Echo bot!");
}
catch (APIException e)
{
sm_logger.Error("Error accepting session '" + sCurrent.GetID() + "'.", e);
}
}
It's so easy, just send a message right after you've accepted the session!
Because I'm using C# to build the bot, I can also use SOAP. I'll show you the code for using the MSN Search API to let your bot search the web for your. You will have to add the SOAP provider to your class first, see the MSDN for that. I've placed the code in a seperate class called "Utilities", but of course you can also place the code in the main class (will be a little bit easier, but this keeps my code clean). The code is explained in the comments, I think there is no need to say more. The Utilities class:
class Utilities
{
/// <summary>
/// Searches the web with MSN Search and displays the results in the conversation
/// </summary>
/// <param name="SearchFor">The Search Query</param>
/// <param name="m_apiBot">A pointer to the BotAPI object</param>
/// <param name="sCurrent">The session where the results should be sent to</param>
public static void SearchMsn(string SearchFor, BotAPI m_apiBot, Session sCurrent)
{
// Code grabbed from the MSDN:
// Create a new MSNSearchService object. MSNSearchService is the top-level
// proxy class for accessing the service. MSNSearchService has one method: Search, which
// takes a single SearchRequest object as an argument.
MSNSearchService s = new MSNSearchService();
// Create a new SearchRequest object that represents the search request.
SearchRequest searchRequest = new SearchRequest();
SourceRequest[] sr = new SourceRequest[2];
// Of course search the web
sr[0] = new SourceRequest();
sr[0].Source = SourceType.Web;
sr[0].ResultFields = ResultFieldMask.All;
sr[0].Count = 5;
sr[0].Offset = 0;
// Look for spelling mistakes / suggestions
sr[1] = new SourceRequest();
sr[1].Source = SourceType.Spelling;
sr[1].ResultFields = ResultFieldMask.Title;
sr[1].Count = 1;
sr[1].Offset = 0;
// Add the fields to the request object
searchRequest.Query = SearchFor;
searchRequest.Requests = sr;
// Some other options
searchRequest.SafeSearch = SafeSearchOptions.Moderate;
searchRequest.AppID = "PLACE YOU APP ID HERE";
searchRequest.Flags = SearchFlags.DisableHostCollapsing;
searchRequest.CultureInfo = "en-US";
// Make a struct to pass my own parameters
SearchStruct ss = new SearchStruct();
ss.SearchFor = SearchFor;
ss.sCurrent = sCurrent;
ss.m_apiBot = m_apiBot;
// Add the event handles
s.SearchCompleted += new SearchCompletedEventHandler(s_SearchCompleted);
// Do the Async request (this function will return immidiatly)
s.SearchAsync(searchRequest, ss);
}
/// <summary>
/// A structure for passing some parameters through the search object
/// </summary>
private struct SearchStruct
{
public BotAPI m_apiBot;
public string SearchFor;
public Session sCurrent;
}
/// <summary>
/// The event handler when the search was completed
/// </summary>
/// <param name="sender">The sender object (not used)</param>
/// <param name="e">The event args</param>
private static void s_SearchCompleted(object sender, SearchCompletedEventArgs e)
{
// Get my SearchStruct back
SearchStruct ss = (SearchStruct)e.UserState;
// Instantiate a new string for the result
string res = "Search results for \"" + ss.SearchFor + "\":\r\n";
// Loop through the results and add them to res
for(int i = 0; i < e.Result.Responses[0].Results.Length; i++) {
res += "\r\n" + e.Result.Responses[0].Results[i].Title + ":\r\n" + e.Result.Responses[0].Results[i].Description;
}
// Is there a spelling suggestion?
if (e.Result.Responses[1].Results.Length > 0)
res += "\r\n\r\nDid you mean \"" + e.Result.Responses[1].Results[0].Title + "\"?";
// Send the result to the conversation
ss.m_apiBot.SendMessageToAllParticipants(ss.sCurrent, res);
}
}
And how the function is used (this is a part of the "SessionMessage" function):
if (strMessage.StartsWith("search: "))
{
string searchfor = strMessage.Substring("search: ".Length);
Utilities.SearchMsn(searchfor, this.m_apiBot, sCurrent);
this.m_apiBot.SendMessageToAllParticipants(sCurrent, "Searching for \"" + searchfor + "\"...");
}
When a users says "search: window live messenger" the bot will respond with 'Searching for "windows live messenger"...' followed by the search results (a few moments later).
Another good part of the Akonix SDK is the fact that they can host the bot for you! And it is free! You will not need to have your own server. But the free trial license is quite limited. The most important parts:
- It replaces the beginning of you message with an X character
- The hosting will only last for 180 days
Besides that, the bot is very slow... It responds really late to your questions, compared with the 2 other platforms.
What I like about this platform is:
- The ability of programming in a language you like (C# in my case)
- The hosting
- Be able to make changes to the code without starting the whole bot again! (you can stop your bot program, compile it and start it again, the bot will stay online on msn so this speeds up the testing)
- They offer extra money for winners of the Robot Invaders contest (but I assure you it will be hard to win something, there are some really nice bots coming up (no, I didn't only mean my bots))
What I don't like:
- The limits (you cannot even normally change the display name of the bot, and it doesn't support Display Pictures, Custom Emoticons, Nudges, Winks, Voice Clips etc!)
- The speed (or you can better say slowness)
- The watermark on each message for the free license
- Some other "weird things" (when you talk to the bot, you can see it has a webcam, but when you click it you get "I'm sorry, I don't support this action)
- The control panel, it should be possible to get your bot hosted there, but I couldn't get it working (all buttons are disabled, you can upload your files but then it says "we will inform you when it is ready" and I've never heard from them)
Conclusion: I think this is the worst of the 3 platforms... So personally I wouldn't go for the "free hosting" and "extra prizes" because I can make 5 bots with the other platforms before I have my Akonix bot online! But that's just my personal opinion, maybe I'm missing something...
Incesoft Bot Platform
The Incesoft platform is the one that is the most easy to use. To set up a bot, the idea is really simple:
1. You register at their site and login
2. Goto Msn account management and create an MSN account
You can sign it in already, the Incesoft servers will keep it online for you. The bot will be "Away" as long as you haven't written the code for the bot.
3. Dowload the SDK in the language you like (again it's C#, C++ or Java)
4. Open the Demo files and fill in your account settings
5. Start the application
5b. If you didn't sign in your account at step 2, do it now
6. The status of the bot will be changed to online, and it should work!
Easy right? I was really surprised by this, it all worked perfectly! The Incesoft platform has got a nice documentation also, so there not much to say about that either. I'll tell you what it supports:
- Welcome messages, responding to messages
- Change font, font style and font color of messages
- Receiving and sending Nudges
- Custom emoticons (the only platform that does it!)
- Display pictures (unfortunatly it is not possible to set the display picture from the code, but you can change it on the controll page)
- A limited way of activity's (is has a function called "sendActivity", so I thought it would support activity's, but it turns out that you can display a webpage in the activity window (in a Incesoft sandbox))
Sending and receiving messages is really straight-forward, so I'll skip that one. The custom emoticons took me a while to figure out, but that is because the second parameter is called "filename", so I thought I could point that to a emoticon file on my harddisk. My mistake, you should first upload your custom emoticon(s) to the server (in the control panel) and then you can use them as expected :-). The display picture should be uploaded there too, and you can choose it there, you will be able to figure that out for yourselve. Finally the activity's, just do: session.sendActivity("http://www.website.com") to show the website in the activity window!
Hint: You can of course give parameters to the url's... You could for example do:
if (msg.StartsWith("search "))
{
session.sendActivity("http://search.msn.com/results.aspx?q=" + msg.Substring("search ".Length));
}
I don't think there's much more to say about this platform, you can use an adapted version of the MSN Search code above on this platform too, because it also supports C#. It's probably nicer to let the bot search and "chat" the results back to you, then open an activity every time you want to search. Finally the pro's and con's, first the pro's:
- Easy to use
- Well documented
- Supports different, well known languages
- Supports Custom Emoticons, Nudges and Display Pictures (extra points for that!)
- Ability to change the message style (font, font color, font style)
Con's:
- No real activity support (I hope they will add this in the future!)
Conclusion:
If you are starting with bot developing and you want to make a bot that doesn't need activity's, this is a really easy to use platform that you should definatly give a try, especially when you already know one of the languages!! But first take a look at my review for the Colloquis platform :-).
Colloquis Buddyscript SDK
Then last but not least the Buddyscript SDK. This is definatly the most powerfull of the 3 SDK's. It's also my favorite one, it is really a nice piece of software! Let me first mention the capabilities:
- Responding to messages in a very very smart way (see below) - Easily change the name and PSM of the bot - Receiving / sending nudges - Setting the display picture of the bot (in settings as well as in code) - Sending and receiving winks!! - Sending and receiving voice clips! (unfortunatly, when you receive one you will not have a wav-file with the voice clip, but you get an event when the user sends a voice clip with the creator name and filesize etc.) - Sharing backgrounds - Full activity support
As you can see, this list is bigger then the other 2 lists. I will discuss all the points and again give some hints / code samples. Let's start with the intelligent matching. The buddyscript SDK has it's own language which makes it possible to let the bot respond intelligent to the user. Instead of directly trying to match the user input on the bot code (for example if message == "hello" then say "hello") this SDK uses some semantics. I'll give you a code sample. Let's say I've got the following buddyscript code:
{editable = 1}
? Hi
- Hello
- Hi
- Yo
It's really easy to understand, the "? hi" is the input and the 3 other lines are output, it will randomly choose one of those 3. You can also have more inputs if you like, but for this example I will keep it simple. Now look what conversation I had with the bot, only containing the above code:
me: hi
bot: Yo
me: hello
bot: Hi
me: yo
bot: Hello
me: hey
bot: Yo
me: hello there!
bot: Hi
me: hi there
bot: Hello
me: hi man
bot: Yo
me: helo
bot: Hi
As you can see, all those words (hi, hello, yo, hey, hello there, hi there, hi man, helo) match on "hi", because they mean the same!! Where the other SDK's will fail when you make typing mistakes (unless you program something for that yourselve) the Conversagent bot's will work perfectly!
Let's continue with the more advanced functions. This was only basic input / output matching. To be able to really "program" something for your bot, you will have to use the Buddyscript syntax. It doesn't really look like another programming language (at least none of the languages I know, which include C#, C++, VB.NET, VB6, Prolog, Java, Basic, and scripting languages, PHP, Javascript, VBScript and JScript). This is a negative point, because it will take some time to learn the language, but in my opinion it is worth it, because you can do so much with it.
To change the Name, PSM or Display picture of the bot, call the following functions:
ABMSNSetFriendlyName(FRIENDLY_NAME)
ABMSNSetPersonalMessage(MESSAGE)
ABMSNSetIcon(INTERNAL_FILENAME)
They are all declared in the Utilities/MSNUtilities.pkg file, together with the functions to send nudges, winks, voiceclips and sharing backgrounds. If you want to use one of those, take a look in that file for more info, shouldn't be too hard to figure out!
Finally the Activity's, take a look at the MSN_Activity sample. The basic idea of using activity's is:
1. Make a new file and add "package lib:/Utilities/MSNActivityUtilities" at the top.
2. Override the "MSNSLPGetAgentMainP4ApplicationName" and "MSNSLPGetAgentMainP4ApplicationId" functions:
function overrides MSNSLPGetAgentMainP4ApplicationName()
return "Tic Tac Toe Classic" // CHANGE ME!!!
function overrides MSNSLPGetAgentMainP4ApplicationId()
return "10331358" // CHANGE ME!!! (default app id for tests is usually 7, check your xml file)
3. Override the "MSNSLPHandleDataEvent" procedure to handle events when data is sent by the activity
3b. call "MSNSLPSendData" to send data to the activity
4. Call "TryToGetUserToOpenP4Window" somewhere in your bot to invite the user. The sample does that when you open a window, but you can also do it when the user says something, for example:
? game
? invite me for a game
? i would like to play the game
? invite me
- Here is my invitation!
call TryToGetUserToOpenP4Window()
Easy isn't it?
Let's continue to a more advanced output. The buddyscript SDK also supports the menu's that you've maybe seen in some bots. Take a look at this code:
{editable = 1}
? help
- Help menu
About {action Help()}
Searching {action Search()}
Another help item {action Another()}
+ about
action Help()
- This bot was build by Jeroen Bransen.
+ search
+ searching
action Search()
- Say "search for searchterm" to search the internet!
+ another help item
action Another()
- Here is another help item
When you say "help", it will display:
Help menu
1 About
2 Searching
3 Another help item
When you say "1" or "about" then, you see "This bot was build by Jeroen Bransen.". "2", "search" or "searching" will display the search line and "3" or "another help item" will display the last line.
I'll give another code sample, this time for searching with MSN Search. It is a very nice and quite easy to use thing, and you will score extra points with it in the contest! Here is the code:
macro MSN_REGISTRATION_KEY "" // <-- Put your key here.
macro MSN_WEBSERVICE_TIMEOUT 1000
// The following function was posted on the Buddyscript forums by ABFrançois
// And was changed by J-Thread
function BuildSearchAPIPostData(SEARCH, TYPE, COUNT, CULTURE_INFO)
POST_DATA = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
POST_DATA = StringConcat(POST_DATA, '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http:/\/schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:tns="http://schemas.microsoft.com/MSNSearch/2005/09/fex" > <SOAP-ENV:Body>')
POST_DATA = StringConcat(POST_DATA, ' <tns:Search xmlns:tns="http:/\/schemas.microsoft.com/MSNSearch/2005/09/fex"> <tns:Request>\n')
POST_DATA = StringConcat(POST_DATA, ' <tns:AppID>', MACRO_MSN_REGISTRATION_KEY, '</tns:AppID>\n')
POST_DATA = StringConcat(POST_DATA, ' <tns:Query>', SEARCH , '</tns:Query>\n')
POST_DATA = StringConcat(POST_DATA, ' <tns:CultureInfo>', CULTURE_INFO, '</tns:CultureInfo> <tns:SafeSearch>Off</tns:SafeSearch> <tns:Flags>None</tns:Flags>')
POST_DATA = StringConcat(POST_DATA, ' <tns:Requests> <tns:SourceRequest>\n')
POST_DATA = StringConcat(POST_DATA, ' <tns:Source>', TYPE, '</tns:Source>\n') // Web / Ads / InlineAnswers / PhoneBook / WordBreaker / Spelling
POST_DATA = StringConcat(POST_DATA, ' <tns:Offset>0</tns:Offset> <tns:Count>', COUNT, '</tns:Count> <tns:ResultFields>All</tns:ResultFields>\n')
POST_DATA = StringConcat(POST_DATA, ' </tns:SourceRequest> </tns:Requests>\n')
POST_DATA = StringConcat(POST_DATA, ' </tns:Request> </tns:Search>\n')
POST_DATA = StringConcat(POST_DATA, '</SOAP-ENV:Body> </SOAP-ENV:Envelope>\n')
return POST_DATA
datasource MSNSearchAPI(TYPE, SEARCH, COUNT, CULTURE_INFO) => Title, Description, Url {expire="in 1 hour" timeout="MACRO_MSN_WEBSERVICE_TIMEOUT"}
preprocess
POST_DATA = BuildSearchAPIPostData(SEARCH, TYPE, COUNT, CULTURE_INFO)
http
http://soap.search.msn.com:80/webservices.asmx
header
Accept: application/soap+xml
postdata {encode=no}
POST_DATA
simple xml
Envelope
Body
SearchResponse
Response
Responses
SourceResponse
Results
Result {loop=content}
Title
Description
Url
And to call it you do:
procedure DisplayResultsDetails(URL, TITLE, SUMMARY)
- <a href="URL"><b>TITLE</b></a><hrefsummary> at URL</hrefsummary>
Description: SUMMARY
procedure DoSearch(KEYWORDS)
TITLE , DESC, URL = MSNSearchAPI("Web", KEYWORDS, 20, "en-US") show 5
* Here are the Web search results from MSN Search for "lc(KEYWORDS)":
- TITLE {call DisplayResultsDetails(URL, TITLE, DESC)}
* <ifmore>Type "<b>more</b>" to see more items.</ifmore>
else
- No results for "lc(KEYWORDS)"!
{editable = 1}
? Search the web.
- What would you like me to search the Web for?
+ STRONGKEYWORDS=AnythingStrong
call DoSearch(STRONGKEYWORDS)
{editable = 1}
? Search for STRONGKEYWORDS=AnythingStrong
call DoSearch(STRONGKEYWORDS)
Hint: Notice that I've used the {} menu function here also to display the results!
This may look a bit complicated, but when you use the buddyscript syntax for a while, you will understand it. The only complicated thing is the "BuildSearchAPIPostData" function, but that's because buddyscript does not support nested SOAP request yet. To use simple SOAP request, you can do something like:
datasource FunctionName() =< Name, Description
soap {expire="now"}
proxy http://api.website.com/Services.asmx
name FunctionName
namespace http://api.website.com/
action http://api.website.com/FunctionName
simple xml
Result
InnerValue
List{loop="content"}
Name
Description
This is of course not an existing SOAP server, but I think it shows how it works. Then a last hint for the Buddyscript SDK, you also need a license for this SDK, but that is automatically e-mailed to you when you request it on the site, so it takes only a few seconds. Follow the instructions and I think you will be able to figure it out, I didn't have problems with it! If your bot doesn't start, look at the error logs. The license has a limit of 50.000 messages session / month (they changed it from 500 to 50.000) so that will be enough for most bots! And don't forget, when you have questions, the forums are pretty active, so don't be afraid to ask your questions there!
The pro's:
- Support almost everything, exept file transfers and Custom Emoticons
- The intelligent matching of input
- No weird limits on the free license
- Good support for SOAP and other data sources
- Very detailed help pages
The con's: - You will have to learn a totally new language
- You have to use a windows server, because the linux variant of the server doesn't support MSN (I heard this, I've not tested it, so I could be wrong)
- To host it you will need to install a pretty large program on your server
Conclusion: As you might have noticed, this is really my favorite, I even made a bot in Akonix but I translated it to Buddyscript because I couldn't get it all working in Akonix. Buddyscript has so much functions, and also a really good support team (questions on the forums are usually answered in 1 or 2 days!). To go further, I'm almost sure the bot that wins the Bot Contest was made with the Buddyscript SDK! I don't think other SDK's can't beat it.
Final conclusion
I would choose the buddyscript SDK, unless you are sure you do not need all those functionality. The Incesoft platform also has some good points, and those bots are easier to host. I wouldn't choose the Akonix platform, just because I cannot figure it out... But as I already said, maybe it's my mistake! But in this post I'm telling you what I think about it.
I hope this post can help some people out, and I'm really looking forward to test all those nice bots! There are already a lot of nice bots out there, but I expect twice as much when the contest ends. You still have a month to go, so start to develop your bot now!
NB: The code I posted was all written by me (exept small parts of the MSN Search code, as stated in the comments), and therefore you can define it as "my code". Because my code doesn't belong in your bot, I hope you will not copy & paste the code into your bot and use it. It was posted as a sample, not to give the direct contents of your bot. So if you want to use the code, please make sure you do understand it, and at least change the input / output structure a bit, because else it isn't your bot, but mine!