예제 #1
0
        private static void CheckForUnknownUserOrRoom(CampfireState campfireInfo, Message msg, ICampfireAPI api)
        {
            // If this userId isn't already known...
            if (!campfireInfo.IsUserKnown(msg.UserId))
            {
                // fetch all the user Info and then add
                User newUser = api.GetUser(msg.UserId);
                if ((newUser != null) && (newUser.Type == User.UserType.Member) && !string.IsNullOrEmpty(newUser.Name) && !string.IsNullOrEmpty(newUser.Email))
                {
                    Utils.TraceVerboseMessage(string.Format("Found a new User: {0}, Id: {1}", newUser.Name, newUser.Id));
                    campfireInfo.AddUser(newUser.Id, newUser.Name, newUser.Email, string.Empty);
                }
            }

            // If this roomId isn't already known...
            if (!campfireInfo.IsRoomKnown(msg.RoomId))
            {
                // fetch all the user Info and then add
                Room newRoom = api.GetRoom(msg.RoomId);
                if (newRoom != null)
                {
                    Utils.TraceVerboseMessage(string.Format("Found a new Room: {0}, Id: {1}", newRoom.Name, newRoom.Id));
                    campfireInfo.AddRoom(newRoom.Id, newRoom.Name, 0);
                }
            }
        }
예제 #2
0
        private static void ProcessMessages_ProcessQueuedMessages(CampfireState campfireInfo, ICampfireAPI api)
        {
            /*
             * For each message that comes from any room:
             *   Remove any entry in “PendingNotification” collection where PendingNotification.user is message.author (and room's match)
             *       (e.g he’s already participating after being called out so no need to notify)
             *   If there’s a User Reference match
             *       Enter (user, time, room) into a PendingNotification collection
             *           (unless user/room already exists in collection)
             *
             * For each entry in PendingNotification
             *   If entry.timestamp  is < Now – entry.user.ConfiguredDelay then
             *        Send that user a notification that he’s been called out in entry.room
             */

            Message msg;

            while ((msg = campfireInfo.PopMessage()) != null)
            {
                CheckForUnknownUserOrRoom(campfireInfo, msg, api);

                if (msg.Type == Message.MType.EnterMessage)
                {
                    ProcessEnterMessage(campfireInfo, msg, api);
                }
                else if (msg.Type == Message.MType.TextMessage)
                {
                    ProcessTextMessage(campfireInfo, msg, api);
                }
            }

            TriggerNotifications(campfireInfo);         // Now look to fire any pending notifications
        }
예제 #3
0
        private static void ProcessMessages_FetchNewMessages(CampfireState campfireInfo, ICampfireAPI api)
        {
            IList <CampfireState.RoomInfo> rooms = campfireInfo.Rooms;

            foreach (CampfireState.RoomInfo room in rooms)
            {
                List <Message> msgs;
                try
                {
                    msgs = api.RecentMessages(room.Id, room.LastMessageId, Message.MType.TextMessage | Message.MType.EnterMessage);
                }
                catch (System.Net.WebException ex)
                {
                    // oops. Let's break out and then try again later
                    Utils.TraceException(TraceLevel.Warning, ex, "Exception calling API.RecentMessages");
                    break;
                }

                int lastMsgId = 0;
                foreach (Message msg in msgs)
                {
                    lastMsgId = msg.Id;
                    QueueMessage(campfireInfo, msg);
                }

                if (lastMsgId != 0)
                {
                    // remember that we've now processed through this message Id. So next time we're only fetch newer messages
                    campfireInfo.UpdateLastMessageId(room.Id, lastMsgId);
                }
            }
        }
예제 #4
0
        public static bool Initialize(string storePath, INotifier notifier)
        {
            bool success = true;

            if (Instance == null)
            {
                BackingStorePath = string.Format(@"{0}\{1}", storePath, "CampfireInfo.xml");

                Instance = Restore(BackingStorePath);

                if (Instance == null)
                {
                    // Data in the xml file was corrupt/unreadable
                    success  = false;
                    Instance = new CampfireState();
                }

                if (notifier == null)
                {
                    notifier = new Notifier();
                }

                Instance.Notifier = notifier;
            }
            return(success);
        }
