Tuesday, October 16, 2007

Creating Bots using the UCMA API and MOSS 2007

Based on the series of Blog posts of Joe Calev ( http://blogs.msdn.com/jcalev/default.aspx ) on using the UCMA API, my colleague(Marc Wetters) created a simple bot. His series of blog post is an excellent start on building bots.

You can ask the bot a question using keywords. The bot then searches a MOSS 2007 environment en presents the results as a series of titles and links to the a set of documents. Next to the set of results (Max 5) the bot returns the names of the author’s. The next step for this bot is to put you through to one of the author’s (which I didn’t get to work yet ;-(  )

For searching a MOSS 2007 environment Marc Wetters used the standard Search Webservice from MOSS 2007.
( http://msdn2.microsoft.com/en-us/library/search.aspx )

Example code

In Visual Studio first you need to add a Web reference to your MOSS search Webservice ( https://<server>/_vti_bin/search.asmx )

In this case it’s called EOSSearch.

Here is the event handler for incoming messages, which does the actual search in MOSS and presents the results. (The session class/object used here is almost identical to the one from the blog posts of Joe Calev, except that it has some extra properties and methods. One of them is an integer called step to know where we are in the process of questions and answers)

void _manager_MessageReceived(object sender, MessageReceivedEventArgs e)

{

Session session = sender as Session;

switch (session.Step)

{

case 0:

{

if (e.MessageType == MessageType.Message && e.HasTextBody)

{

session.SendMessage("Hello " + e.Participant.Name + ".");

EOSSearch.QueryService search = new EOSSearch.QueryService();

search.Credentials =

System.Net.CredentialCache.DefaultCredentials;

string queryXMLString = "<QueryPacket " +

"xmlns='urn:Microsoft.Search.Query'>" +

"<Query><Range>" +

"<Count>5</Count>" +

"</Range><SupportedFormats><Format revision='1'>" +

"urn:Microsoft.Search.Response.Document:Document></Format>" +

"</SupportedFormats><Context>" +

"<TrimDuplicates>true</TrimDuplicates>" +

"<QueryText type=\"MSSQLFT\" language=\"en-us\">" +

"select rank, title, path, author from scope() where " +

"(\"SCOPE\"='All Sites')";

queryXMLString += " AND (freetext('" + e.TextBody + "'))";

queryXMLString += "</QueryText>" + "</Context></Query></QueryPacket>";

string queryResultsString = search.Query(queryXMLString);

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.LoadXml(queryResultsString);

XmlNamespaceManager nsm = new XmlNamespaceManager(xmlDoc.NameTable);

nsm.AddNamespace("q", "urn:Microsoft.Search.Response.Document");

nsm.AddNamespace("d",

"urn:Microsoft.Search.Response.Document.Document");

nsm.AddNamespace("r", "urn:Microsoft.Search.Response");

XmlNode statusnode = xmlDoc.SelectSingleNode("//r:Status", nsm);

if (statusnode.InnerText == "SUCCESS")

{

XmlNode result = xmlDoc.SelectSingleNode("//r:TotalAvailable",

nsm);

int available = Convert.ToInt32(result.InnerText);

XmlNodeList nl = xmlDoc.SelectNodes("//q:Document", nsm);

session.SendMessage("You searched for " +

e.TextBody + " on MOSS.");

if (available > 5)

{

session.SendMessage("Here are the top 5 results from " +

available + " found items.");

}

else

{

session.SendMessage("There are " + available + " results");

}

string[] Authors = new string[5];

int counter = 0;

foreach (XmlNode node in nl)

{

XmlNodeList propertyNl =

node.SelectNodes("d:Properties/d:Property", nsm);

Authors[counter] = propertyNl[3].ChildNodes[2].InnerText;

counter++;

session.SendMessage("(" + counter.ToString() + ") " +

propertyNl[1].ChildNodes[2].InnerText + " " +

node.SelectSingleNode("q:Action/q:LinkUrl",

nsm).InnerText);

}

session.SendMessage("From the following authors:");

for (int i = 0; i < counter; i++)

{

int j = i + 1;

session.SendMessage("(" + j.ToString() + ") " + Authors[i]);

}

session.Authors = Authors;

session.SendMessage("If you want to do another query " +

"please type 'q'. If you want to contact one " +

"of the authors please type the number of the author.");

session.Step = 1;

}

else

{

session.SendMessage("There are no results.");

session.SendMessage("Please try an other query.");

session.Step = 0;

}

}

}

break;

case 1:

{

if (e.MessageType == MessageType.Message && e.HasTextBody)

{

switch (e.TextBody.ToLower())

{

case "q":

session.SendMessage("Please try an other query.");

session.Step = 0;

break;

case "1":

//Not yet functional

Refer(session, 1);

break;

default:

session.SendMessage("I didn't understand you're response.");

break;

}

}

}

break;

}

}

For questions please do not hesitate to ask. I will but you through. Marc great job and a excellent job for the OCS community.

Results in the UI:

image

So we cooked an application and is constantly running:

image image

Tags van Technorati: ,

1 comment:

FUNction said...

hi
I'm really interesting in your bot...
About 3 months ago, I studied Joe Calev's blog and and followed his tips to write a bot, but I failed :(
Before 2 months, I found "Interactive Bot Sample Code" and studied it, but it used workflow fundition and the project is really big, it seems too complicated to understand for me...QQ, i can just run it but cannot modify the bot core(especially WF)
Could you give me some idea about bot core or mail your project to me?? please...
thanks a lot!!
function1122(using Gmail)