bas 1.1.3 → 1.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -0
- data/lib/bas/bot/fetch_billing_from_digital_ocean.rb +77 -0
- data/lib/bas/bot/format_do_bill_alert.rb +103 -0
- data/lib/bas/bot/notify_do_bill_alert_email.rb +94 -0
- data/lib/bas/utils/digital_ocean/request.rb +43 -0
- data/lib/bas/utils/google/send_email.rb +72 -0
- data/lib/bas/version.rb +1 -1
- metadata +37 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3574c150bdecb2fd88551db1b4add9bd5d0458d6b44eec87bd2c3efd44ff8a83
|
4
|
+
data.tar.gz: ffeac8bae610aec6449161f9c267385e84921141d953f98175a05c6186f2e641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8588edfeb8aec0ec204a040e79bd801d1563bf45b94b7ccd50c89ed160a2a2334f4285cd54d5c001228a9de5d14d02a64800c36b10b54f31d01ed1c877c0ae34
|
7
|
+
data.tar.gz: 921b8280f7c071a8aaa7752b99b0fffabb0e1e434f6b051433a44d49f2c137e5092889250f7301e41b678ca763e9f445237a4252bb22a0731920f4731536006e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
# 1.2.1 (16.07.2024)
|
4
|
+
- [Update format message for the digital ocean alert bots use case](https://github.com/kommitters/bas/pull/84)
|
5
|
+
|
6
|
+
# 1.2.0 (12.07.2024)
|
7
|
+
- [Add bots to process digital ocean billing checker](https://github.com/kommitters/bas/issues/78)
|
8
|
+
|
3
9
|
# 1.1.3 (08.07.2024)
|
4
10
|
- [Update write media request to set in process](https://github.com/kommitters/bas/issues/76)
|
5
11
|
|
data/Gemfile
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base"
|
4
|
+
require_relative "../read/default"
|
5
|
+
require_relative "../utils/digital_ocean/request"
|
6
|
+
require_relative "../write/postgres"
|
7
|
+
|
8
|
+
module Bot
|
9
|
+
##
|
10
|
+
# The Bot::FetchBillingFromDigitalOcean class serves as a bot implementation to read digital
|
11
|
+
# ocean current billing using the DigitalOcean API
|
12
|
+
#
|
13
|
+
# <br>
|
14
|
+
# <b>Example</b>
|
15
|
+
#
|
16
|
+
# options = {
|
17
|
+
# process_options: {
|
18
|
+
# secret: "digital_ocean_secret_key"
|
19
|
+
# },
|
20
|
+
# write_options: {
|
21
|
+
# connection: {
|
22
|
+
# host: "host",
|
23
|
+
# port: 5432,
|
24
|
+
# dbname: "bas",
|
25
|
+
# user: "postgres",
|
26
|
+
# password: "postgres"
|
27
|
+
# },
|
28
|
+
# db_table: "use_cases",
|
29
|
+
# tag: "FetchBillingFromDigitalOcean"
|
30
|
+
# }
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
# bot = Bot::FetchBillingFromDigitalOcean.new(options)
|
34
|
+
# bot.execute
|
35
|
+
#
|
36
|
+
class FetchBillingFromDigitalOcean < Bot::Base
|
37
|
+
# Read function to execute the default Read component
|
38
|
+
#
|
39
|
+
def read
|
40
|
+
reader = Read::Default.new
|
41
|
+
|
42
|
+
reader.execute
|
43
|
+
end
|
44
|
+
|
45
|
+
# Process function to execute the DigitalOcean utility to fetch bills
|
46
|
+
#
|
47
|
+
def process
|
48
|
+
response = Utils::DigitalOcean::Request.execute(params)
|
49
|
+
|
50
|
+
if response.code == 200
|
51
|
+
|
52
|
+
{ success: { billing: response.parsed_response } }
|
53
|
+
else
|
54
|
+
{ error: { message: response.parsed_response, status_code: response.code } }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Write function to execute the PostgresDB write component
|
59
|
+
#
|
60
|
+
def write
|
61
|
+
write = Write::Postgres.new(write_options, process_response)
|
62
|
+
|
63
|
+
write.execute
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def params
|
69
|
+
{
|
70
|
+
endpoint: "customers/my/balance",
|
71
|
+
secret: process_options[:secret],
|
72
|
+
method: "get",
|
73
|
+
body: {}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base"
|
4
|
+
require_relative "../read/postgres"
|
5
|
+
require_relative "../write/postgres"
|
6
|
+
|
7
|
+
module Bot
|
8
|
+
##
|
9
|
+
# The Bot::FormatDoBillAlert class serves as a bot implementation to format DigitalOcean bill
|
10
|
+
# alerts from a PostgresDB database, format them with a specific template, and write them on a
|
11
|
+
# PostgresDB table with a specific format.
|
12
|
+
#
|
13
|
+
# <br>
|
14
|
+
# <b>Example</b>
|
15
|
+
#
|
16
|
+
# options = {
|
17
|
+
# read_options: {
|
18
|
+
# connection: {
|
19
|
+
# host: "localhost",
|
20
|
+
# port: 5432,
|
21
|
+
# dbname: "bas",
|
22
|
+
# user: "postgres",
|
23
|
+
# password: "postgres"
|
24
|
+
# },
|
25
|
+
# db_table: "do_billing",
|
26
|
+
# tag: "FetchBillingFromDigitalOcean"
|
27
|
+
# },
|
28
|
+
# process_options: {
|
29
|
+
# threshold: 7
|
30
|
+
# },
|
31
|
+
# write_options: {
|
32
|
+
# connection: {
|
33
|
+
# host: "localhost",
|
34
|
+
# port: 5432,
|
35
|
+
# dbname: "bas",
|
36
|
+
# user: "postgres",
|
37
|
+
# password: "postgres"
|
38
|
+
# },
|
39
|
+
# db_table: "do_billing",
|
40
|
+
# tag: "FormatDoBillAlert"
|
41
|
+
# }
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# bot = Bot::FormatDoBillAlert.new(options)
|
45
|
+
# bot.execute
|
46
|
+
#
|
47
|
+
class FormatDoBillAlert < Bot::Base
|
48
|
+
# read function to execute the PostgresDB Read component
|
49
|
+
#
|
50
|
+
def read
|
51
|
+
reader = Read::Postgres.new(read_options.merge(conditions))
|
52
|
+
|
53
|
+
reader.execute
|
54
|
+
end
|
55
|
+
|
56
|
+
# Process function to format the notification using a template
|
57
|
+
#
|
58
|
+
def process
|
59
|
+
return { success: { notification: "" } } if unprocessable_response || !threshold_exceeded
|
60
|
+
|
61
|
+
{ success: { notification: message } }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Write function to execute the PostgresDB write component
|
65
|
+
#
|
66
|
+
def write
|
67
|
+
write = Write::Postgres.new(write_options, process_response)
|
68
|
+
|
69
|
+
write.execute
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def conditions
|
75
|
+
{
|
76
|
+
where: "archived=$1 AND tag=$2 AND stage=$3 ORDER BY inserted_at ASC",
|
77
|
+
params: [false, read_options[:tag], "unprocessed"]
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def threshold_exceeded
|
82
|
+
daily_usage > process_options[:threshold]
|
83
|
+
end
|
84
|
+
|
85
|
+
def daily_usage
|
86
|
+
balance = read_response.data["billing"]["month_to_date_balance"].to_f
|
87
|
+
day_of_month = Time.now.utc.mday
|
88
|
+
|
89
|
+
balance / day_of_month
|
90
|
+
end
|
91
|
+
|
92
|
+
def message
|
93
|
+
balance = read_response.data["billing"]["month_to_date_balance"]
|
94
|
+
threshold = process_options[:threshold]
|
95
|
+
|
96
|
+
""":warning: The **DigitalOcean** daily usage was exceeded.
|
97
|
+
Current balance: #{balance}
|
98
|
+
Threshold: #{threshold}
|
99
|
+
Current daily usage: #{daily_usage.round(3)}
|
100
|
+
"""
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base"
|
4
|
+
require_relative "../read/postgres"
|
5
|
+
require_relative "../write/postgres"
|
6
|
+
require_relative "../utils/google/send_email"
|
7
|
+
|
8
|
+
module Bot
|
9
|
+
##
|
10
|
+
# The Bot::NotifyDoBillAlertEmail class serves as a bot implementation to send digital
|
11
|
+
# ocean daily bill exceeded alert emails to a recipient using a google account
|
12
|
+
#
|
13
|
+
# <br>
|
14
|
+
# <b>Example</b>
|
15
|
+
#
|
16
|
+
# options = {
|
17
|
+
# read_options: {
|
18
|
+
# connection: {
|
19
|
+
# host: "localhost",
|
20
|
+
# port: 5432,
|
21
|
+
# dbname: "bas",
|
22
|
+
# user: "postgres",
|
23
|
+
# password: "postgres"
|
24
|
+
# },
|
25
|
+
# db_table: "do_billing",
|
26
|
+
# tag: "FetchBillingFromDigitalOcean"
|
27
|
+
# },
|
28
|
+
# process_options: {
|
29
|
+
# refresh_token: "email server refresh token",
|
30
|
+
# client_id: "email server client it",
|
31
|
+
# client_secret: "email server client secret",
|
32
|
+
# user_email: "sender@mail.com",
|
33
|
+
# recipient_email: "recipient@mail.com",
|
34
|
+
# threshold: "THRESHOLD"
|
35
|
+
# },
|
36
|
+
# write_options: {
|
37
|
+
# connection: {
|
38
|
+
# host: "localhost",
|
39
|
+
# port: 5432,
|
40
|
+
# dbname: "bas",
|
41
|
+
# user: "postgres",
|
42
|
+
# password: "postgres"
|
43
|
+
# },
|
44
|
+
# db_table: "do_billing",
|
45
|
+
# tag: "NotifyDoBillAlertEmail"
|
46
|
+
# }
|
47
|
+
# }
|
48
|
+
#
|
49
|
+
# bot = Bot::NotifyDoBillAlertEmail.new(options)
|
50
|
+
# bot.execute
|
51
|
+
#
|
52
|
+
class NotifyDoBillAlertEmail < Bot::Base
|
53
|
+
SUBJECT = "Digital Ocean Daily Threshold Alert"
|
54
|
+
|
55
|
+
# read function to execute the PostgresDB Read component
|
56
|
+
#
|
57
|
+
def read
|
58
|
+
reader = Read::Postgres.new(read_options.merge(conditions))
|
59
|
+
|
60
|
+
reader.execute
|
61
|
+
end
|
62
|
+
|
63
|
+
# process function to execute the Google send email utility
|
64
|
+
#
|
65
|
+
def process
|
66
|
+
return { success: {} } if unprocessable_response
|
67
|
+
|
68
|
+
response = Utils::GoogleService::SendEmail.new(params).execute
|
69
|
+
|
70
|
+
response[:error].nil? ? { success: {} } : { error: response }
|
71
|
+
end
|
72
|
+
|
73
|
+
# write function to execute the PostgresDB write component
|
74
|
+
#
|
75
|
+
def write
|
76
|
+
write = Write::Postgres.new(write_options, process_response)
|
77
|
+
|
78
|
+
write.execute
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def conditions
|
84
|
+
{
|
85
|
+
where: "archived=$1 AND tag=$2 AND stage=$3 ORDER BY inserted_at ASC",
|
86
|
+
params: [false, read_options[:tag], "unprocessed"]
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def params
|
91
|
+
process_options.merge({ subject: SUBJECT, message: read_response.data["notification"] })
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httparty"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Utils
|
7
|
+
module DigitalOcean
|
8
|
+
##
|
9
|
+
# This module is a Notion utility for sending request to create, update, or delete
|
10
|
+
# Notion resources.
|
11
|
+
#
|
12
|
+
module Request
|
13
|
+
DIGITAL_OCEAN_BASE_URL = "https://api.digitalocean.com/v2"
|
14
|
+
|
15
|
+
# Implements the request process logic to Notion.
|
16
|
+
#
|
17
|
+
# <br>
|
18
|
+
# <b>Params:</b>
|
19
|
+
# * <tt>method</tt> HTTP request method: post, get, put, etc.
|
20
|
+
# * <tt>body</tt> Request body (Hash).
|
21
|
+
# * <tt>endpoint</tt> Notion resource endpoint.
|
22
|
+
# * <tt>secret</tt> Notion secret.
|
23
|
+
#
|
24
|
+
# <br>
|
25
|
+
# <b>returns</b> <tt>HTTParty::Response</tt>
|
26
|
+
#
|
27
|
+
def self.execute(params)
|
28
|
+
url = "#{DIGITAL_OCEAN_BASE_URL}/#{params[:endpoint]}"
|
29
|
+
|
30
|
+
headers = headers(params[:secret])
|
31
|
+
|
32
|
+
HTTParty.send(params[:method], url, { body: params[:body].to_json, headers: })
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.headers(secret)
|
36
|
+
{
|
37
|
+
"Authorization" => "Bearer #{secret}",
|
38
|
+
"Content-Type" => "application/json"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "google/apis/gmail_v1"
|
4
|
+
require "googleauth"
|
5
|
+
|
6
|
+
module Utils
|
7
|
+
module GoogleService
|
8
|
+
##
|
9
|
+
# This module is a Google service utility to send emails from a google account
|
10
|
+
#
|
11
|
+
class SendEmail
|
12
|
+
SCOPES = ["https://mail.google.com/", "https://www.googleapis.com/auth/gmail.send"].freeze
|
13
|
+
CONTENT_TYPE = "message/rfc822"
|
14
|
+
|
15
|
+
def initialize(params)
|
16
|
+
@refresh_token = params[:refresh_token]
|
17
|
+
@client_id = params[:client_id]
|
18
|
+
@client_secret = params[:client_secret]
|
19
|
+
@user_email = params[:user_email]
|
20
|
+
@recipient_email = params[:recipient_email]
|
21
|
+
@subject = params[:subject]
|
22
|
+
@message = params[:message]
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute
|
26
|
+
{ send_email: }
|
27
|
+
rescue StandardError => e
|
28
|
+
{ error: e.to_s }
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def send_email
|
34
|
+
service = Google::Apis::GmailV1::GmailService.new
|
35
|
+
|
36
|
+
service.authorization = access_token
|
37
|
+
|
38
|
+
service.send_user_message(@user_email, upload_source:, content_type: CONTENT_TYPE)
|
39
|
+
end
|
40
|
+
|
41
|
+
def upload_source
|
42
|
+
message = <<~END_OF_MESSAGE
|
43
|
+
From: me
|
44
|
+
To: #{@recipient_email.join(",")}
|
45
|
+
Subject: #{@subject}
|
46
|
+
MIME-Version: 1.0
|
47
|
+
Content-Type: text/plain; charset=UTF-8
|
48
|
+
|
49
|
+
#{@message}
|
50
|
+
END_OF_MESSAGE
|
51
|
+
|
52
|
+
StringIO.new(message)
|
53
|
+
end
|
54
|
+
|
55
|
+
def access_token
|
56
|
+
client = Google::Auth::UserRefreshCredentials.new(auth_params)
|
57
|
+
|
58
|
+
client.fetch_access_token!
|
59
|
+
client.access_token
|
60
|
+
end
|
61
|
+
|
62
|
+
def auth_params
|
63
|
+
{
|
64
|
+
client_id: @client_id,
|
65
|
+
client_secret: @client_secret,
|
66
|
+
refresh_token: @refresh_token,
|
67
|
+
scope: SCOPES
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/bas/version.rb
CHANGED
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: 1.1
|
4
|
+
version: 1.2.1
|
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-07-
|
11
|
+
date: 2024-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gmail_xoauth
|
@@ -16,14 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.4.
|
19
|
+
version: 0.4.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.4.
|
26
|
+
version: 0.4.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: google-api-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.53'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.53'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: googleauth
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: httparty
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +187,7 @@ files:
|
|
159
187
|
- lib/bas.rb
|
160
188
|
- lib/bas/bot/base.rb
|
161
189
|
- lib/bas/bot/compare_wip_limit_count.rb
|
190
|
+
- lib/bas/bot/fetch_billing_from_digital_ocean.rb
|
162
191
|
- lib/bas/bot/fetch_birthdays_from_notion.rb
|
163
192
|
- lib/bas/bot/fetch_domains_wip_counts_from_notion.rb
|
164
193
|
- lib/bas/bot/fetch_domains_wip_limit_from_notion.rb
|
@@ -168,11 +197,13 @@ files:
|
|
168
197
|
- lib/bas/bot/fetch_next_week_ptos_from_notion.rb
|
169
198
|
- lib/bas/bot/fetch_ptos_from_notion.rb
|
170
199
|
- lib/bas/bot/format_birthdays.rb
|
200
|
+
- lib/bas/bot/format_do_bill_alert.rb
|
171
201
|
- lib/bas/bot/format_emails.rb
|
172
202
|
- lib/bas/bot/format_wip_limit_exceeded.rb
|
173
203
|
- lib/bas/bot/garbage_collector.rb
|
174
204
|
- lib/bas/bot/humanize_pto.rb
|
175
205
|
- lib/bas/bot/notify_discord.rb
|
206
|
+
- lib/bas/bot/notify_do_bill_alert_email.rb
|
176
207
|
- lib/bas/bot/review_media.rb
|
177
208
|
- lib/bas/bot/update_review_media_state.rb
|
178
209
|
- lib/bas/bot/write_media_review_in_notion.rb
|
@@ -181,9 +212,11 @@ files:
|
|
181
212
|
- lib/bas/read/default.rb
|
182
213
|
- lib/bas/read/postgres.rb
|
183
214
|
- lib/bas/read/types/response.rb
|
215
|
+
- lib/bas/utils/digital_ocean/request.rb
|
184
216
|
- lib/bas/utils/discord/integration.rb
|
185
217
|
- lib/bas/utils/exceptions/function_not_implemented.rb
|
186
218
|
- lib/bas/utils/exceptions/invalid_process_response.rb
|
219
|
+
- lib/bas/utils/google/send_email.rb
|
187
220
|
- lib/bas/utils/imap/request.rb
|
188
221
|
- lib/bas/utils/notion/request.rb
|
189
222
|
- lib/bas/utils/notion/update_db_state.rb
|