예제 #5
0
 /// <summary>
 /// (Thread Safe) Save state to persistant store
 /// </summary>
 public void Save()
 {
     lock (this.saveLock)
     {
         CampfireState.SaveToStore(this);
     }
 }
예제 #6
0
 /// <summary>
 /// Retrieve all 'new' messages from each room. And then "process" them.
 /// </summary>
 /// <param name="campfireInfo"></param>
 /// <param name="api"></param>
 private static void Work_ProcessNewMessagesForAllRooms(CampfireState campfireInfo, ICampfireAPI api)
 {
     /*
      * 2 phases:
      *  - fetch all new message for all the rooms. Plase messages into appropriate queue
      *  - Process all those queue up messages, in order
      *
      * Structuring this as 2 phases in case they are even executes by different threads. E.g. a thread for each room "waiting" on messages.
      */
     ProcessMessages_FetchNewMessages(campfireInfo, api);
     ProcessMessages_ProcessQueuedMessages(campfireInfo, api);
 }
예제 #7
0
        private static void TriggerNotifications(CampfireState campfireInfo)
        {
            IList <CampfireState.PendingNotify> pending = campfireInfo.PendingNotifications;

            foreach (CampfireState.PendingNotify pn in pending)
            {
                if (pn.TriggerTime < DateTime.Now)
                {
                    TriggerNotification(campfireInfo, pn.Reference);                                            // send notification
                    campfireInfo.RemovePendingNotification(pn.Reference.TargetUser.Id, pn.Reference.Room.Id);   // remove from pending list
                }
            }
        }
예제 #8
0
        private static void TriggerNotification(CampfireState campfireInfo, CampfireState.UserReference userRef)
        {
            if ((userRef.TargetUser != null) && (userRef.Room != null))
            {
                string email = userRef.TargetUser.SmokeEmail;

                Utils.TraceVerboseMessage(string.Format("Sending notification: User: {0}, Room: {1}, SmokeEmail: {2}",
                                                        userRef.TargetUser.Name, userRef.Room.Name, userRef.TargetUser.SmokeEmail));

                string userName = (userRef.SourceUser != null) ? userRef.SourceUser.Name : "guest";

                campfireInfo.Notifier.Doit(userRef.TargetUser.Name, userRef.Room.Name, userRef.Room.Id, email,
                                           SmokeSignalConfig.Instance.CampfireName, userName, userRef.NearByText);
            }
        }
예제 #9
0
        public static void TraceMessage(TraceLevel level, Message msg, string extraText)
        {
            CampfireState campState = CampfireState.Instance;
            IList <CampfireState.UserInfo> allUsers = campState.Users;

            CampfireState.UserInfo user = allUsers.FirstOrDefault(u => u.Id == msg.UserId);
            string userName             = (user != null) ? user.NickName : msg.UserId.ToString();

            CampfireState.RoomInfo room = campState.Rooms.FirstOrDefault(r => r.Id == msg.RoomId);
            string roomName             = (room != null) ? room.Name : msg.RoomId.ToString();

            TraceMessage(level, string.Format("At: {0}, User: {1}, Room: {2}, {3}{4}{5}",
                                              msg.PostedAt.ToString(), userName, roomName,
                                              (extraText ?? ""), (!string.IsNullOrEmpty(extraText)) ? ": " : "", msg.TrimmedBody));
        }
