bas 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +25 -22
  4. data/lib/bas/formatter/base.rb +2 -2
  5. data/lib/bas/formatter/birthday.rb +8 -4
  6. data/lib/bas/formatter/pto.rb +8 -4
  7. data/lib/bas/formatter/support_emails.rb +7 -3
  8. data/lib/bas/formatter/types/response.rb +16 -0
  9. data/lib/bas/formatter/work_items_limit.rb +8 -4
  10. data/lib/bas/process/base.rb +39 -0
  11. data/lib/bas/{dispatcher → process}/discord/exceptions/invalid_webhook_token.rb +1 -1
  12. data/lib/bas/process/discord/implementation.rb +71 -0
  13. data/lib/bas/{dispatcher → process}/discord/types/response.rb +1 -1
  14. data/lib/bas/{dispatcher → process}/slack/exceptions/invalid_webhook_token.rb +1 -1
  15. data/lib/bas/process/slack/implementation.rb +70 -0
  16. data/lib/bas/{dispatcher → process}/slack/types/response.rb +1 -1
  17. data/lib/bas/process/types/response.rb +16 -0
  18. data/lib/bas/{fetcher → read}/base.rb +8 -8
  19. data/lib/bas/{fetcher → read}/github/base.rb +7 -7
  20. data/lib/bas/{fetcher → read}/github/types/response.rb +1 -1
  21. data/lib/bas/read/github/use_case/repo_issues.rb +17 -0
  22. data/lib/bas/{fetcher → read}/imap/base.rb +7 -7
  23. data/lib/bas/{fetcher → read}/imap/types/response.rb +1 -1
  24. data/lib/bas/read/imap/use_case/support_emails.rb +26 -0
  25. data/lib/bas/{fetcher → read}/notion/base.rb +8 -8
  26. data/lib/bas/{fetcher → read}/notion/helper.rb +1 -1
  27. data/lib/bas/{fetcher → read}/notion/types/response.rb +1 -1
  28. data/lib/bas/{fetcher → read}/notion/use_case/birthday_next_week.rb +6 -6
  29. data/lib/bas/{fetcher → read}/notion/use_case/birthday_today.rb +6 -6
  30. data/lib/bas/{fetcher → read}/notion/use_case/pto_next_week.rb +6 -6
  31. data/lib/bas/{fetcher → read}/notion/use_case/pto_today.rb +6 -6
  32. data/lib/bas/{fetcher → read}/notion/use_case/work_items_limit.rb +5 -5
  33. data/lib/bas/{fetcher → read}/postgres/base.rb +8 -8
  34. data/lib/bas/{fetcher → read}/postgres/helper.rb +1 -1
  35. data/lib/bas/{fetcher → read}/postgres/types/response.rb +1 -1
  36. data/lib/bas/{fetcher → read}/postgres/use_case/pto_today.rb +6 -6
  37. data/lib/bas/{mapper → serialize}/base.rb +7 -7
  38. data/lib/bas/{mapper → serialize}/github/issues.rb +7 -7
  39. data/lib/bas/{mapper → serialize}/imap/support_emails.rb +7 -7
  40. data/lib/bas/{mapper → serialize}/notion/birthday_today.rb +7 -7
  41. data/lib/bas/{mapper → serialize}/notion/pto_today.rb +14 -12
  42. data/lib/bas/{mapper → serialize}/notion/work_items_limit.rb +7 -7
  43. data/lib/bas/{mapper → serialize}/postgres/pto_today.rb +7 -7
  44. data/lib/bas/use_cases/types/config.rb +6 -5
  45. data/lib/bas/use_cases/use_case.rb +13 -10
  46. data/lib/bas/use_cases/use_cases.rb +71 -61
  47. data/lib/bas/version.rb +1 -1
  48. data/lib/bas/write/base.rb +36 -0
  49. data/lib/bas/write/logs/base.rb +33 -0
  50. data/lib/bas/write/logs/use_case/console_log.rb +22 -0
  51. metadata +42 -37
  52. data/lib/bas/dispatcher/base.rb +0 -31
  53. data/lib/bas/dispatcher/discord/implementation.rb +0 -51
  54. data/lib/bas/dispatcher/slack/implementation.rb +0 -51
  55. data/lib/bas/fetcher/github/use_case/repo_issues.rb +0 -17
  56. data/lib/bas/fetcher/imap/use_case/support_emails.rb +0 -26
  57. /data/lib/bas/{fetcher → read}/notion/exceptions/invalid_api_key.rb +0 -0
  58. /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: 97cc25416cff1a50cad38e85bbc1e7389693ccf2f4004a1c5fb8d5049162b407
4
- data.tar.gz: efef410e0d776c8808655dbd20cb7500c81bcf53c16f072a7103d5827def9e58
3
+ metadata.gz: eb7e143b2fed334e1489ffe66e55c87a997f71b744eefa8aa3ef55d53b8a8659
4
+ data.tar.gz: 7bf4e381847d69f760d5beab142bae8d9fc378dabb0f03583759b00e8b8b4b97
5
5
  SHA512:
