bns 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/CHANGELOG.md +11 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +91 -0
- data/LICENSE +21 -0
- data/README.md +198 -0
- data/Rakefile +12 -0
- data/lib/bns/dispatcher/base.rb +31 -0
- data/lib/bns/dispatcher/discord/exceptions/invalid_webhook_token.rb +16 -0
- data/lib/bns/dispatcher/discord/implementation.rb +51 -0
- data/lib/bns/dispatcher/discord/types/response.rb +22 -0
- data/lib/bns/domain/birthday.rb +23 -0
- data/lib/bns/domain/exceptions/function_not_implemented.rb +18 -0
- data/lib/bns/domain/pto.rb +26 -0
- data/lib/bns/fetcher/base.rb +30 -0
- data/lib/bns/fetcher/notion/birthday.rb +53 -0
- data/lib/bns/fetcher/notion/exceptions/invalid_api_key.rb +15 -0
- data/lib/bns/fetcher/notion/exceptions/invalid_database_id.rb +15 -0
- data/lib/bns/fetcher/notion/helper.rb +21 -0
- data/lib/bns/fetcher/notion/pto.rb +48 -0
- data/lib/bns/fetcher/notion/types/response.rb +26 -0
- data/lib/bns/formatter/base.rb +29 -0
- data/lib/bns/formatter/discord/birthday.rb +43 -0
- data/lib/bns/formatter/discord/exceptions/invalid_data.rb +17 -0
- data/lib/bns/formatter/discord/pto.rb +52 -0
- data/lib/bns/mapper/base.rb +30 -0
- data/lib/bns/mapper/notion/birthday.rb +76 -0
- data/lib/bns/mapper/notion/pto.rb +96 -0
- data/lib/bns/use_cases/types/config.rb +19 -0
- data/lib/bns/use_cases/use_case.rb +39 -0
- data/lib/bns/use_cases/use_cases.rb +150 -0
- data/lib/bns/version.rb +6 -0
- data/lib/bns.rb +9 -0
- data/sig/business_notification_system.rbs +4 -0
- 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
|
data/lib/bns/version.rb
ADDED
data/lib/bns.rb
ADDED
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: []
|