예제 #10
0
        public void SendSettings(CampfireState.UserInfo user, bool haveChanged)
        {
            if (user == null) return;

            try
            {
                MailMessage msg = new MailMessage();

                msg.To.Add(new MailAddress(user.EmailAddress));
                msg.BodyEncoding = Encoding.ASCII;
                msg.Subject = string.Format(haveChanged ? "Your Smoke Signal settings have changed..." : "Your Smoke Signal settings");
                StringBuilder sb = new StringBuilder();

                AppendWithNewLine(sb, string.Format("Dear {0}", user.NickName));
                AppendWithNewLine(sb);

                AppendWithNewLine(sb, string.Format(haveChanged
                    ? "Your SmokeSignal settings have been changed per your request:"
                    : "Here are the Smoke Signal settings as requested:"));

                int delay = user.DelayInMinutes > 0 ? user.DelayInMinutes : SmokeSignalConfig.Instance.DelayBeforeSmokeSignalInMinutes;
                bool defaultDelay = user.DelayInMinutes < 1;

                AppendWithNewLine(sb, string.Format("    Campfire Email     : {0}", user.EmailAddress));
                AppendWithNewLine(sb, string.Format("    Smoke Signal Email : {0}", user.SmokeEmail));
                AppendWithNewLine(sb, string.Format("    Delay In Minutes   : {0}{1}", delay, defaultDelay ? " (default)" : ""));

                AppendWithNewLine(sb);
                AppendWithNewLine(sb, "Sincerely,");
                AppendWithNewLine(sb, "Smoke Signal");

                msg.Body = sb.ToString();

                SmtpClient smtp = ConfigSmtpClient();

                Utils.TraceInfoMessage(string.Format("Sending Settings email. {0}", user.EmailAddress));

                smtp.Send(msg);
            }
            catch (InvalidOperationException ex)
            {
                Utils.TraceException(TraceLevel.Error, ex, "Exception trying to send a help email");
            }
            catch (SmtpException ex)
            {
                Utils.TraceException(TraceLevel.Error, ex, "Exception trying to send a help email");
            }
        }
예제 #11
0
        private static void SaveToStore(CampfireState state, string toPath)
        {
            if (!System.IO.File.Exists(toPath))
            {
                string dir = System.IO.Path.GetDirectoryName(toPath);
                if (!System.IO.Directory.Exists(dir))
                {
                    System.IO.Directory.CreateDirectory(dir);
                }
            }

            XmlSerializer ser = new XmlSerializer(typeof(CampfireState));

            System.IO.StreamWriter file = new System.IO.StreamWriter(toPath);

            ser.Serialize(file, state);
            file.Close();
        }
예제 #12
0
        /// <summary>
        /// This is called every so often to check if users Names or Email address has changed, or User has been Deleted
        /// </summary>
        /// <param name="campfireInfo"></param>
        private static void Work_ScanForUserChanges(CampfireState campfireInfo, ICampfireAPI api)
        {
            // iterate of all known users... and see if name or email address has changed
            // Must do this in a thread safe fashion by first getting all the ids.
            List <int> userIds = campfireInfo.UserIds();

            foreach (int uid in userIds)
            {
                User user = api.GetUser(uid);
                if (user != null && !string.IsNullOrEmpty(user.Name) && !string.IsNullOrEmpty(user.Email))
                {
                    campfireInfo.UpdateUser(user.Id, user.Name, user.Email);
                }
                else
                {
                    campfireInfo.DeleteUser(uid);
                }
            }
        }
예제 #13
0
 private static void QueueMessage(CampfireState campfireInfo, Message msg)
 {
     if (msg.Type == Message.MType.TextMessage)
     {
         // only process messages posted within the last 1 hour
         if (msg.PostedAt >= DateTime.Now.AddHours(-1))
         {
             // put msg into the Text Queue
             Utils.TraceVerboseMessage(msg, "Msg");
             campfireInfo.QueueMessage(msg);
         }
     }
     else if (msg.Type == Message.MType.EnterMessage)
     {
         // put msg into the Enter Queue
         Utils.TraceVerboseMessage(msg, "Enter");
         campfireInfo.QueueMessage(msg);
     }
 }
