///---------------------------------------------------------------------------- /// /// Copyright (c) 2007-2008, AOL LLC /// All rights reserved. /// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: /// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. /// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. /// Neither the name of the AOL LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS /// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT /// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR /// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, /// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, /// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR /// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING /// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS /// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// ///---------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Collections; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO; using System.Net; using System.Xml; using AccCoreLib; namespace MashupSportsBot { class MashupSportsBot : Control { [DllImport("acccore.dll", EntryPoint = "#111", PreserveSig = false)] private static extern void AccCreateSession( [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object session); private AccSession s; private static MashupSportsBot sportsBot; private ArrayList m_subList; private System.Timers.Timer t; const string kQuickParseUrl = "http://www.cricinfo.com/rss/livescores.xml"; private string m_lastUpdateTime; private const string cBaseUrl = "http://xml.searchvideo.com/apiv3?appid=1x1jhj64466mi12ia&method=truveo.videos.getVideos&query={0}"; private string m_replyText; const string kSubscribe = "subscribe"; const string kHelp = "help"; const string kStatus = "status"; const string kUnsubscribe = "unsubscribe"; const string kVideo = "video:"; const string kUnSub = "You have been removed from the bot list. Thanks for using MashupSportsBot!"; const string kSub = "You have successfully subscribed to this bot! You can always check the bot status by sending \"status\" to the bot."; const string kHelpIm = "To subscribe to the MashupSports alerts send \"subscribe\" to MashupSportsBot. To unsubscribe type \"unsubscribe\" to MashupSportsBot."; const string kStillSearching = "The bot is still searching for MashupSports for updates. You will be the first to know when MashupSports has been updated."; [STAThread] static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("usage: acshbuddy screenname password"); return; } sportsBot = new MashupSportsBot(); sportsBot.Run(args[0], args[1]); } private void Run(string username, string password) { try { // create control to allow invokes CreateControl(); // check every 30 mins t = new System.Timers.Timer(1800000); t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); t.SynchronizingObject = sportsBot; m_subList = new ArrayList(); m_lastUpdateTime = ""; m_replyText = ""; // create and init session object o; AccCreateSession(typeof(IAccSession).GUID, out o); s = (AccSession)o; s.OnStateChange += new DAccEvents_OnStateChangeEventHandler(s_OnStateChange); s.OnSecondarySessionStateChange += new DAccEvents_OnSecondarySessionStateChangeEventHandler(s_OnSecondarySessionStateChange); s.OnImReceived += new DAccEvents_OnImReceivedEventHandler(s_OnImReceived); s.ClientInfo.set_Property(AccClientInfoProp.AccClientInfoProp_Description, "MashupSportsBot (key=ma17Nukk0zahjl3d)"); s.Identity = username; // disable idle s.set_Property(AccSessionProp.AccSessionProp_SecondsOfInactivityBeforeIdleState, int.MaxValue); s.SignOn(password); // start main loop Application.Run(); } catch (COMException e) { Console.WriteLine(e.Message); } } void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { UpdateState(); } void s_OnImReceived(AccSession session, IAccImSession imSession, IAccParticipant sender, IAccIm im) { DateTime CurrTime = DateTime.Now; string imText = im.GetConvertedText("text/plain"); imText = imText.ToLower(); if ((imText.CompareTo(kSubscribe) == 0) || (imText.CompareTo("1") == 0)) { Console.WriteLine("*** Subscribe received from {0} @: {1:G}", sender.Name, CurrTime); m_subList.Add(sender.Name); ReplySub(session, imSession, false); } else if ((imText.CompareTo(kStatus) == 0) || (imText.CompareTo("2") == 0)) { Console.WriteLine("*** {0} has asked for status @: {1:G}", sender.Name, CurrTime); ReplyStatus(session, imSession, sender.Name); } else if ((imText.CompareTo(kUnsubscribe) == 0) || (imText.CompareTo("3") == 0)) { Console.WriteLine("*** UN-Subscribe received from {0} @: {1:G}", sender.Name, CurrTime); m_subList.Remove(sender.Name); ReplySub(session, imSession, true); } else if ((imText.CompareTo(kHelp) == 0) || (imText.CompareTo("4") == 0)) { Console.WriteLine("*** {0} has asked for help @: {1:G}", sender.Name, CurrTime); ReplyHelp(session, imSession, sender.Name); } else if ((imText.IndexOf(kVideo) == 0) || (imText.IndexOf("5") == 0)) { if (imText.IndexOf(':') > 0) { string search = ""; if (imText.IndexOf(kVideo) == 0) search = imText.Remove(0, 6); else if (imText.IndexOf("5") == 0) search = imText.Remove(0, 2); Console.WriteLine("*** {0} has asked for a video with search term {2} @: {1:G}", sender.Name, CurrTime, search); ReplyVideo(session, imSession, sender.Name, search); } else { ReplyVideoHelp(session, imSession, sender.Name); Console.WriteLine("*** {0} has asked for a video with ZERO search term @: {1:G}", sender.Name, CurrTime); } } else { Console.WriteLine("*** {0} im-d us with unknown data @: {1:G}", sender.Name, CurrTime); ReplyGarbage(session, imSession, sender.Name); } } void s_OnSecondarySessionStateChange(AccSession session, IAccSecondarySession secondarySession, AccSecondarySessionState State, AccResult hr) { if ((AccSecondarySessionServiceId)secondarySession.get_Property((int)AccSecondarySessionProp.AccSecondarySessionProp_ServiceId) == AccSecondarySessionServiceId.AccSecondarySessionServiceId_Im && State == AccSecondarySessionState.AccSecondarySessionState_ReceivedProposal) { IAccImSession piImSession = (IAccImSession)secondarySession; AccImSessionType type = (AccImSessionType) piImSession.get_Property((int)AccImSessionProp.AccImSessionProp_SessionTypeProposed); if (type == AccImSessionType.AccImSessionType_Im) { string name = (string)secondarySession.get_Property((int)AccSecondarySessionProp.AccSecondarySessionProp_RemoteUserName); Console.WriteLine("> IM Proposal Received from: {0}", name); piImSession.Accept(); } } } void s_OnStateChange(AccSession session, AccSessionState State, AccResult hr) { Console.WriteLine("> State change: {0}", State); if (State == AccSessionState.AccSessionState_Online) { UpdateState(); if (!t.Enabled) t.Start(); } } private static string DumpToConsole(XmlDocument doc) { string reply = ""; XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); mgr.AddNamespace("av", "http://xml.searchvideo.com"); XmlNodeList nodes = doc.SelectNodes("//av:Video/av:title", mgr); XmlNamespaceManager mgr2 = new XmlNamespaceManager(doc.NameTable); mgr2.AddNamespace("av", "http://xml.searchvideo.com"); XmlNodeList nodes2 = doc.SelectNodes("//av:Video/av:videoUrl", mgr2); for (int i = 0; i < nodes.Count; i++) { XmlNode replyNode = nodes.Item(i); XmlNode urlNode = nodes2.Item(i); reply += ""; reply += replyNode.InnerText; reply += "

