Class: ChatSDK::GChat::Adapter

Inherits:
Adapter::Base
  • Object
show all
Includes:
ResourceName
Defined in:
lib/chat_sdk/gchat/adapter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ResourceName

#extract_id

Constructor Details

#initialize(project_number:, credentials: nil) ⇒ Adapter

Returns a new instance of Adapter.

Raises:

  • (ChatSDK::ConfigurationError)


14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/chat_sdk/gchat/adapter.rb', line 14

def initialize(project_number:, credentials: nil)
  @project_number = project_number.to_s

  raise ChatSDK::ConfigurationError, "Google Chat project_number required" if @project_number.empty?

  @credentials = build_credentials(credentials)
  @client = Google::Apps::Chat::V1::ChatService::Client.new do |config|
    config.credentials = @credentials if @credentials
  end
  @verifier = TokenVerifier.new(@project_number)
  @renderer = CardV2Renderer.new
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



12
13
14
# File 'lib/chat_sdk/gchat/adapter.rb', line 12

def client
  @client
end

Instance Method Details

#add_reaction(channel_id:, message_id:, emoji:) ⇒ Object



123
124
125
126
127
128
129
130
131
# File 'lib/chat_sdk/gchat/adapter.rb', line 123

def add_reaction(channel_id:, message_id:, emoji:)
  require_capability!(:reactions)
  @client.create_reaction(
    parent: "spaces/#{channel_id}/messages/#{message_id}",
    reaction: {
      emoji: {unicode: emoji}
    }
  )
end

#delete_message(channel_id:, message_id:) ⇒ Object



96
97
98
99
# File 'lib/chat_sdk/gchat/adapter.rb', line 96

def delete_message(channel_id:, message_id:)
  require_capability!(:delete_messages)
  @client.delete_message(name: "spaces/#{channel_id}/messages/#{message_id}")
end

#edit_message(channel_id:, message_id:, message:) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/chat_sdk/gchat/adapter.rb', line 84

def edit_message(channel_id:, message_id:, message:)
  require_capability!(:edit_messages)
  msg = ChatSDK::PostableMessage.from(message)
  request_body = build_message_body(msg)
  request_body[:name] = "spaces/#{channel_id}/messages/#{message_id}"

  @client.update_message(
    message: request_body,
    update_mask: Google::Protobuf::FieldMask.new(paths: ["text", "cards_v2"])
  )
end

#fetch_messages(channel_id:, thread_id: nil, cursor: nil, limit: 50) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/chat_sdk/gchat/adapter.rb', line 151

def fetch_messages(channel_id:, thread_id: nil, cursor: nil, limit: 50)
  require_capability!(:message_history)
  result = @client.list_messages(
    parent: "spaces/#{channel_id}",
    page_size: limit,
    page_token: cursor
  )

  messages = result.messages.map { |m| parse_gchat_message(m, channel_id) }
  [messages, result.next_page_token.to_s.empty? ? nil : result.next_page_token]
end

#mention(user_id) ⇒ Object



171
172
173
# File 'lib/chat_sdk/gchat/adapter.rb', line 171

def mention(user_id)
  "<users/#{user_id}>"
end

#nameObject



27
28
29
# File 'lib/chat_sdk/gchat/adapter.rb', line 27

def name
  :gchat
end

#open_dm(user_id) ⇒ Object



142
143
144
145
146
147
148
149
# File 'lib/chat_sdk/gchat/adapter.rb', line 142

def open_dm(user_id)
  require_capability!(:direct_messages)
  result = @client.setup_space(
    space: {space_type: "DIRECT_MESSAGE"},
    memberships: [{member: {name: "users/#{user_id}", type: "HUMAN"}}]
  )
  extract_id(result.name)
end

#open_modal(trigger_id:, modal:) ⇒ Object



163
164
165
# File 'lib/chat_sdk/gchat/adapter.rb', line 163

def open_modal(trigger_id:, modal:)
  super
end

#parse_events(rack_request) ⇒ Object



39
40
41
42
43
44
# File 'lib/chat_sdk/gchat/adapter.rb', line 39

