summaryrefslogtreecommitdiff
path: root/lib/gitlab/chat_commands/presenter.rb
blob: 3143dc092a10c0eaffc2b6ed2b452f8ba4883599 (plain)
1
2
3
4
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
module Gitlab
  class ChatCommands
    class Presenter
      class << self
        include Gitlab::Routing.url_helpers

        def authorize_chat_name(url)
          message = if url
                      ":wave: Hi there! Before I do anything for you, please [connect your GitLab account](#{url})."
                    else
                      ":sweat_smile: Couldn't identify you, nor can I autorize you!"
                    end

          ephemeral_response(message)
        end

        def help(commands, trigger)
          if commands.none?
            ephemeral_response("No commands configured")
          else
            commands.map! { |command| "#{trigger} #{command}" }
            message = header_with_list("Available commands", commands)

            ephemeral_response(message)
          end
        end

        def present(subject)
          return not_found unless subject

          if subject.is_a?(Gitlab::ChatCommands::Result)
            show_result(subject)
          elsif subject.respond_to?(:count)
            if subject.many?
              multiple_resources(subject)
            elsif subject.none?
              not_found
            else
              single_resource(subject)
            end
          else
            single_resource(subject)
          end
        end

        def access_denied
          ephemeral_response("Whoops! That action is not allowed. This incident will be [reported](https://xkcd.com/838/).")
        end

        private

        def show_result(result)
          case result.type
          when :success
            in_channel_response(result.message)
          else
            ephemeral_response(result.message)
          end
        end

        def not_found
          ephemeral_response("404 not found! GitLab couldn't find what you were looking for! :boom:")
        end

        def single_resource(resource)
          return error(resource) if resource.errors.any? || !resource.persisted?

          message = "### #{title(resource)}"
          message << "\n\n#{resource.description}" if resource.try(:description)

          in_channel_response(message)
        end

        def multiple_resources(resources)
          resources.map! { |resource| title(resource) }

          message = header_with_list("Multiple results were found:", resources)

          ephemeral_response(message)
        end

        def error(resource)
          message = header_with_list("The action was not successful, because:", resource.errors.messages)

          ephemeral_response(message)
        end

        def title(resource)
          reference = resource.try(:to_reference) || resource.try(:id)
          title = resource.try(:title) || resource.try(:name)

          "[#{reference} #{title}](#{url(resource)})"
        end

        def header_with_list(header, items)
          message = [header]

          items.each do |item|
            message << "- #{item}"
          end

          message.join("\n")
        end

        def url(resource)
          url_for(
            [
              resource.project.namespace.becomes(Namespace),
              resource.project,
              resource
            ]
          )
        end

        def ephemeral_response(message)
          {
            response_type: :ephemeral,
            text: message,
            status: 200
          }
        end

        def in_channel_response(message)
          {
            response_type: :in_channel,
            text: message,
            status: 200
          }
        end
      end
    end
  end
end