Class: Teems::Models::Message

Inherits:
Data
  • Object
show all
Extended by:
Parsing
Defined in:
lib/teems/models/message.rb

Overview

Represents a message in Teams Handles both Graph API and Teams internal API response formats

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Parsing

mention_display_name, normalize_mentions, parse_files_json, parse_mentions, parse_time, strip_html

Instance Attribute Details

#attachmentsObject (readonly)

Returns the value of attribute attachments

Returns:

  • (Object)

    the current value of attachments



7
8
9
# File 'lib/teems/models/message.rb', line 7

def attachments
  @attachments
end

#contentObject (readonly)

Returns the value of attribute content

Returns:

  • (Object)

    the current value of content



7
8
9
# File 'lib/teems/models/message.rb', line 7

def content
  @content
end

#created_atObject (readonly)

Returns the value of attribute created_at

Returns:

  • (Object)

    the current value of created_at



7
8
9
# File 'lib/teems/models/message.rb', line 7

def created_at
  @created_at
end

#editedObject (readonly)

Returns the value of attribute edited

Returns:

  • (Object)

    the current value of edited



7
8
9
# File 'lib/teems/models/message.rb', line 7

def edited
  @edited
end

#idObject (readonly)

Returns the value of attribute id

Returns:

  • (Object)

    the current value of id



7
8
9
# File 'lib/teems/models/message.rb', line 7

def id
  @id
end

#importanceObject (readonly)

Returns the value of attribute importance

Returns:

  • (Object)

    the current value of importance



7
8
9
# File 'lib/teems/models/message.rb', line 7

def importance
  @importance
end

#mentionsObject (readonly)

Returns the value of attribute mentions

Returns:

  • (Object)

    the current value of mentions



7
8
9
# File 'lib/teems/models/message.rb', line 7

def mentions
  @mentions
end

#message_typeObject (readonly)

Returns the value of attribute message_type

Returns:

  • (Object)

    the current value of message_type



7
8
9
# File 'lib/teems/models/message.rb', line 7

def message_type
  @message_type
end

#reactionsObject (readonly)

Returns the value of attribute reactions

Returns:

  • (Object)

    the current value of reactions



7
8
9
# File 'lib/teems/models/message.rb', line 7

def reactions
  @reactions
end

#reply_to_idObject (readonly)

Returns the value of attribute reply_to_id

Returns:

  • (Object)

    the current value of reply_to_id



7
8
9
# File 'lib/teems/models/message.rb', line 7

def reply_to_id
  @reply_to_id
end

#sender_idObject (readonly)

Returns the value of attribute sender_id

Returns:

  • (Object)

    the current value of sender_id



7
8
9
# File 'lib/teems/models/message.rb', line 7

def sender_id
  @sender_id
end

#sender_nameObject (readonly)

Returns the value of attribute sender_name

Returns:

  • (Object)

    the current value of sender_name



7
8
9
# File 'lib/teems/models/message.rb', line 7

def sender_name
  @sender_name
end

Class Method Details

.extract_sender_name(data) ⇒ Object



93
94
95
# File 'lib/teems/models/message.rb', line 93

def self.extract_sender_name(data)
  data.dig('from', 'user', 'displayName') || data.dig('from', 'application', 'displayName') || 'Unknown'
end

.from_api(data) ⇒ Object



14
15
16
17
18
19
# File 'lib/teems/models/message.rb', line 14

def self.from_api(data)
  if data['message'] then from_teams_internal_api(data)
  elsif data['imdisplayname'] || data['messagetype'] then from_ng_msg_api(data)
  else from_graph_api(data)
  end
end

.from_graph_api(data) ⇒ Object



68
69
70
# File 'lib/teems/models/message.rb', line 68

def self.from_graph_api(data)
  new(**graph_attrs(data))
end

.from_ng_msg_api(data) ⇒ Object



21
22
23
# File 'lib/teems/models/message.rb', line 21

def self.from_ng_msg_api(data)
  new(**ng_msg_attrs(data))
end

.from_teams_internal_api(data) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/teems/models/message.rb', line 55

