Exemple #1
0
        internal static async void UpdateGroupLegibleID(BubbleGroup bubbleGroup, Action finished = null)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            try
            {
                await service.GetBubbleGroupLegibleId(bubbleGroup, legibleID =>
                {
                    bubbleGroup.LegibleId = legibleID;
                    if (finished == null)
                    {
                        BubbleGroupEvents.RaiseRefreshed(bubbleGroup);
                    }
                    else
                    {
                        finished();
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group legible ID: " + service.Information.ServiceName +
                                 " - " + bubbleGroup.Address + ": " + ex);
                if (finished != null)
                {
                    finished();
                }
            }
        }
        public static bool UpdatePhoto(BubbleGroup bubbleGroup, Action <DisaThumbnail> finished)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return(false);
            }

            if (bubbleGroup.Service.Information.UsesInternet && !Platform.HasInternetConnection())
            {
                return(false);
            }

            try
            {
                service.GetBubbleGroupPhoto(bubbleGroup, photo =>
                {
                    if (photo != null && photo.Failed)
                    {
                        if (finished != null)
                        {
                            finished(bubbleGroup.Photo);
                        }
                        return;
                    }

                    Action <DisaThumbnail> callbackFinished = thePhoto =>
                    {
                        bubbleGroup.Photo = thePhoto;
                        bubbleGroup.IsPhotoSetFromService = true;
                        if (finished != null)
                        {
                            finished(bubbleGroup.Photo);
                        }
                    };

                    if (photo == null && bubbleGroup.IsParty)
                    {
                        BubbleGroupUtils.StitchPartyPhoto(bubbleGroup, callbackFinished);
                    }
                    else
                    {
                        callbackFinished(photo);
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group photo: " +
                                 service.Information.ServiceName + ": " + ex.Message);
                if (finished != null)
                {
                    finished(null);
                }
            }

            return(true);
        }
Exemple #3
0
        public static void SendPresence(Service service, bool available, bool justAddIfNoLastPresence = false)
        {
            if (!service.Information.DoesSupport(typeof(PresenceBubble)))
            {
                return;
            }

            var presenceBubble = new PresenceBubble(Time.GetNowUnixTimestamp(),
                                                    Bubble.BubbleDirection.Outgoing, null,
                                                    false, service, available);

            Utils.DebugPrint("Sending " + (presenceBubble.Available
                ? "available"
                : "unavailble") + " to " +
                             presenceBubble.Service.Information.ServiceName);
            lock (LastPresenceBubbles)
            {
                Action a = () =>
                {
                    LastPresenceBubbles.RemoveAll(pb => pb.Service == presenceBubble.Service);
                    LastPresenceBubbles.Add(presenceBubble);
                };
                if (!justAddIfNoLastPresence)
                {
                    a();
                }
                else
                {
                    var hasPresence = LastPresenceBubbles.Any(x => x.Service == presenceBubble.Service);
                    if (hasPresence)
                    {
                        // do-nothing
                    }
                    else
                    {
                        a();
                    }
                }
            }

            if (!justAddIfNoLastPresence && ServiceManager.IsRunning(service))
            {
                Send(presenceBubble);
            }

            if (justAddIfNoLastPresence)
            {
                return;
            }

            if (available)
            {
                return;
            }
            foreach (var group in BubbleGroupManager.FindAll(service))
            {
                @group.PresenceType = PresenceBubble.PresenceType.Unavailable;
            }
        }
        public static bool LoadFullyIfNeeded(BubbleGroup group, bool sync = false)
        {
            if (@group == null)
            {
                return(false);
            }

            var loadedSomething = false;

            lock (BubbleGroupDatabase.OperationLock)
            {
                var unifiedGroup = @group as UnifiedBubbleGroup;

                var associatedGroups = unifiedGroup != null
                    ? unifiedGroup.Groups.ToList()
                    : new[] { @group }.ToList();
                var associatedPartiallyLoadedGroups = associatedGroups.Where(x => x.PartiallyLoaded).ToList();
                foreach (var partiallyLoadedGroup in associatedPartiallyLoadedGroups)
                {
                    loadedSomething = true;
                    var partiallyLoadedBubblesToRemove = partiallyLoadedGroup.Bubbles.ToList();
                    foreach (var bubble in BubbleGroupDatabase.FetchBubbles(partiallyLoadedGroup).Reverse())
                    {
                        partiallyLoadedGroup.Bubbles.Add(bubble);
                    }
                    foreach (var partiallyLoadedBubbleToRemove in partiallyLoadedBubblesToRemove)
                    {
                        partiallyLoadedGroup.Bubbles.Remove(partiallyLoadedBubbleToRemove);
                    }
                    partiallyLoadedGroup.PartiallyLoaded = false;
                }

                if (unifiedGroup != null && !unifiedGroup.UnifiedGroupLoaded)
                {
                    Populate(unifiedGroup);
                }
            }

            if (!sync && loadedSomething)
            {
                Task.Factory.StartNew(() =>
                {
                    var unifiedGroup = @group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        BubbleQueueManager.Send(unifiedGroup.Groups.Where(x => ServiceManager.IsRunning(x.Service))
                                                .Select(x => x.Service.Information.ServiceName).ToArray());
                    }
                    else if (ServiceManager.IsRunning(@group.Service))
                    {
                        BubbleQueueManager.Send(new[] { @group.Service.Information.ServiceName });
                    }
                    BubbleManager.SetNotQueuedToFailures(@group);
                });
            }

            return(loadedSomething);
        }
        internal static void UpdateLastOnline(BubbleGroup bubbleGroup, bool updateUi = true, bool fromProcessUpdateLastOnlineQueue = false)
        {
            var service = bubbleGroup.Service;

            if (!fromProcessUpdateLastOnlineQueue)
            {
                if (!ServiceManager.IsRunning(service) && !bubbleGroup.IsParty)
                {
                    lock (UpdateLastOnlineQueue)
                        UpdateLastOnlineQueue.Add(new Tuple <BubbleGroup, bool>(bubbleGroup, updateUi));
                    return;
                }
            }

            if (!ServiceManager.IsRunning(service) || bubbleGroup.IsParty)
            {
                return;
            }

            // reject the last online update if the Presence is currently available
            if (bubbleGroup.Presence)
            {
                return;
            }

            try
            {
                service.GetBubbleGroupLastOnline(bubbleGroup, time =>
                {
                    // reject the last online update if the Presence is currently available
                    if (bubbleGroup.Presence)
                    {
                        return;
                    }

                    bubbleGroup.PresenceType = PresenceBubble.PresenceType.Unavailable;
                    bubbleGroup.LastSeen     = time;

                    if (updateUi)
                    {
                        BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup);
                    }

                    //we constantly need to subscribe to a bubble group. doing it
                    //in last online method is the most effective.
                    BubbleManager.SendSubscribe(bubbleGroup, true);
                    //Presence(service, true);
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group last online: " + service.Information.ServiceName + ": " +
                                 ex.Message);
            }
        }
        public static bool UpdateUnknownPartyParticipant(BubbleGroup bubbleGroup, string participantAddress, Action onAdded = null)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return(false);
            }

            if (string.IsNullOrWhiteSpace(participantAddress))
            {
                return(false);
            }

            if (bubbleGroup.FailedUnknownParticipants.FirstOrDefault(x =>
                                                                     bubbleGroup.Service.BubbleGroupComparer(x, participantAddress)) != null)
            {
                return(false);
            }

            try
            {
                service.GetBubbleGroupUnknownPartyParticipant(bubbleGroup, participantAddress, participant =>
                {
                    if (participant != null)
                    {
                        var contains = bubbleGroup.Participants.FirstOrDefault(x =>
                                                                               bubbleGroup.Service.BubbleGroupComparer(x.Address, participantAddress)) != null;
                        if (!contains)
                        {
                            participant.Unknown = true;
                            bubbleGroup.Participants.Add(participant);
                        }
                    }
                    else
                    {
                        bubbleGroup.FailedUnknownParticipants.Add(participantAddress);
                    }
                    if (onAdded != null)
                    {
                        onAdded();
                    }
                    BubbleGroupEvents.RaiseRefreshed(bubbleGroup);
                    BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup);
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error getting unknown bubble group participant: " + service.Information.ServiceName + ": " +
                                 ex.Message);
                return(false);
            }

            return(true);
        }
        internal static void UpdateLastOnline(BubbleGroup bubbleGroup, bool updateUi = true, bool fromProcessUpdateLastOnlineQueue = false)
        {
            var service = bubbleGroup.Service;

            if (!fromProcessUpdateLastOnlineQueue)
            {
                if (!ServiceManager.IsRunning(service) && !bubbleGroup.IsParty)
                {
                    Utils.DebugPrint(">>>>>>>>>>>>>> Stashing UpdateLastOnline for later.");
                    lock (UpdateLastOnlineQueue)
                        UpdateLastOnlineQueue.Add(new Tuple <BubbleGroup, bool>(bubbleGroup, updateUi));
                    return;
                }
            }

            if (!ServiceManager.IsRunning(service) || bubbleGroup.IsParty)
            {
                return;
            }

            // reject the last online update if the Presence is currently available
            if (bubbleGroup.Presence)
            {
                return;
            }

            try
            {
                Utils.DebugPrint(">>>>>>>>>>>>>> Calling GetBubbleGroupLastOnline.");
                service.GetBubbleGroupLastOnline(bubbleGroup, time =>
                {
                    // reject the last online update if the Presence is currently available
                    if (bubbleGroup.Presence)
                    {
                        return;
                    }

                    bubbleGroup.PresenceType = PresenceBubble.PresenceType.Unavailable;
                    bubbleGroup.LastSeen     = time;

                    if (updateUi)
                    {
                        BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup);
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group last online: " + service.Information.ServiceName + ": " +
                                 ex.Message);
            }
        }
        private static bool SupportsSyncAndIsRunning(Service service)
        {
            if (!ServiceManager.IsRunning(service))
            {
                return(false);
            }

            if (!SupportsSync(service))
            {
                return(false);
            }

            return(true);
        }
Exemple #9
0
 internal static void SyncService(Service service)
 {
     if (ServiceManager.IsRunning(service))
     {
         Utils.DebugPrint("Refreshing service contacts...");
         service.RefreshPhoneBookContacts();
     }
     else
     {
         Utils.DebugPrint("Force refreshing service " + service.Information.ServiceName +
                          " isn't possible. Why? It isn't running!");
     }
     Utils.DebugPrint("Finished refreshing service contacts. Calling contacts update and bubble group update.");
     BubbleGroupUpdater.Update(service);
 }
Exemple #10
0
        public static bool UpdateQuotedMessageTitle(VisualBubble bubble, Action <string> onTitleUpdated)
        {
            var service = bubble.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return(false);
            }
            if (string.IsNullOrWhiteSpace(bubble.QuotedAddress))
            {
                return(false);
            }

            try
            {
                service.GetQuotedMessageTitle(bubble, result =>
                {
                    var bubbleGroup = BubbleGroupManager.FindWithAddress(bubble.Service, bubble.Address);
                    if (bubbleGroup != null)
                    {
                        var quotedTitles = bubbleGroup.QuotedTitles == null ?
                                           new List <DisaQuotedTitle>() : bubbleGroup.QuotedTitles.ToList();
                        var quotedTitle = quotedTitles.FirstOrDefault(x =>
                                                                      bubbleGroup.Service.BubbleGroupComparer(x.Address, bubble.QuotedAddress));
                        if (quotedTitle == null)
                        {
                            quotedTitles.Add(new DisaQuotedTitle
                            {
                                Address = bubble.QuotedAddress,
                                Title   = result,
                            });
                        }
                        else
                        {
                            quotedTitle.Title = result;
                        }
                        bubbleGroup.QuotedTitles = quotedTitles.ToArray();
                    }
                    onTitleUpdated(result);
                });
                return(true);
            }
            catch (Exception e)
            {
                Utils.DebugPrint("Error getting quoted message title " + e);
                return(false);
            }
        }