예제 #14
0
        private static void ProcessTextMessage(CampfireState campfireInfo, Message msg, ICampfireAPI api)
        {
            // The person that posted this message... If they have a pending notification in the room... then cancel it... they've spoken
            campfireInfo.RemovePendingNotification(msg.UserId, msg.RoomId, msg.PostedAt, true);

            IList <CampfireState.UserInfo> allUsers = campfireInfo.Users;

            IList <CampfireState.UserReference> lazyNotificationUsers;
            IList <CampfireState.UserReference> immediateNotificationUsers;
            IList <CampfireState.UserReference> smokeSignalReferences;

            Utils.FindUserReferences(msg.Body, allUsers, out lazyNotificationUsers, out immediateNotificationUsers, out smokeSignalReferences);

            CampfireState.UserInfo source = allUsers.FirstOrDefault(u => u.Id == msg.UserId);
            CampfireState.RoomInfo room   = CampfireState.Instance.Rooms.FirstOrDefault(r => r.Id == msg.RoomId);

            // special smoke signal commands only make sense if a legitimate user issued them
            if (source != null)
            {
                foreach (CampfireState.UserReference ri in smokeSignalReferences)
                {
                    ri.SourceUser = source;
                    ri.Room       = room;
                    ProcessSmokeSignalCommands(source.Id, ri);
                }
            }

            foreach (CampfireState.UserReference ri in immediateNotificationUsers)
            {
                ri.SourceUser = source;
                ri.Room       = room;
                campfireInfo.AddPendingNotification(ri, msg.PostedAt.AddSeconds(0));
            }
            foreach (CampfireState.UserReference ri in lazyNotificationUsers)
            {
                ri.SourceUser = source;
                ri.Room       = room;

                int delay = ri.TargetUser.DelayInMinutes > 0 ? ri.TargetUser.DelayInMinutes : SmokeSignalConfig.Instance.DelayBeforeSmokeSignalInMinutes;
                campfireInfo.AddPendingNotification(ri, msg.PostedAt.AddSeconds(delay * 60));
            }
        }
예제 #15
0
        /// <summary>
        /// This is called every so often to update the known list of rooms
        /// </summary>
        /// <param name="campfireInfo"></param>
        private static void Work_ScanForAddOrRemoveRooms(CampfireState campfireInfo, ICampfireAPI api)
        {
            List <int> roomIds = campfireInfo.RoomIds();

            List <Room> rooms = api.Rooms();

            foreach (Room r in rooms)
            {
                // since r.id exists, remove it from 'roomIds'
                roomIds.Remove(r.Id);
            }
            List <int> roomsToDelete = roomIds;

            foreach (int roomToDeleteId in roomsToDelete)
            {
                campfireInfo.DeleteRoom(roomToDeleteId);
            }

            campfireInfo.AddRooms(rooms);
        }
예제 #16
0
        private static CampfireState Restore(string fromPath)
        {
            CampfireState campInfo = null;
            bool          error    = false;

            if (!System.IO.File.Exists(fromPath))
            {
                campInfo = new CampfireState();
                campInfo.Save();
                return(campInfo);
            }

            Exception caughtException = null;

            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(fromPath);

                XmlSerializer ser = new XmlSerializer(typeof(CampfireState));
                using (StringReader reader = new StringReader(xmlDoc.OuterXml))
                {
                    campInfo = (CampfireState)ser.Deserialize(reader);
                    reader.Close();
                }
            }
            catch (XmlException ex) { caughtException = ex; }
            catch (IOException ex) { caughtException = ex; }
            catch (UnauthorizedAccessException ex) { caughtException = ex; }
            catch (System.Security.SecurityException ex) { caughtException = ex; }
            catch (InvalidOperationException ex) { caughtException = ex; }

            if (caughtException != null)
            {
                // xml file was corrupt. Make a backup and delete original
                Utils.TraceException(TraceLevel.Error, caughtException, string.Format("Campfile.xml was corrupt. Making a backup and starting with a new file."));
                error = Utils.SafeBackupAndDelete(fromPath);
            }

            return(campInfo);
        }
예제 #17
0
 private static void SaveToStore(CampfireState state)
 {
     CampfireState.SaveToStore(state, BackingStorePath);
 }
예제 #18
0
 /// <summary>
 /// Several duties. Starts a thread which looks for new rooms every X minutes.
 /// Starts a thread which read messages for rooms.
 /// </summary>
 public MessageProcessor(CampfireState campfireInfo)
 {
     this.CampfireInfo  = campfireInfo;
     this.WorkerThreads = new List <Thread>();
 }
예제 #19
0
        private static void TriggerNotification(CampfireState campfireInfo, CampfireState.UserReference userRef)
        {
            if ((userRef.TargetUser != null) && (userRef.Room != null))
            {
                string email = userRef.TargetUser.SmokeEmail;

                Utils.TraceVerboseMessage(string.Format("Sending notification: User: {0}, Room: {1}, SmokeEmail: {2}",
                    userRef.TargetUser.Name, userRef.Room.Name, userRef.TargetUser.SmokeEmail));

                string userName = (userRef.SourceUser != null) ? userRef.SourceUser.Name : "guest";

                campfireInfo.Notifier.Doit(userRef.TargetUser.Name, userRef.Room.Name, userRef.Room.Id, email,
                    SmokeSignalConfig.Instance.CampfireName, userName, userRef.NearByText);
            }
        }
