Class: Slk::Models::Message

Inherits:
Data
  • Object
show all
Defined in:
lib/slk/models/message.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ts:, user_id:, text: '', reactions: [], reply_count: 0, thread_ts: nil, files: [], attachments: [], blocks: [], user_profile: nil, bot_profile: nil, username: nil, subtype: nil, channel_id: nil) ⇒ Message

rubocop:disable Metrics/ParameterLists, Naming/MethodParameterName



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/slk/models/message.rb', line 94

def initialize(
  ts:,
  user_id:,
  text: '',
  reactions: [],
  reply_count: 0,
  thread_ts: nil,
  files: [],
  attachments: [],
  blocks: [],
  user_profile: nil,
  bot_profile: nil,
  username: nil,
  subtype: nil,
  channel_id: nil
)
  validate_required_fields!(ts, user_id)
  super(**freeze_attributes(
    ts: ts, user_id: user_id, text: text, reactions: reactions,
    reply_count: reply_count, thread_ts: thread_ts, files: files,
    attachments: attachments, blocks: blocks, user_profile: ,
    bot_profile: bot_profile, username: username, subtype: subtype, channel_id: channel_id
  ))
end

Instance Attribute Details

#attachmentsObject (readonly)

Returns the value of attribute attachments

Returns:

  • (Object)

    the current value of attachments



12
13
14
# File 'lib/slk/models/message.rb', line 12

def attachments
  @attachments
end

#blocksObject (readonly)

Returns the value of attribute blocks

Returns:

  • (Object)

    the current value of blocks



12
13
14
# File 'lib/slk/models/message.rb', line 12

def blocks
  @blocks
end

#bot_profileObject (readonly)

Returns the value of attribute bot_profile

Returns:

  • (Object)

    the current value of bot_profile



12
13
14
# File 'lib/slk/models/message.rb', line 12

def bot_profile
  @bot_profile
end

#channel_idObject (readonly)

Returns the value of attribute channel_id

Returns:

  • (Object)

    the current value of channel_id



12
13
14
# File 'lib/slk/models/message.rb', line 12

def channel_id
  @channel_id
end

#filesObject (readonly)

Returns the value of attribute files

Returns:

  • (Object)

    the current value of files



12
13
14
# File 'lib/slk/models/message.rb', line 12

def files
  @files
end

#reactionsObject (readonly)

Returns the value of attribute reactions

Returns:

  • (Object)

    the current value of reactions



12
13
14
# File 'lib/slk/models/message.rb', line 12

def reactions
  @reactions
end

#reply_countObject (readonly)

Returns the value of attribute reply_count

Returns:

  • (Object)

    the current value of reply_count



12
13
14
# File 'lib/slk/models/message.rb', line 12

def reply_count
  @reply_count
end

#subtypeObject (readonly)

Returns the value of attribute subtype

Returns:

  • (Object)

    the current value of subtype



12
13
14
# File 'lib/slk/models/message.rb', line 12

def subtype
  @subtype
end

#textObject (readonly)

Returns the value of attribute text

Returns:

  • (Object)

    the current value of text



12
13
14
# File 'lib/slk/models/message.rb', line 12

def text
  @text
end

#thread_tsObject (readonly)

Returns the value of attribute thread_ts

Returns:

  • (Object)

    the current value of thread_ts



12
13
14
# File 'lib/slk/models/message.rb', line 12

def thread_ts
  @thread_ts
end

#tsObject (readonly)

Returns the value of attribute ts

Returns:

  • (Object)

    the current value of ts



12
13
14
# File 'lib/slk/models/message.rb', line 12

def ts
  @ts
end

#user_idObject (readonly)

Returns the value of attribute user_id

Returns:

  • (Object)

    the current value of user_id



12
13
14
# File 'lib/slk/models/message.rb', line 12

def user_id
  @user_id
end

#user_profileObject (readonly)

Returns the value of attribute user_profile

Returns:

  • (Object)

    the current value of user_profile



12
13
14
# File 'lib/slk/models/message.rb', line 12

def 
  @user_profile
end

#usernameObject (readonly)

Returns the value of attribute username

Returns:

  • (Object)

    the current value of username



12
13
14
# File 'lib/slk/models/message.rb', line 12

def username
  @username
end

Class Method Details

.build_attributes(data, text, channel_id) ⇒ Object

rubocop:disable Metrics/MethodLength



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/slk/models/message.rb', line 44

def self.build_attributes(data, text, channel_id)
  {
    ts: data['ts'],
    user_id: data['user'] || data['bot_id'] || data['username'],
    text: text,
    reactions: parse_reactions(data['reactions']),
    reply_count: data['reply_count'] || 0,
    thread_ts: data['thread_ts'],
    files: data['files'] || [],
    attachments: data['attachments'] || [],
    blocks: data['blocks'] || [],
    user_profile: data['user_profile'],
    bot_profile: data['bot_profile'],
    username: data['username'],
    subtype: data['subtype'],
    channel_id: channel_id
  }
end

.extract_block_text(blocks) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/slk/models/message.rb', line 68

def self.extract_block_text(blocks)
  return '' unless blocks.is_a?(Array)

  blocks.filter_map do |block|
    case block['type']
    when 'section'
      block.dig('text', 'text')
    when 'rich_text'
      extract_rich_text_content(block['elements'])
    end
  end.join("\n")
end

.extract_message_text(data) ⇒ Object



