Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Birthdays use case implementations #2

Merged
merged 15 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ on:

jobs:
build:
if: false
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby }}
strategy:
Expand All @@ -18,11 +17,11 @@ jobs:
- '3.2.2'

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run the default task
run: bundle exec rake
run: chmod +x bin/console && bundle exec rake
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@ Style/StringLiteralsInInterpolation:

Layout/LineLength:
Max: 120
Severity: info

Style/Documentation:
Severity: info

Metrics/BlockLength:
Severity: info
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ gemspec
gem "rake", "~> 13.0"

gem "rspec", "~> 3.0"
gem "vcr"
gem "webmock"

gem "rubocop", "~> 1.21"

Expand Down
13 changes: 13 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ PATH
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
crack (0.4.5)
rexml
diff-lcs (1.5.0)
hashdiff (1.1.0)
httparty (0.21.0)
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
Expand All @@ -19,6 +24,7 @@ GEM
parser (3.3.0.3)
ast (~> 2.4.1)
racc
public_suffix (5.0.4)
racc (1.7.3)
rainbow (3.1.1)
rake (13.1.0)
Expand Down Expand Up @@ -52,6 +58,11 @@ GEM
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
unicode-display_width (2.5.0)
vcr (6.2.0)
webmock (3.19.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)

PLATFORMS
arm64-darwin-23
Expand All @@ -63,6 +74,8 @@ DEPENDENCIES
rake (~> 13.0)
rspec (~> 3.0)
rubocop (~> 1.21)
vcr
webmock

BUNDLED WITH
2.4.10
31 changes: 0 additions & 31 deletions lib/bns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,4 @@
module Bns
include UseCases
class Error < StandardError; end

today = DateTime.now.strftime("%F").to_s

options = {
fetch_options: {
base_url: "https://api.notion.com",
database_id: "NOTION_DATABASE_ID",
secret: "NOTION_SECRET",
filter: {
"filter": {
"or": [
{
"property": "BD_this_year",
"date": {
"equals": today
}
}
]
},
"sorts": []
}
},
dispatch_options: {
webhook: "WEBHOOK_URL",
name: "BOT_NAME"
}
}

use_case = UseCases.notify_birthday_from_notion_to_discord(options)

use_case.perform
end
Empty file removed lib/bns/domain/response.rb
Empty file.
18 changes: 16 additions & 2 deletions lib/bns/fetcher/birthday/notion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ def fetch
"Content-Type" => "application/json",
"Notion-Version" => "2022-06-28"
}

response = HTTParty.post(url, { body: config[:filter].to_json, headers: headers })
validated_response = validate_response(response)

normalize_response(response["results"])
normalize_response(validated_response["results"])
end

def normalize_response(response)
return [] if response.nil?

normalized_response = []

response.map do |value|
Expand All @@ -38,6 +40,18 @@ def normalize_response(response)

private

def validate_response(response)
error_codes = [401, 404]

begin
raise response["message"] if error_codes.include?(response["status"])

response
rescue ArgumentError => e
puts "Fetcher::Birthday::Notion Error: #{e.message}"
end
end

def normalize(properties)
normalized_value = {}

Expand Down
8 changes: 6 additions & 2 deletions lib/bns/formatter/birthday/discord.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ class Discord
include Base

def format(data)
raise "Invalid data format" unless data.all? { |element| element.is_a?(Domain::Birthday) }

template = "NAME, Wishing you a very happy birthday! Enjoy your special day! :birthday: :gift:"
payload = ""

data.each_index do |index|
payload += "#{template.gsub("NAME", data[index].individual_name)}\n"
data.each do |birthday|
payload += "#{template.gsub("NAME", birthday.individual_name)}\n"
end

payload
rescue ArgumentError => e
puts "Formatter::Birthday::Notion Error: #{e.message}"
end
end
end
Expand Down
Empty file.
2 changes: 2 additions & 0 deletions lib/bns/use_cases/use_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def initialize(options)
def perform
response = fetcher.fetch

return unless response.length.positive?

mappings = mapper.map(response)

formatted_payload = formatter.format(mappings)
Expand Down
3 changes: 2 additions & 1 deletion lib/bns/use_cases/use_cases.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
module UseCases
def self.notify_birthday_from_notion_to_discord(options)
options = {
fetcher: Fetcher::Birthday::Notion.new(options[:fetch_options]), # !TODO: Use a class for specific configs for fetcher and dispatcher, after everything is working
# !TODO: Use a class for specific configs for fetcher and dispatcher, after everything is working
fetcher: Fetcher::Birthday::Notion.new(options[:fetch_options]),
mapper: Mapper::Birthday::Notion.new,
formatter: Formatter::Birthday::Discord.new,
dispatcher: Dispatcher::Discord.new(options[:dispatch_options])
Expand Down
2 changes: 1 addition & 1 deletion spec/bns/dispatcher/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
end

describe ".dispatch" do
it "provides no implementation of the method" do
it "provides no implementation for the method" do
payload = ""
expect { @dispatcher.dispatch(payload) }.to raise_exception("Not implemented yet.")
end
Expand Down
58 changes: 58 additions & 0 deletions spec/bns/dispatcher/discord_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

RSpec.describe Dispatcher::Discord do
before do
@config = {
webhook: "https://discord.com/api/webhooks/1196541734138691615/lFFCvFdMVEvfKWtFID2TSBjNjjBvEwqRbG2czOz3X_HfHfIgmXh6SDlFRXaXLOignsOj",
name: "Test Birthday Bot"
}

@payload = "John Doe, Wishing you a very happy birthday! Enjoy your special day! :birthday: :gift:"

@dispatcher = described_class.new(@config)
end

describe "attributes and arguments" do
it { expect(@dispatcher).to respond_to(:webhook) }
it { expect(@dispatcher).to respond_to(:name) }

it { expect(described_class).to respond_to(:new).with(1).arguments }
it { expect(@dispatcher).to respond_to(:dispatch).with(1).arguments }
end

describe ".dispatch" do
it "dispatch a notification message to discord" do
VCR.use_cassette("discord_success_dispatch") do
discords_dispatcher = described_class.new(@config)

response = discords_dispatcher.dispatch(@payload)

expect(response.code).to eq(204)
end
end

it "doest dispatch a notification message to discord" do
VCR.use_cassette("discord_success_dispatch_empty_name") do
discords_dispatcher = described_class.new(@config)

response = discords_dispatcher.dispatch(@payload)

expect(response.code).to eq(204)
end
end

it "raises an exception caused by incorrect webhook provided" do
VCR.use_cassette("discord_failed_dispatch_invalid_webhook") do
config = @config
config[:webhook] = "https://discord.com/api/webhooks/1196541734138691615/lFFCvFdMVEvfKWtFID2TSBjNjjBvEwqRbG2czOz3X_JfHfIgmXh6SDlFRXaXLOignsIP"

discords_dispatcher = described_class.new(config)

response = discords_dispatcher.dispatch(@payload)

expect(response.code).to eq(401)
expect(response["message"]).to eq("Invalid Webhook Token")
end
end
end
end
4 changes: 2 additions & 2 deletions spec/bns/fetcher/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
end

describe ".fetch" do
it "provides no implementation of the method" do
it "provides no implementation for the method" do
expect { @fetcher.fetch }.to raise_exception("Not implemented yet.")
end
end

describe ".format_response" do
it "provides no implementation of the method" do
it "provides no implementation for the method" do
response = {}
expect { @fetcher.normalize_response(response) }.to raise_exception("Not implemented yet.")
end
Expand Down
Loading