Exemple #11
0
        public static async void UpdatePhoto(BubbleGroup bubbleGroup, Action <DisaThumbnail> finished)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            if (bubbleGroup.Service.Information.UsesInternet && !Platform.HasInternetConnection())
            {
                return;
            }

            try
            {
                await service.GetBubbleGroupPhoto(bubbleGroup, photo =>
                {
                    if (photo != null && photo.Failed)
                    {
                        if (finished != null)
                        {
                            finished(bubbleGroup.Photo);
                        }
                        return;
                    }

                    bubbleGroup.Photo = photo;
                    bubbleGroup.IsPhotoSetFromService = true;
                    if (finished != null)
                    {
                        finished(bubbleGroup.Photo);
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group photo: " + service.Information.ServiceName +
                                 " - " + bubbleGroup.Address + ": " + ex);
                if (finished != null)
                {
                    finished(null);
                }
            }
        }
Exemple #12
0
        public static async void UpdateParticipantPhoto(Service service, DisaParticipant participant, Action <DisaThumbnail> finished)
        {
            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            if (service.Information.UsesInternet && !Platform.HasInternetConnection())
            {
                return;
            }

            var participantClosure = participant;

            try
            {
                await service.GetBubbleGroupPartyParticipantPhoto(participant, result =>
                {
                    if (result != null && result.Failed)
                    {
                        if (finished != null)
                        {
                            finished(participantClosure.Photo);
                        }
                        return;
                    }

                    participantClosure.IsPhotoSetFromService = true;
                    participantClosure.Photo = result;
                    finished(result);
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group participant photo: " + service.Information.ServiceName +
                                 " - " + participant.Address + ": " + ex);
                if (finished != null)
                {
                    finished(null);
                }
            }

            return;
        }
Exemple #13
0
        internal static async void UpdateName(BubbleGroup bubbleGroup, Action finished = null)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            try
            {
                await service.GetBubbleGroupName(bubbleGroup, title =>
                {
                    bubbleGroup.IsTitleSetFromService = true;
                    if (string.IsNullOrWhiteSpace(title))
                    {
                        Utils.DebugPrint("Update name title is null (rejecting): " + service.Information.ServiceName +
                                         " - " + bubbleGroup.Address);
                    }
                    else
                    {
                        bubbleGroup.Title = title;
                    }
                    if (finished == null)
                    {
                        BubbleGroupEvents.RaiseRefreshed(bubbleGroup);
                        BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup);
                    }
                    else
                    {
                        finished();
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group name: " + service.Information.ServiceName +
                                 " - " + bubbleGroup.Address + ": " + ex);
                if (finished != null)
                {
                    finished();
                }
            }
        }
Exemple #14
0
        private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true)
        {
            var unifiedGroup = @group as UnifiedBubbleGroup;

            if (unifiedGroup != null)
            {
                foreach (var innerGroup in unifiedGroup.Groups)
                {
                    SetUnread(innerGroup, false, skipSendReadBubble);
                }
            }

            Action @do = () =>
            {
                var updatedSomething = BubbleGroupSettingsManager.GetUnread(@group);
                BubbleGroupSettingsManager.SetUnread(@group, unread);

                if (unifiedGroup == null)
                {
                    if (!skipSendReadBubble)
                    {
                        if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service))
                        {
                            BubbleManager.Send(new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing,
                                                              @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, updatedSomething));
                        }
                    }
                }

                if (updateUi)
                {
                    BubbleGroupEvents.RaiseRefreshed(@group);
                }
            };

            if (onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service))
            {
                @do();
            }
            else if (!onlySetIfServiceRunning)
            {
                @do();
            }
        }
        private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true)
        {
            var unifiedGroup = @group as UnifiedBubbleGroup;

            if (unifiedGroup != null)
            {
                foreach (var innerGroup in unifiedGroup.Groups)
                {
                    SetUnread(innerGroup, unread, false, skipSendReadBubble, onlySetIfServiceRunning);
                }
            }

            var currentlyUnread = BubbleGroupSettingsManager.GetUnread(@group);

            if ((onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service)) || !onlySetIfServiceRunning)
            {
                BubbleGroupSettingsManager.SetUnread(@group, unread);
                if (unifiedGroup == null)
                {
                    if (!skipSendReadBubble)
                    {
                        if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service))
                        {
                            var readBubble = new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing,
                                                            @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, currentlyUnread);
                            if (@group.IsExtendedParty)
                            {
                                readBubble.ExtendedParty = true;
                            }
                            BubbleManager.Send(readBubble);
                        }
                    }
                }
                if (updateUi)
                {
                    BubbleGroupEvents.RaiseRefreshed(@group);
                }
            }
            else
            {
                BubbleGroupSettingsManager.SetUnreadOffline(@group, unread);
            }
        }
