lex-slack 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.
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Actor
7
+ class MessagePoller
8
+ include Helpers::Client
9
+
10
+ def initialize
11
+ @hwm = {}
12
+ end
13
+
14
+ def run
15
+ return unless enabled?
16
+ return if channels.empty?
17
+
18
+ token = settings.dig('lex-slack', 'token')
19
+ limit = settings.dig('lex-slack', 'poller', 'limit') || 50
20
+
21
+ channels.each do |channel_id|
22
+ poll_channel(channel_id, token: token, limit: limit)
23
+ end
24
+ end
25
+
26
+ def interval
27
+ settings.dig('lex-slack', 'poller', 'interval') || 30
28
+ end
29
+
30
+ private
31
+
32
+ def enabled?
33
+ settings.dig('lex-slack', 'poller', 'enabled') == true
34
+ end
35
+
36
+ def channels
37
+ settings.dig('lex-slack', 'poller', 'channels') || []
38
+ end
39
+
40
+ def poll_channel(channel_id, token:, limit:)
41
+ params = { channel: channel_id, limit: limit }
42
+ params[:oldest] = @hwm[channel_id] if @hwm[channel_id]
43
+
44
+ conn = api_connection(token: token)
45
+ resp = conn.get('conversations.history', params)
46
+ body = resp.body
47
+ return unless body['ok']
48
+
49
+ messages = body['messages'] || []
50
+ return if messages.empty?
51
+
52
+ @hwm[channel_id] = messages.map { |m| m['ts'] }.max
53
+ messages.each { |msg| publish_message(channel_id, msg) }
54
+ end
55
+
56
+ def publish_message(channel_id, message)
57
+ if defined?(Legion::Transport::Message)
58
+ Legion::Transport::Message.new(
59
+ function: 'handle_message',
60
+ namespace: 'Legion::Extensions::Slack',
61
+ args: { channel: channel_id, message: message }
62
+ )
63
+ elsif defined?(Legion::Logging)
64
+ Legion::Logging::Logger.info "Slack message in #{channel_id}: #{message['text']}"
65
+ end
66
+ rescue StandardError => e
67
+ Legion::Logging::Logger.warn "Failed to publish slack message: #{e.message}" if defined?(Legion::Logging)
68
+ end
69
+
70
+ def settings
71
+ return Legion::Settings.to_h if defined?(Legion::Settings)
72
+
73
+ {}
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helpers/client'
4
+ require_relative 'runners/blocks'
5
+ require_relative 'runners/chat'
6
+ require_relative 'runners/conversations'
7
+ require_relative 'runners/users'
8
+ require_relative 'runners/reactions'
9
+ require_relative 'runners/files'
10
+ require_relative 'runners/pins'
11
+ require_relative 'runners/bookmarks'
12
+ require_relative 'runners/reminders'
13
+ require_relative 'runners/usergroups'
14
+ require_relative 'runners/views'
15
+ require_relative 'runners/search'
16
+
17
+ module Legion
18
+ module Extensions
19
+ module Slack
20
+ class Client
21
+ include Helpers::Client
22
+ include Runners::Blocks
23
+ include Runners::Chat
24
+ include Runners::Conversations
25
+ include Runners::Users
26
+ include Runners::Reactions
27
+ include Runners::Files
28
+ include Runners::Pins
29
+ include Runners::Bookmarks
30
+ include Runners::Reminders
31
+ include Runners::Usergroups
32
+ include Runners::Views
33
+ include Runners::Search
34
+
35
+ attr_reader :opts
36
+
37
+ def initialize(token: nil, webhook: nil, **extra)
38
+ @opts = { token: token, webhook: webhook, **extra }.compact
39
+ end
40
+
41
+ def api_connection(**override)
42
+ super(**@opts, **override)
43
+ end
44
+
45
+ def webhook_connection(**override)
46
+ super(**@opts, **override)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Slack
8
+ module Helpers
9
+ module Client
10
+ def api_connection(token: nil, base_url: 'https://slack.com/api/', **)
11
+ Faraday.new(url: base_url) do |conn|
12
+ conn.request :json
13
+ conn.response :json, content_type: /\bjson$/
14
+ conn.headers['Authorization'] = "Bearer #{token}" if token
15
+ conn.adapter Faraday.default_adapter
16
+ end
17
+ end
18
+
19
+ def webhook_connection(base_url: 'https://hooks.slack.com', **)
20
+ Faraday.new(url: base_url) do |conn|
21
+ conn.request :json
22
+ conn.response :json, content_type: /\bjson$/
23
+ conn.adapter Faraday.default_adapter
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Blocks
8
+ def mrkdwn(text)
9
+ { type: 'mrkdwn', text: text }
10
+ end
11
+
12
+ def plain_text(text, emoji: true)
13
+ { type: 'plain_text', text: text, emoji: emoji }
14
+ end
15
+
16
+ def option(text:, value:)
17
+ { text: plain_text(text), value: value }
18
+ end
19
+
20
+ def section(text:, accessory: nil, fields: nil)
21
+ block = { type: 'section', text: mrkdwn(text) }
22
+ block[:accessory] = accessory if accessory
23
+ block[:fields] = fields if fields
24
+ block
25
+ end
26
+
27
+ def divider
28
+ { type: 'divider' }
29
+ end
30
+
31
+ def header(text:)
32
+ { type: 'header', text: plain_text(text) }
33
+ end
34
+
35
+ def context(elements:)
36
+ { type: 'context', elements: elements }
37
+ end
38
+
39
+ def actions(elements:, block_id: nil)
40
+ block = { type: 'actions', elements: elements }
41
+ block[:block_id] = block_id if block_id
42
+ block
43
+ end
44
+
45
+ def image(image_url:, alt_text:, title: nil, block_id: nil)
46
+ block = { type: 'image', image_url: image_url, alt_text: alt_text }
47
+ block[:title] = plain_text(title) if title
48
+ block[:block_id] = block_id if block_id
49
+ block
50
+ end
51
+
52
+ def input(label:, element:, block_id: nil, optional: false, dispatch_action: false)
53
+ block = { type: 'input', label: plain_text(label), element: element,
54
+ optional: optional, dispatch_action: dispatch_action }
55
+ block[:block_id] = block_id if block_id
56
+ block
57
+ end
58
+
59
+ def file_block(external_id:, block_id: nil)
60
+ block = { type: 'file', external_id: external_id, source: 'remote' }
61
+ block[:block_id] = block_id if block_id
62
+ block
63
+ end
64
+
65
+ def button(text:, action_id:, value: nil, style: nil, url: nil)
66
+ el = { type: 'button', text: plain_text(text), action_id: action_id }
67
+ el[:value] = value if value
68
+ el[:style] = style if style
69
+ el[:url] = url if url
70
+ el
71
+ end
72
+
73
+ def overflow_menu(action_id:, options:)
74
+ { type: 'overflow', action_id: action_id, options: options }
75
+ end
76
+
77
+ def static_select(action_id:, placeholder:, options:)
78
+ { type: 'static_select', action_id: action_id,
79
+ placeholder: plain_text(placeholder), options: options }
80
+ end
81
+
82
+ def multi_static_select(action_id:, placeholder:, options:)
83
+ { type: 'multi_static_select', action_id: action_id,
84
+ placeholder: plain_text(placeholder), options: options }
85
+ end
86
+
87
+ def datepicker(action_id:, placeholder: nil, initial_date: nil)
88
+ el = { type: 'datepicker', action_id: action_id }
89
+ el[:placeholder] = plain_text(placeholder) if placeholder
90
+ el[:initial_date] = initial_date if initial_date
91
+ el
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Bookmarks
8
+ include Helpers::Client
9
+
10
+ def add_bookmark(channel:, title:, type:, token: nil, link: nil, emoji: nil, **)
11
+ payload = { channel_id: channel, title: title, type: type }
12
+ payload[:link] = link if link
13
+ payload[:emoji] = emoji if emoji
14
+ conn = api_connection(token: token, **)
15
+ resp = conn.post('bookmarks.add', payload)
16
+ { ok: resp.body['ok'], bookmark: resp.body['bookmark'] }
17
+ end
18
+
19
+ def edit_bookmark(channel:, bookmark_id:, token: nil, title: nil, link: nil, emoji: nil, **)
20
+ payload = { channel_id: channel, bookmark_id: bookmark_id }
21
+ payload[:title] = title if title
22
+ payload[:link] = link if link
23
+ payload[:emoji] = emoji if emoji
24
+ conn = api_connection(token: token, **)
25
+ resp = conn.post('bookmarks.edit', payload)
26
+ { ok: resp.body['ok'], bookmark: resp.body['bookmark'] }
27
+ end
28
+
29
+ def remove_bookmark(channel:, bookmark_id:, token: nil, **)
30
+ conn = api_connection(token: token, **)
31
+ resp = conn.post('bookmarks.remove', { channel_id: channel, bookmark_id: bookmark_id })
32
+ { ok: resp.body['ok'] }
33
+ end
34
+
35
+ def list_bookmarks(channel:, token: nil, **)
36
+ conn = api_connection(token: token, **)
37
+ resp = conn.get('bookmarks.list', { channel_id: channel })
38
+ { ok: resp.body['ok'], bookmarks: resp.body['bookmarks'] }
39
+ end
40
+
41
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Chat
8
+ include Helpers::Client
9
+
10
+ def post_message(channel:, text:, token: nil, blocks: nil, thread_ts: nil, unfurl_links: nil, **)
11
+ payload = { channel: channel, text: text }
12
+ payload[:blocks] = blocks if blocks
13
+ payload[:thread_ts] = thread_ts if thread_ts
14
+ payload[:unfurl_links] = unfurl_links unless unfurl_links.nil?
15
+ conn = api_connection(token: token, **)
16
+ resp = conn.post('chat.postMessage', payload)
17
+ { ok: resp.body['ok'], ts: resp.body['ts'], channel: resp.body['channel'],
18
+ message: resp.body['message'] }
19
+ end
20
+
21
+ def send_webhook(message:, webhook:, **)
22
+ conn = webhook_connection(**)
23
+ resp = conn.post(webhook, { text: message })
24
+ { success: resp.body.nil? || resp.body == 'ok' || resp.body == {}, body: resp.body }
25
+ end
26
+
27
+ def update_message(channel:, ts:, token: nil, text: nil, blocks: nil, **)
28
+ payload = { channel: channel, ts: ts }
29
+ payload[:text] = text if text
30
+ payload[:blocks] = blocks if blocks
31
+ conn = api_connection(token: token, **)
32
+ resp = conn.post('chat.update', payload)
33
+ { ok: resp.body['ok'], ts: resp.body['ts'], channel: resp.body['channel'] }
34
+ end
35
+
36
+ def delete_message(channel:, ts:, token: nil, **)
37
+ conn = api_connection(token: token, **)
38
+ resp = conn.post('chat.delete', { channel: channel, ts: ts })
39
+ { ok: resp.body['ok'] }
40
+ end
41
+
42
+ def schedule_message(channel:, text:, post_at:, token: nil, blocks: nil, **)
43
+ payload = { channel: channel, text: text, post_at: post_at }
44
+ payload[:blocks] = blocks if blocks
45
+ conn = api_connection(token: token, **)
46
+ resp = conn.post('chat.scheduleMessage', payload)
47
+ { ok: resp.body['ok'], scheduled_message_id: resp.body['scheduled_message_id'],
48
+ post_at: resp.body['post_at'] }
49
+ end
50
+
51
+ def delete_scheduled(channel:, scheduled_message_id:, token: nil, **)
52
+ conn = api_connection(token: token, **)
53
+ resp = conn.post('chat.deleteScheduledMessage',
54
+ { channel: channel, scheduled_message_id: scheduled_message_id })
55
+ { ok: resp.body['ok'] }
56
+ end
57
+
58
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Conversations
8
+ include Helpers::Client
9
+
10
+ def list_conversations(token: nil, types: nil, cursor: nil, limit: 200, **)
11
+ params = { limit: limit }
12
+ params[:types] = types if types
13
+ params[:cursor] = cursor if cursor
14
+ conn = api_connection(token: token, **)
15
+ resp = conn.get('conversations.list', params)
16
+ { ok: resp.body['ok'], channels: resp.body['channels'],
17
+ response_metadata: resp.body['response_metadata'] }
18
+ end
19
+
20
+ def conversation_info(channel:, token: nil, **)
21
+ conn = api_connection(token: token, **)
22
+ resp = conn.get('conversations.info', { channel: channel })
23
+ { ok: resp.body['ok'], channel: resp.body['channel'] }
24
+ end
25
+
26
+ def conversation_history(channel:, token: nil, cursor: nil, limit: 100, oldest: nil, latest: nil, **)
27
+ params = { channel: channel, limit: limit }
28
+ params[:cursor] = cursor if cursor
29
+ params[:oldest] = oldest if oldest
30
+ params[:latest] = latest if latest
31
+ conn = api_connection(token: token, **)
32
+ resp = conn.get('conversations.history', params)
33
+ { ok: resp.body['ok'], messages: resp.body['messages'],
34
+ has_more: resp.body['has_more'], response_metadata: resp.body['response_metadata'] }
35
+ end
36
+
37
+ def conversation_replies(channel:, ts:, token: nil, cursor: nil, limit: 100, **)
38
+ params = { channel: channel, ts: ts, limit: limit }
39
+ params[:cursor] = cursor if cursor
40
+ conn = api_connection(token: token, **)
41
+ resp = conn.get('conversations.replies', params)
42
+ { ok: resp.body['ok'], messages: resp.body['messages'], has_more: resp.body['has_more'] }
43
+ end
44
+
45
+ def conversation_members(channel:, token: nil, cursor: nil, limit: 100, **)
46
+ params = { channel: channel, limit: limit }
47
+ params[:cursor] = cursor if cursor
48
+ conn = api_connection(token: token, **)
49
+ resp = conn.get('conversations.members', params)
50
+ { ok: resp.body['ok'], members: resp.body['members'],
51
+ response_metadata: resp.body['response_metadata'] }
52
+ end
53
+
54
+ def join_conversation(channel:, token: nil, **)
55
+ conn = api_connection(token: token, **)
56
+ resp = conn.post('conversations.join', { channel: channel })
57
+ { ok: resp.body['ok'], channel: resp.body['channel'] }
58
+ end
59
+
60
+ def leave_conversation(channel:, token: nil, **)
61
+ conn = api_connection(token: token, **)
62
+ resp = conn.post('conversations.leave', { channel: channel })
63
+ { ok: resp.body['ok'] }
64
+ end
65
+
66
+ def invite_to_conversation(channel:, users:, token: nil, **)
67
+ conn = api_connection(token: token, **)
68
+ resp = conn.post('conversations.invite', { channel: channel, users: users })
69
+ { ok: resp.body['ok'], channel: resp.body['channel'] }
70
+ end
71
+
72
+ def open_conversation(token: nil, users: nil, channel: nil, **)
73
+ payload = {}
74
+ payload[:users] = users if users
75
+ payload[:channel] = channel if channel
76
+ conn = api_connection(token: token, **)
77
+ resp = conn.post('conversations.open', payload)
78
+ { ok: resp.body['ok'], channel: resp.body['channel'] }
79
+ end
80
+
81
+ def create_conversation(name:, token: nil, is_private: false, **)
82
+ conn = api_connection(token: token, **)
83
+ resp = conn.post('conversations.create', { name: name, is_private: is_private })
84
+ { ok: resp.body['ok'], channel: resp.body['channel'] }
85
+ end
86
+
87
+ def archive_conversation(channel:, token: nil, **)
88
+ conn = api_connection(token: token, **)
89
+ resp = conn.post('conversations.archive', { channel: channel })
90
+ { ok: resp.body['ok'] }
91
+ end
92
+
93
+ def set_conversation_topic(channel:, topic:, token: nil, **)
94
+ conn = api_connection(token: token, **)
95
+ resp = conn.post('conversations.setTopic', { channel: channel, topic: topic })
96
+ { ok: resp.body['ok'], topic: resp.body['topic'] }
97
+ end
98
+
99
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Files
8
+ include Helpers::Client
9
+
10
+ def upload_file(filename:, content:, token: nil, channel: nil, title: nil, **)
11
+ conn = api_connection(token: token, **)
12
+ url_resp = conn.get('files.getUploadURLExternal',
13
+ { filename: filename, length: content.bytesize })
14
+ upload_url = url_resp.body['upload_url']
15
+ file_id = url_resp.body['file_id']
16
+ Faraday.put(upload_url, content, { 'Content-Type' => 'application/octet-stream' })
17
+ complete_payload = { files: [{ id: file_id, title: title || filename }] }
18
+ complete_payload[:channel_id] = channel if channel
19
+ complete_resp = conn.post('files.completeUploadExternal', complete_payload)
20
+ { ok: complete_resp.body['ok'], files: complete_resp.body['files'] }
21
+ end
22
+
23
+ def list_files(token: nil, channel: nil, user: nil, types: nil, cursor: nil, limit: 100, **)
24
+ params = { limit: limit }
25
+ params[:channel] = channel if channel
26
+ params[:user] = user if user
27
+ params[:types] = types if types
28
+ params[:cursor] = cursor if cursor
29
+ conn = api_connection(token: token, **)
30
+ resp = conn.get('files.list', params)
31
+ { ok: resp.body['ok'], files: resp.body['files'] }
32
+ end
33
+
34
+ def file_info(file:, token: nil, **)
35
+ conn = api_connection(token: token, **)
36
+ resp = conn.get('files.info', { file: file })
37
+ { ok: resp.body['ok'], file: resp.body['file'] }
38
+ end
39
+
40
+ def delete_file(file:, token: nil, **)
41
+ conn = api_connection(token: token, **)
42
+ resp = conn.post('files.delete', { file: file })
43
+ { ok: resp.body['ok'] }
44
+ end
45
+
46
+ def share_file(file:, token: nil, **)
47
+ conn = api_connection(token: token, **)
48
+ resp = conn.post('files.sharedPublicURL', { file: file })
49
+ { ok: resp.body['ok'], file: resp.body['file'] }
50
+ end
51
+
52
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Pins
8
+ include Helpers::Client
9
+
10
+ def add_pin(channel:, timestamp:, token: nil, **)
11
+ conn = api_connection(token: token, **)
12
+ resp = conn.post('pins.add', { channel: channel, timestamp: timestamp })
13
+ { ok: resp.body['ok'] }
14
+ end
15
+
16
+ def remove_pin(channel:, timestamp:, token: nil, **)
17
+ conn = api_connection(token: token, **)
18
+ resp = conn.post('pins.remove', { channel: channel, timestamp: timestamp })
19
+ { ok: resp.body['ok'] }
20
+ end
21
+
22
+ def list_pins(channel:, token: nil, **)
23
+ conn = api_connection(token: token, **)
24
+ resp = conn.get('pins.list', { channel: channel })
25
+ { ok: resp.body['ok'], items: resp.body['items'] }
26
+ end
27
+
28
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Reactions
8
+ include Helpers::Client
9
+
10
+ def add_reaction(channel:, timestamp:, name:, token: nil, **)
11
+ conn = api_connection(token: token, **)
12
+ resp = conn.post('reactions.add', { channel: channel, timestamp: timestamp, name: name })
13
+ { ok: resp.body['ok'] }
14
+ end
15
+
16
+ def remove_reaction(channel:, timestamp:, name:, token: nil, **)
17
+ conn = api_connection(token: token, **)
18
+ resp = conn.post('reactions.remove', { channel: channel, timestamp: timestamp, name: name })
19
+ { ok: resp.body['ok'] }
20
+ end
21
+
22
+ def get_reactions(channel:, timestamp:, token: nil, **)
23
+ conn = api_connection(token: token, **)
24
+ resp = conn.get('reactions.get', { channel: channel, timestamp: timestamp })
25
+ { ok: resp.body['ok'], message: resp.body['message'] }
26
+ end
27
+
28
+ def list_reactions(token: nil, user: nil, cursor: nil, limit: 100, **)
29
+ params = { limit: limit }
30
+ params[:user] = user if user
31
+ params[:cursor] = cursor if cursor
32
+ conn = api_connection(token: token, **)
33
+ resp = conn.get('reactions.list', params)
34
+ { ok: resp.body['ok'], items: resp.body['items'],
35
+ response_metadata: resp.body['response_metadata'] }
36
+ end
37
+
38
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Slack
6
+ module Runners
7
+ module Reminders
8
+ include Helpers::Client
9
+
10
+ def add_reminder(text:, time:, token: nil, user: nil, **)
11
+ payload = { text: text, time: time }
12
+ payload[:user] = user if user
13
+ conn = api_connection(token: token, **)
14
+ resp = conn.post('reminders.add', payload)
15
+ { ok: resp.body['ok'], reminder: resp.body['reminder'] }
16
+ end
17
+
18
+ def complete_reminder(reminder:, token: nil, **)
19
+ conn = api_connection(token: token, **)
20
+ resp = conn.post('reminders.complete', { reminder: reminder })
21
+ { ok: resp.body['ok'] }
22
+ end
23
+
24
+ def delete_reminder(reminder:, token: nil, **)
25
+ conn = api_connection(token: token, **)
26
+ resp = conn.post('reminders.delete', { reminder: reminder })
27
+ { ok: resp.body['ok'] }
28
+ end
29
+
30
+ def reminder_info(reminder:, token: nil, **)
31
+ conn = api_connection(token: token, **)
32
+ resp = conn.get('reminders.info', { reminder: reminder })
33
+ { ok: resp.body['ok'], reminder: resp.body['reminder'] }
34
+ end
35
+
36
+ def list_reminders(token: nil, **)
37
+ conn = api_connection(token: token, **)
38
+ resp = conn.get('reminders.list', {})
39
+ { ok: resp.body['ok'], reminders: resp.body['reminders'] }
40
+ end
41
+
42
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end