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); } }
internal static void OnBubbleReceived(Bubble b) { var visualBubble = b as VisualBubble; if (visualBubble != null) { try { BubbleManager.Group(visualBubble); } catch (Exception ex) { Utils.DebugPrint("Problem in OnBubbleReceived (VisualBubble) from service " + visualBubble.Service.Information.ServiceName + ": " + ex.Message); } if (visualBubble.Direction == Bubble.BubbleDirection.Incoming && IsRunning(visualBubble.Service) && BubbleQueueManager.HasQueuedBubbles(b.Service.Information.ServiceName, true, true)) { Utils.DebugPrint("Sending queued bubbles as we're getting some received."); BubbleQueueManager.Send(new [] { b.Service.Information.ServiceName }); } } else if (b is AbstractBubble) { Utils.DebugPrint("We got an abstract bubble: " + b.GetType().Name + " Address: " + b.Address); BubbleGroup group = null; var deliveredBubble = b as DeliveredBubble; if (deliveredBubble != null) { @group = BubbleGroupManager.FindWithAddress(deliveredBubble.Service, deliveredBubble.Address); if (@group != null) { BubbleGroupFactory.LoadFullyIfNeeded(@group); var bubbles = @group.Bubbles; for (var i = bubbles.Count - 1; i >= 0; i--) { var bubble = bubbles[i]; if (bubble.ID != deliveredBubble.VisualBubbleID) { continue; } BubbleManager.UpdateStatus(bubble, Bubble.BubbleStatus.Delivered, @group); if (@group.Service.Information.DoesSupport(typeof(DeliveredBubbleReceipt))) { BubbleManager.Send(new DeliveredBubbleReceipt(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing, @group.Service, bubble)); } break; } } } var readBubble = b as ReadBubble; if (readBubble != null) { @group = BubbleGroupManager.FindWithAddress(readBubble.Service, readBubble.Address); if (@group != null) { BubbleGroupFactory.LoadFullyIfNeeded(@group); if (@group.ReadTimes == null || [email protected]) { @group.ReadTimes = new [] { new DisaReadTime { ParticipantAddress = readBubble.ParticipantAddress, Time = readBubble.ReadTime } }; } else { var readTimes = @group.ReadTimes.ToList(); var duplicateReadTime = readTimes.FirstOrDefault(x => @group.Service.BubbleGroupComparer(x.ParticipantAddress, readBubble.ParticipantAddress)); if (duplicateReadTime != null) { readTimes.Remove(duplicateReadTime); } readTimes.Add(new DisaReadTime { ParticipantAddress = readBubble.ParticipantAddress, Time = readBubble.ReadTime }); @group.ReadTimes = readTimes.ToArray(); } } } var prescenceBubble = b as PresenceBubble; if (prescenceBubble != null) { @group = BubbleGroupManager.Find(bubbleGroup => !bubbleGroup.IsParty && bubbleGroup.Service == prescenceBubble.Service && prescenceBubble.Service.BubbleGroupComparer( bubbleGroup.Address, prescenceBubble.Address)); if (@group != null) { if ([email protected] && !prescenceBubble.Available) { var oldPresence = @group.PresenceType; @group.PresenceType = PresenceBubble.PresenceType.Unavailable; if (oldPresence != prescenceBubble.Presence) { BubbleGroupManager.UpdateLastOnline(@group); } } else { @group.PresenceType = prescenceBubble.Presence; @group.PresencePlatformType = prescenceBubble.Platform; } if (!prescenceBubble.Available) { @group.Typing = false; } } } var typingBubble = b as TypingBubble; if (typingBubble != null) { @group = BubbleGroupManager.Find(bubbleGroup => !bubbleGroup.IsParty && bubbleGroup.Service == typingBubble.Service && typingBubble.Service.BubbleGroupComparer( bubbleGroup.Address, typingBubble.Address)); if (@group != null) { if (@group.Presence) { @group.Typing = typingBubble.Typing; @group.TypingIsAudio = typingBubble.IsAudio; } else { @group.Typing = false; } } } try { if (@group != null) { BubbleGroupEvents.RaiseNewAbstractBubble(b as AbstractBubble, @group); } } catch (Exception ex) { Utils.DebugPrint("Problem in OnBubbleReceived (AbstractBubble) from service " + b.Service.Information.ServiceName + ": " + ex.Message); } } }
public static Task <List <Receipt> > Send(string[] serviceNames, bool scheduled = false) { return(Task <List <Receipt> > .Factory.StartNew(() => { //PROCESS: 1) find all bubbles under serviceNames in db // 2) relate db entries to bubbles loaded into memory by Disa // 3) parallel send bubbles based respective to service // 4) delete all successful bubbles out of db lock (_sendLock) { var possibleBubblesFromDatabase = new List <Entry>(); lock (_dbLock) { using (var db = new SqlDatabase <Entry>(Location)) { foreach (var possibleBubble in db.Store.Where(x => serviceNames.Contains(x.ServiceName)).Reverse()) { if (!InsertBubble.IsSending(possibleBubble.Guid)) { possibleBubblesFromDatabase.Add(possibleBubble); } } } } var possibleBubblesInDisa = new List <Tuple <Entry, VisualBubble> >(); foreach (var bubbleGroup in BubbleGroupManager.BubbleGroupsNonUnified) { if (bubbleGroup.PartiallyLoaded) { continue; } foreach (var bubble in bubbleGroup) { if (bubble.Status != Bubble.BubbleStatus.Waiting) { continue; } var possibleBubbleFromDatabase = possibleBubblesFromDatabase.FirstOrDefault(x => x.Guid == bubble.ID); if (possibleBubbleFromDatabase != null) { possibleBubblesInDisa.Add(new Tuple <Entry, VisualBubble>(possibleBubbleFromDatabase, bubble)); } } } var sent = new List <Tuple <Entry, bool> >(); var possibleBubblesInDisaByService = possibleBubblesInDisa.GroupBy(x => x.Item1.ServiceName); Parallel.ForEach(possibleBubblesInDisaByService, possibleBubblesInService => { var failed = false; foreach (var possibleBubble in possibleBubblesInService) { if (failed) { sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false)); continue; } Utils.DebugPrint(">>>>>>>>>>> Sending queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); var sendBubbleTask = BubbleManager.Send(possibleBubble.Item2, true); sendBubbleTask.Wait(); if (sendBubbleTask.Result) { Utils.DebugPrint(">>>>>>>>> Successfully sent queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, true)); lock (_dbLock) { using (var db = new SqlDatabase <Entry>(Location)) { db.Remove(possibleBubble.Item1); } } Utils.Delay(100).Wait(); } else { Utils.DebugPrint(">>>>>>>>> Failed to send queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false)); failed = true; // fail the entire chain for this service from here on out so messages aren't sent out of order } } }); SanityCheckup(); var receipts = sent.Select(x => new Receipt(x.Item1.Guid, x.Item2)).ToList(); if (!scheduled) { if (receipts.FirstOrDefault(x => !x.Success) != null) { ScheduleReSend(serviceNames); } else { var needToSendAgain = serviceNames.Where(x => BubbleQueueManager.HasQueuedBubbles(x, true, true)).ToArray(); if (needToSendAgain.Any()) { Send(needToSendAgain); } } } return receipts; } })); }