Exemple #16
0
        private static BubbleGroup AddNewInternal(VisualBubble newBubble, bool raiseBubbleInserted)
        {
            var group = new BubbleGroup(newBubble, null, false);

            BubbleGroupSettingsManager.SetUnreadIndicatorGuid(group, group.LastBubbleSafe().ID, true);

            if (ServiceManager.IsRunning(@group.Service))
            {
                newBubble.Service.NewBubbleGroupCreated(@group).ContinueWith(x =>
                {
                    // force the UI to refetch the photo
                    @group.IsPhotoSetFromService = false;
                    BubbleManager.SendSubscribe(@group, true);
                    BubbleGroupUpdater.Update(@group);
                });
            }

            BubbleGroupManager.BubbleGroupsAdd(@group);

            BubbleGroupDatabase.AddBubble(@group, newBubble);

            if (raiseBubbleInserted)
            {
                try
                {
                    BubbleGroupEvents.RaiseBubbleInserted(newBubble, @group);
                }
                catch (Exception ex)
                {
                    Utils.DebugPrint(
                        "Error in notifying the interface that the bubble group has been updated (" +
                        newBubble.Service.Information.ServiceName + "): " + ex.Message);
                }
            }

            BubbleGroupUpdater.Update(@group);

            return(@group);
        }
