Module: SlackSmartBot::Commands::General::Teams

Included in:
SlackSmartBot
Defined in:
lib/slack/smart-bot/commands/general/teams/add_team.rb,
lib/slack/smart-bot/commands/general/teams/ping_team.rb,
lib/slack/smart-bot/commands/general/teams/see_teams.rb,
lib/slack/smart-bot/commands/general/teams/delete_team.rb,
lib/slack/smart-bot/commands/general/teams/update_team.rb,
lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb,
lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb,
lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb,
lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb,
lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb,
lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb,
lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb

Defined Under Namespace

Modules: Memos

Instance Method Summary collapse

Instance Method Details

#add_team(user, name, options, info) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/slack/smart-bot/commands/general/teams/add_team.rb', line 5

def add_team(user, name, options, info)
  save_stats(__method__)

  get_teams()
  if @teams.key?(name.to_sym)
    respond "It seems like the team *#{name}* already exists.\nRelated commands `update team TEAM_NAME PROPERTIES`, `delete team TEAM_NAME`, `see team TEAM_NAME`, `see teams`"
  else
    wrong = false
    team = { members: {}, channels: {} }
    last_type = nil
    type_detected = false
    options.split(/\s+/).each do |opt|
      type_detected = false
      if opt.match?(/^\s*$/)
        #blank
      elsif opt.match?(/^[\w\-]+$/i)
        last_type = opt
        type_detected = true
      elsif opt.match(/<@(\w+)>/i)
        team[:members][last_type] ||= []
        if last_type.nil?
          wrong = true
          respond "You need to specify the TYPE for the member."
          break
        else
          member_id = $1
          member_info = find_user(member_id)
          team[:members][last_type] << "#{member_info.team_id}_#{member_info.name}"
        end
      elsif opt.match(/<#(\w+)\|[^>]*>/i)
        team[:channels][last_type] ||= []
        if last_type.nil?
          wrong = true
          respond "You need to specify the TYPE for the channel."
          break
        else
          channel_id = $1
          get_channels_name_and_id() unless @channels_name.keys.include?(channel_id)
          channel = @channels_name[channel_id]
          channel_members = get_channel_members(channel_id) unless channel.nil?
          if channel.nil? or !channel_members.include?(config.nick_id)
            respond ":exclamation: Add the Smart Bot to *<##{channel_id}>* channel first."
            wrong = true
            break
          else
            team[:channels][last_type] << channel
          end
        end
      else
        respond "It seems like the members or channel list is not correct. Please double check."
        wrong = true
        break
      end
    end
    if type_detected #type added but not added a channel or user
      respond "It seems like the parameters supplied are not correct. Please double check."
      wrong = true
    end

    unless wrong
      get_teams()
      team[:info] = info
      team[:status] = :added
      team[:user] = "#{user.team_id}_#{user.name}"
      team[:creator] = "#{user.team_id}_#{user.name}"
      team[:date] = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")[0..18]
      new_team = {}
      team[:name] = name
      new_team[name.to_sym] = team
      update_teams(new_team)
      respond "The *#{name}* team has been added."
      see_teams(user, name, add_stats: false)
    end
  end
end

#delete_team(user, team_name) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/slack/smart-bot/commands/general/teams/delete_team.rb', line 5

def delete_team(user, team_name)
  save_stats(__method__) if answer.empty?

  if Thread.current[:dest][0] == "D"
    respond "This command cannot be called from a DM"
  else
    get_teams()
    if @teams.key?(team_name.to_sym)
      assigned_members = @teams[team_name.to_sym].members.values.flatten
      assigned_members.uniq!
      all_team_members = assigned_members.dup
      team_members = []
      if @teams[team_name.to_sym].channels.key?("members")
        @teams[team_name.to_sym].channels["members"].each do |ch|
          get_channels_name_and_id() unless @channels_id.key?(ch)
          tm = get_channel_members(@channels_id[ch])
          tm.each do |m|
             = find_user(m)
            team_members << "#{.team_id}_#{.name}" unless .nil? or .is_app_user or .is_bot
          end
        end
      end
      team_members.flatten!
      team_members.uniq!
      all_team_members += team_members
      all_team_members.uniq!
    end
    if !@teams.key?(team_name.to_sym)
      respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
    elsif !(all_team_members + [@teams[team_name.to_sym].creator] + config.team_id_masters).flatten.include?("#{user.team_id}_#{user.name}")
      respond "You have to be a member of the team, the creator or a Master admin to be able to delete this team."
    else
      if answer.empty?
        ask "do you really want to delete the #{team_name} team? (yes/no)"
      else
        case answer
        when /yes/i, /yep/i, /sure/i
          answer_delete
          @teams.delete(team_name.to_sym)
          require "fileutils"
          time_deleted = Time.now.strftime("%Y%m%d%H%M%S")
          FileUtils.mv(File.join(config.path, "teams", "t_#{team_name}.yaml"),
                       File.join(config.path, "teams", "t_#{team_name}_#{time_deleted}.yaml.deleted"))
          deleted_memos_file = File.join(config.path, "teams", "t_#{team_name}_memos.yaml.deleted")
          if File.exist?(deleted_memos_file)
            FileUtils.mv(deleted_memos_file,
                         File.join(config.path, "teams", "t_#{team_name}_memos_#{time_deleted}.yaml.deleted"))
          end
          update_teams()
          respond "The team #{team_name} has been deleted."
        when /no/i, /nope/i, /cancel/i
          answer_delete
          respond "Ok, the team was not deleted"
        else
          respond "I don't understand"
          ask "do you really want to delete the #{team_name} team? (yes/no)"
        end
      end
    end
  end
end

#ping_team(user, type, team_name, member_type, message) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/slack/smart-bot/commands/general/teams/ping_team.rb', line 5

def ping_team(user, type, team_name, member_type, message)
  if type == :ping
    save_stats(:ping_team)
    icon = ":large_green_circle:"
  else
    save_stats(:contact_team)
    icon = ":email:"
  end
  if Thread.current[:dest][0] == "D"
    respond "This command cannot be called from a DM"
  else
    get_teams()
    if !@teams.key?(team_name.to_sym)
      respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
    else
      team = @teams[team_name.to_sym].deep_copy

      assigned_members = team.members.values.flatten
      assigned_members.uniq!
      assigned_members.dup.each do |m|
        # extract the team_id from the member name: team_id_user_name. so everything after the first _ is the user_name. user_name can include _.
         = find_user(m)
        assigned_members.delete(m) if .nil? or .deleted
      end
      unassigned_members = []
      not_on_team_channel = []

      if ((!team.members.key?(member_type) or member_type == "all") and team.channels.key?("members"))
        team_members = []
        team.channels["members"].each do |ch|
          get_channels_name_and_id() unless @channels_id.key?(ch)
          tm = get_channel_members(@channels_id[ch])
          tm.each do |m|
             = find_user(m)
            team_members << "#{.team_id}_#{.name}" unless .nil? or .is_app_user or .is_bot or .deleted
          end
        end
        team_members.flatten!
        team_members.uniq!
        unassigned_members = team_members - assigned_members
        unassigned_members.delete("#{config.team_id}_#{config.nick}")

        unless unassigned_members.empty?
          um = unassigned_members.dup
          um.each do |m|
             = find_user(m)
            unless .nil? or .profile.title.to_s == "" or .deleted
              team.members[.profile.title.to_snake_case] ||= []
              team.members[.profile.title.to_snake_case] << m
              unassigned_members.delete(m)
            end
          end
          unless unassigned_members.empty?
            team.members["unassigned"] ||= []
            team.members["unassigned"] += unassigned_members
            team.members["unassigned"].sort!
          end
        end
      end

      if team.members.key?(member_type) or member_type == "all"
        if member_type == "all"
          members_list = team.members.values.flatten.uniq.shuffle
        else
          members_list = team.members[member_type].shuffle
        end
        if type == :ping
          active_members = []
          members_list.each do |member|
            member_info = find_user(member)
            unless member_info.nil? or member_info.deleted
              active = (get_presence(member_info.id).presence.to_s == "active")
              active_members << member if active
            end
          end
          members = active_members
        else
          members = members_list
        end
        members.dup.each do |m|
           = find_user(m)
          members.delete(m) if .nil? or .deleted
        end

        if members.size > 0
          members_names = members.map { |m| m.split("_")[1..-1].join("_") }
          respond "#{icon} *#{type} #{team_name} team #{member_type}*\nfrom <@#{user.name}>\nto <@#{members_names[0..29].join(">, <@")}>#{", #{members_names[30..-1].join(", ")}" if members.size > 30} \n> #{message.split("\n").join("\n> ")}"
        elsif type == :ping
          respond "It seems like there are no available #{member_type} members on #{team_name} team. Please call `see team #{team_name}`"
        else
          respond "It seems like there are no #{member_type} members on #{team_name} team. Please call `see team #{team_name}`"
        end
      else
        respond "The member type #{member_type} doesn't exist, please call `see team #{team_name}`"
      end
    end
  end
end

#see_teams(user, team_name, search = "", add_stats: true, ttype: '') ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/slack/smart-bot/commands/general/teams/see_teams.rb', line 5

def see_teams(user, team_name, search = "", add_stats: true, ttype: '')
  save_stats(__method__) if add_stats

  get_teams()
  teams = @teams.deep_copy
  if teams.empty?
    respond "There are no teams added yet. Use `add team` command to add a team."
  elsif team_name.to_s != "" and !teams.key?(team_name.to_sym) and (teams.keys.select { |t| (t.to_s.gsub("-", "").gsub("_", "") == team_name.to_s) }).empty?
    respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
  else
    users_link = (Thread.current[:dest][0] == "D")
    filter = (search != "")
    members_displayed = []

    react :runner
    @users = get_users() if add_stats

    messages = []
    search_members = []
    search_channels = []
    search_info = []
    if filter
      search.split(" ").each do |s|
        if s.match(/<@(\w+)>/i)
          m = $1
          #upcase since from the smartbot command we get it in lowercase
           = find_user(m.upcase)
          search_members << "#{.team_id}_#{.name}" unless .nil?
        elsif s.match(/<#(\w+)\|[^>]*>/i)
          c = $1.upcase
          search_channels << @channels_name[c] if @channels_name.key?(c)
        else
          search_info << s
        end
      end
    end
    if team_name.to_s == "" and search.to_s == ""
      dest = :on_thread
      messages.unshift("Since there are many lines returned the results are returned on a thread by default.")
    else
      dest = Thread.current[:dest]
    end

    teams.each do |name, team|
      filter ? add = false : add = true
      if team_name.to_s == "" or (team_name.to_s == name.to_s) or (name.to_s.gsub("-", "").gsub("_", "") == team_name.to_s)
        message = []
        message << "*#{name.capitalize}#{" #{ttype}" unless ttype.empty?}*"

        if filter and search_info.size > 0
          all_info = true
          search_info.each do |s|
            if (team.members.keys.find { |e| /#{s}/i =~ e })
              add = true
              break
            end
            if !name.match?(/#{s}/i)
              all_info = false
              break
            end
          end
          add = true if all_info
        end

        message << "   > *_members_*"

        assigned_members, unassigned_members, not_on_team_channel, channels_members, all_team_members = get_team_members(team)

        unless unassigned_members.empty?
          um = unassigned_members.dup
          um.each do |m|
             = find_user(m)
            unless .nil? or .profile.title.to_s == ""
              team.members[.profile.title.to_snake_case] ||= []
              team.members[.profile.title.to_snake_case] << m
              unassigned_members.delete(m)
            end
          end
          unless unassigned_members.empty?
            team.members["unassigned"] ||= []
            team.members["unassigned"] += unassigned_members
            team.members["unassigned"].sort!
          end
        end
        unless not_on_team_channel.empty?
          team.members["not on members channel"] = not_on_team_channel
          team.members["not on members channel"].sort!
        end
        add = true if (team.members.values.flatten & search_members).size > 0
        add = true if (team.channels.values.flatten & search_channels).size > 0
        if filter and search_info.size > 0
          all_info = true
          search_info.each do |s|
            if (team.members.keys.find { |e| /#{s}/i =~ e })
              add = true
              break
            end
            if !team.info.match?(/#{s}/i)
              all_info = false
              break
            end
          end
          add = true if all_info
        end

        if add
          if team_name.to_s != ""
            team.members.each do |type, members|
              if ttype.empty? or type.include?(ttype)
                message << "        _`#{type}`_:  "
                members.each do |member|
                  types = [":palm_tree:", ":spiral_calendar_pad:", ":face_with_thermometer:", ":baby:"]
                  member_info = find_user(member)
                  if !member_info.nil? and !member_info.deleted
                    member_id = member_info.id
                    members_displayed << "#{member_info.team_id}_#{member_info.name}"
                    info = (member_id) #to get the status_emoji right now
                    emoji = info.user.profile.status_emoji
                    if types.include?(emoji)
                      status = emoji
                    else
                      active = (get_presence(member_id).presence.to_s == "active")
                      if active
                        if member_info.key?(:tz_offset) and user.key?(:tz_offset) and (member_info.tz_offset - user.tz_offset).abs <= (4 * 3600)
                          status = ":large_green_circle:"
                        else
                          status = ":large_yellow_circle:"
                        end
                      else
                        status = ":white_circle:"
                      end
                    end
                  else
                    status = ":exclamation:"
                  end
                  unless status == ":exclamation:"
                    if users_link
                      message[-1] += "  #{status}<@#{member_info.name}>, "
                    else
                      unless member_info.nil?
                        if member_info.profile.display_name == ""
                          name = member_info.name
                        else
                          name = member_info.profile.display_name
                        end
                        message[-1] += "  #{status} #{name}, "
                      end
                    end
                  end
                end
                message[-1].chop!
                message[-1].chop!
              end
            end
          else
            team.members.each do |type, members|
              if ttype.empty? or type.include?(ttype)
                if users_link
                  members_displayed += members
                  members_names = members.map { |m| m.split("_")[1..-1].join("_") }
                  message << "        _`#{type}`_:  <@#{members_names.join(">,  <@")}>"
                else
                  membersn = []
                  members.each do |m|
                     = find_user(m)
                    unless .nil? or .deleted
                      members_displayed << "#{.team_id}_#{.name}"
                      if .profile.display_name == ""
                        name = .name
                      else
                        name = .profile.display_name
                      end
                      membersn << name
                    end
                  end
                  message << "        _`#{type}`_:  #{membersn.join("  /  ")}"
                end
              end
            end
          end
        end

        if add
          message << "   > *_channels_*"
          team.channels.each do |type, channels|
            if ttype.empty? or type.include?(ttype)
              channel_ids = []
              channels.each do |ch|
                channel_info = @channels_list.select { |c| c.name.to_s.downcase == ch.to_s.downcase }[-1]
                # remove team_id from team members values
                if @channels_id.key?(ch) and (!channel_info.is_private or (channel_info.is_private and (team.members.values + [team.creator]).flatten.include?("#{user.team_id}_#{user.name}")))
                  channel_ids << @channels_id[ch]
                end
              end
              message << "        _`#{type}`_:  <##{channel_ids.join("> <#")}>" unless channel_ids.empty?
            end
          end

          unless !team.key?(:memos) or team.memos.empty? or (team_name.to_s == "" and search.to_s == "")
            message += see_memos_team(user, type: "all", add_stats: false, team: team, topic: ttype, precise: false)
          end

          unless team.info.empty?
            team.info.split("\n").each do |m|
              message << ">#{m}"
            end
            message << "> "
            message << "> "
          end
          messages << message.join("\n")
        end
      end
    end
    unreact :runner
    if messages.empty?
      if filter
        respond "It seems like we didn't find any team with the criteria supplied. Call `see teams` for a full list of teams."
      else
        respond "It seems like there are no teams added.\nUse `add team TEAM_NAME PROPERTIES` to add one. Call `bot help add team` for extended info."
      end
    else
      if team_name.to_s != ""
        message = "\n\n:palm_tree: On vacation / "
        message += ":spiral_calendar_pad: In a meeting / "
        message += ":face_with_thermometer: :baby: Sick leave / "
        message += ":white_circle: Away / "
        message += ":large_yellow_circle: Available in remote timezone / "
        message += ":large_green_circle: Available"
        messages[-1] << message
        messages[-1] << "\n:information_source: Remote Time zone is >4h away from your current (#{user.tz_label})"
      end
      messages.each do |msg|
        respond msg, dest, unfurl_links: false, unfurl_media: false
      end
      unless team_name.to_s.empty?
        see_vacations_team(user, team_name, Date.today.strftime("%Y/%m/%d"), add_stats: false, filter_members: members_displayed)
      end
    end
  end
end

#see_vacations_team(user, team_name, date, add_stats: true, filter_members: []) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb', line 5

def see_vacations_team(user, team_name, date, add_stats: true, filter_members: [])
  save_stats(__method__) if add_stats

  get_teams()
  teams = @teams.deep_copy
  if teams.empty?
    respond "There are no teams added yet. Use `add team` command to add a team."
  elsif team_name.to_s != "" and !teams.key?(team_name.to_sym) and (teams.keys.select { |t| (t.to_s.gsub("-", "").gsub("_", "") == team_name.to_s) }).empty?
    respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
  else
    teams.each do |name, team|
      if team_name == name.to_s or (name.to_s.gsub("-", "").gsub("_", "") == team_name.to_s)
        team_name = name.to_s
        break
      end
    end
    date.gsub!("-", "/")
    get_vacations()
    members_by_country_region = {}
    team = teams[team_name.to_sym]
    assigned_members = team.members.values.flatten
    assigned_members.uniq!
    assigned_members.dup.each do |m|
       = find_user(m)
      assigned_members.delete(m) if .nil? or .deleted
    end

    channels_members = [] #todo: check if this is used in here. Remove.
    all_team_members = assigned_members.dup
    if team.channels.key?("members")
      team_members = []
      team.channels["members"].each do |ch|
        get_channels_name_and_id() unless @channels_id.key?(ch)
        tm = get_channel_members(@channels_id[ch])
        if tm.nil?
          respond ":exclamation: Add the Smart Bot to *##{ch}* channel to be able to get the list of members.", dest
        else
          channels_members << @channels_id[ch]
          tm.each do |m|
             = find_user(m)
            team_members << "#{.team_id}_#{.name}" unless .nil? or .is_app_user or .is_bot
          end
        end
      end
      team_members.flatten!
      all_team_members += team_members
      all_team_members.uniq!
    end
    if filter_members.size > 0
      all_team_members = all_team_members & filter_members
    end

    unless all_team_members.empty?
      blocks_header =
        {
          "type": "context",
          elements: [
            {
              type: "mrkdwn",
              text: "*Time Off #{team_name} team* from #{date} ",
            },
          ],
        }

      from = Date.parse(date, "%Y/%m/%d")
      blocks = []
      if config[:public_holidays].key?(:default_calendar)
        defaulted_country_region = config[:public_holidays][:default_calendar].downcase
      else
        defaulted_country_region = ""
      end
      all_team_members.each do |m|
        info = find_user(m)
        unless info.nil?
          country_region = ""
          if @vacations.key?(m) and @vacations[m][:public_holidays].to_s != ""
            country_region = @vacations[m][:public_holidays].downcase
          elsif config[:public_holidays].key?(:default_calendar) and country_region.empty?
            country_region = defaulted_country_region
          end
          members_by_country_region[country_region] ||= []
          members_by_country_region[country_region] << "#{info.team_id}_#{info.name}"
          if @vacations.key?(m)
            v = ""
            (from..(from + 20)).each do |d|
              v += "#{d.strftime("%d")} " if d.wday == 1 or d == from
              on_vacation = false
              @vacations[m].periods ||= []
              @vacations[m].periods.each do |p|
                if p.from <= d.strftime("%Y/%m/%d") and p.to >= d.strftime("%Y/%m/%d")
                  if d.wday == 0 or d.wday == 6
                    v += ":large_orange_square: "
                  else
                    v += ":large_red_square: "
                  end
                  on_vacation = true
                  break
                end
              end
              unless on_vacation
                if country_region != "" and (!@public_holidays.key?(country_region) or !@public_holidays[country_region].key?(d.year.to_s))
                  country, location = country_region.split("/")
                  public_holidays(country.to_s, location.to_s, d.year.to_s, "", "", add_stats: false, publish_results: false)
                end
                if @public_holidays.key?(country_region) and @public_holidays[country_region].key?(d.year.to_s)
                  phd = @public_holidays[country_region][d.year.to_s].date.iso
                else
                  phd = []
                end
                date_text = d.strftime("%Y-%m-%d")
                if phd.include?(date_text)
                  v += ":large_red_square: "
                elsif d.wday == 0 or d.wday == 6
                  v += ":large_yellow_square: "
                else
                  v += ":white_square: "
                end
              end
            end
          else
            v = ""
            (from..(from + 20)).each do |d|
              if country_region != "" and (!@public_holidays.key?(country_region) or !@public_holidays[country_region].key?(d.year.to_s))
                country, location = country_region.split("/")
                public_holidays(country.to_s, location.to_s, d.year.to_s, "", "", add_stats: false, publish_results: false)
              end
              if @public_holidays.key?(country_region) and @public_holidays[country_region].key?(d.year.to_s)
                phd = @public_holidays[country_region][d.year.to_s].date.iso
              else
                phd = []
              end
              if d.wday == 1 or d == from
                v += "#{d.strftime("%d")} "
              end
              date_text = d.strftime("%Y-%m-%d")
              if phd.include?(date_text)
                v += ":large_red_square: "
              elsif d.wday == 0 or d.wday == 6
                v += ":large_yellow_square: "
              else
                v += ":white_square: "
              end
            end
          end

          blocks << {
            type: "context",
            elements: [
              {
                type: "image",
                image_url: info.profile.image_24,
                alt_text: info.name,
              },
              {
                    type: "plain_text",
                    text: v,
                  },
            ],
          }
        end
      end
      first = true
      blocks.each_slice(10).each do |b|
        if first
          b.unshift(blocks_header)
          first = false
        end
        respond blocks: b
      end
      message = ""
      if !defaulted_country_region.empty?
        message = "Defaulted public holidays calendar: #{defaulted_country_region}\n"
      end
      if members_by_country_region.size > 0 and members_by_country_region.keys.size > 1
        message_tmp = []
        members_by_country_region.each do |region, members|
          #use only the user name on members
          members_names = members.map { |m| m.split("_")[1..-1].join("_") }
          message_tmp << "`#{region}`: <#{members_names.sort.join(", ")}>"
        end
        message += "Members by region:\n\t#{message_tmp.join(". ")}\n"
      end
      if all_team_members.include?(user.name)
        message += "To change your public holidays calendar, use the command `set public holidays to COUNTRY/STATE`. "
        message += "\nExamples: `set public holidays to Iceland`, `set public holidays to Spain/Madrid`"
      end
      respond message
    end
  end
end

#update_team(user, team_name, new_name: "", new_info: "", delete_opts: "", add_opts: "") ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/slack/smart-bot/commands/general/teams/update_team.rb', line 5

def update_team(user, team_name, new_name: "", new_info: "", delete_opts: "", add_opts: "")
  save_stats(__method__)
  get_teams()
  if @teams.key?(team_name.to_sym)
    assigned_members = @teams[team_name.to_sym].members.values.flatten
    assigned_members.uniq!
    all_team_members = assigned_members.dup
    team_members = []
    if @teams[team_name.to_sym].channels.key?("members")
      @teams[team_name.to_sym].channels["members"].each do |ch|
        get_channels_name_and_id() unless @channels_id.key?(ch)
        tm = get_channel_members(@channels_id[ch])
        tm.each do |m|
           = find_user(m)
          team_members << "#{.team_id}_#{.name}" unless .is_app_user or .is_bot
        end
      end
    end
    team_members.flatten!
    team_members.uniq!
    all_team_members += team_members
    all_team_members.uniq!
  end
  if !@teams.key?(team_name.to_sym)
    respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
  elsif !(all_team_members + [@teams[team_name.to_sym].creator] + config.team_id_masters).flatten.include?("#{user.team_id}_#{user.name}")
    respond "You have to be a member of the team, the creator or a Master admin to be able to update this team."
  else
    wrong = false
    if new_name != ""
      team = @teams[team_name.to_sym].deep_copy
      @teams[new_name.to_sym] = team
      @teams.delete(team_name.to_sym)
      File.delete(File.join(config.path, "teams", "t_#{team_name}.yaml"))
      message = "The *#{team_name}* team has been renamed #{new_name}."
      team_name = new_name
    elsif new_info != ""
      @teams[team_name.to_sym].info = new_info
    elsif delete_opts != ""
      last_type = nil
      delete_opts.split(" ").each do |opt|
        if opt.match?(/^\s*$/)
          #blank
        elsif opt.match?(/^[\w\-]+$/i)
          last_type = opt
        elsif opt.match(/<?@(\w+)>?/i) #accepts also @username for the case the user has been deactivated
          member_id = $1
          member_info = find_user(member_id)
          if last_type.nil?
            @teams[team_name.to_sym].members.each do |type, members|
              @teams[team_name.to_sym].members[type].delete("#{member_info.team_id}_#{member_info.name}")
            end
          else
            @teams[team_name.to_sym].members[last_type] ||= []
            @teams[team_name.to_sym].members[last_type].delete("#{member_info.team_id}_#{member_info.name}")
          end
        elsif opt.match(/<#(\w+)\|[^>]*>/i)
          channel_id = $1
          get_channels_name_and_id() unless @channels_name.keys.include?(channel_id)
          channel = @channels_name[channel_id]
          if last_type.nil?
            @teams[team_name.to_sym].channels.each do |type, channels|
              @teams[team_name.to_sym].channels[type].delete(channel)
            end
          else
            @teams[team_name.to_sym].channels[last_type] ||= []
            @teams[team_name.to_sym].channels[last_type].delete(channel)
          end
        else
          respond "It seems like the members or channel list is not correct. Please double check."
          wrong = true
          break
        end
      end
      tmembers = @teams[team_name.to_sym].members.deep_copy
      tmembers.each do |type, members|
        @teams[team_name.to_sym].members.delete(type) if members.empty?
      end
      tchannels = @teams[team_name.to_sym].channels.deep_copy
      tchannels.each do |type, channels|
        @teams[team_name.to_sym].channels.delete(type) if channels.empty?
      end
    elsif add_opts != ""
      last_type = nil
      add_opts.split(" ").each do |opt|
        if opt.match?(/^\s*$/)
          #blank
        elsif opt.match?(/^[\w\-]+$/i)
          last_type = opt
        elsif opt.match(/<@(\w+)>/i)
          member_id = $1
          last_type = "no_type" if last_type.nil?
          member_info = find_user(member_id)
          @teams[team_name.to_sym].members[last_type] ||= []
          @teams[team_name.to_sym].members[last_type] << "#{member_info.team_id}_#{member_info.name}"
          @teams[team_name.to_sym].members[last_type].uniq!
        elsif opt.match(/<#(\w+)\|[^>]*>/i)
          channel_id = $1
          get_channels_name_and_id() unless @channels_name.keys.include?(channel_id)
          channel = @channels_name[channel_id]
          @teams[team_name.to_sym].channels[last_type] ||= []
          @teams[team_name.to_sym].channels[last_type] << channel
          @teams[team_name.to_sym].channels[last_type].uniq!
        else
          respond "It seems like the members or channel list is not correct. Please double check."
          wrong = true
          break
        end
      end
      tmembers = @teams[team_name.to_sym].members.deep_copy
      tmembers.each do |type, members|
        @teams[team_name.to_sym].members.delete(type) if members.empty?
      end
      tchannels = @teams[team_name.to_sym].channels.deep_copy
      tchannels.each do |type, channels|
        @teams[team_name.to_sym].channels.delete(type) if channels.empty?
      end
    end
    unless wrong
      message ||= "The *#{team_name}* team has been updated."
      @teams[team_name.to_sym].status = :updated
      @teams[team_name.to_sym].user = "#{user.team_id}_#{user.name}"
      @teams[team_name.to_sym].date = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")[0..18]
      update_teams()
    end
    respond message
    see_teams(user, team_name, add_stats: false) unless wrong
  end
end