teems 0.1.0 → 0.3.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/CHANGELOG.md +23 -0
- data/README.md +83 -39
- data/lib/teems/api/client.rb +1 -2
- data/lib/teems/api/meetings.rb +25 -0
- data/lib/teems/cli.rb +5 -1
- data/lib/teems/commands/base.rb +15 -2
- data/lib/teems/commands/cal.rb +1 -51
- data/lib/teems/commands/help.rb +1 -0
- data/lib/teems/commands/meeting.rb +488 -0
- data/lib/teems/commands/meeting_recording.rb +331 -0
- data/lib/teems/commands/meeting_transcript.rb +270 -0
- data/lib/teems/commands/ooo.rb +123 -47
- data/lib/teems/runner.rb +6 -0
- data/lib/teems/services/api_client.rb +3 -3
- data/lib/teems/services/safari_js_runner.rb +89 -0
- data/lib/teems/support/time_parsing.rb +55 -0
- data/lib/teems/version.rb +1 -1
- data/lib/teems.rb +4 -0
- metadata +8 -2
data/lib/teems/commands/ooo.rb
CHANGED
|
@@ -15,9 +15,14 @@ module Teems
|
|
|
15
15
|
|
|
16
16
|
ON OPTIONS:
|
|
17
17
|
--message TEXT Auto-reply and status message
|
|
18
|
-
--start
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
--start TIME Schedule start; enables scheduled mode. Formats:
|
|
19
|
+
YYYY-MM-DD (all-day)
|
|
20
|
+
YYYY-MM-DD HH:MM (timed)
|
|
21
|
+
"today HH:MM", "tomorrow HH:MM", HH:MM
|
|
22
|
+
--end TIME Schedule end, required with --start.
|
|
23
|
+
Must match --start style (date or timed).
|
|
24
|
+
--event Create an OOO calendar event for notify list
|
|
25
|
+
--invite EMAILS Comma-separated invitees; overrides config notify list
|
|
21
26
|
--no-status Skip setting Teams status/presence
|
|
22
27
|
|
|
23
28
|
CONFIGURATION:
|
|
@@ -38,10 +43,43 @@ module Teems
|
|
|
38
43
|
teems ooo on # Enable OOO (always on)
|
|
39
44
|
teems ooo on --message "Vacation" # Custom message
|
|
40
45
|
teems ooo on --start 2026-04-14 --end 2026-04-18
|
|
46
|
+
teems ooo on --start "today 14:00" --end "today 17:00" \\
|
|
47
|
+
--message "Dr appt"
|
|
41
48
|
teems ooo off # Disable OOO
|
|
42
49
|
teems ooo config # Show config
|
|
43
50
|
HELP
|
|
44
51
|
|
|
52
|
+
# A parsed --start or --end value. Produces ISO datetime strings for
|
|
53
|
+
# auto-reply schedules and calendar events. Kind is :timed, :date, or
|
|
54
|
+
# :unscheduled; value is a Time, Date, or nil respectively.
|
|
55
|
+
OooScheduleEntry = Data.define(:kind, :value) do
|
|
56
|
+
def timed? = kind == :timed
|
|
57
|
+
def all_day? = kind == :date
|
|
58
|
+
def unscheduled? = kind == :unscheduled
|
|
59
|
+
|
|
60
|
+
def reply_start_iso
|
|
61
|
+
timed? ? value.strftime('%Y-%m-%dT%H:%M:%S') : "#{value}T00:00:00"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def reply_end_iso
|
|
65
|
+
timed? ? value.strftime('%Y-%m-%dT%H:%M:%S') : "#{value}T23:59:59"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def event_start_iso
|
|
69
|
+
base = value || Date.today
|
|
70
|
+
timed? ? base.strftime('%Y-%m-%dT%H:%M:%S') : "#{base}T00:00:00"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def event_end_iso
|
|
74
|
+
base = value || Date.today
|
|
75
|
+
return base.strftime('%Y-%m-%dT%H:%M:%S') if timed?
|
|
76
|
+
|
|
77
|
+
"#{base + 1}T00:00:00"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
UNSCHEDULED_OOO_SCHEDULE = OooScheduleEntry.new(kind: :unscheduled, value: nil)
|
|
82
|
+
|
|
45
83
|
# Displays current OOO status (auto-reply + presence)
|
|
46
84
|
module OooDisplay
|
|
47
85
|
private
|
|
@@ -90,13 +128,20 @@ module Teems
|
|
|
90
128
|
end
|
|
91
129
|
|
|
92
130
|
def render_schedule(replies)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
131
|
+
start_entry = replies['scheduledStartDateTime']
|
|
132
|
+
return unless start_entry
|
|
133
|
+
|
|
134
|
+
start_str = format_schedule_dt(start_entry)
|
|
135
|
+
end_str = format_schedule_dt(replies['scheduledEndDateTime'])
|
|
136
|
+
puts " Schedule: #{start_str} to #{end_str} #{short_tz_label}"
|
|
96
137
|
end
|
|
97
138
|
|
|
98
|
-
def
|
|
99
|
-
|
|
139
|
+
def format_schedule_dt(entry)
|
|
140
|
+
return '' unless entry
|
|
141
|
+
|
|
142
|
+
raw = entry['dateTime']
|
|
143
|
+
time = entry['timeZone'] == 'UTC' ? Time.parse("#{raw} UTC").getlocal : Time.parse(raw)
|
|
144
|
+
time.strftime('%Y-%m-%d %H:%M')
|
|
100
145
|
rescue ArgumentError
|
|
101
146
|
raw.to_s
|
|
102
147
|
end
|
|
@@ -118,6 +163,60 @@ module Teems
|
|
|
118
163
|
end
|
|
119
164
|
end
|
|
120
165
|
|
|
166
|
+
# Parses and validates --start/--end into @schedule_start and @schedule_end.
|
|
167
|
+
# Each parsed value is a tuple: [:date, Date] for all-day or [:timed, Time] for timed.
|
|
168
|
+
module OooSchedule
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
def validate_create_options
|
|
172
|
+
start_raw = @options[:start]
|
|
173
|
+
end_raw = @options[:end]
|
|
174
|
+
return unless start_raw
|
|
175
|
+
return missing_end_error unless end_raw
|
|
176
|
+
|
|
177
|
+
parse_schedule_pair(start_raw, end_raw)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def missing_end_error
|
|
181
|
+
error('--end is required when using --start')
|
|
182
|
+
1
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def parse_schedule_pair(start_raw, end_raw)
|
|
186
|
+
@schedule_start = parse_schedule_value(start_raw)
|
|
187
|
+
return invalid_schedule_error(:start, start_raw) unless @schedule_start
|
|
188
|
+
|
|
189
|
+
@schedule_end = parse_schedule_value(end_raw)
|
|
190
|
+
return invalid_schedule_error(:end, end_raw) unless @schedule_end
|
|
191
|
+
|
|
192
|
+
return mixed_schedule_error if schedule_kind(@schedule_start) != schedule_kind(@schedule_end)
|
|
193
|
+
|
|
194
|
+
nil
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def parse_schedule_value(raw)
|
|
198
|
+
time = parse_time_input(raw)
|
|
199
|
+
return OooScheduleEntry.new(kind: :timed, value: time) if time
|
|
200
|
+
|
|
201
|
+
OooScheduleEntry.new(kind: :date, value: Date.parse(raw))
|
|
202
|
+
rescue Date::Error
|
|
203
|
+
nil
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def invalid_schedule_error(key, raw)
|
|
207
|
+
error("Invalid value for --#{key}: #{raw}. " \
|
|
208
|
+
"Use YYYY-MM-DD, HH:MM, 'today HH:MM', 'tomorrow HH:MM', or 'YYYY-MM-DD HH:MM'")
|
|
209
|
+
1
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def mixed_schedule_error
|
|
213
|
+
error('--start and --end must both be dates or both include a time')
|
|
214
|
+
1
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def schedule_kind(parsed) = parsed.kind
|
|
218
|
+
end
|
|
219
|
+
|
|
121
220
|
# Enables/disables OOO: auto-reply, status message, presence, calendar event
|
|
122
221
|
module OooActions
|
|
123
222
|
private
|
|
@@ -139,28 +238,6 @@ module Teems
|
|
|
139
238
|
results.values.all? ? 0 : 1
|
|
140
239
|
end
|
|
141
240
|
|
|
142
|
-
def validate_create_options
|
|
143
|
-
validate_schedule_dates || validate_date_format(:start) || validate_date_format(:end)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def validate_schedule_dates
|
|
147
|
-
return unless @options[:start] && !@options[:end]
|
|
148
|
-
|
|
149
|
-
error('--end is required when using --start')
|
|
150
|
-
1
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def validate_date_format(key)
|
|
154
|
-
value = @options[key]
|
|
155
|
-
return unless value
|
|
156
|
-
|
|
157
|
-
Date.parse(value)
|
|
158
|
-
nil
|
|
159
|
-
rescue ArgumentError
|
|
160
|
-
error("Invalid date for --#{key}: #{value}. Expected format: YYYY-MM-DD")
|
|
161
|
-
1
|
|
162
|
-
end
|
|
163
|
-
|
|
164
241
|
def execute_ooo_steps
|
|
165
242
|
results = {}
|
|
166
243
|
results[:auto_reply] = set_auto_reply
|
|
@@ -261,37 +338,29 @@ module Teems
|
|
|
261
338
|
end
|
|
262
339
|
|
|
263
340
|
def add_schedule(settings)
|
|
264
|
-
|
|
265
|
-
settings[:scheduledStartDateTime] = { dateTime:
|
|
266
|
-
settings[:scheduledEndDateTime] = { dateTime:
|
|
341
|
+
timezone = detect_timezone
|
|
342
|
+
settings[:scheduledStartDateTime] = { dateTime: @schedule_start.reply_start_iso, timeZone: timezone }
|
|
343
|
+
settings[:scheduledEndDateTime] = { dateTime: @schedule_end.reply_end_iso, timeZone: timezone }
|
|
267
344
|
end
|
|
268
345
|
|
|
269
346
|
def build_ooo_event
|
|
347
|
+
timezone = detect_timezone
|
|
270
348
|
{ subject: status_message_text,
|
|
271
|
-
start:
|
|
272
|
-
end:
|
|
273
|
-
isAllDay:
|
|
274
|
-
|
|
275
|
-
isReminderOn: false,
|
|
276
|
-
isOnlineMeeting: false,
|
|
349
|
+
start: { dateTime: @schedule_start.event_start_iso, timeZone: timezone },
|
|
350
|
+
end: { dateTime: @schedule_end.event_end_iso, timeZone: timezone },
|
|
351
|
+
isAllDay: !@schedule_start.timed?, showAs: 'free',
|
|
352
|
+
isReminderOn: false, isOnlineMeeting: false,
|
|
277
353
|
transactionId: SecureRandom.uuid,
|
|
278
354
|
attendees: notify_list.map { |email| ooo_attendee(email) },
|
|
279
355
|
responseRequested: false }
|
|
280
356
|
end
|
|
281
357
|
|
|
282
|
-
def ooo_event_time(field)
|
|
283
|
-
date = @options[field] || Date.today.to_s
|
|
284
|
-
end_date = field == :end ? (Date.parse(date) + 1).to_s : date
|
|
285
|
-
tz = detect_timezone
|
|
286
|
-
{ dateTime: "#{end_date}T00:00:00", timeZone: tz }
|
|
287
|
-
end
|
|
288
|
-
|
|
289
358
|
def ooo_attendee(email)
|
|
290
359
|
{ emailAddress: { address: email }, type: 'required' }
|
|
291
360
|
end
|
|
292
361
|
|
|
293
362
|
def notify_list
|
|
294
|
-
@notify_list ||= ooo_config('notify') || []
|
|
363
|
+
@notify_list ||= @options[:invite] || ooo_config('notify') || []
|
|
295
364
|
end
|
|
296
365
|
|
|
297
366
|
def ooo_config(key)
|
|
@@ -302,20 +371,27 @@ module Teems
|
|
|
302
371
|
# Manage out-of-office: auto-reply, status, presence, and calendar event
|
|
303
372
|
class Ooo < Base
|
|
304
373
|
include Support::Timezone
|
|
374
|
+
include Support::TimeParsing
|
|
305
375
|
include OooDisplay
|
|
376
|
+
include OooSchedule
|
|
306
377
|
include OooActions
|
|
307
378
|
include OooBuildHelpers
|
|
308
379
|
|
|
309
380
|
def initialize(args, runner:)
|
|
310
381
|
@options = {}
|
|
382
|
+
@schedule_start = UNSCHEDULED_OOO_SCHEDULE
|
|
383
|
+
@schedule_end = UNSCHEDULED_OOO_SCHEDULE
|
|
311
384
|
super
|
|
312
385
|
end
|
|
313
386
|
|
|
387
|
+
SPLIT_OOO_EMAILS = ->(raw) { raw ? raw.split(',').map(&:strip).reject(&:empty?) : [] }
|
|
388
|
+
|
|
314
389
|
OOO_OPTIONS = {
|
|
315
390
|
'--message' => ->(opts, args) { opts[:message] = args.shift },
|
|
316
391
|
'--start' => ->(opts, args) { opts[:start] = args.shift },
|
|
317
392
|
'--end' => ->(opts, args) { opts[:end] = args.shift },
|
|
318
393
|
'--event' => ->(opts, _args) { opts[:event] = true },
|
|
394
|
+
'--invite' => ->(opts, args) { opts[:invite] = SPLIT_OOO_EMAILS.call(args.shift) },
|
|
319
395
|
'--no-status' => ->(opts, _args) { opts[:no_status] = true }
|
|
320
396
|
}.freeze
|
|
321
397
|
|
data/lib/teems/runner.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module Teems
|
|
4
4
|
# API factory methods for Runner, extracted to keep method count manageable
|
|
5
5
|
module ApiFactories
|
|
6
|
+
def meetings_api = Api::Meetings.new(api_client, account)
|
|
6
7
|
def channels_api = Api::Channels.new(api_client, account)
|
|
7
8
|
def chats_api = Api::Chats.new(api_client, account)
|
|
8
9
|
def messages_api = Api::Messages.new(api_client, account)
|
|
@@ -56,6 +57,11 @@ module Teems
|
|
|
56
57
|
Formatters::MessageFormatter.new(output: @output, cache_store: cache_store)
|
|
57
58
|
end
|
|
58
59
|
|
|
60
|
+
# Safari JS runner for SharePoint automation
|
|
61
|
+
def safari_js_runner
|
|
62
|
+
Services::SafariJsRunner.new(output: @output)
|
|
63
|
+
end
|
|
64
|
+
|
|
59
65
|
# Token extractor for Safari automation
|
|
60
66
|
def token_extractor(auth_mode: :default)
|
|
61
67
|
Services::TokenExtractor.new(output: @output, auth_mode: auth_mode)
|
|
@@ -162,9 +162,9 @@ module Teems
|
|
|
162
162
|
run_request(path, get_http_for_endpoint(endpoint_key)) { |http| http.request(req) }
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def delete(
|
|
166
|
-
uri = URI(
|
|
167
|
-
run_request(
|
|
165
|
+
def delete(endpoint_key, path, account:)
|
|
166
|
+
uri = URI("#{resolve_endpoint(endpoint_key)}#{path}")
|
|
167
|
+
run_request(path, get_http_for_endpoint(endpoint_key)) do |http|
|
|
168
168
|
req = Net::HTTP::Delete.new(uri)
|
|
169
169
|
apply_auth(req, account, endpoint_key)
|
|
170
170
|
http.request(req)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module Teems
|
|
6
|
+
module Services
|
|
7
|
+
# Runs JavaScript in Safari's current tab via AppleScript
|
|
8
|
+
class SafariJsRunner
|
|
9
|
+
def initialize(output: nil)
|
|
10
|
+
@output = output
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def available? = system('which', 'osascript', out: File::NULL, err: File::NULL)
|
|
14
|
+
|
|
15
|
+
def execute_js(js_code)
|
|
16
|
+
escaped = escape_js(js_code)
|
|
17
|
+
run_applescript(safari_js_script(escaped))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def navigate(url)
|
|
21
|
+
run_applescript(navigate_script(url))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def wait_for_load(timeout: 15)
|
|
25
|
+
timeout.times do
|
|
26
|
+
sleep 1
|
|
27
|
+
return if execute_js('document.readyState') == 'complete'
|
|
28
|
+
end
|
|
29
|
+
raise Teems::Error, 'Timed out waiting for page to load'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def page_url
|
|
33
|
+
run_applescript(page_url_script)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def escape_js(js_code)
|
|
39
|
+
js_code.gsub('\\', '\\\\\\\\').gsub('"', '\\"').gsub("\n", '\\n')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def safari_js_script(escaped_js)
|
|
43
|
+
<<~APPLESCRIPT
|
|
44
|
+
tell application "Safari"
|
|
45
|
+
if (count of windows) > 0 then
|
|
46
|
+
return do JavaScript "#{escaped_js}" in current tab of front window
|
|
47
|
+
end if
|
|
48
|
+
return ""
|
|
49
|
+
end tell
|
|
50
|
+
APPLESCRIPT
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def navigate_script(url)
|
|
54
|
+
safe = escape_for_applescript(url)
|
|
55
|
+
"tell application \"Safari\"\nactivate\n" \
|
|
56
|
+
"if (count of windows) = 0 then\nmake new document with properties {URL:\"#{safe}\"}\n" \
|
|
57
|
+
"else\nset URL of current tab of front window to \"#{safe}\"\n" \
|
|
58
|
+
"end if\nend tell\n"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def escape_for_applescript(str)
|
|
62
|
+
str.gsub('\\', '\\\\\\\\').gsub('"', '\\"')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def page_url_script
|
|
66
|
+
<<~APPLESCRIPT
|
|
67
|
+
tell application "Safari"
|
|
68
|
+
if (count of windows) > 0 then
|
|
69
|
+
return URL of current tab of front window
|
|
70
|
+
end if
|
|
71
|
+
return ""
|
|
72
|
+
end tell
|
|
73
|
+
APPLESCRIPT
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def run_applescript(script)
|
|
77
|
+
out, _err, status = Open3.capture3('osascript', '-e', script)
|
|
78
|
+
return nil unless status.success?
|
|
79
|
+
|
|
80
|
+
out.strip
|
|
81
|
+
rescue IOError, SystemCallError => e
|
|
82
|
+
log("AppleScript execution failed: #{e.message}")
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def log(message) = @output&.debug(message)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Teems
|
|
4
|
+
module Support
|
|
5
|
+
# Shared time-input parsing for commands that accept schedule inputs
|
|
6
|
+
# like "HH:MM", "today HH:MM", "tomorrow HH:MM", and "YYYY-MM-DD HH:MM".
|
|
7
|
+
module TimeParsing
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def parse_time_input(raw)
|
|
11
|
+
date, time_str = split_time_input(raw)
|
|
12
|
+
return unless time_str
|
|
13
|
+
|
|
14
|
+
date.is_a?(String) ? parse_absolute_time(date, time_str) : parse_relative_time(date, time_str)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def split_time_input(raw)
|
|
18
|
+
base = Date.today
|
|
19
|
+
split_tomorrow_time(raw, base) || split_today_time(raw, base) || split_absolute_time(raw)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def split_tomorrow_time(raw, base)
|
|
23
|
+
return unless raw.start_with?('tomorrow ')
|
|
24
|
+
|
|
25
|
+
[base + 1, raw.delete_prefix('tomorrow ')]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def split_today_time(raw, base)
|
|
29
|
+
return unless raw.match?(/\A(?:today\s+)?\d{1,2}:\d{2}\z/)
|
|
30
|
+
|
|
31
|
+
[base, raw.delete_prefix('today ')]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def split_absolute_time(raw)
|
|
35
|
+
return unless raw.match?(/\A\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}\z/)
|
|
36
|
+
|
|
37
|
+
raw.split(/\s+/, 2)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def parse_relative_time(date, time_str)
|
|
41
|
+
hour, min = time_str.split(':').map(&:to_i)
|
|
42
|
+
Time.new(date.year, date.month, date.day, hour, min, 0)
|
|
43
|
+
rescue ArgumentError
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def parse_absolute_time(date_str, time_str)
|
|
48
|
+
date = Date.parse(date_str)
|
|
49
|
+
parse_relative_time(date, time_str)
|
|
50
|
+
rescue Date::Error
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/teems/version.rb
CHANGED
data/lib/teems.rb
CHANGED
|
@@ -67,6 +67,7 @@ module Teems
|
|
|
67
67
|
autoload :TeamsUrlParser, 'teems/services/teams_url_parser'
|
|
68
68
|
autoload :SyncStore, 'teems/services/sync_store'
|
|
69
69
|
autoload :SyncDirNaming, 'teems/services/sync_dir_naming'
|
|
70
|
+
autoload :SafariJsRunner, 'teems/services/safari_js_runner'
|
|
70
71
|
autoload :SyncEngine, 'teems/services/sync_engine'
|
|
71
72
|
end
|
|
72
73
|
|
|
@@ -93,6 +94,7 @@ module Teems
|
|
|
93
94
|
autoload :Who, 'teems/commands/who'
|
|
94
95
|
autoload :Ooo, 'teems/commands/ooo'
|
|
95
96
|
autoload :Org, 'teems/commands/org'
|
|
97
|
+
autoload :Meeting, 'teems/commands/meeting'
|
|
96
98
|
autoload :Status, 'teems/commands/status'
|
|
97
99
|
end
|
|
98
100
|
|
|
@@ -103,6 +105,7 @@ module Teems
|
|
|
103
105
|
autoload :Channels, 'teems/api/channels'
|
|
104
106
|
autoload :Chats, 'teems/api/chats'
|
|
105
107
|
autoload :Files, 'teems/api/files'
|
|
108
|
+
autoload :Meetings, 'teems/api/meetings'
|
|
106
109
|
autoload :Messages, 'teems/api/messages'
|
|
107
110
|
autoload :Users, 'teems/api/users'
|
|
108
111
|
end
|
|
@@ -113,5 +116,6 @@ module Teems
|
|
|
113
116
|
autoload :HelpFormatter, 'teems/support/help_formatter'
|
|
114
117
|
autoload :ErrorLogger, 'teems/support/error_logger'
|
|
115
118
|
autoload :Timezone, 'teems/support/timezone'
|
|
119
|
+
autoload :TimeParsing, 'teems/support/time_parsing'
|
|
116
120
|
end
|
|
117
121
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: teems
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Boehs
|
|
@@ -28,6 +28,7 @@ files:
|
|
|
28
28
|
- lib/teems/api/chats.rb
|
|
29
29
|
- lib/teems/api/client.rb
|
|
30
30
|
- lib/teems/api/files.rb
|
|
31
|
+
- lib/teems/api/meetings.rb
|
|
31
32
|
- lib/teems/api/messages.rb
|
|
32
33
|
- lib/teems/api/users.rb
|
|
33
34
|
- lib/teems/api/users_mailbox.rb
|
|
@@ -40,6 +41,9 @@ files:
|
|
|
40
41
|
- lib/teems/commands/channels.rb
|
|
41
42
|
- lib/teems/commands/chats.rb
|
|
42
43
|
- lib/teems/commands/help.rb
|
|
44
|
+
- lib/teems/commands/meeting.rb
|
|
45
|
+
- lib/teems/commands/meeting_recording.rb
|
|
46
|
+
- lib/teems/commands/meeting_transcript.rb
|
|
43
47
|
- lib/teems/commands/messages.rb
|
|
44
48
|
- lib/teems/commands/ooo.rb
|
|
45
49
|
- lib/teems/commands/org.rb
|
|
@@ -66,6 +70,7 @@ files:
|
|
|
66
70
|
- lib/teems/services/configuration.rb
|
|
67
71
|
- lib/teems/services/file_downloader.rb
|
|
68
72
|
- lib/teems/services/headless_extract.rb
|
|
73
|
+
- lib/teems/services/safari_js_runner.rb
|
|
69
74
|
- lib/teems/services/safari_oauth.rb
|
|
70
75
|
- lib/teems/services/sync_dir_naming.rb
|
|
71
76
|
- lib/teems/services/sync_engine.rb
|
|
@@ -78,6 +83,7 @@ files:
|
|
|
78
83
|
- lib/teems/services/token_store.rb
|
|
79
84
|
- lib/teems/support/error_logger.rb
|
|
80
85
|
- lib/teems/support/help_formatter.rb
|
|
86
|
+
- lib/teems/support/time_parsing.rb
|
|
81
87
|
- lib/teems/support/timezone.rb
|
|
82
88
|
- lib/teems/support/xdg_paths.rb
|
|
83
89
|
- lib/teems/version.rb
|
|
@@ -104,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
104
110
|
- !ruby/object:Gem::Version
|
|
105
111
|
version: '0'
|
|
106
112
|
requirements: []
|
|
107
|
-
rubygems_version:
|
|
113
|
+
rubygems_version: 4.0.10
|
|
108
114
|
specification_version: 4
|
|
109
115
|
summary: A command-line interface for Microsoft Teams
|
|
110
116
|
test_files: []
|