"; // each title on new line Console.WriteLine(replyNode.InnerText); } return reply; } private void ReplyVideo(IAccSession session, IAccImSession imSession, string sender, string search) { // create url to include the query string url = String.Format(cBaseUrl, search); XmlDocument doc = new XmlDocument(); doc.Load(url); //Console.WriteLine(doc.OuterXml); //not so pretty string reply = DumpToConsole(doc); IAccIm im; if (reply.Length > 0) { reply = reply.Insert(0, ""); reply = reply.Insert(reply.Length, ""); im = session.CreateIm(reply, "text/html"); } else { reply = "Zero results found for your search!"; im = session.CreateIm(reply, "text/html"); } if (sender.IndexOf('+') >= 0) { string plain = im.GetConvertedText("text/plain"); IAccIm im2 = session.CreateIm(plain, "text/plain"); imSession.SendIm(im2); } else { imSession.SendIm(im); } } private void ReplyVideoHelp(IAccSession session, IAccImSession imSession, string sender) { if (sender.IndexOf('+') >= 0) { string reply = "To search for videos type video:term, where term is the search term you want to search for."; IAccIm im = session.CreateIm(reply, "text/plain"); imSession.SendIm(im); } else { string reply = "To search for videos type video:term, where term is the search term you want to search for."; IAccIm im = session.CreateIm(reply, "text/html"); imSession.SendIm(im); } } private void ReplyHelp(IAccSession session, IAccImSession imSession, string sender) { if (sender.IndexOf('+') >= 0) { string reply = "This is the help for the MashupSportsBot! Commands are: subscribe, status, unsubscribe, help."; IAccIm im = session.CreateIm(reply, "text/plain"); imSession.SendIm(im); } else { string reply = string.Format("This is the help for the MashupSportsBot! To use the bot please do one of send the following:
1. {1} - Subscribe to the bot.
2. {2} - Get Latest Cricket News.
3. {3} - Unsubscribe from the bot.
4. {4} - Get help from the bot.
5. {5} - Search for videos.", kQuickParseUrl, "SUBSCRIBE", "STAUTS", "UNSUBSCRIBE", "HELP", "VIDEOS"); IAccIm im = session.CreateIm(reply, "text/html"); imSession.SendIm(im); } } private void ReplyGarbage(IAccSession session, IAccImSession imSession, string sender) { if (sender.IndexOf('+') >= 0) { string reply = "This is the help for the MashupSportsBot! Commands are: subscribe, status, unsubscribe, help."; IAccIm im = session.CreateIm(reply, "text/plain"); imSession.SendIm(im); } else { string reply = string.Format("This is the help for the MashupSportsBot! To use the bot please do one of send the following:
1. {1} - Subscribe to the bot.
2. {2} - Get Latest Cricket News.
3. {3} - Unsubscribe from the bot.
4. {4} - Get help from the bot.
5. {5} - Search for videos.", kQuickParseUrl, "SUBSCRIBE", "STAUTS", "UNSUBSCRIBE", "HELP", "VIDEOS"); IAccIm im = session.CreateIm(reply, "text/html"); imSession.SendIm(im); } } private void ReplySub(IAccSession session, IAccImSession imSession, bool leaving) { IAccIm im; if (leaving) im = session.CreateIm(kUnSub, "text/plain"); else im = session.CreateIm(kSub, "text/plain"); imSession.SendIm(im); } private void ReplyStatus(IAccSession session, IAccImSession imSession, string sender) { IAccIm im = session.CreateIm(m_replyText, "text/html"); if (sender.IndexOf('+') >= 0) { string plain = im.GetConvertedText("text/plain"); IAccIm im2 = session.CreateIm(plain, "text/plain"); imSession.SendIm(im2); return; } imSession.SendIm(im); } private void ReplyToSubList() { int count = m_subList.Count; for (int i = 0; i < count; i++) { string subscriber = (string)m_subList[i]; IAccImSession ims = s.CreateImSession(subscriber, AccImSessionType.AccImSessionType_Im); IAccIm im = s.CreateIm(m_replyText, "text/html"); ims.SendIm(im); DateTime CurrTime = DateTime.Now; Console.WriteLine("> An update alert was sent to {0} @: {1:G}", subscriber, CurrTime); } return; } private void UpdateState() { try { string url = kQuickParseUrl; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Stream stream = resp.GetResponseStream(); StreamReader reader = new StreamReader(stream); string buf = reader.ReadToEnd(); int lastUpdate = buf.IndexOf(""); lastUpdate = lastUpdate + 15; int endUpdate = buf.IndexOf(" No new sports news last updated @ {0}, checked @: {1:G}", m_lastUpdateTime, CurrTime); return; } else { Console.WriteLine("> Found new sports news new update time @ {0}, old update time @ {1} checked @: {2:G}", time, m_lastUpdateTime, CurrTime); ParseContent(); m_lastUpdateTime = time; ReplyToSubList(); } } catch (Exception e) { DumpException(e); } } private void ParseContent() { m_replyText = ""; m_replyText += ""; bool writeTitle = false, writeLink = false; string title = ""; XmlTextReader reader = new XmlTextReader(kQuickParseUrl); reader.WhitespaceHandling = WhitespaceHandling.None; while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name == "title") { writeTitle = true; } else if (reader.Name == "link") { writeLink = true; } break; case XmlNodeType.CDATA: case XmlNodeType.Text: if (writeTitle) { title = reader.Value; writeTitle = false; } else if (writeLink) { string link = string.Format("", reader.Value); m_replyText += link; m_replyText += title; m_replyText += "

"; writeTitle = false; writeLink = false; } break; } } reader.Close(); m_replyText += ""; return; } static private void DumpException(Exception e) { Console.WriteLine("{0}", e.ToString()); } } }