bas 0.4.0 → 1.0.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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +68 -147
  4. data/lib/bas/bot/base.rb +74 -0
  5. data/lib/bas/bot/compare_wip_limit_count.rb +92 -0
  6. data/lib/bas/bot/fetch_birthdays_from_notion.rb +128 -0
  7. data/lib/bas/bot/fetch_domains_wip_counts_from_notion.rb +121 -0
  8. data/lib/bas/bot/fetch_domains_wip_limit_from_notion.rb +134 -0
  9. data/lib/bas/bot/fetch_emails_from_imap.rb +99 -0
  10. data/lib/bas/bot/fetch_next_week_birthdays_from_notion.rb +142 -0
  11. data/lib/bas/bot/fetch_next_week_ptos_from_notion.rb +162 -0
  12. data/lib/bas/bot/fetch_ptos_from_notion.rb +138 -0
  13. data/lib/bas/bot/format_birthdays.rb +97 -0
  14. data/lib/bas/bot/format_emails.rb +124 -0
  15. data/lib/bas/bot/format_wip_limit_exceeded.rb +97 -0
  16. data/lib/bas/bot/garbage_collector.rb +85 -0
  17. data/lib/bas/bot/humanize_pto.rb +119 -0
  18. data/lib/bas/bot/notify_discord.rb +96 -0
  19. data/lib/bas/read/base.rb +10 -23
  20. data/lib/bas/read/default.rb +16 -0
  21. data/lib/bas/read/postgres.rb +44 -0
  22. data/lib/bas/read/types/response.rb +18 -0
  23. data/lib/bas/utils/discord/integration.rb +43 -0
  24. data/lib/bas/utils/exceptions/function_not_implemented.rb +16 -0
  25. data/lib/bas/utils/exceptions/invalid_process_response.rb +16 -0
  26. data/lib/bas/utils/imap/request.rb +76 -0
  27. data/lib/bas/utils/notion/request.rb +45 -0
  28. data/lib/bas/utils/openai/run_assistant.rb +99 -0
  29. data/lib/bas/utils/postgres/request.rb +50 -0
  30. data/lib/bas/version.rb +1 -1
  31. data/lib/bas/write/base.rb +12 -17
  32. data/lib/bas/write/postgres.rb +45 -0
  33. data/lib/bas/write/postgres_update.rb +49 -0
  34. data/lib/bas.rb +1 -3
  35. metadata +30 -67
  36. data/lib/bas/domain/birthday.rb +0 -25
  37. data/lib/bas/domain/email.rb +0 -34
  38. data/lib/bas/domain/exceptions/function_not_implemented.rb +0 -18
  39. data/lib/bas/domain/issue.rb +0 -22
  40. data/lib/bas/domain/notification.rb +0 -23
  41. data/lib/bas/domain/pto.rb +0 -69
  42. data/lib/bas/domain/work_items_limit.rb +0 -25
  43. data/lib/bas/formatter/base.rb +0 -53
  44. data/lib/bas/formatter/birthday.rb +0 -38
  45. data/lib/bas/formatter/exceptions/invalid_data.rb +0 -15
  46. data/lib/bas/formatter/notification.rb +0 -34
  47. data/lib/bas/formatter/pto.rb +0 -89
  48. data/lib/bas/formatter/support_emails.rb +0 -73
  49. data/lib/bas/formatter/types/response.rb +0 -16
  50. data/lib/bas/formatter/work_items_limit.rb +0 -68
  51. data/lib/bas/process/base.rb +0 -39
  52. data/lib/bas/process/discord/exceptions/invalid_webhook_token.rb +0 -16
  53. data/lib/bas/process/discord/implementation.rb +0 -71
  54. data/lib/bas/process/discord/types/response.rb +0 -22
  55. data/lib/bas/process/openai/base.rb +0 -72
  56. data/lib/bas/process/openai/helper.rb +0 -19
  57. data/lib/bas/process/openai/types/response.rb +0 -27
  58. data/lib/bas/process/openai/use_case/humanize_pto.rb +0 -53
  59. data/lib/bas/process/slack/exceptions/invalid_webhook_token.rb +0 -16
  60. data/lib/bas/process/slack/implementation.rb +0 -70
  61. data/lib/bas/process/slack/types/response.rb +0 -21
  62. data/lib/bas/process/types/response.rb +0 -16
  63. data/lib/bas/read/github/base.rb +0 -57
  64. data/lib/bas/read/github/types/response.rb +0 -27
  65. data/lib/bas/read/github/use_case/repo_issues.rb +0 -17
  66. data/lib/bas/read/imap/base.rb +0 -70
  67. data/lib/bas/read/imap/types/response.rb +0 -27
  68. data/lib/bas/read/imap/use_case/support_emails.rb +0 -26
  69. data/lib/bas/read/notion/base.rb +0 -52
  70. data/lib/bas/read/notion/exceptions/invalid_api_key.rb +0 -15
  71. data/lib/bas/read/notion/exceptions/invalid_database_id.rb +0 -15
  72. data/lib/bas/read/notion/helper.rb +0 -21
  73. data/lib/bas/read/notion/types/response.rb +0 -26
  74. data/lib/bas/read/notion/use_case/birthday_next_week.rb +0 -41
  75. data/lib/bas/read/notion/use_case/birthday_today.rb +0 -29
  76. data/lib/bas/read/notion/use_case/notification.rb +0 -28
  77. data/lib/bas/read/notion/use_case/pto_next_week.rb +0 -71
  78. data/lib/bas/read/notion/use_case/pto_today.rb +0 -30
  79. data/lib/bas/read/notion/use_case/work_items_limit.rb +0 -37
  80. data/lib/bas/read/postgres/base.rb +0 -46
  81. data/lib/bas/read/postgres/helper.rb +0 -16
  82. data/lib/bas/read/postgres/types/response.rb +0 -42
  83. data/lib/bas/read/postgres/use_case/pto_today.rb +0 -32
  84. data/lib/bas/serialize/base.rb +0 -30
  85. data/lib/bas/serialize/github/issues.rb +0 -57
  86. data/lib/bas/serialize/imap/support_emails.rb +0 -56
  87. data/lib/bas/serialize/notion/birthday_today.rb +0 -68
  88. data/lib/bas/serialize/notion/notification.rb +0 -56
  89. data/lib/bas/serialize/notion/pto_today.rb +0 -75
  90. data/lib/bas/serialize/notion/work_items_limit.rb +0 -65
  91. data/lib/bas/serialize/postgres/pto_today.rb +0 -47
  92. data/lib/bas/use_cases/types/config.rb +0 -20
  93. data/lib/bas/use_cases/use_case.rb +0 -42
  94. data/lib/bas/use_cases/use_cases.rb +0 -465
  95. data/lib/bas/write/logs/base.rb +0 -33
  96. data/lib/bas/write/logs/use_case/console_log.rb +0 -22
  97. data/lib/bas/write/notion/base.rb +0 -36
  98. data/lib/bas/write/notion/use_case/empty_notification.rb +0 -38
  99. data/lib/bas/write/notion/use_case/notification.rb +0 -38
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../domain/exceptions/function_not_implemented"
4
-
5
- module Serialize
6
- ##
7
- # The Serialize::Base module serves as the foundation for implementing specific data shaping logic within the
8
- # Serialize module. Defines essential methods, that provide a blueprint for organizing or shaping data in a manner
9
- # suitable for downstream formatting processes.
10
- #
11
- module Base
12
- # An method meant to prepare or organize the data coming from an implementation of the Read::Base interface.
13
- # Must be overridden by subclasses, with specific logic based on the use case.
14
- #
15
- # <br>
16
- # <b>Params:</b>
17
- # * <tt>Read::Notion::Types::Response</tt> response: Response produced by a reader.
18
- #
19
- # <br>
20
- #
21
- # <b>raises</b> <tt>Domain::Exceptions::FunctionNotImplemented</tt> when missing implementation.
22
- # <br>
23
- #
24
- # <b>returns</b> <tt>List<Domain::></tt> Serialize list of data, ready to be formatted.
25
- #
26
- def execute(_response)
27
- raise Domain::Exceptions::FunctionNotImplemented
28
- end
29
- end
30
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/issue"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Github
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for
10
- # preparing or shaping Github issues data coming from a Read::Base implementation.
11
- class Issues
12
- include Base
13
-
14
- # Implements the logic for shaping the results from a reader response.
15
- #
16
- # <br>
17
- # <b>Params:</b>
18
- # * <tt>Read::Github::Types::Response</tt> github_response: Array of github issues data.
19
- #
20
- # <br>
21
- # <b>return</b> <tt>List<Domain::Issue></tt> serialized github issues to be used by a
22
- # Formatter::Base implementation.
23
- #
24
- def execute(github_response)
25
- return [] if github_response.results.empty?
26
-
27
- normalized_github_data = normalize_response(github_response.results)
28
-
29
- normalized_github_data.map do |issue|
30
- Domain::Issue.new(
31
- issue["title"], issue["state"], issue["assignees"], issue["body"], issue["url"]
32
- )
33
- end
34
- end
35
-
36
- private
37
-
38
- def normalize_response(results)
39
- return [] if results.nil?
40
-
41
- results.map do |value|
42
- {
43
- "title" => value[:title],
44
- "state" => value[:state],
45
- "assignees" => extract_assignees(value[:assignees]),
46
- "body" => value[:body],
47
- "url" => value[:url]
48
- }
49
- end
50
- end
51
-
52
- def extract_assignees(assignees)
53
- assignees.map { |assignee| assignee[:login] }
54
- end
55
- end
56
- end
57
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/email"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Imap
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for
10
- # preparing or shaping support emails data coming from a Read::Base implementation.
11
- class SupportEmails
12
- include Base
13
-
14
- # Implements the logic for shaping the results from a reader response.
15
- #
16
- # <br>
17
- # <b>Params:</b>
18
- # * <tt>Read::Imap::Types::Response</tt> imap_response: Array of imap emails data.
19
- #
20
- # <br>
21
- # <b>return</b> <tt>List<Domain::Email></tt> support_emails_list, serialized support emails to be used by a
22
- # Formatter::Base implementation.
23
- #
24
- def execute(imap_response)
25
- return [] if imap_response.results.empty?
26
-
27
- normalized_email_data = normalize_response(imap_response.results)
28
-
29
- normalized_email_data.map do |email|
30
- Domain::Email.new(email["subject"], email["sender"], email["date"])
31
- end
32
- end
33
-
34
- private
35
-
36
- def normalize_response(results)
37
- return [] if results.nil?
38
-
39
- results.map do |value|
40
- {
41
- "sender" => extract_sender(value),
42
- "date" => value.date,
43
- "subject" => value.subject
44
- }
45
- end
46
- end
47
-
48
- def extract_sender(value)
49
- mailbox = value.sender[0]["mailbox"]
50
- host = value.sender[0]["host"]
51
-
52
- "#{mailbox}@#{host}"
53
- end
54
- end
55
- end
56
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/birthday"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Notion
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for preparing or
10
- # shaping birthdays data coming from a Read::Base implementation.
11
- class BirthdayToday
12
- include Base
13
-
14
- BIRTHDAY_PARAMS = ["Complete Name", "BD_this_year"].freeze
15
-
16
- # Implements the logic for shaping the results from a reader response.
17
- #
18
- # <br>
19
- # <b>Params:</b>
20
- # * <tt>Read::Notion::Types::Response</tt> notion_response: Notion response object.
21
- #
22
- # <br>
23
- # <b>return</b> <tt>List<Domain::Birthday></tt> birthdays_list, serialized birthdays to be used by a
24
- # Formatter::Base implementation.
25
- #
26
- def execute(notion_response)
27
- return [] if notion_response.results.empty?
28
-
29
- normalized_notion_data = normalize_response(notion_response.results)
30
-
31
- normalized_notion_data.map do |birthday|
32
- Domain::Birthday.new(birthday["Complete Name"], birthday["BD_this_year"])
33
- end
34
- end
35
-
36
- private
37
-
38
- def normalize_response(results)
39
- return [] if results.nil?
40
-
41
- results.map do |value|
42
- birthday_fields = value["properties"].slice(*BIRTHDAY_PARAMS)
43
-
44
- birthday_fields.each do |field, birthday_value|
45
- birthday_fields[field] = extract_birthday_value(field, birthday_value)
46
- end
47
-
48
- birthday_fields
49
- end
50
- end
51
-
52
- def extract_birthday_value(field, value)
53
- case field
54
- when "Complete Name" then extract_rich_text_field_value(value)
55
- when "BD_this_year" then extract_date_field_value(value)
56
- end
57
- end
58
-
59
- def extract_rich_text_field_value(data)
60
- data["rich_text"][0]["plain_text"]
61
- end
62
-
63
- def extract_date_field_value(data)
64
- data["formula"]["date"]["start"]
65
- end
66
- end
67
- end
68
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/notification"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Notion
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for preparing or
10
- # shaping Notification's data coming from a Read::Base implementation.
11
- #
12
- class Notification
13
- include Base
14
-
15
- NOTIFICATION_PARAMS = ["Notification"].freeze
16
-
17
- # Implements the logic for shaping the results from a reader response.
18
- #
19
- # <br>
20
- # <b>Params:</b>
21
- # * <tt>Read::Notion::Types::Response</tt> notion_response: Notion response object.
22
- #
23
- # <br>
24
- # <b>returns</b> <tt>List<Domain::Notification></tt> notification_list, serialized
25
- # notifications to be used by a Formatter::Base implementation.
26
- #
27
- def execute(notion_response)
28
- return [] if notion_response.results.empty?
29
-
30
- normalized_notion_data = normalize_response(notion_response.results)
31
-
32
- normalized_notion_data.map do |notification|
33
- Domain::Notification.new(notification["Notification"])
34
- end
35
- end
36
-
37
- private
38
-
39
- def normalize_response(response)
40
- return [] if response.nil?
41
-
42
- response.map do |value|
43
- notification_fields = value["properties"].slice(*NOTIFICATION_PARAMS)
44
-
45
- {
46
- "Notification" => extract_notification_field_value(notification_fields["Notification"])
47
- }
48
- end
49
- end
50
-
51
- def extract_notification_field_value(notification)
52
- notification["rich_text"][0]["plain_text"]
53
- end
54
- end
55
- end
56
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/pto"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Notion
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for preparing or
10
- # shaping PTO's data coming from a Read::Base implementation.
11
- #
12
- class PtoToday
13
- include Base
14
-
15
- PTO_PARAMS = ["Description", "Desde?", "Hasta?"].freeze
16
-
17
- # Implements the logic for shaping the results from a reader response.
18
- #
19
- # <br>
20
- # <b>Params:</b>
21
- # * <tt>Read::Notion::Types::Response</tt> notion_response: Notion response object.
22
- #
23
- # <br>
24
- # <b>returns</b> <tt>List<Domain::Pto></tt> ptos_list, serialized PTO's to be used by a Formatter::Base
25
- # implementation.
26
- #
27
- def execute(notion_response)
28
- return [] if notion_response.results.empty?
29
-
30
- normalized_notion_data = normalize_response(notion_response.results)
31
-
32
- normalized_notion_data.map do |pto|
33
- Domain::Pto.new(pto["Description"], pto["Desde?"], pto["Hasta?"])
34
- end
35
- end
36
-
37
- private
38
-
39
- def normalize_response(response)
40
- return [] if response.nil?
41
-
42
- response.map do |value|
43
- pto_fields = value["properties"].slice(*PTO_PARAMS)
44
-
45
- {
46
- "Description" => extract_description_field_value(pto_fields["Description"]),
47
- "Desde?" => extract_date_field_value(pto_fields["Desde?"]),
48
- "Hasta?" => extract_date_field_value(pto_fields["Hasta?"])
49
- }
50
- end
51
- end
52
-
53
- def extract_description_field_value(data)
54
- names = data["title"].map { |name| name["plain_text"] }
55
-
56
- names.join(" ")
57
- end
58
-
59
- def extract_date_field_value(date)
60
- {
61
- from: extract_start_date(date),
62
- to: extract_end_date(date)
63
- }
64
- end
65
-
66
- def extract_start_date(data)
67
- data["date"]["start"]
68
- end
69
-
70
- def extract_end_date(data)
71
- data["date"]["end"]
72
- end
73
- end
74
- end
75
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/work_items_limit"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Notion
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed
10
- # for preparing or shaping work items data coming from a Read::Base implementation.
11
- class WorkItemsLimit
12
- include Base
13
-
14
- WORK_ITEM_PARAMS = ["Responsible domain"].freeze
15
-
16
- # Implements the logic for shaping the results from a reader response.
17
- #
18
- # <br>
19
- # <b>Params:</b>
20
- # * <tt>Read::Notion::Types::Response</tt> notion_response: Notion response object.
21
- #
22
- # <br>
23
- # <b>return</b> <tt>List<Domain::WorkItem></tt> work_items_list, serialized work items to be used by a
24
- # Formatter::Base implementation.
25
- #
26
- def execute(notion_response)
27
- return [] if notion_response.results.empty?
28
-
29
- normalized_notion_data = normalize_response(notion_response.results)
30
-
31
- domain_items_count = count_domain_items(normalized_notion_data)
32
-
33
- domain_items_count.map do |domain, items_count|
34
- Domain::WorkItemsLimit.new(domain, items_count)
35
- end
36
- end
37
-
38
- private
39
-
40
- def normalize_response(results)
41
- return [] if results.nil?
42
-
43
- results.map do |value|
44
- work_item_fields = value["properties"].slice(*WORK_ITEM_PARAMS)
45
-
46
- work_item_fields.each do |field, work_item_value|
47
- work_item_fields[field] = extract_domain_field_value(work_item_value)
48
- end
49
-
50
- work_item_fields
51
- end
52
- end
53
-
54
- def extract_domain_field_value(data)
55
- data["select"]["name"]
56
- end
57
-
58
- def count_domain_items(work_items_list)
59
- domain_work_items = work_items_list.group_by { |work_item| work_item["Responsible domain"] }
60
-
61
- domain_work_items.transform_values(&:count)
62
- end
63
- end
64
- end
65
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../domain/pto"
4
- require_relative "../base"
5
-
6
- module Serialize
7
- module Postgres
8
- ##
9
- # This class implements the methods of the Serialize::Base module, specifically designed for preparing or
10
- # shaping PTO's data coming from the Read::Postgres::Pto class.
11
- #
12
- class PtoToday
13
- # Implements the logic for shaping the results from a reader response.
14
- #
15
- # <br>
16
- # <b>Params:</b>
17
- # * <tt>Read::Postgres::Types::Response</tt> pg_response: Postgres response object.
18
- #
19
- # <br>
20
- # <b>returns</b> <tt>List<Domain::Pto></tt> ptos_list, serialized PTO's to be used by a Formatter::Base
21
- # implementation.
22
- #
23
- def execute(pg_response)
24
- return [] if pg_response.records.empty?
25
-
26
- ptos = build_map(pg_response)
27
-
28
- ptos.map do |pto|
29
- name = pto["name"]
30
- start_date = { from: pto["start_date"], to: nil }
31
- end_date = { from: pto["end_date"], to: nil }
32
-
33
- Domain::Pto.new(name, start_date, end_date)
34
- end
35
- end
36
-
37
- private
38
-
39
- def build_map(pg_response)
40
- fields = pg_response.fields
41
- values = pg_response.records
42
-
43
- values.map { |value| Hash[fields.zip(value)] }
44
- end
45
- end
46
- end
47
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UseCases
4
- module Types
5
- ##
6
- # Represents a the configuration composing the initial components required by a UseCases::UseCase implementation.
7
- #
8
- class Config
9
- attr_reader :read, :serialize, :formatter, :process, :write
10
-
11
- def initialize(read, serialize, formatter, process, write)
12
- @read = read
13
- @serialize = serialize
14
- @formatter = formatter
15
- @process = process
16
- @write = write
17
- end
18
- end
19
- end
20
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UseCases
4
- ##
5
- # The UseCases::UseCase class represents a generic structure for use cases within the system. It encapsulates the
6
- # logic flow by coordinating the execution of its components to fulfill a specific use case.
7
- #
8
- class UseCase
9
- attr_reader :read, :serialize, :formatter, :process, :write
10
-
11
- # Initializes the use case with the necessary components.
12
- #
13
- # <br>
14
- # <b>Params:</b>
15
- # * <tt>Usecases::Types::Config</tt> config, The components required to instantiate a use case.
16
- #
17
- def initialize(config)
18
- @read = config.read
19
- @serialize = config.serialize
20
- @formatter = config.formatter
21
- @process = config.process
22
- @write = config.write
23
- end
24
-
25
- # Executes the use case by orchestrating the sequential execution of the read, serialize, formatter, and process.
26
- #
27
- # <br>
28
- # <b>returns</b> <tt>Process::Discord::Types::Response</tt>
29
- #
30
- def perform
31
- response = read.execute
32
-
33
- serialization = serialize.execute(response)
34
-
35
- format_response = formatter.format(serialization)
36
-
37
- process_response = process.execute(format_response)
38
-
39
- write.execute(process_response)
40
- end
41
- end
42
- end