예제 #20
0
        /// <summary>
        /// This is called every so often to check if users Names or Email address has changed, or User has been Deleted
        /// </summary>
        /// <param name="campfireInfo"></param>
        private static void Work_ScanForUserChanges(CampfireState campfireInfo, ICampfireAPI api)
        {
            // iterate of all known users... and see if name or email address has changed
            // Must do this in a thread safe fashion by first getting all the ids.
            List<int> userIds = campfireInfo.UserIds();

            foreach (int uid in userIds)
            {
                User user = api.GetUser(uid);
                if (user != null && !string.IsNullOrEmpty(user.Name) && !string.IsNullOrEmpty(user.Email))
                {
                    campfireInfo.UpdateUser(user.Id, user.Name, user.Email);
                }
                else
                {
                    campfireInfo.DeleteUser(uid);
                }
            }
        }
예제 #21
0
        /// <summary>
        /// This is called every so often to update the known list of rooms
        /// </summary>
        /// <param name="campfireInfo"></param>
        private static void Work_ScanForAddOrRemoveRooms(CampfireState campfireInfo, ICampfireAPI api)
        {
            List<int> roomIds = campfireInfo.RoomIds();

            List<Room> rooms = api.Rooms();

            foreach (Room r in rooms)
            {
                // since r.id exists, remove it from 'roomIds'
                roomIds.Remove(r.Id);
            }
            List<int> roomsToDelete = roomIds;
            foreach (int roomToDeleteId in roomsToDelete)
            {
                campfireInfo.DeleteRoom(roomToDeleteId);
            }

            campfireInfo.AddRooms(rooms);
        }
예제 #22
0
 /// <summary>
 /// Retrieve all 'new' messages from each room. And then "process" them.
 /// </summary>
 /// <param name="campfireInfo"></param>
 /// <param name="api"></param>
 private static void Work_ProcessNewMessagesForAllRooms(CampfireState campfireInfo, ICampfireAPI api)
 {
     /*
      * 2 phases:
      *  - fetch all new message for all the rooms. Plase messages into appropriate queue
      *  - Process all those queue up messages, in order
      *  
      * Structuring this as 2 phases in case they are even executes by different threads. E.g. a thread for each room "waiting" on messages.
      */
     ProcessMessages_FetchNewMessages(campfireInfo, api);
     ProcessMessages_ProcessQueuedMessages(campfireInfo, api);
 }
예제 #23
0
        private static void ProcessTextMessage(CampfireState campfireInfo, Message msg, ICampfireAPI api)
        {
            // The person that posted this message... If they have a pending notification in the room... then cancel it... they've spoken
            campfireInfo.RemovePendingNotification(msg.UserId, msg.RoomId, msg.PostedAt, true);

            IList<CampfireState.UserInfo> allUsers = campfireInfo.Users;

            IList<CampfireState.UserReference> lazyNotificationUsers;
            IList<CampfireState.UserReference> immediateNotificationUsers;
            IList<CampfireState.UserReference> smokeSignalReferences;
            Utils.FindUserReferences(msg.Body, allUsers, out lazyNotificationUsers, out immediateNotificationUsers, out smokeSignalReferences);

            CampfireState.UserInfo source = allUsers.FirstOrDefault(u => u.Id == msg.UserId);
            CampfireState.RoomInfo room = CampfireState.Instance.Rooms.FirstOrDefault(r => r.Id == msg.RoomId);

            // special smoke signal commands only make sense if a legitimate user issued them
            if (source != null)
            {
                foreach (CampfireState.UserReference ri in smokeSignalReferences)
                {
                    ri.SourceUser = source;
                    ri.Room = room;
                    ProcessSmokeSignalCommands(source.Id, ri);
                }
            }

            foreach (CampfireState.UserReference ri in immediateNotificationUsers)
            {
                ri.SourceUser = source;
                ri.Room = room;
                campfireInfo.AddPendingNotification(ri, msg.PostedAt.AddSeconds(0));
            }
            foreach (CampfireState.UserReference ri in lazyNotificationUsers)
            {
                ri.SourceUser = source;
                ri.Room = room;

                int delay = ri.TargetUser.DelayInMinutes > 0 ? ri.TargetUser.DelayInMinutes : SmokeSignalConfig.Instance.DelayBeforeSmokeSignalInMinutes;
                campfireInfo.AddPendingNotification(ri, msg.PostedAt.AddSeconds(delay * 60));
            }
        }