6
- metadata.gz: f7d915c41461667d858750e117e63468fba9cdea4fac59dfd80b0dcf1a7c4ce749b773378b06a81e2cdfafbefce92a61a2ee8415a80edd6a1e1a61380c5bdda9
7
- data.tar.gz: fa174b7e86b013055efabe32b7dc7c2f213bd8dd18600c35e655d4c7512ce8e8f7ed4e104c091ca5b4def7180d4499a1c37f3dd5f4ad5e0a936ac79d716f03b1
6
+ metadata.gz: 38e5f2ff3e0c3f76f8d74a8cd8b3b25f2eae63dfe0d9595f9e97503bce057c45e24c21ea7f9625ec367c9851131bbe7b70824176e01da913d7209666840d3dd6
7
+ data.tar.gz: 5b993cfb181d61f647a48bdd2a38f39849068274aea4819cabd5e8691571fca4afd27205c6af862a7fc5b81789ba00a32a8afed291e40b71dbbc46ebc490f20b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.1 (16.04.2024)
4
+ - [Use case format error](https://github.com/kommitters/bas/issues/22)
5
+
6
+ ## 0.3.0 (16.04.2024)
7
+ - [Rename the Fetcher to Read](https://github.com/kommitters/bas/issues/13)
8
+ - [Rename the Mapper to Serialize](https://github.com/kommitters/bas/issues/14)
9
+ - [Rename the Dispatcher to Process](https://github.com/kommitters/bas/issues/15)
10
+ - [Add the Writer Component](https://github.com/kommitters/bas/issues/16)
11
+
3
12
  ## 0.2.0 (04.04.2024)
4
13
  - [Add a GitHub fetcher component](https://github.com/kommitters/bas/issues/6)
5
14
  - [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 dispatching the
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 4 main components, having it's own responsibility:
45
+ A *Use Case* object, consists on 5 main components, having it's own responsibility:
46
46
 
47
- ### 1. Fetcher - Obtaining the data
47
+ ### 1. Read - Obtaining the data
48
48
 
49
- Specifically, a fetcher is an object in charged of bringing data from a data source. The gem already provides the base interface
50
- for building your own fetcher for your specific data source, or rely on already built classes if they match your purpose.
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 fetcher can be found under the `bas/fetcher/base.rb` class. Since this is a implementation of the `Fetcher::Base`
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/fetcher/notion/use_case/birthday_today.rb`. It implements specific logic for fetching the data and validating the response.
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. Mapper - Shaping it
56
+ ### 2. Serialize - Shaping it
57
57
 
58
- The **Mapper** responsibility, is to shape the data using custom types from the app domain, bringing it into a
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 Mapper implementation for it, relies on specific types for representing a Birthday it self. It can be found
62
- under `/bas/mapper/notion/birthday_today.rb`
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. Dispatcher - Sending your notification
70
+ ### 4. Process - Optional Data Process
71
71
 
72
- Finally, the **Dispatcher** basically, sends or dispatches the formatted message into a destination, since the use case was implemented for
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/dispatcher/discord/implementation.rb`
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 dispatch to Discord. For this specific case, the format of the messages should be:
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
- fetch_options: {
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
- dispatch_options: {
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 = { fetch_options:, dispatch_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.fetch_options
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": fetch_filter }
258
+ filter: { "and": read_filter }
256
259
  }
257
260
  }
258
261
  end
259
262
 
260
- def self.fetch_filter
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.dispatch_options
272
+ def self.process_options
270
273
  {
271
274
  webhook: DISCORD_WEBHOOK,
272
275
  name: DISCORD_BOT_NAME
@@ -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 Mapper::Base interface.
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 Dispatcher::Base implementation.
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 dispatcher.
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 mapped birthdays.
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>String</tt> payload: formatted payload suitable for a Dispatcher.
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
@@ -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 dispatcher.
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 mapped PTO's.
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>String</tt> payload, formatted payload suitable for a Dispatcher.
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 dispatcher.
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>String</tt> payload: formatted payload suitable for a Dispatcher.
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 dispatcher.
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 mapped work items limits.
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>String</tt> payload, formatted payload suitable for a Dispatcher.
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dispatcher
3
+ module Process
4
4
  module Discord
5
5
  module Exceptions
6
6
  ##
@@ -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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dispatcher
3
+ module Process
4
4
  module Discord
5
5
  module Types
6
6
  ##
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dispatcher
3
+ module Process
4
4
  module Slack
5
5
  module Exceptions
6
6
  ##
@@ -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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dispatcher
3
+ module Process
4
4
  module Slack
5
5
  module Types
6
6
  ##
@@ -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 Fetcher
5
+ module Read
6
6
  ##
7
- # The Fetcher::Base class serves as the foundation for implementing specific data fetchers within the Fetcher module.
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 fetchers tailored to different data sources.
9
+ # custom readers tailored to different data sources.
10
10
  #
11
11
  class Base
12
12
  attr_reader :config
13
13
 
14
- # Initializes the fetcher with essential configuration parameters.
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 fetch data from an specific source depending on the implementation.
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 fetch
26
+ def execute
27
27
  raise Domain::Exceptions::FunctionNotImplemented
28
28
  end
29
29
 
30
30
  protected
31
31
 
32
- # A method meant to execute the fetch request, retrieven the required data
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 execute
39
+ def read(*_filters)
40
40
  raise Domain::Exceptions::FunctionNotImplemented
41
41
  end
42
42
  end