bns 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +14 -0
  4. data/CHANGELOG.md +11 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/CONTRIBUTING.md +66 -0
  7. data/Gemfile +18 -0
  8. data/Gemfile.lock +91 -0
  9. data/LICENSE +21 -0
  10. data/README.md +198 -0
  11. data/Rakefile +12 -0
  12. data/lib/bns/dispatcher/base.rb +31 -0
  13. data/lib/bns/dispatcher/discord/exceptions/invalid_webhook_token.rb +16 -0
  14. data/lib/bns/dispatcher/discord/implementation.rb +51 -0
  15. data/lib/bns/dispatcher/discord/types/response.rb +22 -0
  16. data/lib/bns/domain/birthday.rb +23 -0
  17. data/lib/bns/domain/exceptions/function_not_implemented.rb +18 -0
  18. data/lib/bns/domain/pto.rb +26 -0
  19. data/lib/bns/fetcher/base.rb +30 -0
  20. data/lib/bns/fetcher/notion/birthday.rb +53 -0
  21. data/lib/bns/fetcher/notion/exceptions/invalid_api_key.rb +15 -0
  22. data/lib/bns/fetcher/notion/exceptions/invalid_database_id.rb +15 -0
  23. data/lib/bns/fetcher/notion/helper.rb +21 -0
  24. data/lib/bns/fetcher/notion/pto.rb +48 -0
  25. data/lib/bns/fetcher/notion/types/response.rb +26 -0
  26. data/lib/bns/formatter/base.rb +29 -0
  27. data/lib/bns/formatter/discord/birthday.rb +43 -0
  28. data/lib/bns/formatter/discord/exceptions/invalid_data.rb +17 -0
  29. data/lib/bns/formatter/discord/pto.rb +52 -0
  30. data/lib/bns/mapper/base.rb +30 -0
  31. data/lib/bns/mapper/notion/birthday.rb +76 -0
  32. data/lib/bns/mapper/notion/pto.rb +96 -0
  33. data/lib/bns/use_cases/types/config.rb +19 -0
  34. data/lib/bns/use_cases/use_case.rb +39 -0
  35. data/lib/bns/use_cases/use_cases.rb +150 -0
  36. data/lib/bns/version.rb +6 -0
  37. data/lib/bns.rb +9 -0
  38. data/sig/business_notification_system.rbs +4 -0
  39. metadata +84 -0
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../domain/pto"
4
+ require_relative "../base"
5
+
6
+ module Mapper
7
+ module Notion
8
+ ##
9
+ # This class implementats the methods of the Mapper::Base module, specifically designed for preparing or
10
+ # shaping PTO's data coming from a Fetcher::Base implementation.
11
+ #
12
+ class Pto
13
+ include Base
14
+
15
+ # Implements the logic for shaping the results from a fetcher response.
16
+ #
17
+ # <br>
18
+ # <b>Params:</b>
19
+ # * <tt>Fetcher::Notion::Types::Response</tt> notion_response: Notion response object.
20
+ #
21
+ # <br>
22
+ # <b>returns</b> <tt>List<Domain::Pto></tt> ptos_list, mapped PTO's to be used by a Formatter::Base
23
+ # implementation.
24
+ #
25
+ def map(notion_response)
26
+ return [] if notion_response.results.empty?
27
+
28
+ normalized_notion_data = normalize_response(notion_response.results)
29
+ normalized_notion_data.map do |pto|
30
+ Domain::Pto.new(pto["name"], format_date(pto["start"]), format_date(pto["end"]))
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def normalize_response(response)
37
+ return [] if response.nil?
38
+
39
+ normalized_response = []
40
+
41
+ response.map do |value|
42
+ properties = value["properties"]
43
+ properties.delete("Name")
44
+
45
+ normalized_value = normalize(properties)
46
+
47
+ normalized_response.append(normalized_value)
48
+ end
49
+
50
+ normalized_response
51
+ end
52
+
53
+ def normalize(properties)
54
+ normalized_value = {}
55
+
56
+ properties.each do |k, v|
57
+ extract_pto_fields(k, v, normalized_value)
58
+ end
59
+
60
+ normalized_value
61
+ end
62
+
63
+ def extract_pto_fields(key, value, normalized_value)
64
+ case key
65
+ when "Person"
66
+ user_name = extract_person_field_value(value)
67
+ normalized_value["name"] = user_name
68
+ when "Desde?"
69
+ normalized_value["start"] = extract_date_field_value(value)
70
+ when "Hasta?"
71
+ normalized_value["end"] = extract_date_field_value(value)
72
+ end
73
+ end
74
+
75
+ def extract_person_field_value(data)
76
+ data["people"][0]["name"]
77
+ end
78
+
79
+ def extract_date_field_value(data)
80
+ data["date"]["start"]
81
+ end
82
+
83
+ def format_date(str_date)
84
+ return "" if str_date.nil?
85
+
86
+ if str_date.include?("T")
87
+ format = "%Y-%m-%d|%I:%M %p"
88
+ datetime = Time.new(str_date)
89
+ datetime.strftime(format)
90
+ else
91
+ str_date
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,19 @@
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 :fetcher, :mapper, :formatter, :dispatcher
10
+
11
+ def initialize(fetcher, mapper, formatter, dispatcher)
12
+ @fetcher = fetcher
13
+ @mapper = mapper
14
+ @formatter = formatter
15
+ @dispatcher = dispatcher
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
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 :fetcher, :mapper, :formatter, :dispatcher
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
+ @fetcher = config.fetcher
19
+ @mapper = config.mapper
20
+ @formatter = config.formatter
21
+ @dispatcher = config.dispatcher
22
+ end
23
+
24
+ # Executes the use case by orchestrating the sequential execution of the fetcher, mapper, formatter, and dispatcher.
25
+ #
26
+ # <br>
27
+ # <b>returns</b> <tt>Dispatcher::Discord::Types::Response</tt>
28
+ #
29
+ def perform
30
+ response = fetcher.fetch
31
+
32
+ mappings = mapper.map(response)
33
+
34
+ formatted_payload = formatter.format(mappings)
35
+
36
+ dispatcher.dispatch(formatted_payload)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../fetcher/notion/birthday"
4
+ require_relative "../mapper/notion/birthday"
5
+ require_relative "../formatter/discord/birthday"
6
+
7
+ require_relative "../fetcher/notion/pto"
8
+ require_relative "../mapper/notion/pto"
9
+ require_relative "../formatter/discord/pto"
10
+
11
+ require_relative "../dispatcher/discord/implementation"
12
+ require_relative "use_case"
13
+ require_relative "./types/config"
14
+
15
+ ##
16
+ # This module provides factory methods for use cases within the system. Each method
17
+ # represents a use case implementation introduced in the system.
18
+ #
19
+ module UseCases
20
+ # Provides an instance of the Birthdays notifications from Notion to Discord use case implementation.
21
+ #
22
+ # <b>Example</b>
23
+ #
24
+ # "filter": {
25
+ # "or": [
26
+ # {
27
+ # "property": "BD_this_year",
28
+ # "date": {
29
+ # "equals": today
30
+ # }
31
+ # }
32
+ # ]
33
+ # },
34
+ # "sorts": []
35
+ # }
36
+ #
37
+ # options = {
38
+ # fetch_options: {
39
+ # base_url: "https://api.notion.com",
40
+ # database_id: NOTION_DATABASE_ID,
41
+ # secret: NOTION_API_INTEGRATION_SECRET,
42
+ # filter: filter
43
+ # },
44
+ # dispatch_options: {
45
+ # webhook: "https://discord.com/api/webhooks/1199213527672565760/KmpoIzBet9xYG16oFh8W1RWHbpIqT7UtTBRrhfLcvWZdNiVZCTM-gpil2Qoy4eYEgpdf",
46
+ # name: "Birthday Bot"
47
+ # }
48
+ # }
49
+ #
50
+ # use_case = UseCases.notify_birthday_from_notion_to_discord(options)
51
+ # use_case.perform
52
+ #
53
+ # #################################################################################
54
+ #
55
+ # Requirements:
56
+ # * Notion database ID, from a database with the following structure:
57
+ #
58
+ # _________________________________________________________________________________
59
+ # | Complete Name (text) | BD_this_year (formula) | BD (date) |
60
+ # | -------------------- | --------------------------- | ------------------------ |
61
+ # | John Doe | January 24, 2024 | January 24, 2000 |
62
+ # | Jane Doe | June 20, 2024 | June 20, 2000 |
63
+ # ---------------------------------------------------------------------------------
64
+ # With the following formula for the BD_this_year column:
65
+ # dateAdd(prop("BD"), year(now()) - year(prop("BD")), "years")
66
+ #
67
+ # * A Notion secret, which can be obtained, by creating an integration here: `https://developers.notion.com/`,
68
+ # browsing on the <View my integations> option, and selecting the <New Integration> or <Create new>
69
+ # integration** buttons.
70
+ # * A webhook key, which can be generated directly on discrod on the desired channel, following this instructions:
71
+ # https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
72
+ #
73
+ def self.notify_birthday_from_notion_to_discord(options)
74
+ fetcher = Fetcher::Notion::Birthday.new(options[:fetch_options])
75
+ mapper = Mapper::Notion::Birthday.new
76
+ formatter = Formatter::Discord::Birthday.new
77
+ dispatcher = Dispatcher::Discord::Implementation.new(options[:dispatch_options])
78
+ use_case_cofig = UseCases::Types::Config.new(fetcher, mapper, formatter, dispatcher)
79
+
80
+ UseCases::UseCase.new(use_case_cofig)
81
+ end
82
+
83
+ # Provides an instance of the PTO notifications from Notion to Discord use case implementation.
84
+ #
85
+ # <br>
86
+ # <b>Example</b>
87
+ #
88
+ # "filter": {
89
+ # "and": [
90
+ # {
91
+ # property: "Desde?",
92
+ # date: {
93
+ # "on_or_before": today
94
+ # }
95
+ # },
96
+ # {s
97
+ # property: "Hasta?",
98
+ # date: {
99
+ # "on_or_after": today
100
+ # }
101
+ # }
102
+ # ]
103
+ # },
104
+ # "sorts": []
105
+ # }
106
+ #
107
+ # options = {
108
+ # fetch_options: {
109
+ # base_url: "https://api.notion.com",
110
+ # database_id: NOTION_DATABASE_ID,
111
+ # secret: NOTION_API_INTEGRATION_SECRET,
112
+ # filter: filter
113
+ # },
114
+ # dispatch_options: {
115
+ # webhook: "https://discord.com/api/webhooks/1199213527672565760/KmpoIzBet9xYG16oFh8W1RWHbpIqT7UtTBRrhfLcvWZdNiVZCTM-gpil2Qoy4eYEgpdf",
116
+ # name: "Pto Bot"
117
+ # }
118
+ # }
119
+ #
120
+ # use_case = UseCases.notify_pto_from_notion_to_discord(options)
121
+ # use_case.perform
122
+ #
123
+ # #################################################################################
124
+ #
125
+ # Requirements:
126
+ # * Notion database ID, from a database with the following structure:
127
+ #
128
+ # ________________________________________________________________________________________________________
129
+ # | Person (person) | Desde? (date) | Hasta? (date) |
130
+ # | -------------------- | --------------------------------------- | ------------------------------------ |
131
+ # | John Doe | January 24, 2024 | January 27, 2024 |
132
+ # | Jane Doe | November 11, 2024 2:00 PM | November 11, 2024 6:00 PM |
133
+ # ---------------------------------------------------------------------------------------------------------
134
+ #
135
+ # * A Notion secret, which can be obtained, by creating an integration here: `https://developers.notion.com/`,
136
+ # browsing on the <View my integations> option, and selecting the <New Integration> or <Create new>
137
+ # integration** buttons.
138
+ # * A webhook key, which can be generated directly on discrod on the desired channel, following this instructions:
139
+ # https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
140
+ #
141
+ def self.notify_pto_from_notion_to_discord(options)
142
+ fetcher = Fetcher::Notion::Pto.new(options[:fetch_options])
143
+ mapper = Mapper::Notion::Pto.new
144
+ formatter = Formatter::Discord::Pto.new
145
+ dispatcher = Dispatcher::Discord::Implementation.new(options[:dispatch_options])
146
+ use_case_cofig = UseCases::Types::Config.new(fetcher, mapper, formatter, dispatcher)
147
+
148
+ UseCases::UseCase.new(use_case_cofig)
149
+ end
150
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bns
4
+ # Gem version
5
+ VERSION = "0.1.0"
6
+ end
data/lib/bns.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "bns/version"
4
+ require_relative "bns/use_cases/use_cases"
5
+
6
+ module Bns # rubocop:disable Style/Documentation
7
+ include UseCases
8
+ class Error < StandardError; end
9
+ end
@@ -0,0 +1,4 @@
1
+ module BusinessNotificationSystem
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - kommitters Open Source
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-02-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A versatile business notification system offering key components for
14
+ building various use cases. It provides an easy-to-use tool for implementing
15
+ notifications without excessive complexity.
16
+ email:
17
+ - oss@kommit.co
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".rspec"
23
+ - ".rubocop.yml"
24
+ - CHANGELOG.md
25
+ - CODE_OF_CONDUCT.md
26
+ - CONTRIBUTING.md
27
+ - Gemfile
28
+ - Gemfile.lock
29
+ - LICENSE
30
+ - README.md
31
+ - Rakefile
32
+ - lib/bns.rb
33
+ - lib/bns/dispatcher/base.rb
34
+ - lib/bns/dispatcher/discord/exceptions/invalid_webhook_token.rb
35
+ - lib/bns/dispatcher/discord/implementation.rb
36
+ - lib/bns/dispatcher/discord/types/response.rb
37
+ - lib/bns/domain/birthday.rb
38
+ - lib/bns/domain/exceptions/function_not_implemented.rb
39
+ - lib/bns/domain/pto.rb
40
+ - lib/bns/fetcher/base.rb
41
+ - lib/bns/fetcher/notion/birthday.rb
42
+ - lib/bns/fetcher/notion/exceptions/invalid_api_key.rb
43
+ - lib/bns/fetcher/notion/exceptions/invalid_database_id.rb
44
+ - lib/bns/fetcher/notion/helper.rb
45
+ - lib/bns/fetcher/notion/pto.rb
46
+ - lib/bns/fetcher/notion/types/response.rb
47
+ - lib/bns/formatter/base.rb
48
+ - lib/bns/formatter/discord/birthday.rb
49
+ - lib/bns/formatter/discord/exceptions/invalid_data.rb
50
+ - lib/bns/formatter/discord/pto.rb
51
+ - lib/bns/mapper/base.rb
52
+ - lib/bns/mapper/notion/birthday.rb
53
+ - lib/bns/mapper/notion/pto.rb
54
+ - lib/bns/use_cases/types/config.rb
55
+ - lib/bns/use_cases/use_case.rb
56
+ - lib/bns/use_cases/use_cases.rb
57
+ - lib/bns/version.rb
58
+ - sig/business_notification_system.rbs
59
+ homepage: https://github.com/kommitters/bns
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ homepage_uri: https://github.com/kommitters/bns
64
+ source_code_uri: https://github.com/kommitters/bns
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.6.0
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubygems_version: 3.5.3
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: BNS - Business notification system
84
+ test_files: []