Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
.bundle/
log/*.log
pkg/
Expand Down
62 changes: 33 additions & 29 deletions lib/magicbell.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
# frozen_string_literal: true

require 'forwardable'

require "openssl"
require "base64"

require "magicbell/config"

require "httparty"
require "magicbell/api_operations"
require "magicbell/client"
require "magicbell/api_resource"
require "magicbell/singleton_api_resource"
require "magicbell/api_resource_collection"
require "magicbell/api_resources/notification"
require "magicbell/api_resources/user"
require "magicbell/api_resources/user_notification"
require "magicbell/api_resources/user_notifications"
require "magicbell/api_resources/user_notification_read"
require "magicbell/api_resources/user_notification_unread"
require "magicbell/api_resources/user_notifications_read"
require "magicbell/api_resources/user_notifications_seen"
require "magicbell/api_resources/user_notification_preferences"

require "magicbell/railtie" if defined?(Rails)
require 'openssl'
require 'base64'

require 'magicbell/config'

require 'httparty'
require 'magicbell/api_operations'
require 'magicbell/client'
require 'magicbell/api_resource'
require 'magicbell/singleton_api_resource'
require 'magicbell/api_resource_collection'
require 'magicbell/api_resources/notification'
require 'magicbell/api_resources/user'
require 'magicbell/api_resources/user_notification'
require 'magicbell/api_resources/user_notifications'
require 'magicbell/api_resources/user_notification_read'
require 'magicbell/api_resources/user_notification_unread'
require 'magicbell/api_resources/user_notifications_read'
require 'magicbell/api_resources/user_notifications_seen'
require 'magicbell/api_resources/user_notification_preferences'

require 'magicbell/railtie' if defined?(Rails)

module MagicBell
WIDGET_JAVASCRIPT_URL = "https://assets.magicbell.io/widget.magicbell.js"
EXTRAS_CSS_URL = "https://assets.magicbell.io/extras.magicbell.css"
WIDGET_JAVASCRIPT_URL = 'https://assets.magicbell.io/widget.magicbell.js'
EXTRAS_CSS_URL = 'https://assets.magicbell.io/extras.magicbell.css'

class << self
extend Forwardable

def_delegators :config, :api_key,
:api_secret,
:api_host
:api_secret,
:api_host,
:max_network_retries

def configure
yield(config)
Expand All @@ -48,14 +51,15 @@ def reset_config

def authentication_headers(client_api_key: nil, client_api_secret: nil)
{
"X-MAGICBELL-API-KEY" => client_api_key || api_key,
"X-MAGICBELL-API-SECRET" => client_api_secret || api_secret
'X-MAGICBELL-API-KEY' => client_api_key || api_key,
'X-MAGICBELL-API-SECRET' => client_api_secret || api_secret
}
end

# Calculate HMAC for user's email
def hmac(message)
MagicBell::Client.new(api_key: api_key, api_secret: api_secret).hmac(message)
MagicBell::Client.new(api_key: api_key, api_secret: api_secret,
max_network_retries: max_network_retries).hmac(message)
end
end
end
4 changes: 4 additions & 0 deletions lib/magicbell/action_mailer_extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ def magicbell_notification_skip
headers["X-MagicBell-Notification-Skip"] = true
end
end

def self.max_network_reties
# code here
end
end
16 changes: 9 additions & 7 deletions lib/magicbell/api_operations.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'json'
require 'colorize'
module MagicBell
Expand Down Expand Up @@ -29,28 +31,28 @@ def put(url, options = {})
protected

def default_headers
authentication_headers.merge({ "Content-Type" => "application/json", "Accept"=> "application/json" })
authentication_headers.merge({ 'Content-Type' => 'application/json', 'Accept'=> 'application/json' })
end

private

def raise_http_error_unless_2xx_response(response)
return if response.success?

e = MagicBell::Client::HTTPError.new
e.response_status = response.code
e.response_headers = response.headers.to_h
e.response_body = response.body
e.errors = []
unless e.response_body.nil? || e.response_body.empty?
body = JSON.parse(response.body)
e.errors = body["errors"].is_a?(Array) ? body["errors"] : []
e.errors = body['errors'].is_a?(Array) ? body['errors'] : []
e.errors.each do |error, index|
suggestion = error["suggestion"]
help_link = error["help_link"]
suggestion = error['suggestion']
help_link = error['help_link']

puts "#{suggestion.red}" if suggestion
puts "#{help_link.blue.on_white}" if help_link
puts suggestion.red.to_s if suggestion
puts help_link.blue.on_white.to_s if help_link
end
end

Expand Down
34 changes: 27 additions & 7 deletions lib/magicbell/api_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,23 @@ def path
end

def create
response = @client.post(
create_url,
body: { name => attributes }.to_json,
headers: extra_headers
)
parse_response(response)
begin
retries ||= 0

response = @client.post(
create_url,
body: { name => attributes }.to_json,
headers: extra_headers
)

parse_response(response)
rescue MagicBell::Client::HTTPError => e
retry if server_error(e) && can_retry_again((retries += 1))
raise e
rescue Net::OpenTimeout => e
retry if can_retry_again(retries += 1)
raise
end

self
end
Expand All @@ -105,12 +116,21 @@ def extra_headers

private

def can_retry_again(retries)
(retries <= MagicBell.max_network_retries)
end

def server_error(server_error)
server_error.response_status > 499 || server_error.response_status == 408
end

attr_reader :response,
:response_hash

def retrieve_unless_retrieved
return unless id # Never retrieve a new unsaved resource
return if @retrieved

retrieve
end

Expand Down
13 changes: 8 additions & 5 deletions lib/magicbell/client.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module MagicBell
class Client
class HTTPError < StandardError
Expand All @@ -9,9 +11,10 @@ class HTTPError < StandardError

include ApiOperations

def initialize(api_key: nil, api_secret: nil)
def initialize(api_key: nil, api_secret: nil, max_network_retries: 2)
@api_key = api_key
@api_secret = api_secret
@max_network_retries = max_network_retries
end

def create_notification(notification_attributes)
Expand All @@ -20,12 +23,12 @@ def create_notification(notification_attributes)

def user_with_email(email)
client = self
MagicBell::User.new(client, "email" => email)
MagicBell::User.new(client, 'email' => email)
end

def user_with_external_id(external_id)
client = self
MagicBell::User.new(client, "external_id" => external_id)
MagicBell::User.new(client, 'external_id' => external_id)
end

def authentication_headers
Expand All @@ -35,13 +38,13 @@ def authentication_headers
def hmac(message)
secret = @api_secret || MagicBell.api_secret

Base64.encode64(OpenSSL::HMAC::digest(sha256_digest, secret, message)).strip
Base64.encode64(OpenSSL::HMAC.digest(sha256_digest, secret, message)).strip
end

private

def sha256_digest
OpenSSL::Digest::Digest.new('sha256')
OpenSSL::Digest.new('sha256')
end
end
end
18 changes: 11 additions & 7 deletions lib/magicbell/config.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
# frozen_string_literal: true

module MagicBell
class Config
attr_writer :api_key
attr_writer :api_secret
attr_writer :api_host
attr_writer :api_key, :api_secret, :api_host, :max_network_retries

def initialize
@api_host = "https://api.magicbell.io"
@api_host = 'https://api.magicbell.io'
end

def api_key
@api_key || ENV["MAGICBELL_API_KEY"]
@api_key || ENV['MAGICBELL_API_KEY']
end

def api_secret
@api_secret || ENV["MAGICBELL_API_SECRET"]
@api_secret || ENV['MAGICBELL_API_SECRET']
end

def api_host
@api_host || ENV["MAGICBELL_API_HOST"] || "https://api.magicbell.io"
@api_host || ENV['MAGICBELL_API_HOST'] || 'https://api.magicbell.io'
end

def max_network_retries
@max_network_retries || 2
end
end
end
Loading