예제 #24
0
        private static void ProcessSmokeSignalCommands(int userId, CampfireState.UserReference ri)
        {
            // ??? Should a syntax error generate an email to the user explaining the problem?

            int pos = ri.NearByText.IndexOf(':');
            if (pos < 0) return;

            string cmd = ri.NearByText.Remove(0, pos + 1);
            string[] args = cmd.Split('=');

            switch (args[0].ToLowerInvariant())
            {
                case "help":
                    CampfireState.Instance.Notifier.SendHelp(ri.SourceUser.Name, ri.SourceUser.EmailAddress);
                    break;
                case "settings":
                    CampfireState.Instance.Notifier.SendSettings(ri.SourceUser, false);
                    break;
                case "delay":
                    int newDelay;
                    string newDelayStr = "";
                    if (args.Length > 2) return;
                    if (args.Length == 2) newDelayStr = args[1];
                    if (string.IsNullOrEmpty(newDelayStr)) newDelayStr = "-1";

                    if (Int32.TryParse(newDelayStr, out newDelay))
                    {
                        ri.SourceUser = CampfireState.Instance.UpdateUser(userId, newDelay);
                        CampfireState.Instance.Notifier.SendSettings(ri.SourceUser, true);
                    }
                    break;
                case "altemail":
                    string newEmail = null;
                    if (args.Length > 2) return;
                    if (args.Length == 2) newEmail = args[1];

                    if (!string.IsNullOrEmpty(newEmail) && !IsValidEmail(newEmail))
                    {
                        return;
                    }

                    ri.SourceUser = CampfireState.Instance.UpdateAltEmail(ri.SourceUser.Id, newEmail);
                    CampfireState.Instance.Notifier.SendSettings(ri.SourceUser, true);
                    break;
                default:
                    break;
            }
        }
예제 #25
0
 private static void ProcessEnterMessage(CampfireState campfireInfo, Message msg, ICampfireAPI api)
 {
     // remove any pending notifications for this user in the room in which this Enter message appeared
     campfireInfo.RemovePendingNotification(msg.UserId, msg.RoomId, msg.PostedAt, true);
 }
예제 #26
0
        private static CampfireState.UserReference InitReferenceInfo(string text, string target, CampfireState.UserInfo user, bool smokeSignalCommands)
        {
            string refText;

            if (smokeSignalCommands)
            {
                refText = target;
            }
            else if (text.Length < 80)
            {
                refText = text;
            }
            else
            {
                try
                {
                    refText = FindSentenceContaining(text, target);
                }
                catch (ArgumentException ex)
                {
                    refText = string.Empty;
                }
            }

            return new CampfireState.UserReference(refText, user);
        }
예제 #27
0
        private static void SaveToStore(CampfireState state, string toPath)
        {
            if (!System.IO.File.Exists(toPath))
            {
                string dir = System.IO.Path.GetDirectoryName(toPath);
                if (!System.IO.Directory.Exists(dir))
                {
                    System.IO.Directory.CreateDirectory(dir);
                }
            }

            XmlSerializer ser = new XmlSerializer(typeof(CampfireState));

            System.IO.StreamWriter file = new System.IO.StreamWriter(toPath);

            ser.Serialize(file, state);
            file.Close();
        }