33
34
35
36
37
38
39
40
41
# File 'lib/slk/models/message.rb', line 33

def self.extract_message_text(data)
  text = data['text'] || ''
  blocks = data['blocks'] || []

  return text if text.length >= MESSAGE_BLOCK_TEXT_THRESHOLD

  blocks_text = extract_block_text(blocks)
  blocks_text.empty? ? text : blocks_text
end

.extract_rich_text_content(elements) ⇒ Object



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

def self.extract_rich_text_content(elements)
  return '' unless elements.is_a?(Array)

  elements.filter_map do |element|
    next unless element['elements'].is_a?(Array)

    element['elements'].filter_map do |item|
      item['text'] if item['type'] == 'text'
    end.join
  end.join
end

.from_api(data, channel_id: nil) ⇒ Object



28
29
30
31
# File 'lib/slk/models/message.rb', line 28

def self.from_api(data, channel_id: nil)
  text = extract_message_text(data)
  new(**build_attributes(data, text, channel_id))
end

.parse_reactions(reactions_data) ⇒ Object

rubocop:enable Metrics/MethodLength



64
65
66
# File 'lib/slk/models/message.rb', line 64

def self.parse_reactions(reactions_data)
  (reactions_data || []).map { |r| Reaction.from_api(r) }
end

Instance Method Details

#blocks?Boolean

Returns:

  • (Boolean)


196
197
198
# File 'lib/slk/models/message.rb', line 196

def blocks?
  !blocks.empty?
end

#bot?Boolean

Returns:

  • (Boolean)


227
228
229
# File 'lib/slk/models/message.rb', line 227

def bot?
  user_id.start_with?('B') || subtype == 'bot_message'
end

#deep_freeze(obj) ⇒ Object

Instance method delegate to class method for use in initialize



172
173
174
# File 'lib/slk/models/message.rb', line 172

def deep_freeze(obj)
  self.class.send(:deep_freeze, obj)
end

#embedded_usernameObject



200
201
202
# File 'lib/slk/models/message.rb', line 200

def embedded_username
   || username_from_bot_profile || fallback_username
end

#fallback_usernameObject



223
224
225
# File 'lib/slk/models/message.rb', line 223

def fallback_username
  username.to_s.empty? ? nil : username
end

#files?Boolean

Returns:

  • (Boolean)


192
193
194
# File 'lib/slk/models/message.rb', line 192

def files?
  !files.empty?
end

#freeze_attributes(attrs) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/slk/models/message.rb', line 129

def freeze_attributes(attrs)
  {
    ts: attrs[:ts].to_s.strip.freeze,
    user_id: attrs[:user_id].to_s.strip.freeze,
    text: attrs[:text].to_s.freeze,
    reactions: attrs[:reactions].freeze,
    reply_count: attrs[:reply_count].to_i,
    thread_ts: attrs[:thread_ts]&.freeze,
    files: deep_freeze(attrs[:files]),
    attachments: deep_freeze(attrs[:attachments]),
    blocks: deep_freeze(attrs[:blocks]),
    user_profile: deep_freeze(attrs[:user_profile]),
    bot_profile: deep_freeze(attrs[:bot_profile]),
    username: attrs[:username]&.freeze,
    subtype: attrs[:subtype]&.freeze,
    channel_id: attrs[:channel_id]&.freeze
  }
end

#reactions?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/slk/models/message.rb', line 188

def reactions?
  !reactions.empty?
end

#reply?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/slk/models/message.rb', line 184

def reply?
  thread_ts && thread_ts != ts
end

#system_message?Boolean

Returns:

  • (Boolean)


231
232
233
# File 'lib/slk/models/message.rb', line 231

def system_message?
  %w[channel_join channel_leave channel_topic channel_purpose].include?(subtype)
end

#thread?Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/slk/models/message.rb', line 180

def thread?
  reply_count.positive?
end

#timestampObject



176
177
178
# File 'lib/slk/models/message.rb', line 176

def timestamp
  Time.at(ts.to_f)
end

#username_from_bot_profileObject



216
217
218
219
220
221
# File 'lib/slk/models/message.rb', line 216

def username_from_bot_profile
  return nil unless bot_profile

  name = bot_profile['name']
  name.to_s.empty? ? nil : name
end

#username_from_user_profileObject



204
205
206
207
208
209
210
211
212
213
214
# File 'lib/slk/models/message.rb', line 204

def 
  return nil unless 

  display = ['display_name']
  return display unless display.to_s.empty?

  real = ['real_name']
  return real unless real.to_s.empty?

  nil
end

#validate_required_fields!(timestamp, user) ⇒ Object

rubocop:enable Metrics/ParameterLists, Naming/MethodParameterName

Raises:

  • (ArgumentError)


120
121
122
123
124
125
126
# File 'lib/slk/models/message.rb', line 120

def validate_required_fields!(timestamp, user)
  ts_str = timestamp.to_s.strip
  user_id_str = user.to_s.strip

  raise ArgumentError, 'ts cannot be empty' if ts_str.empty?
  raise ArgumentError, 'user_id cannot be empty' if user_id_str.empty?
end

#with_reactions(new_reactions) ⇒ Object

Create a copy of this message with updated reactions



236
237
238
# File 'lib/slk/models/message.rb', line 236

def with_reactions(new_reactions)
  Message.new(**to_h, reactions: new_reactions)
end