Exemple #17
0
 public static Task ForceUpdate(Service service)
 {
     return(Task.Factory.StartNew(() =>
     {
         Utils.DebugPrint("Querying phone contacts...");
         _phoneBookContacts = Platform.GetPhoneBookContacts();
         if (service != null)
         {
             if (ServiceManager.IsRunning(service))
             {
                 Utils.DebugPrint("Refreshing service contacts...");
                 service.RefreshPhoneBookContacts();
             }
             else
             {
                 Utils.DebugPrint("Force refreshing service " + service.Information.ServiceName +
                                  " isn't possible. Why? It isn't running!");
             }
             Utils.DebugPrint("Finished refreshing service contacts. Calling contacts update and bubble group update.");
             BubbleGroupUpdater.Update(service);
         }
     }));
 }
Exemple #18
0
        public static void GetMentions(BubbleGroup group, Action <List <Mention> > result)
        {
            if (ServiceManager.IsRunning(group.Service))
            {
                // Pull latest mention values
                Task.Factory.StartNew(() =>
                {
                    var uiMentions = group.Service as IMentions;
                    if (uiMentions != null)
                    {
                        uiMentions.GetMentions(group, (mentions) =>
                        {
                            // No RemoveAll for ThreadSafeList
                            var itemsToRemove = group.Mentions.ToList();
                            foreach (var itemToRemove in itemsToRemove)
                            {
                                group.Mentions.Remove(itemToRemove);
                            }
                            group.Mentions.AddRange(mentions);

                            result(mentions);
                        });
                    }
                    else
                    {
                        result(new List <Mention>());
                    }
                });
            }
            else
            {
                // TODO: For hashtags we pull across all groups.
                var mentions = group.Mentions.Where(m => m.BubbleGroupId == group.ID).ToList();
                result(mentions);
            }
        }
        internal static void UpdateName(BubbleGroup bubbleGroup, Action finished = null)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            try
            {
                service.GetBubbleGroupName(bubbleGroup, title =>
                {
                    bubbleGroup.IsTitleSetFromService = true;
                    bubbleGroup.Title = title;
                    if (finished == null)
                    {
                        BubbleGroupEvents.RaiseRefreshed(bubbleGroup);
                        BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup);
                    }
                    else
                    {
                        finished();
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group name: " + service.Information.ServiceName + ": " +
                                 ex.Message);
                if (finished != null)
                {
                    finished();
                }
            }
        }
