private static LinkedList <SignalMessage> InsertIdentityChangedMessages(string number) { long now = Util.CurrentTimeMillis(); LinkedList <SignalMessage> messages = new LinkedList <SignalMessage>(); using (var ctx = new SignalDBContext()) { SignalContact contact = SignalDBContext.GetSignalContactByThreadId(ctx, number); if (contact != null) { string str = $"Your safety numbers with {contact.ThreadDisplayName} have changed."; SignalMessage msg = new SignalMessage() { Author = contact, ComposedTimestamp = now, ReceivedTimestamp = now, Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.IdentityKeyChange, ThreadId = contact.ThreadId, ThreadGuid = contact.ThreadGuid, Content = new SignalMessageContent() { Content = str } }; contact.LastMessage = msg; contact.MessagesCount += 1; contact.UnreadCount += 1; ctx.Messages.Add(msg); messages.AddLast(msg); var groups = ctx.GroupMemberships .Where(gm => gm.ContactId == contact.Id) .Include(gm => gm.Group); foreach (var gm in groups) { msg = new SignalMessage() { Author = contact, ComposedTimestamp = now, ReceivedTimestamp = now, Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.IdentityKeyChange, ThreadId = gm.Group.ThreadId, ThreadGuid = gm.Group.ThreadGuid, Content = new SignalMessageContent() { Content = str } }; gm.Group.LastMessage = msg; gm.Group.MessagesCount += 1; gm.Group.UnreadCount += 1; ctx.Messages.Add(msg); messages.AddLast(msg); } } ctx.SaveChanges(); } return(messages); }
internal async void AddButton_Click(object sender, RoutedEventArgs e) { if (UIEnabled) { UIEnabled = false; Debug.WriteLine("creating contact {0} ({1})", ContactName, ContactNumber); SignalContact contact = new SignalContact() { ThreadDisplayName = ContactName, ThreadId = ContactNumber, CanReceive = true, AvatarFile = null, LastActiveTimestamp = 0, Draft = null, Color = "red", UnreadCount = 0 }; ContactName = ""; ContactNumber = ""; await Task.Run(() => { SignalDBContext.InsertOrUpdateContactLocked(contact, MainPageVM); }); UIEnabled = true; } }
private void UpdateHeader(SignalConversation thread) { ThreadDisplayName = thread.ThreadDisplayName; ThreadUsername = thread.ThreadId; if (thread is SignalContact) { SignalContact contact = (SignalContact)thread; HeaderBackground = Utils.GetBrushFromColor(contact.Color); if (ThreadUsername != ThreadDisplayName) { ThreadUsernameVisibility = Visibility.Visible; SeparatorVisibility = Visibility.Visible; } else { ThreadUsernameVisibility = Visibility.Collapsed; SeparatorVisibility = Visibility.Collapsed; } } else { HeaderBackground = Utils.Blue; ThreadUsernameVisibility = Visibility.Collapsed; SeparatorVisibility = Visibility.Collapsed; } }
public static SignalContact GetOrCreateContactLocked(string username, long timestamp) { SignalContact contact; lock (DBLock) { using (var ctx = new SignalDBContext()) { contact = ctx.Contacts .Where(c => c.ThreadId == username) .SingleOrDefault(); if (contact == null) { contact = new SignalContact() { ThreadId = username, ThreadDisplayName = username, CanReceive = true, LastActiveTimestamp = timestamp, Color = null //Utils.CalculateDefaultColor(username) }; ctx.Contacts.Add(contact); ctx.SaveChanges(); } } } return(contact); }
public void UpdateBlockedContactElement() { if (Model != null) { SignalContact contact = (SignalContact)Model; FillBrush = contact.Color != null?Utils.GetBrushFromColor((contact.Color)) : Utils.GetBrushFromColor(Utils.CalculateDefaultColor(Model.ThreadDisplayName)); ConversationDisplayName.Text = Model.ThreadDisplayName; Initials = Utils.GetInitials(Model.ThreadDisplayName); LastMessage = null; } }
private async Task AddContact(string name, string number) { Debug.WriteLine("creating contact {0} ({1})", name, number); SignalContact contact = new SignalContact() { ThreadDisplayName = name, ThreadId = number, CanReceive = true, AvatarFile = null, LastActiveTimestamp = 0, Draft = null, Color = Utils.CalculateDefaultColor(name), UnreadCount = 0 }; await Task.Run(() => { SignalDBContext.InsertOrUpdateContactLocked(contact, MainPageVM); }); }
private async Task AddContact(string name, string number) { Debug.WriteLine("creating contact {0} ({1})", name, number); SignalContact contact = new SignalContact() { ThreadDisplayName = name, ThreadId = number, CanReceive = true, AvatarFile = null, LastActiveTimestamp = 0, Draft = null, Color = Utils.CalculateDefaultColor(name), UnreadCount = 0 }; await Task.Run(() => { //TODO inform UI }); }
public static void InsertOrUpdateContactLocked(SignalContact contact, MainPageViewModel mpvm) { bool is_new = false; lock (DBLock) { using (var ctx = new SignalDBContext()) { var c = ctx.Contacts.SingleOrDefault(b => b.ThreadId == contact.ThreadId); if (c == null) { is_new = true; ctx.Contacts.Add(contact); } else { c.Color = contact.Color; c.ThreadId = contact.ThreadId; c.ThreadDisplayName = contact.ThreadDisplayName; c.CanReceive = contact.CanReceive; c.AvatarFile = contact.AvatarFile; c.Draft = contact.Draft; c.UnreadCount = contact.UnreadCount; } ctx.SaveChanges(); } if (is_new) { Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mpvm.AddThread(contact); }).AsTask().Wait(); } else { Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mpvm.UIUpdateThread(contact); }).AsTask().Wait(); } } }
private async Task AddContact(string name, string number, Guid?guid) { Debug.WriteLine("creating contact {0} ({1})", name, number); SignalContact contact = new SignalContact() { ThreadDisplayName = name, ThreadId = number, ThreadGuid = guid, CanReceive = true, AvatarFile = null, LastActiveTimestamp = 0, Draft = null, Color = Utils.CalculateDefaultColor(name), UnreadCount = 0 }; await Task.Run(() => { App.Handle.SaveAndDispatchSignalConversation(contact, null); }); }
public static SignalContact GetOrCreateContactLocked(string username, long timestamp, MainPageViewModel mpvm) { SignalContact contact; bool is_new = false; lock (DBLock) { using (var ctx = new SignalDBContext()) { contact = ctx.Contacts .Where(c => c.ThreadId == username) .SingleOrDefault(); if (contact == null) { is_new = true; contact = new SignalContact() { ThreadId = username, ThreadDisplayName = username, CanReceive = true, LastActiveTimestamp = timestamp, Color = Utils.Colors[Utils.CalculateDefaultColorIndex(username)] }; ctx.Contacts.Add(contact); ctx.SaveChanges(); } } if (is_new) { Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mpvm.AddThread(contact); }).AsTask().Wait(); } } return(contact); }
public static LinkedList <SignalMessage> InsertIdentityChangedMessages(string number) { long now = Util.CurrentTimeMillis(); LinkedList <SignalMessage> messages = new LinkedList <SignalMessage>(); lock (DBLock) { using (var ctx = new SignalDBContext()) { SignalContact contact = ctx.Contacts .Where(c => c.ThreadId == number) .SingleOrDefault(); if (contact != null) { string str = $"Your safety numbers with {contact.ThreadDisplayName} have changed."; SignalMessage msg = new SignalMessage() { Author = contact, ComposedTimestamp = now, ReceivedTimestamp = now, Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.IdentityKeyChange, ThreadId = contact.ThreadId, Content = new SignalMessageContent() { Content = str } }; contact.LastMessage = msg; contact.MessagesCount += 1; ctx.Messages.Add(msg); messages.AddLast(msg); var groups = ctx.GroupMemberships .Where(gm => gm.ContactId == contact.Id) .Include(gm => gm.Group); foreach (var gm in groups) { msg = new SignalMessage() { Author = contact, ComposedTimestamp = now, ReceivedTimestamp = now, Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.IdentityKeyChange, ThreadId = gm.Group.ThreadId, Content = new SignalMessageContent() { Content = str } }; gm.Group.LastMessage = msg; gm.Group.MessagesCount += 1; ctx.Messages.Add(msg); messages.AddLast(msg); } } else { Debug.WriteLine("InsertIdentityChangedMessages for non-existing contact!"); } ctx.SaveChanges(); } } return(messages); }
private async Task HandleGroupLeaveMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp) { SignalServiceGroup sentGroup = dataMessage.Group; if (sentGroup != null) { string groupid = Base64.EncodeBytes(sentGroup.GroupId); SignalGroup group = await SignalDBContext.GetOrCreateGroupLocked(groupid, 0); if (isSync) { SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0); SignalMessage sm = new SignalMessage() { Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.GroupLeave, Status = SignalMessageStatus.Received, Author = author, Content = new SignalMessageContent() { Content = $"You have left the group." }, ThreadId = groupid, DeviceId = (uint)envelope.GetSourceDevice(), Receipts = 0, ComposedTimestamp = envelope.GetTimestamp(), ReceivedTimestamp = timestamp, }; SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm); await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm); } else { SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0); SignalMessage sm = new SignalMessage() { Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.GroupLeave, Status = SignalMessageStatus.Received, Author = author, Content = new SignalMessageContent() { Content = $"{author.ThreadDisplayName} has left the group." }, ThreadId = groupid, DeviceId = (uint)envelope.GetSourceDevice(), Receipts = 0, ComposedTimestamp = envelope.GetTimestamp(), ReceivedTimestamp = timestamp, }; SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm); await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm); } } else { Logger.LogError("HandleGroupLeaveMessage() received group update without group info"); } }
private async Task HandleMessage(SignalServiceEnvelope envelope) { var cipher = new SignalServiceCipher(new SignalServiceAddress(SignalLibHandle.Instance.Store.Username), new Store()); var content = cipher.Decrypt(envelope); long timestamp = Util.CurrentTimeMillis(); if (content.Message != null) { SignalServiceDataMessage message = content.Message; if (message.EndSession) { await HandleSessionResetMessage(envelope, content, message, false, timestamp); } else if (message.IsGroupUpdate()) { if (message.Group.Type == SignalServiceGroup.GroupType.UPDATE) { await HandleGroupUpdateMessage(envelope, content, message, false, timestamp); } else if (message.Group.Type == SignalServiceGroup.GroupType.QUIT) { await HandleGroupLeaveMessage(envelope, content, message, false, timestamp); } else if (message.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO) { Logger.LogWarning("Received REQUEST_INFO request"); } } else if (message.ExpirationUpdate) { await HandleExpirationUpdateMessage(envelope, content, message, false, timestamp); } else { await HandleSignalMessage(envelope, content, message, false, timestamp); } } else if (content.SynchronizeMessage != null) { if (content.SynchronizeMessage.Sent != null) { var syncMessage = content.SynchronizeMessage.Sent; var dataMessage = syncMessage.Message; if (dataMessage.EndSession) { await HandleSessionResetMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.IsGroupUpdate()) { if (dataMessage.Group.Type == SignalServiceGroup.GroupType.UPDATE) { await HandleGroupUpdateMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.QUIT) { await HandleGroupLeaveMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO) { Logger.LogWarning("Received synced REQUEST_INFO request"); } } else if (dataMessage.ExpirationUpdate) { await HandleExpirationUpdateMessage(envelope, content, dataMessage, true, timestamp); } else { await HandleSignalMessage(envelope, content, dataMessage, true, timestamp); } } else if (content.SynchronizeMessage.Reads != null) { var readMessages = content.SynchronizeMessage.Reads; foreach (var readMessage in readMessages) { try { await HandleSyncedReadMessage(readMessage); } catch (Exception e) { Logger.LogError("HandleReadMessage failed: {0}\n{1}", e.Message, e.StackTrace); } } } else if (content.SynchronizeMessage.BlockedList != null) { List <string> blockedNumbers = content.SynchronizeMessage.BlockedList.Numbers; await HandleBlockedNumbers(blockedNumbers); } else if (content.SynchronizeMessage.Groups != null) { Logger.LogInformation("HandleMessage() handling groups sync message from device {0}", envelope.GetSourceDevice()); int read; var avatarBuffer = new byte[4096]; var groups = content.SynchronizeMessage.Groups; using (var tmpFile = LibUtils.CreateTmpFile("groups_sync")) { var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, groups.AsPointer(), tmpFile, 10000, null); var deviceGroupsStream = new DeviceGroupsInputStream(plaintextStream); var groupsList = new List <(SignalGroup, IList <string>)>(); DeviceGroup g; while ((g = deviceGroupsStream.Read()) != null) { if (g.Avatar != null) { SignalServiceAttachmentStream ssas = g.Avatar.AsStream(); while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0) { } } var group = new SignalGroup() { ThreadDisplayName = g.Name, ThreadId = Base64.EncodeBytes(g.Id), GroupMemberships = new List <GroupMembership>(), CanReceive = true, ExpiresInSeconds = g.ExpirationTimer != null ? g.ExpirationTimer.Value : 0 }; groupsList.Add((group, g.Members)); } List <SignalConversation> dbGroups = await SignalDBContext.InsertOrUpdateGroups(groupsList); await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbGroups); } } else if (content.SynchronizeMessage.Contacts != null && content.SynchronizeMessage.Contacts.Complete) //TODO incomplete updates { Logger.LogInformation("HandleMessage() handling contacts sync message from device {0}", envelope.GetSourceDevice()); int read; var avatarBuffer = new byte[4096]; ContactsMessage contacts = content.SynchronizeMessage.Contacts; using (var tmpFile = LibUtils.CreateTmpFile("contacts_sync")) { var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, contacts.Contacts.AsPointer(), tmpFile, 10000, null); var deviceContactsStream = new DeviceContactsInputStream(plaintextStream); List <SignalContact> contactsList = new List <SignalContact>(); DeviceContact c; while ((c = deviceContactsStream.Read()) != null) { if (c.Avatar != null) { SignalServiceAttachmentStream ssas = c.Avatar.AsStream(); while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0) { } } SignalContact contact = new SignalContact() { ThreadDisplayName = c.Name, ThreadId = c.Number, Color = c.Color, CanReceive = true, ExpiresInSeconds = c.ExpirationTimer != null ? c.ExpirationTimer.Value : 0 }; contactsList.Add(contact); } var dbContacts = SignalDBContext.InsertOrUpdateContacts(contactsList); await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbContacts); } } } else if (content.ReadMessage != null) { SignalServiceReceiptMessage receiptMessage = content.ReadMessage; Logger.LogTrace("HandleMessage() received ReceiptMessage (type={0}, when={1})", receiptMessage.ReceiptType, receiptMessage.When); } else { //TODO callmessages Logger.LogWarning("HandleMessage() received unrecognized message"); } }