bas 0.2.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 +6 -0
- data/README.md +25 -22
- data/lib/bas/formatter/base.rb +2 -2
- data/lib/bas/formatter/birthday.rb +8 -4
- data/lib/bas/formatter/pto.rb +8 -4
- data/lib/bas/formatter/support_emails.rb +7 -3
- data/lib/bas/formatter/types/response.rb +16 -0
- data/lib/bas/formatter/work_items_limit.rb +8 -4
- data/lib/bas/process/base.rb +39 -0
- data/lib/bas/{dispatcher → process}/discord/exceptions/invalid_webhook_token.rb +1 -1
- data/lib/bas/process/discord/implementation.rb +71 -0
- data/lib/bas/{dispatcher → process}/discord/types/response.rb +1 -1
- data/lib/bas/{dispatcher → process}/slack/exceptions/invalid_webhook_token.rb +1 -1
- data/lib/bas/process/slack/implementation.rb +70 -0
- data/lib/bas/{dispatcher → process}/slack/types/response.rb +1 -1
- data/lib/bas/process/types/response.rb +16 -0
- data/lib/bas/{fetcher → read}/base.rb +8 -8
- data/lib/bas/{fetcher → read}/github/base.rb +7 -7
- data/lib/bas/{fetcher → read}/github/types/response.rb +1 -1
- data/lib/bas/read/github/use_case/repo_issues.rb +17 -0
- data/lib/bas/{fetcher → read}/imap/base.rb +7 -7
- data/lib/bas/{fetcher → read}/imap/types/response.rb +1 -1
- data/lib/bas/read/imap/use_case/support_emails.rb +26 -0
- data/lib/bas/{fetcher → read}/notion/base.rb +8 -8
- data/lib/bas/{fetcher → read}/notion/helper.rb +1 -1
- data/lib/bas/{fetcher → read}/notion/types/response.rb +1 -1
- data/lib/bas/{fetcher → read}/notion/use_case/birthday_next_week.rb +6 -6
- data/lib/bas/{fetcher → read}/notion/use_case/birthday_today.rb +6 -6
- data/lib/bas/{fetcher → read}/notion/use_case/pto_next_week.rb +6 -6
- data/lib/bas/{fetcher → read}/notion/use_case/pto_today.rb +6 -6
- data/lib/bas/{fetcher → read}/notion/use_case/work_items_limit.rb +5 -5
- data/lib/bas/{fetcher → read}/postgres/base.rb +8 -8
- data/lib/bas/{fetcher → read}/postgres/helper.rb +1 -1
- data/lib/bas/{fetcher → read}/postgres/types/response.rb +1 -1
- data/lib/bas/{fetcher → read}/postgres/use_case/pto_today.rb +6 -6
- data/lib/bas/{mapper → serialize}/base.rb +7 -7
- data/lib/bas/{mapper → serialize}/github/issues.rb +7 -7
- data/lib/bas/{mapper → serialize}/imap/support_emails.rb +7 -7
- data/lib/bas/{mapper → serialize}/notion/birthday_today.rb +7 -7
- data/lib/bas/{mapper → serialize}/notion/pto_today.rb +14 -12
- data/lib/bas/{mapper → serialize}/notion/work_items_limit.rb +7 -7
- data/lib/bas/{mapper → serialize}/postgres/pto_today.rb +7 -7
- data/lib/bas/use_cases/types/config.rb +6 -5
- data/lib/bas/use_cases/use_case.rb +13 -10
- data/lib/bas/use_cases/use_cases.rb +71 -61
- data/lib/bas/version.rb +1 -1
- data/lib/bas/write/base.rb +36 -0
- data/lib/bas/write/logs/base.rb +33 -0
- data/lib/bas/write/logs/use_case/console_log.rb +22 -0
- metadata +42 -37
- data/lib/bas/dispatcher/base.rb +0 -31
- data/lib/bas/dispatcher/discord/implementation.rb +0 -51
- data/lib/bas/dispatcher/slack/implementation.rb +0 -51
- data/lib/bas/fetcher/github/use_case/repo_issues.rb +0 -17
- data/lib/bas/fetcher/imap/use_case/support_emails.rb +0 -26
- /data/lib/bas/{fetcher → read}/notion/exceptions/invalid_api_key.rb +0 -0
- /data/lib/bas/{fetcher → read}/notion/exceptions/invalid_database_id.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 362d8c607c7fbfd0405b4e7e349505f45e12b5218ae9c23416954919920bdb63
|
4
|
+
data.tar.gz: 78513d4ae926c12a290ceb200c1aa718d15f05c8e4536a8b58deabb3c9ca17b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a27723bb27bc0e9aefee19b4e9a159b2da7a1171da540f910a5a1affaa940ab7861afbdafadd34fa16ed71ce2284a69503b5e43a0ac1f4f399a3cf99e5aa90f
|
7
|
+
data.tar.gz: 0da18b42118777de21d8c7a0a91c8ee32f3499d7a0f0bc8d5671442762cbd4a20bcb5a0daa24d9b1bfac63c1a2bb03bcedfd867c18ee52667b3e5634e79be6b6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.3.0 (16.04.2024)
|
4
|
+
- [Rename the Fetcher to Read](https://github.com/kommitters/bas/issues/13)
|
5
|
+
- [Rename the Mapper to Serialize](https://github.com/kommitters/bas/issues/14)
|
6
|
+
- [Rename the Dispatcher to Process](https://github.com/kommitters/bas/issues/15)
|
7
|
+
- [Add the Writer Component](https://github.com/kommitters/bas/issues/16)
|
8
|
+
|
3
9
|
## 0.2.0 (04.04.2024)
|
4
10
|
- [Add a GitHub fetcher component](https://github.com/kommitters/bas/issues/6)
|
5
11
|
- [Allow daily hours pto for more than one day pto](https://github.com/kommitters/bas/issues/8)
|
data/README.md
CHANGED
@@ -39,27 +39,27 @@ There are 7 currently implemented use cases:
|
|
39
39
|
* WIP limit exceeded - from Notion to Discord
|
40
40
|
* Support email notification - from IMAP to Discord
|
41
41
|
|
42
|
-
For this example we'll analyze the birthday notification use case, bringing data from a notion database, and
|
42
|
+
For this example we'll analyze the birthday notification use case, bringing data from a notion database, and sending the
|
43
43
|
notifications to a Discord channel.
|
44
44
|
|
45
|
-
A *Use Case* object, consists on
|
45
|
+
A *Use Case* object, consists on 5 main components, having it's own responsibility:
|
46
46
|
|
47
|
-
### 1.
|
47
|
+
### 1. Read - Obtaining the data
|
48
48
|
|
49
|
-
Specifically, a
|
50
|
-
for building your own
|
49
|
+
Specifically, a reader is an object in charged of bringing data from a data source. The gem already provides the base interface
|
50
|
+
for building your own reader for your specific data source, or rely on already built classes if they match your purpose.
|
51
51
|
|
52
|
-
The base interface for a
|
52
|
+
The base interface for a reader can be found under the `bas/read/base.rb` class. Since this is a implementation of the `Read::Base`
|
53
53
|
for bringing data from a Notion database, it was created on a new namespace for that data source, it can be found under
|
54
|
-
`/bas/
|
54
|
+
`/bas/read/notion/use_case/birthday_today.rb`. It implements specific logic for reading the data and validating the response.
|
55
55
|
|
56
|
-
### 2.
|
56
|
+
### 2. Serialize - Shaping it
|
57
57
|
|
58
|
-
The **
|
58
|
+
The **Serializer** responsibility, is to shape the data using custom types from the app domain, bringing it into a
|
59
59
|
common structure understandable for other components, specifically the **Formatter**.
|
60
60
|
|
61
|
-
Because of the use case, the
|
62
|
-
under `/bas/
|
61
|
+
Because of the use case, the Serializer implementation for it, relies on specific types for representing a Birthday it self. It can be found
|
62
|
+
under `/bas/serialize/notion/birthday_today.rb`
|
63
63
|
|
64
64
|
### 3. Formatter - Preparing the message
|
65
65
|
|
@@ -67,11 +67,14 @@ The **Formatter**, is in charge of preparing the message to be sent in our notif
|
|
67
67
|
The template or 'format' to be used should be included in the use case configurations, which we'll review in a further step. It's
|
68
68
|
implementation can be found under `/bas/formatter/birthday.rb`.
|
69
69
|
|
70
|
-
### 4.
|
70
|
+
### 4. Process - Optional Data Process
|
71
71
|
|
72
|
-
Finally, the **
|
72
|
+
Finally, the **Process** basically, allow required data process depending on the use case like sending formatted messages into a destination. In this case, since the use case was implemented for
|
73
73
|
Discord, it implements specific logic to communicate with a Discord channel using a webhook. The webhook configuration and name for the 'Sender'
|
74
|
-
in the channel should be provided with the initial use case configurations. It can be found under `/bas/
|
74
|
+
in the channel should be provided with the initial use case configurations. It can be found under `/bas/process/discord/implementation.rb`
|
75
|
+
|
76
|
+
### 5. Write - Apply changes in a destination
|
77
|
+
Finally, the **Write** is in charge of creating or updating information in a destination. This is the last step in the pipeline, and it aims to allow the users to apply changes in a destination depending on the use case. These changes can be a transaction in a database, adding files in a cloud storage, or simply creating logs. For the Birthday use case, after the Process sends the notification, the Write creates a Log in the `$stdout`. It can be found under `lib/bas/write/logs/use_case/console_log.rb`
|
75
78
|
|
76
79
|
## Examples
|
77
80
|
|
@@ -113,7 +116,7 @@ today = Date.now
|
|
113
116
|
}
|
114
117
|
```
|
115
118
|
|
116
|
-
* A template for the formatter to be used for formatting the payload to
|
119
|
+
* A template for the formatter to be used for formatting the payload to be send to Discord. For this specific case, the format of the messages should be:
|
117
120
|
|
118
121
|
`"NAME, Wishing you a very happy birthday! Enjoy your special day! :birthday: :gift:"`
|
119
122
|
|
@@ -139,13 +142,13 @@ filter = {
|
|
139
142
|
}
|
140
143
|
|
141
144
|
options = {
|
142
|
-
|
145
|
+
read_options: {
|
143
146
|
base_url: "https://api.notion.com",
|
144
147
|
database_id: NOTION_DATABASE_ID,
|
145
148
|
secret: NOTION_API_INTEGRATION_SECRET,
|
146
149
|
filter: filter
|
147
150
|
},
|
148
|
-
|
151
|
+
process_options: {
|
149
152
|
webhook: "https://discord.com/api/webhooks/1199213527672565760/KmpoIzBet9xYG16oFh8W1RWHbpIqT7UtTBRrhfLcvWZdNiVZCTM-gpil2Qoy4eYEgpdf",
|
150
153
|
name: "Birthday Bot"
|
151
154
|
}
|
@@ -235,7 +238,7 @@ module Notifier
|
|
235
238
|
# Service description
|
236
239
|
class UseCaseName
|
237
240
|
def self.notify(*)
|
238
|
-
options = {
|
241
|
+
options = { read_options:, process_options: }
|
239
242
|
|
240
243
|
begin
|
241
244
|
use_case = UseCases.use_case_build_function(options)
|
@@ -246,18 +249,18 @@ module Notifier
|
|
246
249
|
end
|
247
250
|
end
|
248
251
|
|
249
|
-
def self.
|
252
|
+
def self.read_options
|
250
253
|
{
|
251
254
|
base_url: NOTION_BASE_URL,
|
252
255
|
database_id: NOTION_DATABASE_ID,
|
253
256
|
secret: NOTION_SECRET,
|
254
257
|
filter: {
|
255
|
-
filter: { "and":
|
258
|
+
filter: { "and": read_filter }
|
256
259
|
}
|
257
260
|
}
|
258
261
|
end
|
259
262
|
|
260
|
-
def self.
|
263
|
+
def self.read_filter
|
261
264
|
today = Common::TimeZone.set_colombia_time_zone.strftime('%F').to_s
|
262
265
|
|
263
266
|
[
|
@@ -266,7 +269,7 @@ module Notifier
|
|
266
269
|
]
|
267
270
|
end
|
268
271
|
|
269
|
-
def self.
|
272
|
+
def self.process_options
|
270
273
|
{
|
271
274
|
webhook: DISCORD_WEBHOOK,
|
272
275
|
name: DISCORD_BOT_NAME
|
data/lib/bas/formatter/base.rb
CHANGED
@@ -20,7 +20,7 @@ module Formatter
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# This method is designed to provide a specified format for data from any implementation of
|
23
|
-
# the
|
23
|
+
# the Serialize::Base interface.
|
24
24
|
# Must be overridden by subclasses, with specific logic based on the use case.
|
25
25
|
#
|
26
26
|
# <br>
|
@@ -30,7 +30,7 @@ module Formatter
|
|
30
30
|
# <br>
|
31
31
|
# <b>raises</b> <tt>Domain::Exceptions::FunctionNotImplemented</tt> when missing implementation.
|
32
32
|
#
|
33
|
-
# <b>returns</b> <tt>String</tt> Formatted payload suitable for a
|
33
|
+
# <b>returns</b> <tt>String</tt> Formatted payload suitable for a Process::Base implementation.
|
34
34
|
#
|
35
35
|
def format(_domain_data)
|
36
36
|
raise Domain::Exceptions::FunctionNotImplemented
|
@@ -3,32 +3,36 @@
|
|
3
3
|
require_relative "../domain/birthday"
|
4
4
|
require_relative "./exceptions/invalid_data"
|
5
5
|
require_relative "./base"
|
6
|
+
require_relative "./types/response"
|
6
7
|
|
7
8
|
module Formatter
|
8
9
|
##
|
9
10
|
# This class implements methods from the Formatter::Base module, tailored to format the
|
10
|
-
# Domain::Birthday structure for a
|
11
|
+
# Domain::Birthday structure for a Process.
|
11
12
|
class Birthday < Base
|
12
13
|
# Implements the logic for building a formatted payload with the given template for birthdays.
|
13
14
|
#
|
14
15
|
# <br>
|
15
16
|
# <b>Params:</b>
|
16
|
-
# * <tt>List<Domain::Birthday></tt> birthdays_list: list of
|
17
|
+
# * <tt>List<Domain::Birthday></tt> birthdays_list: list of serialized birthdays.
|
17
18
|
#
|
18
19
|
# <br>
|
19
20
|
# <b>raises</b> <tt>Formatter::Exceptions::InvalidData</tt> when invalid data is provided.
|
20
21
|
#
|
21
22
|
# <br>
|
22
|
-
# <b>returns</b> <tt>
|
23
|
+
# <b>returns</b> <tt>Formatter::Types::Response</tt> formatter response: standard output for
|
24
|
+
# the formatted payload suitable for a Process.
|
23
25
|
#
|
24
26
|
def format(birthdays_list)
|
25
27
|
raise Formatter::Exceptions::InvalidData unless birthdays_list.all? do |brithday|
|
26
28
|
brithday.is_a?(Domain::Birthday)
|
27
29
|
end
|
28
30
|
|
29
|
-
birthdays_list.reduce("") do |payload, birthday|
|
31
|
+
response = birthdays_list.reduce("") do |payload, birthday|
|
30
32
|
payload + build_template(Domain::Birthday::ATTRIBUTES, birthday)
|
31
33
|
end
|
34
|
+
|
35
|
+
Formatter::Types::Response.new(response)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
data/lib/bas/formatter/pto.rb
CHANGED
@@ -5,11 +5,12 @@ require "date"
|
|
5
5
|
require_relative "../domain/pto"
|
6
6
|
require_relative "./exceptions/invalid_data"
|
7
7
|
require_relative "./base"
|
8
|
+
require_relative "./types/response"
|
8
9
|
|
9
10
|
module Formatter
|
10
11
|
##
|
11
12
|
# This class implements methods from the Formatter::Base module, tailored to format the
|
12
|
-
# Domain::Pto structure for a
|
13
|
+
# Domain::Pto structure for a Process.
|
13
14
|
class Pto < Base
|
14
15
|
DEFAULT_TIME_ZONE = "+00:00"
|
15
16
|
|
@@ -26,13 +27,14 @@ module Formatter
|
|
26
27
|
#
|
27
28
|
# <br>
|
28
29
|
# <b>Params:</b>
|
29
|
-
# * <tt>List<Domain::Pto></tt> pto_list: List of
|
30
|
+
# * <tt>List<Domain::Pto></tt> pto_list: List of serialized PTO's.
|
30
31
|
#
|
31
32
|
# <br>
|
32
33
|
# <b>raises</b> <tt>Formatter::Exceptions::InvalidData</tt> when invalid data is provided.
|
33
34
|
#
|
34
35
|
# <br>
|
35
|
-
# <b>returns</b> <tt>
|
36
|
+
# <b>returns</b> <tt>Formatter::Types::Response</tt> formatter response: standard output for
|
37
|
+
# the formatted payload suitable for a Process.
|
36
38
|
#
|
37
39
|
|
38
40
|
def format(ptos_list)
|
@@ -40,10 +42,12 @@ module Formatter
|
|
40
42
|
|
41
43
|
ptos_list.each { |pto| pto.format_timezone(@timezone) }
|
42
44
|
|
43
|
-
ptos_list.reduce("") do |payload, pto|
|
45
|
+
response = ptos_list.reduce("") do |payload, pto|
|
44
46
|
built_template = build_template(Domain::Pto::ATTRIBUTES, pto)
|
45
47
|
payload + format_message_by_case(built_template.gsub("\n", ""), pto)
|
46
48
|
end
|
49
|
+
|
50
|
+
Formatter::Types::Response.new(response)
|
47
51
|
end
|
48
52
|
|
49
53
|
private
|
@@ -3,11 +3,12 @@
|
|
3
3
|
require_relative "../domain/email"
|
4
4
|
require_relative "./exceptions/invalid_data"
|
5
5
|
require_relative "./base"
|
6
|
+
require_relative "./types/response"
|
6
7
|
|
7
8
|
module Formatter
|
8
9
|
##
|
9
10
|
# This class implements methods from the Formatter::Base module, tailored to format the
|
10
|
-
# Domain::Email structure for a
|
11
|
+
# Domain::Email structure for a Process.
|
11
12
|
class SupportEmails < Base
|
12
13
|
DEFAULT_TIME_ZONE = "+00:00"
|
13
14
|
|
@@ -31,16 +32,19 @@ module Formatter
|
|
31
32
|
# <b>raises</b> <tt>Formatter::Exceptions::InvalidData</tt> when invalid data is provided.
|
32
33
|
#
|
33
34
|
# <br>
|
34
|
-
# <b>returns</b> <tt>
|
35
|
+
# <b>returns</b> <tt>Formatter::Types::Response</tt> formatter response: standard output for
|
36
|
+
# the formatted payload suitable for a Process.
|
35
37
|
#
|
36
38
|
def format(support_emails_list)
|
37
39
|
raise Formatter::Exceptions::InvalidData unless support_emails_list.all? do |support_email|
|
38
40
|
support_email.is_a?(Domain::Email)
|
39
41
|
end
|
40
42
|
|
41
|
-
process_emails(support_emails_list).reduce("") do |payload, support_email|
|
43
|
+
response = process_emails(support_emails_list).reduce("") do |payload, support_email|
|
42
44
|
payload + build_template(Domain::Email::ATTRIBUTES, support_email)
|
43
45
|
end
|
46
|
+
|
47
|
+
Formatter::Types::Response.new(response)
|
44
48
|
end
|
45
49
|
|
46
50
|
private
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Formatter
|
4
|
+
module Types
|
5
|
+
##
|
6
|
+
# Represents a response received from a Formatter. It encapsulates the formatted data to be used by
|
7
|
+
# a Process or a Write component.
|
8
|
+
class Response
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize(response)
|
12
|
+
@data = response
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -3,11 +3,12 @@
|
|
3
3
|
require_relative "../domain/work_items_limit"
|
4
4
|
require_relative "./exceptions/invalid_data"
|
5
5
|
require_relative "./base"
|
6
|
+
require_relative "./types/response"
|
6
7
|
|
7
8
|
module Formatter
|
8
9
|
##
|
9
10
|
# This class implements methods from the Formatter::Base module, tailored to format the
|
10
|
-
# Domain::WorkItemsLimit structure for a
|
11
|
+
# Domain::WorkItemsLimit structure for a Process.
|
11
12
|
class WorkItemsLimit < Base
|
12
13
|
DEFAULT_DOMAIN_LIMIT = 6
|
13
14
|
|
@@ -24,13 +25,14 @@ module Formatter
|
|
24
25
|
#
|
25
26
|
# <br>
|
26
27
|
# <b>Params:</b>
|
27
|
-
# * <tt>List<Domain::WorkItemsLimit></tt> work_items_list: List of
|
28
|
+
# * <tt>List<Domain::WorkItemsLimit></tt> work_items_list: List of serialized work items limits.
|
28
29
|
#
|
29
30
|
# <br>
|
30
31
|
# <b>raises</b> <tt>Formatter::Exceptions::InvalidData</tt> when invalid data is provided.
|
31
32
|
#
|
32
33
|
# <br>
|
33
|
-
# <b>returns</b> <tt>
|
34
|
+
# <b>returns</b> <tt>Formatter::Types::Response</tt> formatter response: standard output for
|
35
|
+
# the formatted payload suitable for a Process.
|
34
36
|
#
|
35
37
|
|
36
38
|
def format(work_items_list)
|
@@ -38,10 +40,12 @@ module Formatter
|
|
38
40
|
work_item.is_a?(Domain::WorkItemsLimit)
|
39
41
|
end
|
40
42
|
|
41
|
-
exceeded_domains(work_items_list).reduce("") do |payload, work_items_limit|
|
43
|
+
response = exceeded_domains(work_items_list).reduce("") do |payload, work_items_limit|
|
42
44
|
built_template = build_template(Domain::WorkItemsLimit::ATTRIBUTES, work_items_limit)
|
43
45
|
payload + format_message_by_case(built_template.gsub("\n", ""), work_items_limit)
|
44
46
|
end
|
47
|
+
|
48
|
+
Formatter::Types::Response.new(response)
|
45
49
|
end
|
46
50
|
|
47
51
|
private
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../domain/exceptions/function_not_implemented"
|
4
|
+
require_relative "./types/response"
|
5
|
+
|
6
|
+
module Process
|
7
|
+
##
|
8
|
+
# Serves as a foundational structure for implementing specific process. Acting as an interface,
|
9
|
+
# this class defines essential attributes and methods, providing a blueprint for creating custom
|
10
|
+
# process tailored to different platforms or services.
|
11
|
+
#
|
12
|
+
class Base
|
13
|
+
attr_reader :config
|
14
|
+
|
15
|
+
# Initializes the process with essential configuration parameters.
|
16
|
+
#
|
17
|
+
def initialize(config = {})
|
18
|
+
@config = config
|
19
|
+
end
|
20
|
+
|
21
|
+
# A method meant to send messages to an specific destination depending on the implementation.
|
22
|
+
# Must be overridden by subclasses, with specific logic based on the use case.
|
23
|
+
#
|
24
|
+
# <br>
|
25
|
+
# <b>returns</b> a <tt>Process::Types::Response</tt>: standard output for a process
|
26
|
+
#
|
27
|
+
def execute(format_response)
|
28
|
+
Process::Types::Response.new(format_response.data)
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def valid_format_response(format_response)
|
34
|
+
return format_response if format_response.is_a?(Formatter::Types::Response)
|
35
|
+
|
36
|
+
raise Formatter::Exceptions::InvalidData
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
require_relative "./exceptions/invalid_webhook_token"
|
5
|
+
require_relative "./types/response"
|
6
|
+
|
7
|
+
module Process
|
8
|
+
module Discord
|
9
|
+
##
|
10
|
+
# This class is an implementation of the Process::Base interface, specifically designed
|
11
|
+
# for sending messages to Discord.
|
12
|
+
#
|
13
|
+
class Implementation < Base
|
14
|
+
attr_reader :webhook, :name
|
15
|
+
|
16
|
+
# Initializes the process with essential configuration parameters.
|
17
|
+
#
|
18
|
+
def initialize(config = {})
|
19
|
+
super(config)
|
20
|
+
|
21
|
+
@webhook = config[:webhook]
|
22
|
+
@name = config[:name]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Implements the sending process logic for the Discord use case. It sends a POST request to
|
26
|
+
# the Discord webhook with the specified payload.
|
27
|
+
#
|
28
|
+
# <br>
|
29
|
+
# <b>Params:</b>
|
30
|
+
# * <tt>Formatter::Types::Response</tt> formatter response: standard formatter response
|
31
|
+
# with the Payload to be send to discord.
|
32
|
+
# <br>
|
33
|
+
# <b>raises</b> <tt>Exceptions::Discord::InvalidWebookToken</tt> if the provided webhook
|
34
|
+
# token is invalid.
|
35
|
+
#
|
36
|
+
# <br>
|
37
|
+
# <b>returns</b> <tt>Process::Types::Response</tt>
|
38
|
+
#
|
39
|
+
def execute(format_response)
|
40
|
+
response = valid_format_response(format_response)
|
41
|
+
|
42
|
+
body = post_body(response.data)
|
43
|
+
|
44
|
+
response = HTTParty.post(webhook, { body: body, headers: { "Content-Type" => "application/json" } })
|
45
|
+
|
46
|
+
discord_response = Process::Discord::Types::Response.new(response)
|
47
|
+
|
48
|
+
validate_response(discord_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def post_body(payload)
|
54
|
+
{
|
55
|
+
username: name,
|
56
|
+
avatar_url: "",
|
57
|
+
content: payload
|
58
|
+
}.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_response(response)
|
62
|
+
case response.code
|
63
|
+
when 50_027
|
64
|
+
raise Discord::Exceptions::InvalidWebookToken, response.message
|
65
|
+
else
|
66
|
+
Process::Types::Response.new(response)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
require_relative "./exceptions/invalid_webhook_token"
|
5
|
+
require_relative "./types/response"
|
6
|
+
|
7
|
+
module Process
|
8
|
+
module Slack
|
9
|
+
##
|
10
|
+
# This class is an implementation of the Process::Base interface, specifically designed
|
11
|
+
# for sending messages to Slack.
|
12
|
+
#
|
13
|
+
class Implementation < Base
|
14
|
+
attr_reader :webhook, :name
|
15
|
+
|
16
|
+
# Initializes the process with essential configuration parameters.
|
17
|
+
#
|
18
|
+
def initialize(config = {})
|
19
|
+
super(config)
|
20
|
+
|
21
|
+
@webhook = config[:webhook]
|
22
|
+
@name = config[:name]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Implements the sending process logic for the Slack use case. It sends a POST request to
|
26
|
+
# the Slack webhook with the specified payload.
|
27
|
+
#
|
28
|
+
# <br>
|
29
|
+
# <b>Params:</b>
|
30
|
+
# * <tt>Formatter::Types::Response</tt> formatter response: standard formatter response
|
31
|
+
# with the Payload to be send to slack.
|
32
|
+
# <br>
|
33
|
+
# <b>raises</b> <tt>Exceptions::Slack::InvalidWebookToken</tt> if the provided webhook
|
34
|
+
# token is invalid.
|
35
|
+
#
|
36
|
+
# <br>
|
37
|
+
# <b>returns</b> <tt>Process::Types::Response</tt>
|
38
|
+
#
|
39
|
+
def execute(format_response)
|
40
|
+
response = valid_format_response(format_response)
|
41
|
+
|
42
|
+
body = post_body(response.data)
|
43
|
+
|
44
|
+
response = HTTParty.post(webhook, { body: body, headers: { "Content-Type" => "application/json" } })
|
45
|
+
|
46
|
+
slack_response = Process::Discord::Types::Response.new(response)
|
47
|
+
|
48
|
+
validate_response(slack_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def post_body(payload)
|
54
|
+
{
|
55
|
+
username: name,
|
56
|
+
text: payload
|
57
|
+
}.to_json
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_response(response)
|
61
|
+
case response.http_code
|
62
|
+
when 403
|
63
|
+
raise Process::Slack::Exceptions::InvalidWebookToken, response.message
|
64
|
+
else
|
65
|
+
Process::Types::Response.new(response)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Process
|
4
|
+
module Types
|
5
|
+
##
|
6
|
+
# Represents a response received from a Process. It encapsulates the formatted data to be used by
|
7
|
+
# a Write component.
|
8
|
+
class Response
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize(response)
|
12
|
+
@data = response
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,41 +2,41 @@
|
|
2
2
|
|
3
3
|
require_relative "../domain/exceptions/function_not_implemented"
|
4
4
|
|
5
|
-
module
|
5
|
+
module Read
|
6
6
|
##
|
7
|
-
# The
|
7
|
+
# The Read::Base class serves as the foundation for implementing specific data readers within the Read module.
|
8
8
|
# Operating as an interface, this class defines essential attributes and methods, providing a blueprint for creating
|
9
|
-
# custom
|
9
|
+
# custom readers tailored to different data sources.
|
10
10
|
#
|
11
11
|
class Base
|
12
12
|
attr_reader :config
|
13
13
|
|
14
|
-
# Initializes the
|
14
|
+
# Initializes the reader with essential configuration parameters.
|
15
15
|
#
|
16
16
|
def initialize(config)
|
17
17
|
@config = config
|
18
18
|
end
|
19
19
|
|
20
|
-
# A method meant to
|
20
|
+
# A method meant to execute the read request from an specific source depending on the implementation.
|
21
21
|
# Must be overridden by subclasses, with specific logic based on the use case.
|
22
22
|
#
|
23
23
|
# <br>
|
24
24
|
# <b>raises</b> <tt>Domain::Exceptions::FunctionNotImplemented</tt> when missing implementation.
|
25
25
|
#
|
26
|
-
def
|
26
|
+
def execute
|
27
27
|
raise Domain::Exceptions::FunctionNotImplemented
|
28
28
|
end
|
29
29
|
|
30
30
|
protected
|
31
31
|
|
32
|
-
# A method meant to
|
32
|
+
# A method meant to read from the source, retrieven the required data
|
33
33
|
# from an specific filter configuration depending on the use case implementation.
|
34
34
|
# Must be overridden by subclasses, with specific logic based on the use case.
|
35
35
|
#
|
36
36
|
# <br>
|
37
37
|
# <b>raises</b> <tt>Domain::Exceptions::FunctionNotImplemented</tt> when missing implementation.
|
38
38
|
#
|
39
|
-
def
|
39
|
+
def read(*_filters)
|
40
40
|
raise Domain::Exceptions::FunctionNotImplemented
|
41
41
|
end
|
42
42
|
end
|