bas 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +9 -0
- data/lib/bas/domain/notification.rb +23 -0
- data/lib/bas/formatter/notification.rb +34 -0
- data/lib/bas/process/discord/implementation.rb +1 -1
- data/lib/bas/process/openai/base.rb +72 -0
- data/lib/bas/process/openai/helper.rb +19 -0
- data/lib/bas/process/openai/types/response.rb +27 -0
- data/lib/bas/process/openai/use_case/humanize_pto.rb +53 -0
- data/lib/bas/process/slack/implementation.rb +1 -1
- data/lib/bas/read/github/types/response.rb +1 -1
- data/lib/bas/read/imap/types/response.rb +1 -1
- data/lib/bas/read/notion/base.rb +1 -1
- data/lib/bas/read/notion/helper.rb +1 -1
- data/lib/bas/read/notion/types/response.rb +1 -1
- data/lib/bas/read/notion/use_case/notification.rb +28 -0
- data/lib/bas/read/notion/use_case/pto_next_week.rb +2 -2
- data/lib/bas/read/postgres/helper.rb +1 -1
- data/lib/bas/read/postgres/types/response.rb +1 -1
- data/lib/bas/serialize/notion/notification.rb +56 -0
- data/lib/bas/use_cases/use_cases.rb +79 -3
- data/lib/bas/version.rb +1 -1
- data/lib/bas/write/notion/base.rb +36 -0
- data/lib/bas/write/notion/use_case/empty_notification.rb +38 -0
- data/lib/bas/write/notion/use_case/notification.rb +38 -0
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f5359b994975192b92fe8582bd37c23e9ce212bbe7d90bd9b93566421f88cd2
|
4
|
+
data.tar.gz: 3d8a0d0f9a8ea9529f3538600a471d32506fa865d45c8e1621d1d3851b6a5682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d88b0b00ca6da83a2168051a685d60bea43766ec677285e129ced8e48dc55660203b8c7994e347f3e043e898838ed6e3910f9e5271f78e22e219a035929f85f9
|
7
|
+
data.tar.gz: 0a01df01e758f0b97931debeedc150045c1ba5f0978fe475ae775139fed7ed1d622cf66f17740f098ddfabf1d29a48511b83cffb67a97316b0dfeea51b2e5694
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -42,6 +42,15 @@ At this point, you're waiting on us. We like to at least comment on pull request
|
|
42
42
|
business days (typically, one business day). We may suggest some changes, improvements or
|
43
43
|
alternatives.
|
44
44
|
|
45
|
+
# Stale issues
|
46
|
+
|
47
|
+
To ensure that our issue tracker remains organized and relevant, we have implemented a policy for handling Stale issues. Please review the following guidelines:
|
48
|
+
|
49
|
+
1. **Marking as Stale**: Issues will be automatically marked as **Stale** after 60 days of inactivity.
|
50
|
+
2. **Closing Stale Issues**: After an issue has been marked as Stale, a comment will be posted on the issue indicating that it will be closed if there is no further activity or information provided within a specified period.
|
51
|
+
|
52
|
+
Thank you for helping us maintain a clean and efficient issue tracker!
|
53
|
+
|
45
54
|
## Resources
|
46
55
|
|
47
56
|
- [How to Contribute to Open Source][oss-how-to]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Domain
|
4
|
+
##
|
5
|
+
# The Domain::Notification class provides a domain-specific representation of a Notification object.
|
6
|
+
# It encapsulates the notification text.
|
7
|
+
#
|
8
|
+
class Notification
|
9
|
+
attr_reader :notification
|
10
|
+
|
11
|
+
ATTRIBUTES = %w[notification].freeze
|
12
|
+
|
13
|
+
# Initializes a Domain::Notification instance with the specified notification text.
|
14
|
+
#
|
15
|
+
# <br>
|
16
|
+
# <b>Params:</b>
|
17
|
+
# * <tt>String</tt> notification
|
18
|
+
#
|
19
|
+
def initialize(notification)
|
20
|
+
@notification = notification
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../domain/notification"
|
4
|
+
require_relative "./exceptions/invalid_data"
|
5
|
+
require_relative "./base"
|
6
|
+
require_relative "./types/response"
|
7
|
+
|
8
|
+
module Formatter
|
9
|
+
##
|
10
|
+
# This class implements methods from the Formatter::Base module, tailored to format the
|
11
|
+
# Domain::Notification structure for a Process.
|
12
|
+
class Notification < Base
|
13
|
+
# Implements the logic for building a formatted notification message
|
14
|
+
#
|
15
|
+
# <br>
|
16
|
+
# <b>Params:</b>
|
17
|
+
# * <tt>List<Domain::Notification></tt> notifications_list: list of serialized notifications.
|
18
|
+
#
|
19
|
+
# <br>
|
20
|
+
# <b>raises</b> <tt>Formatter::Exceptions::InvalidData</tt> when invalid data is provided.
|
21
|
+
#
|
22
|
+
# <br>
|
23
|
+
# <b>returns</b> <tt>Formatter::Types::Response</tt> formatter response: standard output for
|
24
|
+
# the formatted payload suitable for a Process.
|
25
|
+
#
|
26
|
+
def format(notifications_list)
|
27
|
+
raise Formatter::Exceptions::InvalidData unless notifications_list.all? do |notification|
|
28
|
+
notification.is_a?(Domain::Notification)
|
29
|
+
end
|
30
|
+
|
31
|
+
Formatter::Types::Response.new(notifications_list[0].notification)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -41,7 +41,7 @@ module Process
|
|
41
41
|
|
42
42
|
body = post_body(response.data)
|
43
43
|
|
44
|
-
response = HTTParty.post(webhook, { body
|
44
|
+
response = HTTParty.post(webhook, { body:, headers: { "Content-Type" => "application/json" } })
|
45
45
|
|
46
46
|
discord_response = Process::Discord::Types::Response.new(response)
|
47
47
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httparty"
|
4
|
+
|
5
|
+
require_relative "../base"
|
6
|
+
require_relative "./types/response"
|
7
|
+
require_relative "./helper"
|
8
|
+
|
9
|
+
module Process
|
10
|
+
module OpenAI
|
11
|
+
##
|
12
|
+
# This class is an implementation of the Process::Base interface, specifically designed
|
13
|
+
# for requesting to the OpenAI API for chat completion.
|
14
|
+
#
|
15
|
+
class Base < Process::Base
|
16
|
+
OPENAI_BASE_URL = "https://api.openai.com"
|
17
|
+
DEFAULT_N_CHOICES = 1
|
18
|
+
|
19
|
+
# Initializes the process with essential configuration parameters.
|
20
|
+
#
|
21
|
+
def initialize(config = {})
|
22
|
+
super(config)
|
23
|
+
|
24
|
+
@n_choices = config[:n_choices] || DEFAULT_N_CHOICES
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# Implements the sending process logic for the OpenAI API. It sends a
|
30
|
+
# POST request to the OpenAI API for chat completion with the specified payload.
|
31
|
+
#
|
32
|
+
# <br>
|
33
|
+
# <b>Params:</b>
|
34
|
+
# * <tt>Formatter::Types::Response</tt> formatter response: standard formatter response
|
35
|
+
# with the data to be send to OpenAI.
|
36
|
+
# <br>
|
37
|
+
# <b>raises</b> <tt>StandardError</tt> if the API returns an error response
|
38
|
+
#
|
39
|
+
# <br>
|
40
|
+
# <b>returns</b> <tt>Process::Types::Response</tt>
|
41
|
+
#
|
42
|
+
def process(messages)
|
43
|
+
url = "#{OPENAI_BASE_URL}/v1/chat/completions"
|
44
|
+
|
45
|
+
httparty_response = HTTParty.post(url, { body: body(messages).to_json, headers: })
|
46
|
+
|
47
|
+
openai_response = Process::OpenAI::Types::Response.new(httparty_response)
|
48
|
+
|
49
|
+
response = Process::OpenAI::Helper.validate_response(openai_response)
|
50
|
+
|
51
|
+
Process::Types::Response.new(response)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def body(messages)
|
57
|
+
{
|
58
|
+
"model": config[:model],
|
59
|
+
"n": @n_choices,
|
60
|
+
"messages": messages
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def headers
|
65
|
+
{
|
66
|
+
"Authorization" => "Bearer #{config[:secret]}",
|
67
|
+
"Content-Type" => "application/json"
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Process
|
4
|
+
module OpenAI
|
5
|
+
##
|
6
|
+
# Provides common fuctionalities along the Process::OpenAI domain.
|
7
|
+
#
|
8
|
+
module Helper
|
9
|
+
def self.validate_response(response)
|
10
|
+
case response.status_code
|
11
|
+
when 200
|
12
|
+
response
|
13
|
+
else
|
14
|
+
raise StandardError, response.message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Process
|
4
|
+
module OpenAI
|
5
|
+
module Types
|
6
|
+
##
|
7
|
+
# Represents a response received from the OpenAI chat completion service API. It encapsulates
|
8
|
+
# essential information about the response, providing a structured way to handle and analyze
|
9
|
+
# its responses.
|
10
|
+
class Response
|
11
|
+
attr_reader :status_code, :message, :choices
|
12
|
+
|
13
|
+
def initialize(response)
|
14
|
+
if response["error"]
|
15
|
+
@status_code = response.code
|
16
|
+
@message = response["error"]
|
17
|
+
@choices = []
|
18
|
+
else
|
19
|
+
@status_code = 200
|
20
|
+
@message = "success"
|
21
|
+
@choices = response["choices"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Process
|
6
|
+
module OpenAI
|
7
|
+
##
|
8
|
+
# This class is an implementation of the Process::OpenAI::Base interface, specifically designed
|
9
|
+
# to humanize formatted PTO messages for better understanding.
|
10
|
+
#
|
11
|
+
class HumanizePto < OpenAI::Base
|
12
|
+
# Implements the data process to humanize formatted PTO messages.
|
13
|
+
#
|
14
|
+
def execute(format_response)
|
15
|
+
messages = [
|
16
|
+
{
|
17
|
+
"role": "user",
|
18
|
+
"content": content(format_response.data)
|
19
|
+
}
|
20
|
+
]
|
21
|
+
|
22
|
+
process(messages)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def content(data)
|
28
|
+
<<~MESSAGE
|
29
|
+
The following message is too complex for a human to read since it has specific dates formatted as YYYY-MM-DD:
|
30
|
+
|
31
|
+
\"#{data}\"
|
32
|
+
|
33
|
+
Create a text that gives the same message in a more human-readable and context-valuable fashion for a human.
|
34
|
+
Use the current date (#{current_date}) to provide context.
|
35
|
+
Try grouping information and using bullet points to make it easier to read the information at a quick glance.
|
36
|
+
Additionally, keep in mind that we work from Monday to Friday - not weekends.
|
37
|
+
Please, just give the PTOs message and avoid the intro message such as \"Here is a reader-friendly message\".
|
38
|
+
Add emojis for a cool message, but keep it seriously.
|
39
|
+
|
40
|
+
For example:
|
41
|
+
The input "Jane Doe is on PTO from 2024-04-08 to 2024-04-26", means that Jane will be on PTO starting at 2024-04-08
|
42
|
+
and ending at 2024-04-26, i.e, she will be back the next work-day which is 2024-04-29.
|
43
|
+
MESSAGE
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_date
|
47
|
+
utc_today = Time.now.utc
|
48
|
+
|
49
|
+
Time.at(utc_today, in: config[:timezone]).strftime("%A, %F").to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -41,7 +41,7 @@ module Process
|
|
41
41
|
|
42
42
|
body = post_body(response.data)
|
43
43
|
|
44
|
-
response = HTTParty.post(webhook, { body
|
44
|
+
response = HTTParty.post(webhook, { body:, headers: { "Content-Type" => "application/json" } })
|
45
45
|
|
46
46
|
slack_response = Process::Discord::Types::Response.new(response)
|
47
47
|
|
@@ -6,7 +6,7 @@ module Read
|
|
6
6
|
##
|
7
7
|
# Represents a response received from the Octokit Github client. It encapsulates essential
|
8
8
|
# information about the response, providing a structured way to handle and analyze
|
9
|
-
#
|
9
|
+
# its responses.
|
10
10
|
class Response
|
11
11
|
attr_reader :status_code, :message, :results
|
12
12
|
|
@@ -6,7 +6,7 @@ module Read
|
|
6
6
|
##
|
7
7
|
# Represents a response received from the Imap client. It encapsulates essential
|
8
8
|
# information about the response, providing a structured way to handle and analyze
|
9
|
-
#
|
9
|
+
# its responses.
|
10
10
|
class Response
|
11
11
|
attr_reader :status_code, :message, :results
|
12
12
|
|
data/lib/bas/read/notion/base.rb
CHANGED
@@ -31,7 +31,7 @@ module Read
|
|
31
31
|
def read(filter)
|
32
32
|
url = "#{NOTION_BASE_URL}/v1/databases/#{config[:database_id]}/query"
|
33
33
|
|
34
|
-
httparty_response = HTTParty.post(url, { body: filter.to_json, headers:
|
34
|
+
httparty_response = HTTParty.post(url, { body: filter.to_json, headers: })
|
35
35
|
|
36
36
|
notion_response = Read::Notion::Types::Response.new(httparty_response)
|
37
37
|
|
@@ -5,7 +5,7 @@ module Read
|
|
5
5
|
module Types
|
6
6
|
##
|
7
7
|
# Represents a response received from the Notion API. It encapsulates essential information about the response,
|
8
|
-
# providing a structured way to handle and analyze
|
8
|
+
# providing a structured way to handle and analyze its responses.
|
9
9
|
class Response
|
10
10
|
attr_reader :status_code, :message, :results
|
11
11
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Read
|
6
|
+
module Notion
|
7
|
+
##
|
8
|
+
# This class is an implementation of the Read::Notion::Base interface, specifically designed
|
9
|
+
# for reading Notification data from Notion.
|
10
|
+
#
|
11
|
+
class Notification < Notion::Base
|
12
|
+
# Implements the reading filter for notification data from Notion.
|
13
|
+
#
|
14
|
+
def execute
|
15
|
+
filter = {
|
16
|
+
filter: {
|
17
|
+
property: "Use Case",
|
18
|
+
title: {
|
19
|
+
equals: config[:use_case_title]
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
read(filter)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -52,8 +52,8 @@ module Read
|
|
52
52
|
def belong_next_week(property, after_day, before_day)
|
53
53
|
{
|
54
54
|
and: [
|
55
|
-
{ property
|
56
|
-
{ property
|
55
|
+
{ property:, date: { on_or_after: after_day } },
|
56
|
+
{ property:, date: { on_or_before: before_day } }
|
57
57
|
]
|
58
58
|
}
|
59
59
|
end
|
@@ -5,7 +5,7 @@ module Read
|
|
5
5
|
module Types
|
6
6
|
##
|
7
7
|
# Represents a response received from the Postgres API. It encapsulates essential information about the response,
|
8
|
-
# providing a structured way to handle and analyze
|
8
|
+
# providing a structured way to handle and analyze its responses.
|
9
9
|
class Response
|
10
10
|
attr_reader :status, :message, :response, :fields, :records
|
11
11
|
|
@@ -0,0 +1,56 @@
|
|
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
|
@@ -5,6 +5,7 @@ require_relative "../read/notion/use_case/birthday_today"
|
|
5
5
|
require_relative "../read/notion/use_case/birthday_next_week"
|
6
6
|
require_relative "../read/notion/use_case/pto_today"
|
7
7
|
require_relative "../read/notion/use_case/pto_next_week"
|
8
|
+
require_relative "../read/notion/use_case/notification"
|
8
9
|
require_relative "../read/notion/use_case/work_items_limit"
|
9
10
|
require_relative "../read/postgres/use_case/pto_today"
|
10
11
|
require_relative "../read/imap/use_case/support_emails"
|
@@ -14,6 +15,7 @@ require_relative "../read/github/use_case/repo_issues"
|
|
14
15
|
require_relative "../serialize/notion/birthday_today"
|
15
16
|
require_relative "../serialize/notion/pto_today"
|
16
17
|
require_relative "../serialize/notion/work_items_limit"
|
18
|
+
require_relative "../serialize/notion/notification"
|
17
19
|
require_relative "../serialize/postgres/pto_today"
|
18
20
|
require_relative "../serialize/imap/support_emails"
|
19
21
|
require_relative "../serialize/github/issues"
|
@@ -23,13 +25,17 @@ require_relative "../formatter/birthday"
|
|
23
25
|
require_relative "../formatter/pto"
|
24
26
|
require_relative "../formatter/work_items_limit"
|
25
27
|
require_relative "../formatter/support_emails"
|
28
|
+
require_relative "../formatter/notification"
|
26
29
|
|
27
30
|
# process
|
28
31
|
require_relative "../process/discord/implementation"
|
29
32
|
require_relative "../process/slack/implementation"
|
33
|
+
require_relative "../process/openai/use_case/humanize_pto"
|
30
34
|
|
31
35
|
# write
|
32
36
|
require_relative "../write/logs/use_case/console_log"
|
37
|
+
require_relative "../write/notion/use_case/notification"
|
38
|
+
require_relative "../write/notion/use_case/empty_notification"
|
33
39
|
|
34
40
|
require_relative "use_case"
|
35
41
|
require_relative "./types/config"
|
@@ -150,10 +156,19 @@ module UseCases
|
|
150
156
|
# read_options: {
|
151
157
|
# database_id: NOTION_DATABASE_ID,
|
152
158
|
# secret: NOTION_API_INTEGRATION_SECRET,
|
159
|
+
# use_case_title: "PTO"
|
160
|
+
# },
|
161
|
+
# format_options: {
|
162
|
+
# template: ":beach: individual_name is on PTO",
|
163
|
+
# timezone: "-05:00"
|
153
164
|
# },
|
154
165
|
# process_options: {
|
155
166
|
# webhook: "https://discord.com/api/webhooks/1199213527672565760/KmpoIzBet9xYG16oFh8W1RWHbpIqT7UtTBRrhfLcvWZdNiVZCTM-gpil2Qoy4eYEgpdf",
|
156
|
-
# name: "
|
167
|
+
# name: "notificationBOT"
|
168
|
+
# },
|
169
|
+
# write_options: {
|
170
|
+
# secret: NOTION_API_INTEGRATION_SECRET,
|
171
|
+
# page_id: WRITE_NOTION_PAGE_ID
|
157
172
|
# }
|
158
173
|
# }
|
159
174
|
#
|
@@ -172,6 +187,8 @@ module UseCases
|
|
172
187
|
# | Jane Doe | November 11, 2024 2:00 PM | November 11, 2024 6:00 PM |
|
173
188
|
# ---------------------------------------------------------------------------------------------------------
|
174
189
|
#
|
190
|
+
# * Write Notion page ID, from a page with a "Notification" text property.
|
191
|
+
# This property will be updated with the humanized notification.
|
175
192
|
# * A Notion secret, which can be obtained, by creating an integration here: `https://developers.notion.com/`,
|
176
193
|
# browsing on the <View my integations> option, and selecting the <New Integration> or <Create new>
|
177
194
|
# integration** buttons.
|
@@ -179,11 +196,70 @@ module UseCases
|
|
179
196
|
# https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
|
180
197
|
#
|
181
198
|
def self.notify_pto_from_notion_to_discord(options)
|
199
|
+
read = Read::Notion::Notification.new(options[:read_options])
|
200
|
+
serialize = Serialize::Notion::Notification.new
|
201
|
+
formatter = Formatter::Notification.new(options[:format_options])
|
202
|
+
process = Process::Discord::Implementation.new(options[:process_options])
|
203
|
+
write = Write::Notion::EmptyNotification.new(options[:write_options])
|
204
|
+
|
205
|
+
use_case_config = UseCases::Types::Config.new(read, serialize, formatter, process, write)
|
206
|
+
|
207
|
+
UseCases::UseCase.new(use_case_config)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Provides an instance of the humanized PTO write from Notion to Notion use case implementation.
|
211
|
+
#
|
212
|
+
# <br>
|
213
|
+
# <b>Example</b>
|
214
|
+
#
|
215
|
+
# options = {
|
216
|
+
# read_options: {
|
217
|
+
# database_id: READ_NOTION_DATABASE_ID,
|
218
|
+
# secret: NOTION_API_INTEGRATION_SECRET
|
219
|
+
# },
|
220
|
+
# format_options: {
|
221
|
+
# template: ":beach: individual_name is on PTO",
|
222
|
+
# timezone: "-05:00"
|
223
|
+
# },
|
224
|
+
# process_options: {
|
225
|
+
# secret: OPENAI_API_SECRET_KEY,
|
226
|
+
# model: "gpt-4",
|
227
|
+
# timezone: "-05:00"
|
228
|
+
# },
|
229
|
+
# write_options: {
|
230
|
+
# secret: NOTION_API_INTEGRATION_SECRET,
|
231
|
+
# page_id: WRITE_NOTION_PAGE_ID,
|
232
|
+
# }
|
233
|
+
# }
|
234
|
+
#
|
235
|
+
# use_case = UseCases.write_humanized_pto_from_notion_to_notion(options)
|
236
|
+
# use_case.perform
|
237
|
+
#
|
238
|
+
# #################################################################################
|
239
|
+
#
|
240
|
+
# Requirements:
|
241
|
+
# * Read Notion database ID, from a database with the following structure:
|
242
|
+
#
|
243
|
+
# ________________________________________________________________________________________________________
|
244
|
+
# | Person (person) | Desde? (date) | Hasta? (date) |
|
245
|
+
# | -------------------- | --------------------------------------- | ------------------------------------ |
|
246
|
+
# | John Doe | January 24, 2024 | January 27, 2024 |
|
247
|
+
# | Jane Doe | November 11, 2024 2:00 PM | November 11, 2024 6:00 PM |
|
248
|
+
# ---------------------------------------------------------------------------------------------------------
|
249
|
+
#
|
250
|
+
# * Write Notion page ID, from a page with a "Notification" text property.
|
251
|
+
# This property will be updated with the humanized notification.
|
252
|
+
# * A Notion secret, which can be obtained, by creating an integration here: `https://developers.notion.com/`,
|
253
|
+
# browsing on the <View my integations> option, and selecting the <New Integration> or <Create new>
|
254
|
+
# integration** buttons. This should have permission to update.
|
255
|
+
#
|
256
|
+
def self.write_humanized_pto_from_notion_to_notion(options)
|
182
257
|
read = Read::Notion::PtoToday.new(options[:read_options])
|
183
258
|
serialize = Serialize::Notion::PtoToday.new
|
184
259
|
formatter = Formatter::Pto.new(options[:format_options])
|
185
|
-
process = Process::
|
186
|
-
write = Write::
|
260
|
+
process = Process::OpenAI::HumanizePto.new(options[:process_options])
|
261
|
+
write = Write::Notion::Notification.new(options[:write_options])
|
262
|
+
|
187
263
|
use_case_config = UseCases::Types::Config.new(read, serialize, formatter, process, write)
|
188
264
|
|
189
265
|
UseCases::UseCase.new(use_case_config)
|
data/lib/bas/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Write
|
6
|
+
module Notion
|
7
|
+
##
|
8
|
+
# This class is an implementation of the Write::Base interface, specifically designed
|
9
|
+
# to create or update pages in a Notion database.
|
10
|
+
#
|
11
|
+
class Base < Write::Base
|
12
|
+
NOTION_BASE_URL = "https://api.notion.com"
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
# Implements the writing logic to create or update pages in a Notion.database. It sends
|
17
|
+
# a request to the Notion API given the method (post, patch, etc), endpoint and body.
|
18
|
+
#
|
19
|
+
def write(method, endpoint, body)
|
20
|
+
url = "#{NOTION_BASE_URL}#{endpoint}"
|
21
|
+
|
22
|
+
HTTParty.send(method, url, { body: body.to_json, headers: })
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def headers
|
28
|
+
{
|
29
|
+
"Authorization" => "Bearer #{config[:secret]}",
|
30
|
+
"Content-Type" => "application/json",
|
31
|
+
"Notion-Version" => "2022-06-28"
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Write
|
6
|
+
module Notion
|
7
|
+
##
|
8
|
+
# This class is an implementation of the Write::Notion::Base interface, specifically designed
|
9
|
+
# to update an existing page in a Notion database to write an empty text.
|
10
|
+
class EmptyNotification < Notion::Base
|
11
|
+
# Implements the writting process logic for the Notification use case.
|
12
|
+
#
|
13
|
+
# <br>
|
14
|
+
# <b>Params:</b>
|
15
|
+
# * <tt>Process::Types::Response</tt> process response: standard process response.
|
16
|
+
#
|
17
|
+
def execute(_process_response)
|
18
|
+
endpoint = "/v1/pages/#{config[:page_id]}"
|
19
|
+
|
20
|
+
body = body("")
|
21
|
+
|
22
|
+
write("patch", endpoint, body)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def body(content)
|
28
|
+
{
|
29
|
+
properties: {
|
30
|
+
Notification: {
|
31
|
+
rich_text: [{ text: { content: } }]
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Write
|
6
|
+
module Notion
|
7
|
+
##
|
8
|
+
# This class is an implementation of the Write::OpenAI::Base interface, specifically designed
|
9
|
+
# to update an existing page on a Notion database to write the notification text.
|
10
|
+
class Notification < Notion::Base
|
11
|
+
# Implements the writting process logic for the Notification use case.
|
12
|
+
#
|
13
|
+
# <br>
|
14
|
+
# <b>Params:</b>
|
15
|
+
# * <tt>Process::Types::Response</tt> process response: standard process response with the data to be updated.
|
16
|
+
#
|
17
|
+
def execute(process_response)
|
18
|
+
endpoint = "/v1/pages/#{config[:page_id]}"
|
19
|
+
|
20
|
+
body = body(process_response.data.choices[0]["message"]["content"])
|
21
|
+
|
22
|
+
write("patch", endpoint, body)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def body(content)
|
28
|
+
{
|
29
|
+
properties: {
|
30
|
+
Notification: {
|
31
|
+
rich_text: [{ text: { content: } }]
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kommitters Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A versatile business automation system offering key components for building
|
14
14
|
various use cases. It provides an easy-to-use tool for implementing automation
|
@@ -35,11 +35,13 @@ files:
|
|
35
35
|
- lib/bas/domain/email.rb
|
36
36
|
- lib/bas/domain/exceptions/function_not_implemented.rb
|
37
37
|
- lib/bas/domain/issue.rb
|
38
|
+
- lib/bas/domain/notification.rb
|
38
39
|
- lib/bas/domain/pto.rb
|
39
40
|
- lib/bas/domain/work_items_limit.rb
|
40
41
|
- lib/bas/formatter/base.rb
|
41
42
|
- lib/bas/formatter/birthday.rb
|
42
43
|
- lib/bas/formatter/exceptions/invalid_data.rb
|
44
|
+
- lib/bas/formatter/notification.rb
|
43
45
|
- lib/bas/formatter/pto.rb
|
44
46
|
- lib/bas/formatter/support_emails.rb
|
45
47
|
- lib/bas/formatter/types/response.rb
|
@@ -48,6 +50,10 @@ files:
|
|
48
50
|
- lib/bas/process/discord/exceptions/invalid_webhook_token.rb
|
49
51
|
- lib/bas/process/discord/implementation.rb
|
50
52
|
- lib/bas/process/discord/types/response.rb
|
53
|
+
- lib/bas/process/openai/base.rb
|
54
|
+
- lib/bas/process/openai/helper.rb
|
55
|
+
- lib/bas/process/openai/types/response.rb
|
56
|
+
- lib/bas/process/openai/use_case/humanize_pto.rb
|
51
57
|
- lib/bas/process/slack/exceptions/invalid_webhook_token.rb
|
52
58
|
- lib/bas/process/slack/implementation.rb
|
53
59
|
- lib/bas/process/slack/types/response.rb
|
@@ -66,6 +72,7 @@ files:
|
|
66
72
|
- lib/bas/read/notion/types/response.rb
|
67
73
|
- lib/bas/read/notion/use_case/birthday_next_week.rb
|
68
74
|
- lib/bas/read/notion/use_case/birthday_today.rb
|
75
|
+
- lib/bas/read/notion/use_case/notification.rb
|
69
76
|
- lib/bas/read/notion/use_case/pto_next_week.rb
|
70
77
|
- lib/bas/read/notion/use_case/pto_today.rb
|
71
78
|
- lib/bas/read/notion/use_case/work_items_limit.rb
|
@@ -77,6 +84,7 @@ files:
|
|
77
84
|
- lib/bas/serialize/github/issues.rb
|
78
85
|
- lib/bas/serialize/imap/support_emails.rb
|
79
86
|
- lib/bas/serialize/notion/birthday_today.rb
|
87
|
+
- lib/bas/serialize/notion/notification.rb
|
80
88
|
- lib/bas/serialize/notion/pto_today.rb
|
81
89
|
- lib/bas/serialize/notion/work_items_limit.rb
|
82
90
|
- lib/bas/serialize/postgres/pto_today.rb
|
@@ -87,6 +95,9 @@ files:
|
|
87
95
|
- lib/bas/write/base.rb
|
88
96
|
- lib/bas/write/logs/base.rb
|
89
97
|
- lib/bas/write/logs/use_case/console_log.rb
|
98
|
+
- lib/bas/write/notion/base.rb
|
99
|
+
- lib/bas/write/notion/use_case/empty_notification.rb
|
100
|
+
- lib/bas/write/notion/use_case/notification.rb
|
90
101
|
- renovate.json
|
91
102
|
- sig/business_automation_system.rbs
|
92
103
|
homepage: https://github.com/kommitters/bas
|
@@ -103,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
114
|
requirements:
|
104
115
|
- - ">="
|
105
116
|
- !ruby/object:Gem::Version
|
106
|
-
version:
|
117
|
+
version: 3.1.0
|
107
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
119
|
requirements:
|
109
120
|
- - ">="
|