예제 #28
0
        private static CampfireState Restore(string fromPath)
        {
            CampfireState campInfo = null;
            bool error = false;

            if (!System.IO.File.Exists(fromPath))
            {
                campInfo = new CampfireState();
                campInfo.Save();
                return campInfo;
            }

            Exception caughtException = null;
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(fromPath);

                XmlSerializer ser = new XmlSerializer(typeof(CampfireState));
                using (StringReader reader = new StringReader(xmlDoc.OuterXml))
                {
                    campInfo = (CampfireState)ser.Deserialize(reader);
                    reader.Close();
                }
            }
            catch (XmlException ex) { caughtException = ex; }
            catch (IOException ex) { caughtException = ex; }
            catch (UnauthorizedAccessException ex) { caughtException = ex; }
            catch (System.Security.SecurityException ex) { caughtException = ex; }
            catch (InvalidOperationException ex) { caughtException = ex; }

            if (caughtException != null)
            {
                // xml file was corrupt. Make a backup and delete original
                Utils.TraceException(TraceLevel.Error, caughtException, string.Format("Campfile.xml was corrupt. Making a backup and starting with a new file."));
                error = Utils.SafeBackupAndDelete(fromPath);
            }

            return campInfo;
        }
예제 #29
0
 public UserReference(string text, CampfireState.UserInfo target)
 {
     this.TargetUser = target;
     this.NearByText = text;
 }
예제 #30
0
 private static void ProcessEnterMessage(CampfireState campfireInfo, Message msg, ICampfireAPI api)
 {
     // remove any pending notifications for this user in the room in which this Enter message appeared
     campfireInfo.RemovePendingNotification(msg.UserId, msg.RoomId, msg.PostedAt, true);
 }
예제 #31
0
        private static void ProcessMessages_FetchNewMessages(CampfireState campfireInfo, ICampfireAPI api)
        {
            IList<CampfireState.RoomInfo> rooms = campfireInfo.Rooms;

            foreach (CampfireState.RoomInfo room in rooms)
            {
                List<Message> msgs;
                try
                {
                    msgs = api.RecentMessages(room.Id, room.LastMessageId, Message.MType.TextMessage | Message.MType.EnterMessage);
                }
                catch (System.Net.WebException ex)
                {
                    // oops. Let's break out and then try again later
                    Utils.TraceException(TraceLevel.Warning, ex, "Exception calling API.RecentMessages");
                    break;
                }

                int lastMsgId = 0;
                foreach (Message msg in msgs)
                {
                    lastMsgId = msg.Id;
                    QueueMessage(campfireInfo, msg);
                }

                if (lastMsgId != 0)
                {
                    // remember that we've now processed through this message Id. So next time we're only fetch newer messages
                    campfireInfo.UpdateLastMessageId(room.Id, lastMsgId);
                }
            }
        }
예제 #32
0
 private static void QueueMessage(CampfireState campfireInfo, Message msg)
 {
     if (msg.Type == Message.MType.TextMessage)
     {
         // only process messages posted within the last 1 hour
         if (msg.PostedAt >= DateTime.Now.AddHours(-1))
         {
             // put msg into the Text Queue
             Utils.TraceVerboseMessage(msg, "Msg");
             campfireInfo.QueueMessage(msg);
         }
     }
     else if (msg.Type == Message.MType.EnterMessage)
     {
         // put msg into the Enter Queue
         Utils.TraceVerboseMessage(msg, "Enter");
         campfireInfo.QueueMessage(msg);
     }
 }
예제 #33
0
        public static bool Initialize(string storePath, INotifier notifier)
        {
            bool success = true;
            if (Instance == null)
            {
                BackingStorePath = string.Format(@"{0}\{1}", storePath, "CampfireInfo.xml");

                Instance = Restore(BackingStorePath);

                if (Instance == null)
                {
                    // Data in the xml file was corrupt/unreadable
                    success = false;
                    Instance = new CampfireState();
                }

                if (notifier == null)
                {
                    notifier = new Notifier();
                }

                Instance.Notifier = notifier;
            }
            return success;
        }