def self.from_teams_internal_api(data)
  msg = data['message']
  new(
    id: data['id'], sender_id: msg['from'],
    sender_name: msg['imDisplayName'] || msg['fromDisplayNameInToken'] || 'Unknown',
    content: strip_html(msg['content'] || ''),
    created_at: parse_time(msg['composeTime'] || data['latestMessageTime']),
    message_type: msg['type'], reply_to_id: nil, reactions: [],
    attachments: parse_files_json(msg.dig('properties', 'files')),
    importance: nil, edited: false, mentions: []
  )
end

.graph_attrs(data) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/teems/models/message.rb', line 72

def self.graph_attrs(data)
  {
    id: data['id'],
    sender_id: data.dig('from', 'user', 'id') || data.dig('from', 'application', 'id'),
    sender_name: extract_sender_name(data),
    content: strip_html(data.dig('body', 'content') || ''),
    created_at: parse_time(data['createdDateTime']),
    **graph_extras(data)
  }
end

.graph_extras(data) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/teems/models/message.rb', line 83

def self.graph_extras(data)
  {
    message_type: data['messageType'], reply_to_id: data['replyToId'],
    reactions: parse_reactions(data['reactions']),
    attachments: data['attachments'] || [],
    importance: data['importance'],
    edited: false, mentions: []
  }
end

.ng_msg_attrs(data) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/teems/models/message.rb', line 25

def self.ng_msg_attrs(data)
  props = data['properties'] || {}
  {
    id: data['id'], sender_id: data['from'],
    sender_name: data['imdisplayname'] || data['fromDisplayNameInToken'] || 'Unknown',
    content: strip_html(data['content'] || ''),
    created_at: parse_time(data['composetime'] || data['originalarrivaltime']),
    message_type: data['messagetype'],
    **ng_msg_extras(data, props)
  }
end

.ng_msg_extras(data, props) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/teems/models/message.rb', line 37

def self.ng_msg_extras(data, props)
  root_message_id = data['rootMessageId']
  {
    reply_to_id: root_message_id == data['id'] ? nil : root_message_id,
    reactions: parse_ng_msg_reactions(props['emotions']),
    attachments: parse_files_json(props['files']),
    importance: props['importance'],
    edited: props.key?('edittime'),
    mentions: parse_mentions(props['mentions'])
  }
end

.parse_ng_msg_reactions(emotions) ⇒ Object



49
50
51
52
53
# File 'lib/teems/models/message.rb', line 49

def self.parse_ng_msg_reactions(emotions)
  return [] unless emotions.is_a?(Array)

  emotions.map { |emotion| { type: emotion['key'], count: emotion['users']&.length || 1 } }
end

.parse_reactions(reactions_data) ⇒ Object



97
98
99
100
101
# File 'lib/teems/models/message.rb', line 97

def self.parse_reactions(reactions_data)
  return [] unless reactions_data.is_a?(Array)

  reactions_data.map { |reaction| { type: reaction['reactionType'], count: reaction['user']&.length || 1 } }
end

Instance Method Details

#content_with_mentions_highlightedObject



105
106
107
108
109
# File 'lib/teems/models/message.rb', line 105

def content_with_mentions_highlighted
  return content if mentions.empty?

  mentions.inject(content) { |text, name| text.gsub(name, yield(name)) }
end

#downloadable_attachmentsObject



103
# File 'lib/teems/models/message.rb', line 103

def downloadable_attachments = attachments.grep(Hash).select { |att| att.key?('sharepointIds') }

#edited?Boolean

Returns:

  • (Boolean)


114
# File 'lib/teems/models/message.rb', line 114

def edited? = !!edited

#important?Boolean

Returns:

  • (Boolean)


115
# File 'lib/teems/models/message.rb', line 115

def important? = %w[urgent high].include?(importance)

#reply?Boolean

Returns:

  • (Boolean)


113
# File 'lib/teems/models/message.rb', line 113

def reply? = !!reply_to_id

#short_hashObject



111
# File 'lib/teems/models/message.rb', line 111

def short_hash = Digest::SHA256.hexdigest(id.to_s)[0, 6]

#system_message?Boolean

Returns:

  • (Boolean)


116
# File 'lib/teems/models/message.rb', line 116

def system_message? = message_type && !normal_message_type? && !rich_text_type?

#timestampObject



112
# File 'lib/teems/models/message.rb', line 112

def timestamp = created_at

#to_sObject



117
# File 'lib/teems/models/message.rb', line 117

def to_s = "[#{created_at&.strftime('%H:%M')}] #{sender_name}: #{content}"