Module: Slk::Services::ProfileBuilder

Defined in:
lib/slk/services/profile_builder.rb

Overview

Builds Models::Profile from raw users.profile.get + users.info + team.profile.get responses. Pure data assembly — no API calls.

Class Method Summary collapse

Class Method Details

.build(profile_response:, info_response: nil, schema_response: nil, workspace_team_id: nil) ⇒ Object

rubocop:disable Metrics/MethodLength



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/slk/services/profile_builder.rb', line 11

def build(profile_response:, info_response: nil, schema_response: nil, workspace_team_id: nil)
  info_data = extract_info(info_response)
  profile_data = extract_profile(profile_response, info_data)
  schema = extract_schema(schema_response)
  team_id = info_data['team_id'] || profile_data['team']

  Models::Profile.new(
    **identity(profile_data, info_data),
    **status(profile_data),
    **tz(info_data),
    **flags(info_data, team_id, workspace_team_id),
    team_id: team_id,
    home_team_name: nil,
    presence: nil,
    sections: schema[:sections],
    custom_fields: build_fields(profile_data['fields'] || {}, schema[:fields_by_id]),
    resolved_users: {}
  )
end

.build_field(field_id, field_data, schema) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/slk/services/profile_builder.rb', line 118

def build_field(field_id, field_data, schema)
  Models::ProfileField.new(
    id: field_id, label: field_data['label'] || schema['label'] || field_id,
    value: field_data['value'].to_s, alt: field_data['alt'].to_s,
    type: schema['type'] || 'text', ordering: schema['ordering'].to_i,
    section_id: schema['section_id'],
    hidden: schema['is_hidden'] == true, inverse: schema['is_inverse'] == true
  )
end

.build_fields(profile_fields, schema_fields_by_id) ⇒ Object



112
113
114
115
116
# File 'lib/slk/services/profile_builder.rb', line 112

def build_fields(profile_fields, schema_fields_by_id)
  profile_fields.map do |field_id, field_data|
    build_field(field_id, field_data, schema_fields_by_id[field_id] || {})
  end
end

.contact(profile_data) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/slk/services/profile_builder.rb', line 71

def contact(profile_data)
  {
    title: profile_data['title'],
    email: profile_data['email'],
    phone: profile_data['phone'],
    pronouns: profile_data['pronouns'],
    image_url: profile_data['image_512'] || profile_data['image_192'] || profile_data['image_72'],
    start_date: profile_data['start_date']
  }
end

.external?(team_id, workspace_team_id) ⇒ Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/slk/services/profile_builder.rb', line 108

def external?(team_id, workspace_team_id)
  !!(workspace_team_id && team_id && team_id != workspace_team_id)
end

.extract_info(response) ⇒ Object



42
43
44
45
46
# File 'lib/slk/services/profile_builder.rb', line 42

def extract_info(response)
  return {} unless response.is_a?(Hash)

  response['user'] || {}
end

.extract_profile(response, info_data = {}) ⇒ Object

Slack Connect external users often fail users.profile.get with user_not_found, but users.info still returns the same fields nested at user.profile. Fall back to that so we render a useful card.



35
36
37
38
39
40
# File 'lib/slk/services/profile_builder.rb', line 35

def extract_profile(response, info_data = {})
  primary = response.is_a?(Hash) ? (response['profile'] || {}) : {}
  return primary unless primary.empty?

  info_data['profile'] || {}
end

.extract_schema(response) ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/slk/services/profile_builder.rb', line 48

def extract_schema(response)
  section = response.is_a?(Hash) ? (response['profile'] || {}) : {}
  fields = section['fields'] || []
  {
    fields_by_id: fields.to_h { |f| [f['id'], f] },
    sections: section['sections'] || []
  }
end

.flags(info_data, team_id, workspace_team_id) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/slk/services/profile_builder.rb', line 98

def flags(info_data, team_id, workspace_team_id)
  {
    is_admin: info_data['is_admin'] || false,
    is_owner: info_data['is_owner'] || false,
    is_bot: info_data['is_bot'] || false,
    is_external: external?(team_id, workspace_team_id),
    deleted: info_data['deleted'] == true
  }
end

.identity(profile_data, info_data) ⇒ Object



57
58
59
# File 'lib/slk/services/profile_builder.rb', line 57

def identity(profile_data, info_data)
  names(profile_data, info_data).merge(contact(profile_data))
end

.names(profile_data, info_data) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/slk/services/profile_builder.rb', line 61

def names(profile_data, info_data)
  {
    user_id: info_data['id'] || profile_data['id'] || '',
    real_name: profile_data['real_name'] || info_data['real_name'],
    display_name: profile_data['display_name'],
    first_name: profile_data['first_name'],
    last_name: profile_data['last_name']
  }
end

.status(profile_data) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/slk/services/profile_builder.rb', line 82

def status(profile_data)
  {
    status_text: profile_data['status_text'] || '',
    status_emoji: profile_data['status_emoji'] || '',
    status_expiration: profile_data['status_expiration'] || 0
  }
end

.tz(info_data) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/slk/services/profile_builder.rb', line 90

def tz(info_data)
  {
    tz: info_data['tz'],
    tz_label: info_data['tz_label'],
    tz_offset: info_data['tz_offset'] || 0
  }
end