lex-microsoft_teams 0.6.35 → 0.6.37

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a180c2f6406a210f6d7f76959fd16a2030e0c43d3269901228f7a6464425d456
4
- data.tar.gz: 7ea5b4c6a093f23875cc841b18e490c5812654a2bda3faf73a36453345ff4d0f
3
+ metadata.gz: 850930c48981007e5ba07fb8315bf3f5da8cb9eff02ca11911e3a531b820ca71
4
+ data.tar.gz: b199dce28d0301f690870ae99e9930a8b178a3842ce6800e3f4fc6d4134943e4
5
5
  SHA512:
6
- metadata.gz: 4d7cbc835079bdeed837263bfbb98269ed0685223a18c002c2b11e726c85c9f2d141b97a1cb58b1270322ef63766ec5d1ee5de415e84a272bf86e48c5347bd04
7
- data.tar.gz: 9e30a76561740ce85410bbf278958a2f7bff53a3dfc9476d10db329b0ee174e0baffeac9bdaec01c0c04784f2922287756c50876555984c02d1f1bf0f25cda52
6
+ metadata.gz: 998911159c181f88202dcd509fafb838adcbd2f1efd2368297ac20fa86cefdff591481986f7d063a69c5f4ffe3225a254ef70f4f6cc9a3f1e7c43080540bec59
7
+ data.tar.gz: 33ae5434516d523cf1433f0a387d00646a06ae364714a52fb467403b0e93094b41d42f68daf847f1c052e2845f273c2e8e87d5af43d3a74e6eb7aeeba1fa41f6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.7.0] - unreleased
6
+
7
+ ### Added
8
+ - New `Runners::Loop` module with four functions for Microsoft Loop component support via `fluidEmbedCard`:
9
+ - `create_loop_file` — Creates a new `.loop` file in a user's OneDrive via the Graph API; returns drive item metadata including `webUrl`
10
+ - `loop_attachment` — Builds the `fluidEmbedCard` + placeholder attachment pair required to embed a Loop component in a Teams message
11
+ - `post_loop_to_chat` — Posts a Loop component inline into a Teams chat thread
12
+ - `post_loop_to_channel` — Posts a Loop component inline into a Teams channel thread
13
+ - Requires `Files.ReadWrite` and `Sites.ReadWrite.All` Graph API permissions for `create_loop_file`; `Chat.ReadWrite` and `ChannelMessage.Send` are already required by existing runners
14
+ - **Note:** Programmatic write access to Loop page *content* (Fluid Framework) is not yet available via Microsoft Graph; Loop files must be opened in Teams to initialize the collaborative session
15
+
16
+ ## [0.6.36] - 2026-04-13
17
+
18
+ ### Fixed
19
+ - `TokenCache#load_from_vault` now passes `vault_path` explicitly to `vault_get`, matching the `save_to_vault` pattern (#10)
20
+
5
21
  ## [0.6.35] - 2026-04-09
6
22
 
7
23
  ### Changed
data/README.md CHANGED
@@ -113,6 +113,14 @@ gem install lex-microsoft_teams
113
113
  - `action_submit` — Create a Submit action
114
114
  - `message_attachment` — Wrap a card as a message attachment
115
115
 
116
+ ### Loop Components
117
+ - `create_loop_file` — Create a new `.loop` file in a user's OneDrive; returns drive item metadata including `webUrl`
118
+ - `loop_attachment` — Build a `fluidEmbedCard` attachment array for embedding an existing Loop component URL in a Teams message
119
+ - `post_loop_to_chat` — Post a Loop component inline into a Teams chat thread
120
+ - `post_loop_to_channel` — Post a Loop component inline into a Teams channel thread
121
+
122
+ > **Note:** Creating a `.loop` file provisions the OneDrive item; the Fluid Framework collaborative session is initialized by Teams on first open. Programmatic write access to Loop page *content* is not yet available via Microsoft Graph.
123
+
116
124
  ### Bot Framework
117
125
  - `send_activity` — Send an activity to a conversation
118
126
  - `reply_to_activity` — Reply to an existing activity
@@ -15,6 +15,7 @@ require 'legion/extensions/microsoft_teams/runners/meetings'
15
15
  require 'legion/extensions/microsoft_teams/runners/transcripts'
16
16
  require 'legion/extensions/microsoft_teams/runners/people'
17
17
  require 'legion/extensions/microsoft_teams/runners/ownership'
18
+ require 'legion/extensions/microsoft_teams/runners/loop'
18
19
 
19
20
  module Legion
20
21
  module Extensions
@@ -37,6 +38,7 @@ module Legion
37
38
  include Runners::CacheIngest
38
39
  include Runners::People
39
40
  include Runners::Ownership
41
+ include Runners::Loop
40
42
 
41
43
  attr_reader :opts
42
44
 
@@ -138,7 +138,7 @@ module Legion
138
138
  def load_from_vault
139
139
  if vault_available?
140
140
  log.info("Loading delegated token from Vault (#{vault_path})")
141
- data = vault_get
141
+ data = vault_get(vault_path)
142
142
  if data && data[:access_token]
143
143
  @mutex.synchronize do
144
144
  @delegated_cache = {
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'legion/extensions/microsoft_teams/helpers/client'
5
+
6
+ module Legion
7
+ module Extensions
8
+ module MicrosoftTeams
9
+ module Runners
10
+ module Loop
11
+ include Legion::Extensions::MicrosoftTeams::Helpers::Client
12
+ include Legion::JSON::Helper
13
+
14
+ # Creates a new .loop file in the user's OneDrive via the Graph API.
15
+ # The Fluid Framework collaborative session is initialized by Teams on first open.
16
+ # Returns the drive item metadata including +webUrl+, which can be passed to
17
+ # +post_loop_to_chat+ or +post_loop_to_channel+.
18
+ #
19
+ # @param filename [String] Name of the file (e.g. "incident-status" or "incident-status.loop")
20
+ # @param folder_path [String] OneDrive folder path relative to root (default: root)
21
+ # @param user_id [String] Graph user ID or 'me' (default: 'me')
22
+ def create_loop_file(filename:, folder_path: nil, user_id: 'me', **)
23
+ filename = "#{filename}.loop" unless filename.end_with?('.loop')
24
+
25
+ path = if folder_path.nil? || folder_path.empty?
26
+ "users/#{user_id}/drive/root:/#{filename}:/content"
27
+ else
28
+ "users/#{user_id}/drive/root:/#{folder_path}/#{filename}:/content"
29
+ end
30
+
31
+ response = graph_connection(**).put(path, '', 'Content-Type' => 'application/octet-stream')
32
+ { result: response.body }
33
+ end
34
+
35
+ # Builds the fluidEmbedCard attachment array required to embed a Loop component
36
+ # in a Teams message. Pass the resulting array as +attachments:+ to
37
+ # +send_chat_message+ / +send_channel_message+, or use the convenience methods
38
+ # +post_loop_to_chat+ and +post_loop_to_channel+.
39
+ #
40
+ # @param component_url [String] SharePoint/OneDrive URL of the .loop file
41
+ # (the +webUrl+ from +create_loop_file+)
42
+ # @param source_type [String] 'Compose' (default) or 'Loop'
43
+ def loop_attachment(component_url:, source_type: 'Compose', **)
44
+ attachment_id = SecureRandom.hex(16)
45
+ {
46
+ result: [
47
+ {
48
+ id: attachment_id,
49
+ contentType: 'application/vnd.microsoft.card.fluidEmbedCard',
50
+ contentUrl: nil,
51
+ content: json_generate({ componentUrl: component_url, sourceType: source_type }),
52
+ teamsAppId: 'FluidEmbedCard'
53
+ },
54
+ {
55
+ id: 'placeholderCard',
56
+ contentType: 'application/vnd.microsoft.card.codesnippet',
57
+ content: '{}',
58
+ teamsAppId: 'FLUID_PLACEHOLDER_CARD'
59
+ }
60
+ ]
61
+ }
62
+ end
63
+
64
+ # Posts a message into a Teams chat thread with a Loop component embedded inline.
65
+ #
66
+ # @param chat_id [String] Teams chat thread ID (e.g. 19:...@thread.v2)
67
+ # @param component_url [String] SharePoint/OneDrive URL of the .loop file
68
+ # @param body_text [String] Optional plain-text preamble shown above the component
69
+ def post_loop_to_chat(chat_id:, component_url:, body_text: '', **)
70
+ attachments = loop_attachment(component_url: component_url, **)[:result]
71
+ content = body_text.empty? ? '<p></p>' : "<p>#{body_text}</p>"
72
+ payload = { body: { contentType: 'html', content: content }, attachments: attachments }
73
+ response = graph_connection(**).post("chats/#{chat_id}/messages", payload)
74
+ { result: response.body }
75
+ end
76
+
77
+ # Posts a message into a Teams channel thread with a Loop component embedded inline.
78
+ #
79
+ # @param team_id [String] Teams team ID
80
+ # @param channel_id [String] Teams channel ID
81
+ # @param component_url [String] SharePoint/OneDrive URL of the .loop file
82
+ # @param body_text [String] Optional plain-text preamble shown above the component
83
+ # @param subject [String] Optional thread subject line
84
+ def post_loop_to_channel(team_id:, channel_id:, component_url:, body_text: '', subject: nil, **)
85
+ attachments = loop_attachment(component_url: component_url, **)[:result]
86
+ content = body_text.empty? ? '<p></p>' : "<p>#{body_text}</p>"
87
+ payload = { body: { contentType: 'html', content: content }, attachments: attachments }
88
+ payload[:subject] = subject if subject
89
+ response = graph_connection(**).post("teams/#{team_id}/channels/#{channel_id}/messages", payload)
90
+ { result: response.body }
91
+ end
92
+
93
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
94
+ Legion::Extensions::Helpers.const_defined?(:Lex, false)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module MicrosoftTeams
6
- VERSION = '0.6.35'
6
+ VERSION = '0.6.37'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-microsoft_teams
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.35
4
+ version: 0.6.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -218,6 +218,7 @@ files:
218
218
  - lib/legion/extensions/microsoft_teams/runners/channels.rb
219
219
  - lib/legion/extensions/microsoft_teams/runners/chats.rb
220
220
  - lib/legion/extensions/microsoft_teams/runners/local_cache.rb
221
+ - lib/legion/extensions/microsoft_teams/runners/loop.rb
221
222
  - lib/legion/extensions/microsoft_teams/runners/meetings.rb
222
223
  - lib/legion/extensions/microsoft_teams/runners/messages.rb
223
224
  - lib/legion/extensions/microsoft_teams/runners/ownership.rb