public FromPart AddFrom(string value, string name, FromOperator @operator) { var part = new FromPart(value, name, @operator); From.Add(part); return(part); }
/// <summary> /// Returns a new <see cref="TimeBlock"/> in which its entries are offset by the specified <see cref="TimeSpan"/>. /// </summary> public TimeBlock Offset(TimeSpan time) { TimeBlock next = Clone(); next.From = From.Add(time); next.To = To.Add(time); return(next); }
public Message(string sender, string recipient, string subject, string body, DateTime date) { From.Add(new MailboxAddress("", sender)); To.Add(new MailboxAddress("", recipient)); Subject = subject; Body = new TextPart(TextFormat.Plain) { Text = body }; Date = date; }
internal ICollection <FetchData> Partition() { //TODO: maybe partition on MetricNames first, but not sure if that's gonna affect minimal timegrain //TODO: make sure we actually decreased the interval var range = Till - From; var half = TimeSpan.FromSeconds(Math.Floor(range.TotalSeconds / 2)); return(new [] { new FetchData { ResourceId = ResourceId, From = From, Till = From.Add(half), MetricNames = MetricNames, TimeGrain = TimeGrain }, new FetchData { ResourceId = ResourceId, From = From.Add(half), Till = Till, MetricNames = MetricNames, TimeGrain = TimeGrain }, }); }
internal void addFrom(Query table) { if (From == null) { From = new List <Query>(); } if (From.Count == 0) { if (table.Name == null) // es query { From.Add(table); } else // es tabla { From = table.From; PreSelect = table.PreSelect; } } else { From.Add(table); } }
public void Shift(TimeSpan amount) { From = From.Add(amount); To = To.Add(amount); }
public EmailMessage(EmailAddress from, EmailAddress to) { From.Add(from); To.Add(to); }
public Period Move(TimeSpan duration) => new Period(From.Add(duration), To.Add(duration));
public Delete(Table tableName) { From.Add(tableName); }
public Select From(string table, string alias) { _from.Add(table, alias); return(this); }
public void Shift(int milliseconds) { From = From.Add(new TimeSpan(0, 0, 0, 0, milliseconds)); To = To.Add(new TimeSpan(0, 0, 0, 0, milliseconds)); }
public Select(Table tableName) { From.Add(tableName); }
protected async Task GenerateTextContentExtractUsersAndUpdateSubject() { if (ctx == null || !ctx.HasValue) { return; } var nonNullContext = ctx.Value; try { var textContent = new StringBuilder(); if (Messagetype == MessageType.RichText_Html) { HtmlContent = Internal_Content; } else if (Messagetype == MessageType.ThreadActivity_AddMember || (Messagetype == MessageType.ThreadActivity_MemberJoined && Internal_Content.StartsWith("<addmember>")) // there seem to be (old?) addmember messages that come with the wrong message type of ThreadActivity_MemberJoined... handle this here ) { XmlDocument doc = new XmlDocument(); // need to force single XML values into array type since we know it also can be an array doc.LoadXml($"<root xmlns:json='http://james.newtonking.com/projects/json'>{Internal_Content.Replace("<target", "<target json:Array='true'").Replace("<detailedtargetinfo", "<detailedtargetinfo json:Array='true'") ?? ""}</root>"); var json = JsonConvert.SerializeXmlNode(doc); var data = JsonUtils.DeserializeObject <ThreadActivityAddMemberWrapper>(logger, json); await Task.WhenAll(data.root.addmember.detailedtargetinfo?.Select(targetInfo => teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)targetInfo.id, targetInfo.friendlyName, OriginalArrivalTime)) ?? new List <Task>()); if (!string.IsNullOrWhiteSpace(data.root.addmember.initiator)) { await teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)data.root.addmember.initiator, data.root.addmember.detailedinitiatorinfo?.friendlyName, OriginalArrivalTime); } // TODO: process alternate user display name var memberNames = await Task.WhenAll(data.root.addmember.target.Select(t => teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)t))); MessageSubject = $"✈️ {await teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)data.root.addmember.initiator)} added: " + string.Join(", ", memberNames); textContent.Append(MessageSubject); } else if (Messagetype == MessageType.ThreadActivity_DeleteMember) { XmlDocument doc = new XmlDocument(); doc.LoadXml($"<root xmlns:json='http://james.newtonking.com/projects/json'>{Internal_Content.Replace("<target", "<target json:Array='true'").Replace("<detailedtargetinfo", "<detailedtargetinfo json:Array='true'")}</root>"); var json = JsonConvert.SerializeXmlNode(doc); var data = JsonUtils.DeserializeObject <ThreadActivityDeleteMemberWrapper>(logger, json); await Task.WhenAll(data.root.deletemember.detailedtargetinfo?.Select(targetInfo => teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)targetInfo.id, targetInfo.friendlyName, OriginalArrivalTime)) ?? new List <Task>()); if (!string.IsNullOrWhiteSpace(data.root.deletemember.initiator)) { await teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)data.root.deletemember.initiator, data.root.deletemember.detailedinitiatorinfo?.friendlyName, OriginalArrivalTime); } var memberNames = await Task.WhenAll(data.root.deletemember.target.Select(t => teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)t))); MessageSubject = $"✈️ {await teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, new TeamsParticipant(data.root.deletemember?.initiator))} removed: " + string.Join(", ", memberNames); textContent.Append(MessageSubject); } else if (Messagetype == MessageType.Event_Call) { XmlDocument doc = new XmlDocument(); // prepare XML to JSON conversion; force "part" being a list which cannot be infered from XML if there is only one element doc.LoadXml($"<root xmlns:json='http://james.newtonking.com/projects/json'>{Internal_Content.Replace("<part ", "<part json:Array='true' ")}</root>"); var json = JsonConvert.SerializeXmlNode(doc); var data = JsonUtils.DeserializeObject <EventCallWrapper>(logger, json); await Task.WhenAll(data.root.partlist?.part?.Select(member => teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)member.identity, member.displayName, OriginalArrivalTime)) ?? new List <Task>()); // sometimes p.name contains the user id and p.identity is empty var memberNames = await Task.WhenAll(data.root.partlist?.part?.Select(p => teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, TeamsParticipant.FromFirstValid(p.identity, p.name))) ?? new List <Task <string> >()); var callEnded = Internal_Content.Contains("<ended/>"); if (callEnded) { MessageSubject = "☎️ Call ended for: " + string.Join(", ", memberNames); } else { var from = (TeamsParticipant)Internal_FromContactUrl; var displayName = await teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, from); MessageSubject = $"☎️ Call started by {displayName}"; } textContent.Append(MessageSubject); } else if (Messagetype == MessageType.ThreadActivity_MemberJoined) { var data = JsonUtils.DeserializeObject <ThreadEventMemberJoined>(logger, Internal_Content); await Task.WhenAll(data.members.Select(member => teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)member.id, member.friendlyname, OriginalArrivalTime))); var memberNames = (await Task.WhenAll(data.members.Select(member => teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)member.id)))); MessageSubject = "✈️ Member(s) joined: " + string.Join(", ", memberNames); // note: friendlyname is sometimes empty; second note: für ehemalige Mitarbeiter kann ein ID-Lookup fehlschlagen, aber der friendlyName dennoch gesetzt sein textContent.Append(MessageSubject); } else if (Messagetype == MessageType.ThreadActivity_MemberLeft) { var data = JsonUtils.DeserializeObject <ThreadEventMemberLeft>(logger, Internal_Content); await Task.WhenAll(data.members.Select(member => teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)member.id, member.friendlyname, OriginalArrivalTime))); var memberNames = await Task.WhenAll(data.members.Select(member => teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)member.id))); MessageSubject = "✈️ Member(s) left: " + string.Join(", ", memberNames); textContent.Append(MessageSubject); } else if (Messagetype == MessageType.RichText_Media_CallRecording) { XmlDocument doc = new XmlDocument(); // prepare XML to JSON conversion; force "part" being a list which cannot be infered from XML if there is only one element doc.LoadXml($"<root xmlns:json='http://james.newtonking.com/projects/json'>{Internal_Content.Replace("<Identifiers>", "<Identifiers json:Array='true'>").Replace("<RecordingContent ", "<RecordingContent json:Array='true' ").Replace("<RequestedExports ", "<RequestedExports json:Array='true' ")}</root>"); var json = JsonConvert.SerializeXmlNode(doc); var data = JsonUtils.DeserializeObject <RichTextMedia_CallRecordingWrapper>(logger, json); MessageSubject = $"✍️ Recording started by {await teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, new TeamsParticipant(data.root?.URIObject?.RecordingInitiatorId?.value))}"; textContent.Append(MessageSubject); } else if (Messagetype == MessageType.Text) { HtmlContent = Internal_Content; } else if (Messagetype == MessageType.ThreadActivity_TopicUpdate) { XmlDocument doc = new XmlDocument(); // <topicupdate><eventtime>0000000000000</eventtime><initiator>8:orgid:00000000-0000-beef-0000-000000000000</initiator><value>New topic</value></topicupdate> doc.LoadXml($"<root xmlns:json='http://james.newtonking.com/projects/json'>{Internal_Content}</root>"); var json = JsonConvert.SerializeXmlNode(doc); var data = JsonUtils.DeserializeObject <ThreadActivityTopicUpdateWrapper>(logger, json); var user = await teamsUserRegistry.GetUserByIdAsync(nonNullContext, (TeamsParticipant)data.root.topicupdate.initiator, false); if (user != null && user.HasDisplayName) { if (From.Count == 1 && (From[0].UserId.Kind == ParticipantKind.TeamsChat || From[0].UserId.Kind == ParticipantKind.Unknown)) { From.Clear(); From.Add(user); } } MessageSubject = $"®️ Topic set to '{data.root.topicupdate.value}' by {await teamsUserRegistry.GetDisplayNameForUserIdAsync(nonNullContext, new TeamsParticipant(data.root.topicupdate.initiator))}"; textContent.Append(MessageSubject); } else { textContent.Append("Unknown message type, don't know how to render: " + Messagetype); } if (string.IsNullOrWhiteSpace(HtmlContent)) { HtmlContent = MessageSubject; } TextContent = textContent.ToString(); } catch (Exception e) { // exceptions here will cancel the whole chat from being parsed; log the message content to analyze it later logger.Error(e, "[{TenantName}] Exception while processing message content in method {MethodName}; Original message content: {MessageContent}", nonNullContext.Tenant.TenantName, nameof(GenerateTextContentExtractUsersAndUpdateSubject), SerializeOriginalMessageAsJson()); // don't just skip a failed message, but cancel chat retrieval and fix the underlying issue, then try again throw; } }
protected async Task ExtractSendersReceiversAndSubject(string chatId) { if (ctx == null || !ctx.HasValue) { return; } var nonNullContext = ctx.Value; var messageFromTeams = false; var messageFromMe = false; if (Internal_FromContactUrl?.EndsWith(chatId, StringComparison.InvariantCultureIgnoreCase) ?? false) { messageFromTeams = true; } #pragma warning disable CS8604 // Possible null reference argument. if (Internal_FromContactUrl?.ToString().EndsWith(nonNullContext.Tenant.UserId, StringComparison.InvariantCultureIgnoreCase) ?? false) #pragma warning restore CS8604 // Possible null reference argument. { messageFromMe = true; } // determine senders if (messageFromTeams) { var teamsChatUser = new ProcessedTeamsUser(nonNullContext, (TeamsParticipant)chatId); teamsChatUser.RegisterAlternateDisplayName(Constants.MicrosoftTeamsChatSenderName, OriginalArrivalTime); teamsChatUser.RegisterAlternateEmailAddress(Constants.MicrosoftTeamsChatSenderEmailAddress, OriginalArrivalTime); From.Add(teamsChatUser); } else { var userId = (TeamsParticipant)Internal_FromContactUrl; if (userId.IsValid) { await teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, userId, Internal_DisplayName, OriginalArrivalTime); var user = await teamsUserRegistry.GetUserByIdOrDummyAsync(nonNullContext, userId); if (user.HasDisplayName && user.HasEmailAddress) { From.Add(user); } } else { if (From.Count == 0) { // no valid user id? phew... var dummyUser = new ProcessedTeamsUser(nonNullContext, userId); dummyUser.RegisterAlternateDisplayName(Internal_DisplayName, OriginalArrivalTime); From.Add(dummyUser); } } } // determine receivers if (Internal_Mentions?.Count > 0) { foreach (var mention in Internal_Mentions) { var userId = (TeamsParticipant)mention.mri; var user = await teamsUserRegistry.GetUserByIdAsync(nonNullContext, userId, true); if (user != null && user.HasDisplayName && user.HasEmailAddress) { To.Add(user); } else { var toUser = new ProcessedTeamsUser(nonNullContext, userId); toUser.RegisterAlternateDisplayName(mention.displayName, OriginalArrivalTime); toUser.RegisterAlternateEmailAddress(mention.IsChannelMention ? Constants.ChannelMentionEmailAddress : Constants.UnknownUserEmailAddress, OriginalArrivalTime); To.Add(toUser); } } } else { var toUser = new ProcessedTeamsUser(nonNullContext, TeamsParticipant.Null); toUser.RegisterAlternateDisplayName(Constants.UnknownReceiversDisplayName, OriginalArrivalTime); toUser.RegisterAlternateEmailAddress(Constants.UnknownUserEmailAddress, OriginalArrivalTime); To.Add(toUser); } // determine subject if (!string.IsNullOrWhiteSpace(Internal_Subject)) { MessageSubject = Internal_Subject; } else { string displayName = Internal_DisplayName ?? ""; if (displayName == null && (Messagetype != MessageType.Text || Messagetype != MessageType.RichText_Html)) { displayName = "Microsoft Teams"; } await teamsUserRegistry.RegisterDisplayNameForUserIdAsync(nonNullContext, (TeamsParticipant)Internal_FromContactUrl, displayName, OriginalArrivalTime); displayName = await teamsUserRegistry.ReplaceUserIdsWithDisplayNamesAsync(nonNullContext, displayName); var messagePreview = "Message"; if (Messagetype == MessageType.RichText_Html) { // not sure if needed string html = string.Format("<html><head></head><body>{0}</body></html>", Internal_Content); HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(html); var body = doc.DocumentNode.SelectSingleNode("//body"); messagePreview = body.InnerText ?? ""; } else if (Messagetype == MessageType.Text) { messagePreview = Internal_Content ?? ""; } messagePreview = HttpUtility.HtmlDecode(messagePreview).Trim(); // need to replace etc. if (messagePreview.Length > 100) { messagePreview = messagePreview.Truncate(100) + "..."; } else if (messagePreview.Length == 0) { messagePreview = $"Message"; } var truncatedDisplayName = displayName.Truncate(10)?.Trim() ?? ""; MessageSubject = $"[{(messageFromMe ? "ME" : truncatedDisplayName)}] {messagePreview}"; } }
/// <summary> /// Constructs a new <see cref="TimeBlock"/> starting from <see cref="DateTime.UtcNow"/> offset by a specified <see cref="TimeSpan"/>. /// </summary> public TimeBlock(TimeSpan length) { From = DateTime.UtcNow; To = From.Add(length); }
public State(string name, State from) : this(name) { from.To.Add(this); From.Add(from); }