Yaahhr, the Talk Like a Pirate MSN Addin
Seeing as today is Talk Like a Pirate Day (http://www.talklikeapirateday.com/wordpress/), I thought I'd have a look at the relatively new addin api provided for MSN Live Messenger. To head off with the conclusion, I must say I'm not 100% pleased. Obviously there are safety issues to consider, but I still believe that the API has come out somewhat crippled. The receiver will be notified that a plugin is sending the messages, and the sender will literally be spammed with notifications along the lines of "This isn't really you typing you know... You know? Are you sure you know? I'll just add some large black lines and vertical spacings, so you're really sure!".
Anyhoo, I wrote up a quick addin which replaces matched words and sentences from outgoing messages. If a match is found in the outgoing string, a replacement is randomly selected from their pirate counterpart. "Hi" would be "Avast", "Ahoy", "Arrr", or who-knows-what :)
Instructions, downloads and such
The addin can be found in an installation package at http://www.indev.no/Yaaahhr_Install.exe. Running this will enable addins in your Messenger, granted that you have got version 8 installed, and put the plugin and configuration in a folder named "Indev\Yaaahhr" within your "Program Files". Once installed, you can restart MSN, go to the options panel and select the new "Addins" tab. From there you can navigate to the "ThePirateSays.Yaaahhr.dll" found in the before-mentioned folder. Next, go back to the main MSN window and open the drop down box which holds your current status (right next to your display picture). Select "Turn on Yaaahhr", and you should be good to go.
The default pirationary (duh) isn't all that broad. Luckily, it can easily be extended. After installing the addin, you will have a shortcut on your start menu's programs folder, under "Yaaahhr!", called "Yaaahhr Dictionary Configuration". This links to a .xml file, which should pretty much explain itself. Play around with it.
The code
Long story short, just about as short as the actual API documentation (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlive/html/messengeraddin_sdk.asp), here's my code:
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Microsoft.Messenger;
namespace ThePirateSays
{
public class Yaaahhr : IMessengerAddIn
{
private MessengerClient m_client;
private Random m_random;
private int m_prefixChance;
private string[] m_prefixPhrases;
private List<DictionaryPair> m_dictionaryPairs;
public void Initialize(MessengerClient client)
{
m_client = client;
m_random = new Random();
m_dictionaryPairs = new List<DictionaryPair>();
LoadConfiguration();
m_client.AddInProperties.FriendlyName = "Yaaahhr";
m_client.AddInProperties.Description = "You're a pirate!";
m_client.AddInProperties.Creator = "Einar Otto Stangvik";
m_client.AddInProperties.Url = new Uri("http://www.indev.no");
m_client.OutgoingTextMessage += new EventHandler<OutgoingTextMessageEventArgs>(this.OnOutgoingMessage);
}
private void LoadConfiguration()
{
try
{
ConfigHelper ch = new ConfigHelper("yaaahhr.xml");
ch.LoadPrefixPhrases(out m_prefixChance, out m_prefixPhrases);
ch.LoadDictionary(ref m_dictionaryPairs);
}
catch
{
throw new Exception("Configuration could not be loaded.");
}
}
public void OnOutgoingMessage(object sender, OutgoingTextMessageEventArgs args)
{
string toSend = args.TextMessage;
foreach(DictionaryPair pair in m_dictionaryPairs)
{
toSend = RandomlyReplaceStrings(toSend, pair.matches, pair.replacements);
}
toSend = RandomlyPrefixString(toSend, m_prefixChance, m_prefixPhrases);
if (toSend.CompareTo(args.TextMessage) != 0)
{
args.Cancel = true;
m_client.SendTextMessage(toSend, args.UserTo);
}
}
private string RandomlyPrefixString(string input, int chanceOfPrefix, params string[] prefixes)
{
if (m_random.Next(0, 100) < chanceOfPrefix)
{
return prefixes[m_random.Next(0, prefixes.Length)] + " " + input;
}
return input;
}
private string RandomlyReplaceStrings(string input, string[] matches, params string[] replacements)
{
string match;
string replacement;
match = "(" + String.Join("|", matches) + ")";
replacement = replacements[(replacements.Length > 1) ? m_random.Next(0, replacements.Length) : 0];
return Regex.Replace(input, "(?i)(?<R>^|\\W)" + match + "(?<L>$|\\W)", "${R}" + replacement + "${L}");
}
}
}
The heart of this thing is the OnOutgoingMessage event handler. In the Initialize function, which happens to be the only function enforced by the IMessengerAddIn interface, I add my callback to the list of callbacks which receive notifications for outgoing messages. In this handler, I do some string replacement (this is not at all dictionary optimized), cancel the original message and ship off a new one.
The match and replacement texts are parsed from a the tag-along xml file, mentioned earlier, which is installed to the same folder as the dll. Feel free to change it, reload the plugin and go for another ride.