def parse_events(rack_request)
  payload = read_json_body(rack_request)
  EventParser.parse(payload)
rescue JSON::ParserError
  []
end

#parse_pubsub_event(rack_request) ⇒ Array<ChatSDK::Events::Base>

Parses a Google Cloud Pub/Sub push message containing a Google Chat event.

When a Pub/Sub subscription is configured externally (via Google Cloud Console or Terraform) for Google Workspace Events, push messages arrive as HTTP POSTs with the Chat event base64-encoded inside message.data. This method decodes the envelope and delegates to EventParser.

Parameters:

  • rack_request (Rack::Request)

    the incoming Pub/Sub push request

Returns:

  • (Array<ChatSDK::Events::Base>)

    parsed events (empty on bad payload)



56
57
58
59
60
61
62
63
64
65
# File 'lib/chat_sdk/gchat/adapter.rb', line 56

def parse_pubsub_event(rack_request)
  envelope = read_json_body(rack_request)
  data = envelope.dig("message", "data")
  return [] unless data

  decoded = JSON.parse(Base64.decode64(data))
  EventParser.parse(decoded)
rescue JSON::ParserError, ArgumentError
  []
end

#post_ephemeral(channel_id:, user_id:, message:, thread_id: nil) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/chat_sdk/gchat/adapter.rb', line 101

def post_ephemeral(channel_id:, user_id:, message:, thread_id: nil)
  require_capability!(:ephemeral_messages)
  msg = ChatSDK::PostableMessage.from(message)
  request_body = build_message_body(msg)
  request_body[:private_message_viewer] = {name: "users/#{user_id}"}

  if thread_id
    request_body[:thread] = {name: "spaces/#{channel_id}/threads/#{thread_id}"}
  end

  result = @client.create_message(
    parent: "spaces/#{channel_id}",
    message: request_body
  )

  build_response_message(result, channel_id, msg)
end

#post_message(channel_id:, message:, thread_id: nil) ⇒ Object

Outbound



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/chat_sdk/gchat/adapter.rb', line 68

def post_message(channel_id:, message:, thread_id: nil)
  msg = ChatSDK::PostableMessage.from(message)
  request_body = build_message_body(msg)

  if thread_id
    request_body[:thread] = {name: "spaces/#{channel_id}/threads/#{thread_id}"}
  end

  result = @client.create_message(
    parent: "spaces/#{channel_id}",
    message: request_body
  )

  build_response_message(result, channel_id, msg)
end

#remove_reaction(channel_id:, message_id:, emoji:) ⇒ Object



133
134
135
136
137
138
139
140
# File 'lib/chat_sdk/gchat/adapter.rb', line 133

def remove_reaction(channel_id:, message_id:, emoji:)
  require_capability!(:reactions)
  # Google Chat requires the reaction resource name to delete
  # We construct it from the emoji unicode
  @client.delete_reaction(
    name: "spaces/#{channel_id}/messages/#{message_id}/reactions/#{emoji}"
  )
end

#render(postable_message) ⇒ Object



175
176
177
178
179
180
181
# File 'lib/chat_sdk/gchat/adapter.rb', line 175

def render(postable_message)
  if postable_message.card?
    @renderer.render(postable_message.card)
  else
    postable_message.text
  end
end

#start_typing(channel_id:, thread_id: nil) ⇒ Object



167
168
169
# File 'lib/chat_sdk/gchat/adapter.rb', line 167

def start_typing(channel_id:, thread_id: nil)
  super
end

#upload_file(channel_id:, io:, filename:, thread_id: nil, comment: nil) ⇒ Object



119
120
121
# File 'lib/chat_sdk/gchat/adapter.rb', line 119

def upload_file(channel_id:, io:, filename:, thread_id: nil, comment: nil)
  super
end

#verify_request!(rack_request) ⇒ Object

Inbound



32
33
34
35
36
37
# File 'lib/chat_sdk/gchat/adapter.rb', line 32

def verify_request!(rack_request)
  auth_header = rack_request.env["HTTP_AUTHORIZATION"] || ""
  token = auth_header.sub(/\ABearer\s+/i, "")
  @verifier.verify!(token)
  true
end