chat_sdk-teams 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/chat_sdk/teams/adapter.rb +44 -2
- data/lib/chat_sdk/teams/graph_client.rb +83 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26f507aa00b122a92a3b175ec79248a0cd4cf0d8a63d192ff5ada84eb8a4b307
|
|
4
|
+
data.tar.gz: 54295b00effe5c4d7b37b906209dbcbb2685068da76eee7f3a68c020cdf391e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aeac84b76ec10f316e3836676d85826d708b026293897ca7abfe77b3532af466519d2acc267ac41a21429d02af91feac58623ce40c6146eeda3f9fc35a204d56
|
|
7
|
+
data.tar.gz: 3535fa1ecd603951f94d2df234f1fdc68239c66624cc0adf393be7def189168d910b377d8de1f6598178e60f94de5bdc05c1f630f9b3b35b2314540fa592bd59
|
|
@@ -4,11 +4,12 @@ module ChatSDK
|
|
|
4
4
|
module Teams
|
|
5
5
|
class Adapter < ChatSDK::Adapter::Base
|
|
6
6
|
capabilities :edit_messages, :delete_messages, :threads, :direct_messages,
|
|
7
|
-
:file_uploads, :streaming_edit, :typing_indicator
|
|
7
|
+
:file_uploads, :streaming_edit, :typing_indicator, :message_history
|
|
8
8
|
|
|
9
9
|
attr_reader :client
|
|
10
10
|
|
|
11
|
-
def initialize(app_id: nil, app_password: nil, tenant_id: nil
|
|
11
|
+
def initialize(app_id: nil, app_password: nil, tenant_id: nil,
|
|
12
|
+
graph_client_id: nil, graph_client_secret: nil, graph_tenant_id: nil)
|
|
12
13
|
@app_id = app_id || ENV["TEAMS_APP_ID"]
|
|
13
14
|
@app_password = app_password || ENV["TEAMS_APP_PASSWORD"]
|
|
14
15
|
@tenant_id = tenant_id || ENV["TEAMS_TENANT_ID"]
|
|
@@ -16,6 +17,11 @@ module ChatSDK
|
|
|
16
17
|
raise ChatSDK::ConfigurationError, "Teams app_id required" unless @app_id
|
|
17
18
|
raise ChatSDK::ConfigurationError, "Teams app_password required" unless @app_password
|
|
18
19
|
|
|
20
|
+
@graph_client_id = graph_client_id || ENV["TEAMS_GRAPH_CLIENT_ID"]
|
|
21
|
+
@graph_client_secret = graph_client_secret || ENV["TEAMS_GRAPH_CLIENT_SECRET"]
|
|
22
|
+
@graph_tenant_id = graph_tenant_id || ENV["TEAMS_GRAPH_TENANT_ID"]
|
|
23
|
+
@graph_client = GraphClient.new(@graph_client_id, @graph_client_secret, @graph_tenant_id) if @graph_client_id
|
|
24
|
+
|
|
19
25
|
@client = BotFrameworkClient.new(app_id: @app_id, app_password: @app_password)
|
|
20
26
|
@jwt_verifier = JwtVerifier.new(app_id: @app_id)
|
|
21
27
|
@renderer = AdaptiveCardRenderer.new
|
|
@@ -177,6 +183,20 @@ module ChatSDK
|
|
|
177
183
|
end
|
|
178
184
|
end
|
|
179
185
|
|
|
186
|
+
def fetch_messages(channel_id:, thread_id: nil, cursor: nil, limit: 50)
|
|
187
|
+
require_capability!(:message_history)
|
|
188
|
+
unless @graph_client
|
|
189
|
+
raise ChatSDK::ConfigurationError,
|
|
190
|
+
"Teams message history requires Graph API credentials " \
|
|
191
|
+
"(TEAMS_GRAPH_CLIENT_ID, TEAMS_GRAPH_CLIENT_SECRET, TEAMS_GRAPH_TENANT_ID)"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
result = @graph_client.fetch_messages(chat_id: channel_id, limit: limit)
|
|
195
|
+
messages = (result["value"] || []).map { |m| parse_graph_message(m, channel_id) }
|
|
196
|
+
next_link = result["@odata.nextLink"]
|
|
197
|
+
[messages, next_link]
|
|
198
|
+
end
|
|
199
|
+
|
|
180
200
|
# Store a service URL for a conversation (useful when sending proactive messages)
|
|
181
201
|
def register_service_url(conversation_id, service_url)
|
|
182
202
|
@service_urls[conversation_id] = service_url
|
|
@@ -211,6 +231,28 @@ module ChatSDK
|
|
|
211
231
|
end
|
|
212
232
|
url
|
|
213
233
|
end
|
|
234
|
+
|
|
235
|
+
def parse_graph_message(data, channel_id)
|
|
236
|
+
from = data["from"] || {}
|
|
237
|
+
user = from["user"] || from["application"] || {}
|
|
238
|
+
is_bot = !from["application"].nil?
|
|
239
|
+
|
|
240
|
+
ChatSDK::Message.new(
|
|
241
|
+
id: data["id"],
|
|
242
|
+
text: data.dig("body", "content") || "",
|
|
243
|
+
author: ChatSDK::Author.new(
|
|
244
|
+
id: user["id"] || "unknown",
|
|
245
|
+
name: user["displayName"] || "unknown",
|
|
246
|
+
platform: :teams,
|
|
247
|
+
bot: is_bot
|
|
248
|
+
),
|
|
249
|
+
thread_id: data["replyToId"] || data["id"],
|
|
250
|
+
channel_id: channel_id,
|
|
251
|
+
platform: :teams,
|
|
252
|
+
timestamp: data["createdDateTime"],
|
|
253
|
+
raw: data
|
|
254
|
+
)
|
|
255
|
+
end
|
|
214
256
|
end
|
|
215
257
|
end
|
|
216
258
|
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ChatSDK
|
|
4
|
+
module Teams
|
|
5
|
+
class GraphClient
|
|
6
|
+
TOKEN_URL_TEMPLATE = "https://login.microsoftonline.com/%s/oauth2/v2.0/token"
|
|
7
|
+
GRAPH_BASE_URL = "https://graph.microsoft.com/v1.0"
|
|
8
|
+
SCOPE = "https://graph.microsoft.com/.default"
|
|
9
|
+
|
|
10
|
+
def initialize(client_id, client_secret, tenant_id)
|
|
11
|
+
@client_id = client_id
|
|
12
|
+
@client_secret = client_secret
|
|
13
|
+
@tenant_id = tenant_id
|
|
14
|
+
@access_token = nil
|
|
15
|
+
@token_expires_at = nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def fetch_messages(chat_id:, limit: 50)
|
|
19
|
+
token = fetch_token
|
|
20
|
+
url = "#{GRAPH_BASE_URL}/chats/#{chat_id}/messages?$top=#{limit}&$orderby=createdDateTime desc"
|
|
21
|
+
|
|
22
|
+
response = api_connection.get(url) do |req|
|
|
23
|
+
req.headers["Authorization"] = "Bearer #{token}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
unless response.success?
|
|
27
|
+
raise ChatSDK::PlatformError.new(
|
|
28
|
+
"Graph API error: #{response.status}",
|
|
29
|
+
status: response.status,
|
|
30
|
+
body: response.body,
|
|
31
|
+
adapter_name: :teams
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
response.body
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def fetch_token
|
|
39
|
+
return @access_token if @access_token && @token_expires_at && Time.now < @token_expires_at
|
|
40
|
+
|
|
41
|
+
token_url = format(TOKEN_URL_TEMPLATE, @tenant_id)
|
|
42
|
+
|
|
43
|
+
response = token_connection.post(token_url, {
|
|
44
|
+
grant_type: "client_credentials",
|
|
45
|
+
client_id: @client_id,
|
|
46
|
+
client_secret: @client_secret,
|
|
47
|
+
scope: SCOPE
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
unless response.success?
|
|
51
|
+
raise ChatSDK::PlatformError.new(
|
|
52
|
+
"Failed to acquire Graph API token: #{response.status}",
|
|
53
|
+
status: response.status,
|
|
54
|
+
body: response.body,
|
|
55
|
+
adapter_name: :teams
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
data = JSON.parse(response.body)
|
|
60
|
+
@access_token = data["access_token"]
|
|
61
|
+
@token_expires_at = Time.now + (data["expires_in"].to_i - 60)
|
|
62
|
+
@access_token
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def token_connection
|
|
68
|
+
@token_connection ||= Faraday.new do |f|
|
|
69
|
+
f.request :url_encoded
|
|
70
|
+
f.adapter :net_http
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def api_connection
|
|
75
|
+
@api_connection ||= Faraday.new do |f|
|
|
76
|
+
f.request :json
|
|
77
|
+
f.response :json
|
|
78
|
+
f.adapter :net_http
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chat_sdk-teams
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Quentin Rousseau
|
|
@@ -63,6 +63,7 @@ files:
|
|
|
63
63
|
- lib/chat_sdk/teams/adapter.rb
|
|
64
64
|
- lib/chat_sdk/teams/adaptive_card_renderer.rb
|
|
65
65
|
- lib/chat_sdk/teams/bot_framework_client.rb
|
|
66
|
+
- lib/chat_sdk/teams/graph_client.rb
|
|
66
67
|
- lib/chat_sdk/teams/jwt_verifier.rb
|
|
67
68
|
homepage: https://github.com/rootlyhq/chat-sdk
|
|
68
69
|
licenses:
|