예제 #34
0
        private static void ProcessMessages_ProcessQueuedMessages(CampfireState campfireInfo, ICampfireAPI api)
        {
            /*
             For each message that comes from any room:
                 Remove any entry in “PendingNotification” collection where PendingNotification.user is message.author (and room's match)
                     (e.g he’s already participating after being called out so no need to notify)
                 If there’s a User Reference match
                     Enter (user, time, room) into a PendingNotification collection 
                         (unless user/room already exists in collection)
                    
             For each entry in PendingNotification
                 If entry.timestamp  is < Now – entry.user.ConfiguredDelay then
                      Send that user a notification that he’s been called out in entry.room
            */
            
            Message msg;
            while ((msg = campfireInfo.PopMessage()) != null)
            {
                CheckForUnknownUserOrRoom(campfireInfo, msg, api);

                if (msg.Type == Message.MType.EnterMessage)
                {
                    ProcessEnterMessage(campfireInfo, msg, api);
                }
                else if (msg.Type == Message.MType.TextMessage)
                {
                    ProcessTextMessage(campfireInfo, msg, api);
                }

            }

            TriggerNotifications(campfireInfo);         // Now look to fire any pending notifications
        }
예제 #35
0
 private static void SaveToStore(CampfireState state)
 {
     CampfireState.SaveToStore(state, BackingStorePath);
 }
예제 #36
0
        private static void CheckForUnknownUserOrRoom(CampfireState campfireInfo, Message msg, ICampfireAPI api)
        {
            // If this userId isn't already known...
            if (!campfireInfo.IsUserKnown(msg.UserId))
            {
                // fetch all the user Info and then add
                User newUser = api.GetUser(msg.UserId);
                if ((newUser != null) && (newUser.Type == User.UserType.Member) && !string.IsNullOrEmpty(newUser.Name) && !string.IsNullOrEmpty(newUser.Email))
                {
                    Utils.TraceVerboseMessage(string.Format("Found a new User: {0}, Id: {1}", newUser.Name, newUser.Id));
                    campfireInfo.AddUser(newUser.Id, newUser.Name, newUser.Email, string.Empty);
                }
            }

            // If this roomId isn't already known...
            if (!campfireInfo.IsRoomKnown(msg.RoomId))
            {
                // fetch all the user Info and then add
                Room newRoom = api.GetRoom(msg.RoomId);
                if (newRoom != null)
                {
                    Utils.TraceVerboseMessage(string.Format("Found a new Room: {0}, Id: {1}", newRoom.Name, newRoom.Id));
                    campfireInfo.AddRoom(newRoom.Id, newRoom.Name, 0);
                }
            }
        }
예제 #37
0
 public void SendSettings(CampfireState.UserInfo user, bool haveChanged)
 {
     LogSent(user.Name, null, "Settings-Email");
 }
예제 #38
0
        private static void TriggerNotifications(CampfireState campfireInfo)
        {
            IList<CampfireState.PendingNotify> pending = campfireInfo.PendingNotifications;

            foreach (CampfireState.PendingNotify pn in pending)
            {
                if (pn.TriggerTime < DateTime.Now)
                {
                    TriggerNotification(campfireInfo, pn.Reference);                                            // send notification
                    campfireInfo.RemovePendingNotification(pn.Reference.TargetUser.Id, pn.Reference.Room.Id);   // remove from pending list
                }
            }
        }
예제 #39
0
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private void Match(CampfireState expected, CampfireState actual)
        {
            Assert.AreEqual(expected.Users.Count, actual.Users.Count);
            Assert.AreEqual(expected.Rooms.Count, actual.Rooms.Count);

            foreach (CampfireState.RoomInfo room in expected.Rooms)
            {
                Assert.IsTrue(actual.Rooms.Count(r => r.Id == room.Id && r.LastMessageId == room.LastMessageId && r.Name == room.Name) == 1);
            }

            foreach (CampfireState.UserInfo user in expected.Users)
            {
                Assert.IsTrue(actual.Users.Count(u => u.Id == user.Id && 
                                                        u.Name == user.Name && 
                                                        u.EmailAddress == user.EmailAddress &&
                                                        u.AltEmailAddress == user.AltEmailAddress) == 1);
            }
        }
예제 #40
0
 /// <summary>
 /// Several duties. Starts a thread which looks for new rooms every X minutes.
 /// Starts a thread which read messages for rooms.
 /// </summary>
 public MessageProcessor(CampfireState campfireInfo)
 {
     this.CampfireInfo = campfireInfo;
     this.WorkerThreads = new List<Thread>();
 }