action_push 0.1.0

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.
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'action_push/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'action_push'
9
+ spec.version = ActionPush::VERSION
10
+ spec.authors = ['Aliaksandr Shylau']
11
+ spec.email = %w[alex.shilov.by@gmail.com]
12
+
13
+ spec.summary = 'ActionPush is a lightweight tool which allows you to organize Push notifications the same way Action Mailer does'
14
+ spec.description = 'It includes includes built-in support for the GORUSH gateway'
15
+ spec.homepage = 'https://github.com/shlima/action_push'
16
+ spec.license = 'MIT'
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ end
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = %w[lib]
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.17'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.0'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'rubocop-performance'
33
+ spec.add_development_dependency 'webmock'
34
+ spec.add_development_dependency 'i18n'
35
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'action_push'
5
+ require 'pry'
6
+
7
+ Pry.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+
3
+ rm ./*.gem
4
+ gem build action_push.gemspec
5
+ gem push action_push-*
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,14 @@
1
+ version: '3.5'
2
+
3
+ services:
4
+ gorush:
5
+ image: appleboy/gorush
6
+ ports:
7
+ - '8088:8088'
8
+ volumes:
9
+ - ./gorush.ci.yml:/config.yml
10
+ networks:
11
+ - default
12
+
13
+ networks:
14
+ default:
@@ -0,0 +1,63 @@
1
+ core:
2
+ enabled: true # enabale httpd server
3
+ address: "" # ip address to bind (default: any)
4
+ port: "8088" # ignore this port number if auto_tls is enabled (listen 443).
5
+ worker_num: 0 # default worker number is runtime.NumCPU()
6
+ queue_num: 0 # default queue number is 8192
7
+ max_notification: 100
8
+ sync: false # set true if you need get error message from fail push notification in API response.
9
+ feedback_hook_url: "" # set a hook url if you need get error message asynchronously from fail push notification in API response.
10
+ mode: "release"
11
+ ssl: false
12
+ cert_path: "cert.pem"
13
+ key_path: "key.pem"
14
+ cert_base64: ""
15
+ key_base64: ""
16
+ http_proxy: "" # only working for FCM server
17
+ pid:
18
+ enabled: false
19
+ path: "gorush.pid"
20
+ override: true
21
+ auto_tls:
22
+ enabled: false # Automatically install TLS certificates from Let's Encrypt.
23
+ folder: ".cache" # folder for storing TLS certificates
24
+ host: "" # which domains the Let's Encrypt will attempt
25
+
26
+ grpc:
27
+ enabled: false # enabale gRPC server
28
+ port: 9000
29
+
30
+ api:
31
+ push_uri: "/api/push"
32
+ stat_go_uri: "/api/stat/go"
33
+ stat_app_uri: "/api/stat/app"
34
+ config_uri: "/api/config"
35
+ sys_stat_uri: "/sys/stats"
36
+ metric_uri: "/metrics"
37
+ health_uri: "/healthz"
38
+
39
+ android:
40
+ enabled: false
41
+ apikey: ""
42
+ max_retry: 0 # resend fail notification, default value zero is disabled
43
+
44
+ ios:
45
+ enabled: true
46
+ key_base64: "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\nDgQIHD0SlMQbgK4CAggABIIEyMq+JgIQTie33sQTpabPzm/qcBSTvEUyQo/f\nyrmciqHNIZox0QDzhVCe6PnAXNL58zlyY/IjTSJAe1e4JyeakZVJF0JJCqol\ns9z8qkKvyw3Aha8S3AeCJ+HlEZnGc3l9jeQFbzOzYuIVOo2sHS2i5bAP0bTK\nv2W6s2m5MXI2sFW7tEEb944CjgNmLSvsc/RGRUt/6aXnfuS7EGWXU4j2v8A0\nDqT7GI8oJic84ehY+d2tHDanMWr63jRmf29YGX6DcqGOwlNVSzz+yTWreH2J\nRJfHpuhJba96yXNSwAbWSy2yzSKBF05qtV3qvYWTffy/eXYILbdb9Po6VjCM\n5hWonfx9/in0T9sMiSW8UbgwtGTgKZjSY1OLCSKXOOIF1cckXm+sr19sIWba\n5/xkAfyUxyxbthWyPIpyv3rbu34Uv1DEwEaukMLKg2E8SvH8cyG7507kBm4e\nX2mYyiuTDrdQ1iJJdyI9ieMx0X4pasMP9Cj/RvwOS+d7om1fYPkthQu+FdZU\ncTy7twonLjVaS9f4gl485qSkUjTE3z3+ojR0QOGbhWQWMwfMS998Q8TGpsQG\n0Yt1GrmxE/eWLkyrK84jrpLFghWn6g8TtW+eK+t9e+JSk7phNYizEtZYsUhQ\nzHDsFwlretUevY5t/RDtBnL/kIopWsJSmSsQYSjX9xgJ5nlQ5GQhEYDhYqz2\nV6AjIXWUaBmAOc3dlP/2L4Uwl1cLHXSNfqu3jh51mp5X+nh8AjCGSMB173EW\noUpdhZmKOKVOMkKoNSSzneg3DELN1osYDzRS20+8x7AnilWuqj46EyJSCXEt\nAUkjjUO50MseiYeVa77N1xL8B5BLW9s+GmK0dq6PPr3ttmSxCzc5XCAY7tyO\nrRNQJuuSDdMXN74s2GcSa6gKqyKpCTXoaAeNERIuQCjg9FRDXButxsu96oHz\nX2M5RbvlSX8ncRVZMEuqsfAET1WlwVbJbHhEUUh0eJpqpgUh2bMGezw3NF9F\np+HzeKIa/ckWiMFYoBPChSjufK1DdApuhGxe/XrCpmCbwiGWWsM/vbTdGpES\nZonUr42+EFjnqIDKYCRpvlcgV0dLK7VYykcfUokTFYORB1Ab8Api25tSEyaZ\nV7ekLykJqFsmgaP92eDNkApu3MDIVjd2TyKedKrQ1v1MuyK/OF/kcSaM+vl6\ncX+EikA6FXc99jhZpNqBVB2EQp/ieTEERzxUhouR6i6Be+nxrfv25ImhUkfd\n0aKTwh8qhGV1rTyEcnom8p903hHmpHd2+feuJAwuKiem5KXatXXciRMYT9y4\n7y+xq5vrIQMp/2aJXDZsaIVPB4boGnHeycKCAdtNDpTacs0GeCDu/bwn8/Uq\nPH4l9WcK4Ub3cRoJ4TcET7AMDgI5s+TDuG6LWQTS3xzaz1pxg6ELz+RF7PPC\noxT/1WnrC4F35SrdYvO4+CV2QG7KbllSW6NvRm67rV7pt3wohp0wNLixpzfo\nm4DYzCpRm3se+EPDkI+WLqTmRNPxOLnt7rWL1w8oW1lWqMEXCcM1DbRJ+VEa\nL5l5QZygvkeLb6lYkEVD6mcKi1m7pYYwjkOFap8PPiVqtrcYjMyxAS4EyTBl\ngnh6HojzFtrvud6tHzdD87YTY10B3ubDipscUDFWMC8GCSqGSIb3DQEJFDEi\nHiAEFAQ8BDgEQgRABDgEOQAgBBMEPgQ9BEcENQQ9BDoEPjAjBgkqhkiG9w0B\nCRUxFgQUMCl5eNLZn3NrLN4OhU4j3rv+chswMDAhMAkGBSsOAwIaBQAEFHbe\n9PHdNOlRMsIKgXj54VUejst+BAi09C/pGD/jgAIBAQ==\n"
47
+ key_type: "p12" # could be pem, p12 or p8 type
48
+ password: "" # certificate password, default as empty string.
49
+ production: true
50
+ max_retry: 0 # resend fail notification, default value zero is disabled
51
+ key_id: "" # KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
52
+ team_id: "" # TeamID from developer account (View Account -> Membership)
53
+
54
+ log:
55
+ format: "string" # string or json
56
+ access_log: "stdout" # stdout: output to console, or define log path like "log/access_log"
57
+ access_level: "debug"
58
+ error_log: "stderr" # stderr: output to console, or define log path like "log/error_log"
59
+ error_level: "error"
60
+ hide_token: true
61
+
62
+ stat:
63
+ engine: "memory" # support memory, redis, boltdb, buntdb or leveldb
@@ -0,0 +1,63 @@
1
+ core:
2
+ enabled: true # enabale httpd server
3
+ address: "" # ip address to bind (default: any)
4
+ port: "8088" # ignore this port number if auto_tls is enabled (listen 443).
5
+ worker_num: 0 # default worker number is runtime.NumCPU()
6
+ queue_num: 0 # default queue number is 8192
7
+ max_notification: 100
8
+ sync: false # set true if you need get error message from fail push notification in API response.
9
+ feedback_hook_url: "" # set a hook url if you need get error message asynchronously from fail push notification in API response.
10
+ mode: "release"
11
+ ssl: false
12
+ cert_path: "cert.pem"
13
+ key_path: "key.pem"
14
+ cert_base64: ""
15
+ key_base64: ""
16
+ http_proxy: "" # only working for FCM server
17
+ pid:
18
+ enabled: false
19
+ path: "gorush.pid"
20
+ override: true
21
+ auto_tls:
22
+ enabled: false # Automatically install TLS certificates from Let's Encrypt.
23
+ folder: ".cache" # folder for storing TLS certificates
24
+ host: "" # which domains the Let's Encrypt will attempt
25
+
26
+ grpc:
27
+ enabled: false # enabale gRPC server
28
+ port: 9000
29
+
30
+ api:
31
+ push_uri: "/api/push"
32
+ stat_go_uri: "/api/stat/go"
33
+ stat_app_uri: "/api/stat/app"
34
+ config_uri: "/api/config"
35
+ sys_stat_uri: "/sys/stats"
36
+ metric_uri: "/metrics"
37
+ health_uri: "/healthz"
38
+
39
+ android:
40
+ enabled: false
41
+ apikey: ""
42
+ max_retry: 0 # resend fail notification, default value zero is disabled
43
+
44
+ ios:
45
+ enabled: true
46
+ key_base64: "MIIM+QIBAzCCDMAGCS==\n"
47
+ key_type: "p12" # could be pem, p12 or p8 type
48
+ password: "123" # certificate password, default as empty string.
49
+ production: true
50
+ max_retry: 0 # resend fail notification, default value zero is disabled
51
+ key_id: "" # KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
52
+ team_id: "" # TeamID from developer account (View Account -> Membership)
53
+
54
+ log:
55
+ format: "string" # string or json
56
+ access_log: "stdout" # stdout: output to console, or define log path like "log/access_log"
57
+ access_level: "debug"
58
+ error_log: "stderr" # stderr: output to console, or define log path like "log/error_log"
59
+ error_level: "error"
60
+ hide_token: true
61
+
62
+ stat:
63
+ engine: "memory" # support memory, redis, boltdb, buntdb or leveldb
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'action_push/version'
5
+ require 'action_push/errors'
6
+
7
+ module ActionPush
8
+ autoload :Base, 'action_push/base'
9
+ autoload :Envelope, 'action_push/envelope'
10
+ autoload :Util, 'action_push/util'
11
+
12
+ module Concerns
13
+ autoload :ClassMethodDelivery, 'action_push/concerns/class_method_delivery'
14
+ autoload :RegisterDefault, 'action_push/concerns/register_default'
15
+ autoload :RegisterDeliveryMethod, 'action_push/concerns/register_delivery_method'
16
+ end
17
+
18
+ module Delivery
19
+ autoload :Explosion, 'action_push/delivery/explosion'
20
+ autoload :Gorush, 'action_push/delivery/gorush'
21
+ autoload :Memory, 'action_push/delivery/memory'
22
+ end
23
+
24
+ module Provider
25
+ autoload :Base, 'action_push/provider/base'
26
+ autoload :Test, 'action_push/provider/test'
27
+ end
28
+
29
+ module Ios
30
+ autoload :Message, 'action_push/ios/message'
31
+ autoload :Alert, 'action_push/ios/alert'
32
+ end
33
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPush
4
+ class Base
5
+ extend Concerns::ClassMethodDelivery
6
+ extend Concerns::RegisterDefault
7
+ extend Concerns::RegisterDeliveryMethod
8
+
9
+ register_default :ios, Ios::Message.new
10
+
11
+ attr_accessor :action_name
12
+
13
+ def self.inherited(subclass)
14
+ super
15
+
16
+ defaults.each do |name, placeholder|
17
+ subclass.register_default name, placeholder.clone
18
+ end
19
+
20
+ delivery_methods.each do |name, handler|
21
+ subclass.register_delivery_method(name, handler)
22
+ end
23
+ end
24
+
25
+ def initialize(action_name: nil)
26
+ @action_name = action_name
27
+ end
28
+
29
+ def envelope
30
+ @envelope ||= Envelope.new do |env|
31
+ self.class.defaults.each do |name, placeholder|
32
+ env.add(name, placeholder.dup)
33
+ end
34
+ end
35
+ end
36
+
37
+ # @return [Provider::Envelope]
38
+ def push(provider, attributes = {})
39
+ push = envelope.for(provider)
40
+
41
+ push.title = envelope.title if envelope.title
42
+ push.body = envelope.body if envelope.body
43
+ push.payload = envelope.payload if envelope.payload
44
+ push.scheduled = true
45
+ push.delivery_method = self.class.delivery_methods.fetch(provider, Delivery::Explosion)
46
+
47
+ # after all
48
+ push.assign(attributes)
49
+ yield(push) if block_given?
50
+
51
+ envelope
52
+ end
53
+
54
+ def translate(key, options = {})
55
+ I18n.translate(key, { scope: i18n_scope }.merge(options))
56
+ end
57
+
58
+ def i18n_scope
59
+ "#{Util.underscore(self.class.to_s)}.#{action_name}"
60
+ end
61
+
62
+ alias_method :t, :translate
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPush
4
+ module Concerns
5
+ module ClassMethodDelivery
6
+ # Acts like ActionMailer::Base
7
+ #
8
+ # class ApplePush < ActionPush
9
+ # def welcome
10
+ # # ....
11
+ # end
12
+ # end
13
+ #
14
+ # ApplePush.new.welcome will build PUSH message, but not send it
15
+ # ApplePush.welcome will build PUSH message and DELIVER it
16
+ #
17
+ # @return [Envelope]
18
+ def method_missing(method, *argv, &block)
19
+ return super unless action_methods.include?(method)
20
+
21
+ instance = new(action_name: method)
22
+ instance.public_send(method, *argv, &block)
23
+ instance.envelope.deliver
24
+ instance.envelope
25
+ end
26
+
27
+ def respond_to_missing?(method_name, include_private = false)
28
+ action_methods.include?(method_name) || super
29
+ end
30
+
31
+ def action_methods
32
+ @action_methods ||= public_instance_methods(false).to_set
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPush
4
+ module Concerns
5
+ module RegisterDefault
6
+ def defaults
7
+ @defaults ||= {}
8
+ end
9
+
10
+ def register_default(provider, placeholder)
11
+ defaults[provider] = placeholder.dup.freeze
12
+ end
13
+
14
+ def default(provider)
15
+ placeholder = defaults[provider].dup
16
+
17
+ yield(placeholder) if block_given?
18
+
19
+ register_default(provider, placeholder)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPush
4
+ module Concerns
5
+ module RegisterDeliveryMethod
6
+ def delivery_methods
7
+ @delivery_methods ||= {}
8
+ end
9
+
10
+ def register_delivery_method(name, handler)
11
+ delivery_methods[name] = handler
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPush
4
+ module Delivery
5
+ module Explosion
6
+ module_function
7
+
8
+ def call(push)
9
+ raise Error, <<~DOC
10
+ Delivery method fot the <#{push}> was not set"
11
+ DOC
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ module ActionPush
7
+ module Delivery
8
+ # cli = ActionPush::Delivery::Gorush.new(url: 'http://localhost:8088/api/push', topic: 'com.app.id')
9
+ #
10
+ # push = ActionPush::Ios::Message.new do |p|
11
+ # p.title = 'Title'
12
+ # p.thread_id = 'comments'
13
+ # p.badge = 10
14
+ # p.body = 'Body'
15
+ # p.token = '4589***A938'
16
+ # end
17
+ #
18
+ # cli.send_to_apple(push)
19
+ class Gorush
20
+ attr_accessor :url
21
+ attr_accessor :logger
22
+ attr_accessor :topic
23
+
24
+ def initialize(params = {})
25
+ params.each { |key, value| public_send("#{key}=", value) }
26
+ yield(self) if block_given?
27
+ end
28
+
29
+ # @param [Ios::Message]
30
+ # @return [Net::HTTPResponse]
31
+ # rubocop:disable Metrics/MethodLength
32
+ def send_to_apple(push)
33
+ alert = push.alert
34
+
35
+ notification = {
36
+ tokens: [push.token],
37
+ platform: 1,
38
+ 'thread-id': push.thread_id,
39
+ content_available: push.content_available,
40
+ topic: topic,
41
+ badge: push.badge,
42
+ category: push.category,
43
+ data: push.payload,
44
+ sound: {
45
+ name: push.sound
46
+ },
47
+ alert: {
48
+ title: alert.title,
49
+ body: alert.body,
50
+ 'action-loc-key': alert.action_loc_key,
51
+ 'launch-image': alert.launch_image,
52
+ 'loc-args': alert.loc_args,
53
+ 'loc-key': alert.loc_key,
54
+ 'title-loc-args': alert.title_loc_args,
55
+ 'title-loc-key': alert.title_loc_key
56
+ }
57
+ }
58
+
59
+ response = post(notifications: [notification])
60
+
61
+ push.delivery_response = response
62
+ push.delivered = response.is_a?(Net::HTTPSuccess)
63
+
64
+ response
65
+ end
66
+ # rubocop:enable Metrics/MethodLength
67
+
68
+ private
69
+
70
+ def uri
71
+ @uri ||= URI(url)
72
+ end
73
+
74
+ def post(json = {})
75
+ req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
76
+ req.body = json.to_json
77
+ transport.start do |h|
78
+ h.request(req)
79
+ end
80
+ end
81
+
82
+ def transport
83
+ @transport ||= begin
84
+ http = Net::HTTP.new(uri.host, uri.port)
85
+ http.set_debug_output(logger) if logger
86
+ http
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end