Exemple #20
0
        public static bool LoadFullyIfNeeded(BubbleGroup group, bool sync = false)
        {
            if (@group == null)
            {
                return(false);
            }

            var loadedSomething = false;

            lock (BubbleGroupDatabase.OperationLock)
            {
                var unifiedGroup = @group as UnifiedBubbleGroup;

                var adjustUnifiedGroupUnreadIndicatorIfExists = false;
                var associatedGroups = unifiedGroup != null
                    ? unifiedGroup.Groups.ToList()
                    : new[] { @group }.ToList();
                var associatedPartiallyLoadedGroups = associatedGroups.Where(x => x.PartiallyLoaded).ToList();
                foreach (var partiallyLoadedGroup in associatedPartiallyLoadedGroups)
                {
                    var partiallyLoadedBubblesToRemove = partiallyLoadedGroup.Bubbles.ToList();
                    var rollingBack = false;
TryAgain:
                    try
                    {
                        loadedSomething = true;
                        partiallyLoadedGroup.PartiallyLoaded = false;
                        foreach (var bubble in BubbleGroupDatabase.FetchBubbles(partiallyLoadedGroup).Reverse())
                        {
                            partiallyLoadedGroup.Bubbles.Add(bubble);
                        }
                        foreach (var partiallyLoadedBubbleToRemove in partiallyLoadedBubblesToRemove)
                        {
                            partiallyLoadedGroup.Bubbles.Remove(partiallyLoadedBubbleToRemove);
                        }
                        if (partiallyLoadedGroup.Bubbles.Count < 1)
                        {
                            foreach (var partiallyLoadedBubbleToRemove in partiallyLoadedBubblesToRemove)
                            {
                                partiallyLoadedGroup.Bubbles.Add(partiallyLoadedBubbleToRemove);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Failed to fully load partially loaded group " + partiallyLoadedGroup.ID + ": " + ex);
                        if (!rollingBack)
                        {
                            Utils.DebugPrint("Attempting to roll back the last transaction....");
                            BubbleGroupSettingsManager.SetUnreadIndicatorGuid(partiallyLoadedGroup, null, false);
                            adjustUnifiedGroupUnreadIndicatorIfExists = true;
                            rollingBack = true;
                            var lastModifiedIndex = BubbleGroupIndex.GetLastModifiedIndex(partiallyLoadedGroup.ID);
                            if (lastModifiedIndex.HasValue)
                            {
                                try
                                {
                                    BubbleGroupDatabase.RollBackTo(partiallyLoadedGroup, lastModifiedIndex.Value);
                                    goto TryAgain;
                                }
                                catch (Exception ex2)
                                {
                                    Utils.DebugPrint("Failed to rollback: " + ex2);
                                    // fall-through. It's unrecoverable!
                                }
                            }
                            else
                            {
                                // fall-through. It's unrecoverable!
                            }
                        }
                        Utils.DebugPrint("Partially loaded group is dead. Killing and restarting (lost data occurred).");
                        BubbleGroupDatabase.Kill(partiallyLoadedGroup);
                        BubbleGroupSync.RemoveFromSync(partiallyLoadedGroup);
                        BubbleGroupDatabase.AddBubbles(partiallyLoadedGroup,
                                                       partiallyLoadedBubblesToRemove.ToArray());
                    }
                }

                if (unifiedGroup != null && !unifiedGroup.UnifiedGroupLoaded)
                {
                    Populate(unifiedGroup);
                }
                if (unifiedGroup != null && adjustUnifiedGroupUnreadIndicatorIfExists)
                {
                    BubbleGroupSettingsManager.SetUnreadIndicatorGuid(unifiedGroup, null, false);
                }
            }

            if (!sync && loadedSomething)
            {
                Task.Factory.StartNew(() =>
                {
                    var unifiedGroup = @group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        BubbleQueueManager.Send(unifiedGroup.Groups.Where(x => ServiceManager.IsRunning(x.Service))
                                                .Select(x => x.Service.Information.ServiceName).ToArray());
                    }
                    else if (ServiceManager.IsRunning(@group.Service))
                    {
                        BubbleQueueManager.Send(new[] { @group.Service.Information.ServiceName });
                    }
                    BubbleQueueManager.SetNotQueuedToFailures(@group);
                });
            }

            return(loadedSomething);
        }
Exemple #21
0
        public static Task Sync(BubbleGroup group, bool force = false)
        {
            return(Task.Factory.StartNew(() =>
            {
                Utils.DebugPrint("Syncing convo " + group.ID);

                lock (SyncLock)
                {
                    Utils.DebugPrint("Syncing convo " + group.ID + " (after lock)");

                    var somethingSynced = true;

                    var groupsToSync = new List <BubbleGroup>();

                    var unifiedGroup = group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        groupsToSync.AddRange(unifiedGroup.Groups);
                    }
                    else
                    {
                        groupsToSync.Add(group);
                    }

                    foreach (var groupToSync in groupsToSync)
                    {
                        if (!groupToSync.NeedsSync && !force)
                        {
                            continue;
                        }

                        var groupToSyncAgent = groupToSync.Service as Agent;

                        if (groupToSyncAgent == null)
                        {
                            continue;
                        }

                        if (!ServiceManager.IsRunning(groupToSync.Service))
                        {
                            continue;
                        }

                        try
                        {
                            var syncTask = groupToSyncAgent.Sync(groupToSync, Database.GetActionId(groupToSync));
                            syncTask.Wait();
                            var syncResult = syncTask.Result;
                            if (!syncResult.EmptyResult && !syncResult.NullActionId && !syncResult.JustRefresh)
                            {
                                lock (BubbleGroupDatabase.OperationLock)
                                {
                                    if (syncResult.ResultType == Result.Type.Purge)
                                    {
                                        Utils.DebugPrint("Sync is purging the database for bubble group " + groupToSync.ID
                                                         + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleGroupDatabase.Kill(groupToSync);
                                    }
                                    if (!syncResult.EmptyInserts)
                                    {
                                        Utils.DebugPrint("Sync is inserting " + syncResult.Inserts.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        if (syncResult.ResultType == Result.Type.Purge)
                                        {
                                            syncResult.Inserts.TimSort((x, y) => x.Time.CompareTo(y.Time));
                                            BubbleGroupDatabase.AddBubbles(groupToSync, syncResult.Inserts);
                                        }
                                        else
                                        {
                                            BubbleGroupDatabase.InsertBubblesByTime(groupToSync, syncResult.Inserts, SearchDepth);
                                        }
                                    }
                                    if (!syncResult.EmptyUpdates)
                                    {
                                        Utils.DebugPrint("Sync is updating " + syncResult.Updates.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleManager.Update(groupToSync, syncResult.Updates, SearchDepth);
                                    }
                                    Database.SetActionId(groupToSync, syncResult.NewActionId);
                                }
                            }
                            else
                            {
                                Utils.DebugPrint("Sync for bubble group " +
                                                 groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName +
                                                 " returned an empty result (" + syncResult.ResultType.ToString() + ").");
                                somethingSynced = syncResult.JustRefresh;
                            }
                            groupToSync.NeedsSync = false;
                        }
                        catch (Exception ex)
                        {
                            Utils.DebugPrint("Failed to sync bubble group " + groupToSync.ID
                                             + " on service " + groupToSync.Service.Information.ServiceName + ": " + ex);
                            somethingSynced = false;
                        }
                    }

                    if (somethingSynced)
                    {
                        lock (BubbleGroupDatabase.OperationLock)
                        {
                            var sendingBubbles = BubbleManager.FetchAllSendingAndDownloading(group).ToList();
                            BubbleGroupFactory.UnloadFullLoad(group);
                            BubbleGroupFactory.LoadFullyIfNeeded(group, true);
                            if (sendingBubbles.Any())
                            {
                                BubbleManager.Replace(group, sendingBubbles);
                            }
                            group.RaiseBubblesSynced();
                        }
                    }
                }
            }));
        }
        public static Task Sync(BubbleGroup group, bool force = false)
        {
            return(Task.Factory.StartNew(() =>
            {
                Utils.DebugPrint("Syncing convo " + group.ID);

                lock (SyncLock)
                {
                    Utils.DebugPrint("Syncing convo " + group.ID + " (after lock)");

                    var somethingSynced = false;

                    var groupsToSync = new List <BubbleGroup>();

                    var unifiedGroup = group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        groupsToSync.AddRange(unifiedGroup.Groups);
                    }
                    else
                    {
                        groupsToSync.Add(group);
                    }

                    foreach (var groupToSync in groupsToSync)
                    {
                        if (!groupToSync.NeedsSync && !force)
                        {
                            continue;
                        }

                        var groupToSyncAgent = groupToSync.Service as Agent;

                        if (groupToSyncAgent == null)
                        {
                            continue;
                        }

                        if (!ServiceManager.IsRunning(groupToSync.Service))
                        {
                            continue;
                        }

                        somethingSynced = true;

                        try
                        {
                            ReSync:
                            var syncTime = Time.GetNowUnixTimestamp();
                            var syncTask = groupToSyncAgent.Sync(groupToSync, Database.GetActionId(groupToSync));
                            syncTask.Wait();
                            var syncResult = syncTask.Result;
                            if (!syncResult.EmptyResult && !syncResult.NullActionId && !syncResult.JustRefresh)
                            {
                                lock (BubbleGroupDatabase.OperationLock)
                                {
                                    if (syncResult.ResultType == Result.Type.Purge)
                                    {
                                        if (BubbleGroupManager.LastBubbleSentTimestamps.ContainsKey(groupToSync.ID))
                                        {
                                            lock (BubbleGroupManager.LastBubbleSentTimestamps)
                                            {
                                                var lastBubbleSentTime = BubbleGroupManager.LastBubbleSentTimestamps[groupToSync.ID];
                                                if (lastBubbleSentTime >= syncTime)
                                                {
                                                    Utils.DebugPrint("Sync has detected that a bubble was sent during the time the sync was fetched. Redoing sync...");
                                                    goto ReSync;
                                                }
                                            }
                                        }
                                        Utils.DebugPrint("Sync is purging the database for bubble group " + groupToSync.ID
                                                         + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleGroupDatabase.Kill(groupToSync);
                                    }
                                    if (!syncResult.EmptyInserts)
                                    {
                                        Utils.DebugPrint("Sync is inserting " + syncResult.Inserts.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        if (syncResult.ResultType == Result.Type.Purge)
                                        {
                                            syncResult.Inserts.TimSort((x, y) => x.Time.CompareTo(y.Time));
                                            BubbleGroupDatabase.AddBubbles(groupToSync, syncResult.Inserts);
                                            // If a purge is issued, then we need to carry over all sending bubbles to the new BubbleGroup being created.
                                            // Additionally, we need to remove any sending bubbles that are already on the insert list to avoid duplicates.
                                            var sendingBubbles = BubbleManager.FetchAllSending(groupToSync).ToList();
                                            var sendingBubblesFiltered = new List <VisualBubble>();
                                            foreach (var sendingBubble in sendingBubbles)
                                            {
                                                var hasInsertBubble = syncResult.Inserts.FirstOrDefault(x => x.ID == sendingBubble.ID) != null;
                                                if (!hasInsertBubble)
                                                {
                                                    sendingBubblesFiltered.Add(sendingBubble);
                                                }
                                            }
                                            if (sendingBubblesFiltered.Any())
                                            {
                                                BubbleGroupDatabase.InsertBubblesByTime(groupToSync, sendingBubblesFiltered.ToArray(), SearchDepth);
                                            }
                                        }
                                        else
                                        {
                                            BubbleGroupDatabase.InsertBubblesByTime(groupToSync, syncResult.Inserts, SearchDepth);
                                        }
                                    }
                                    if (!syncResult.EmptyUpdates)
                                    {
                                        Utils.DebugPrint("Sync is updating " + syncResult.Updates.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleManager.Update(groupToSync, syncResult.Updates, SearchDepth);
                                    }
                                }
                            }
                            else
                            {
                                Utils.DebugPrint("Sync for bubble group " +
                                                 groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName +
                                                 " returned an empty result (" + syncResult.ResultType.ToString() + ").");
                            }
                            if (!syncResult.NullActionId)
                            {
                                Database.SetActionId(groupToSync, syncResult.NewActionId);
                            }
                            groupToSync.NeedsSync = false;
                        }
                        catch (Exception ex)
                        {
                            Utils.DebugPrint("Failed to sync bubble group " + groupToSync.ID
                                             + " on service " + groupToSync.Service.Information.ServiceName + ": " + ex);
                        }
                    }

                    if (somethingSynced)
                    {
                        lock (BubbleGroupDatabase.OperationLock)
                        {
                            // Here we need to replace all the sending or downloading bubbles with the 'real' ones.
                            // If this is never done, then on the UI, a 'sending' will never be set to 'sent', and any download
                            // progress will never be updated. Why? Different memory objects.
                            var sendingBubbles = BubbleManager.FetchAllSendingAndDownloading(group).ToList();
                            BubbleGroupFactory.UnloadFullLoad(group);
                            BubbleGroupFactory.LoadFullyIfNeeded(group, true);
                            if (sendingBubbles.Any())
                            {
                                BubbleManager.Replace(group, sendingBubbles);
                            }
                            group.RaiseBubblesSynced();
                        }
                    }
                }
            }));
        }
Exemple #23
0
        internal static async void UpdatePartyParticipants(BubbleGroup bubbleGroup, Action finished = null)
        {
            var service = bubbleGroup.Service;

            if (!ServiceManager.IsRunning(service))
            {
                return;
            }

            if (!bubbleGroup.IsParty)
            {
                if (finished != null)
                {
                    finished();
                }
                return;
            }

            try
            {
                await service.GetBubbleGroupPartyParticipants(bubbleGroup, participants =>
                {
                    // we need to propogate the old participant photos to the new participant list
                    var newParticipants = participants == null ? new List <DisaParticipant>() : participants.ToList();
                    foreach (var oldParticipant in bubbleGroup.Participants)
                    {
                        var newParticipant = newParticipants.FirstOrDefault(x => service.BubbleGroupComparer(x.Address, oldParticipant.Address));
                        if (newParticipant != null)
                        {
                            newParticipant.Photo = oldParticipant.Photo;
                            newParticipant.IsPhotoSetFromService = oldParticipant.IsPhotoSetFromService;
                        }
                    }
                    // move all unknown participants over
                    foreach (var unknownParticipant in bubbleGroup.Participants.Where(x => x.Unknown))
                    {
                        if (newParticipants.FirstOrDefault(x => service.BubbleGroupComparer(x.Address, unknownParticipant.Address)) == null)
                        {
                            newParticipants.Add(unknownParticipant);
                        }
                    }
                    bubbleGroup.Participants = new ThreadSafeList <DisaParticipant>(newParticipants);
                    bubbleGroup.IsParticipantsSetFromService = true;
                    if (finished == null)
                    {
                        BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup);
                    }
                    else
                    {
                        finished();
                    }
                });
            }
            catch (Exception ex)
            {
                Utils.DebugPrint("Error updating bubble group participants: " + service.Information.ServiceName +
                                 " - " + bubbleGroup.Address + ": " + ex);
                if (finished != null)
                {
                    finished();
                }
            }
        }
Exemple #24
0
        private static Task <bool> Send(Bubble b, BubbleGroup group, bool resend)
        {
            return(Task <bool> .Factory.StartNew(() =>
            {
                var vb = b as VisualBubble;
                if (vb != null)
                {
                    if (vb.Status == Bubble.BubbleStatus.Sent)
                    {
                        Utils.DebugPrint("Trying to send a bubble that is already sent! On " + vb.Service.Information.ServiceName);
                        return true;
                    }

                    Func <bool> restartServiceIfNeeded = () =>
                    {
                        if (!ServiceManager.IsRegistered(b.Service) ||
                            ServiceManager.IsRunning(b.Service) ||
                            ServiceManager.IsAborted(b.Service))
                        {
                            return false;
                        }

                        Utils.DebugPrint(
                            "For f***s sakes. The scheduler isn't doing it's job properly, or " +
                            "you're sending a message to it at a weird time. Starting it up bra (" +
                            b.Service.Information.ServiceName + ").");
                        ServiceManager.AbortAndRestart(b.Service);
                        return true;
                    };

                    var visualBubbleServiceId = vb.Service as IVisualBubbleServiceId;
                    if (vb.IdService == null && vb.IdService2 == null && visualBubbleServiceId != null)
                    {
                        visualBubbleServiceId.AddVisualBubbleIdServices(vb);
                    }

                    try
                    {
                        @group = Group(vb, resend, true);
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Problem in Send:GroupBubble from service " +
                                         vb.Service.Information.ServiceName + ": " + ex.Message);
                        return false;
                    }

                    if (@group == null)
                    {
                        Utils.DebugPrint("Could not find a suitable group for bubble " + vb.ID
                                         + " on " + vb.Service.Information.ServiceName);
                        return false;
                    }

                    var shouldQueue = vb.Service.QueuedBubblesParameters == null ||
                                      !vb.Service.QueuedBubblesParameters.BubblesNotToQueue.Contains(vb.GetType());

                    try
                    {
                        if (shouldQueue && !resend &&
                            BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName,
                                                                true, false))
                        {
                            BubbleQueueManager.JustQueue(group, vb);
                            restartServiceIfNeeded();
                            return false;
                        }

                        if (shouldQueue)
                        {
                            Monitor.Enter(vb.Service.SendBubbleLock);
                        }

                        using (var queued = new BubbleQueueManager.InsertBubble(group, vb, shouldQueue))
                        {
                            Action checkForQueued = () =>
                            {
                                if (!resend &&
                                    BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName, true, true))
                                {
                                    BubbleQueueManager.Send(new [] { vb.Service.Information.ServiceName });
                                }
                            };

                            try
                            {
                                FailBubbleIfPathDoesntExist(vb);
                                SendBubbleInternal(b);
                            }
                            catch (ServiceQueueBubbleException ex)
                            {
                                Utils.DebugPrint("Queuing visual bubble on service " +
                                                 vb.Service.Information.ServiceName + ": " + ex.Message);

                                UpdateStatus(vb, Bubble.BubbleStatus.Waiting, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                return false;
                            }
                            catch (Exception ex)
                            {
                                queued.CancelQueue();

                                Utils.DebugPrint("Visual bubble on " +
                                                 vb.Service.Information.ServiceName + " failed to be sent: " +
                                                 ex);

                                UpdateStatus(vb, Bubble.BubbleStatus.Failed, @group);
                                BubbleGroupEvents.RaiseBubbleFailed(vb, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                //FIXME: if the bubble fails to send, allow the queue manager to continue.
                                if (resend)
                                {
                                    return true;
                                }

                                return false;
                            }

                            queued.CancelQueue();

                            lock (BubbleGroupManager.LastBubbleSentTimestamps)
                            {
                                BubbleGroupManager.LastBubbleSentTimestamps[group.ID] = Time.GetNowUnixTimestamp();
                            }

                            if (vb.Status == Bubble.BubbleStatus.Delivered)
                            {
                                Utils.DebugPrint(
                                    "************ Race condition. The server set the status to delivered/read before we could send it to sent. :')");
                                checkForQueued();
                                return true;
                            }

                            UpdateStatus(vb, Bubble.BubbleStatus.Sent, @group);

                            checkForQueued();
                            return true;
                        }
                    }
                    finally
                    {
                        if (shouldQueue)
                        {
                            Monitor.Exit(vb.Service.SendBubbleLock);
                        }
                    }
                }
                else
                {
                    var composeBubble = b as ComposeBubble;

                    if (composeBubble != null)
                    {
                        var bubbleToSend = composeBubble.BubbleToSend;
                        var visualBubbleServiceId = bubbleToSend.Service as IVisualBubbleServiceId;
                        if (bubbleToSend.IdService == null && bubbleToSend.IdService2 == null &&
                            visualBubbleServiceId != null)
                        {
                            visualBubbleServiceId.AddVisualBubbleIdServices(bubbleToSend);
                        }
                        @group.InsertByTime(bubbleToSend);
                        try
                        {
                            BubbleGroupEvents.RaiseBubbleInserted(bubbleToSend, @group);
                        }
                        catch
                        {
                            // do nothing
                        }
                    }

                    try
                    {
                        SendBubbleInternal(b);
                    }
                    catch (ServiceBubbleGroupAddressException ex)
                    {
                        if (!String.IsNullOrWhiteSpace(ex.Address))
                        {
                            if (composeBubble != null)
                            {
                                composeBubble.BubbleToSend.Address = ex.Address;
                                composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Sent;

                                var actualGroup = Group(composeBubble.BubbleToSend, resend, true);

                                ServiceEvents.RaiseComposeFinished(
                                    @group as ComposeBubbleGroup, actualGroup);

                                return true;
                            }
                        }

                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Failed to send bubble on service " + b.Service.Information.ServiceName);

                        if (composeBubble != null)
                        {
                            composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        }

                        return false;
                    }

                    if (composeBubble != null)
                    {
                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }

                    return true;
                }
            }));
        }