pushpop 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.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ $stdout.sync = true
2
+
3
+ $: << File.join(File.dirname(__FILE__), './lib')
4
+
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+ desc 'Run Rspec unit tests'
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = 'spec/**/*_spec.rb'
10
+ end
11
+
12
+ task default: :spec
13
+ rescue LoadError
14
+ end
15
+
16
+ def require_jobfiles(args)
17
+ require 'pushpop'
18
+ if jobfile = args[:jobfile]
19
+ load "#{File.dirname(__FILE__)}/#{jobfile}"
20
+ else
21
+ Dir.glob("#{File.dirname(__FILE__)}/jobs/**/*.rb").each { |file|
22
+ require file
23
+ }
24
+ end
25
+ end
26
+
27
+ namespace :jobs do
28
+ desc 'Describe jobs'
29
+ task :describe, :jobfile do |_, args|
30
+ require_jobfiles(args)
31
+ Pushpop.jobs.each do |job|
32
+ puts job.name
33
+ end
34
+ end
35
+
36
+ desc 'Run each job once'
37
+ task :run_once, :jobfile do |_, args|
38
+ require_jobfiles(args)
39
+ Pushpop.run
40
+ end
41
+
42
+ desc 'Run jobs ongoing'
43
+ task :run, :jobfile do |_, args|
44
+ require_jobfiles(args)
45
+ Pushpop.schedule
46
+ Clockwork.manager.run
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ require 'pushpop'
2
+
3
+ job 'Simple Math' do
4
+
5
+ every 1.minutes
6
+
7
+ step 'return 10' do 10 end
8
+
9
+ step 'increase by 20' do |response|
10
+ 20 + response
11
+ end
12
+
13
+ step 'print out via template' do |response|
14
+ html = template 'first_template.html.erb', response
15
+ puts 'Hey Pushpop, let\'s do a math!'
16
+ puts html
17
+ html
18
+ end
19
+
20
+ end
@@ -0,0 +1,78 @@
1
+ require 'keen'
2
+
3
+ module Pushpop
4
+
5
+ class Keen < Step
6
+
7
+ PLUGIN_NAME = 'keen'
8
+
9
+ attr_accessor :_event_collection
10
+ attr_accessor :_analysis_type
11
+ attr_accessor :_timeframe
12
+ attr_accessor :_target_property
13
+ attr_accessor :_group_by
14
+ attr_accessor :_interval
15
+ attr_accessor :_filters
16
+ attr_accessor :_steps
17
+ attr_accessor :_analyses
18
+
19
+ def run(last_response=nil, step_responses=nil)
20
+ self.configure(last_response, step_responses)
21
+ ::Keen.send(self._analysis_type, self._event_collection, self.to_analysis_options)
22
+ end
23
+
24
+ def configure(last_response=nil, step_responses=nil)
25
+ self.instance_exec(last_response, step_responses, &block)
26
+ end
27
+
28
+ def to_analysis_options
29
+ { timeframe: self._timeframe,
30
+ target_property: self._target_property,
31
+ group_by: self._group_by,
32
+ interval: self._interval,
33
+ filters: self._filters,
34
+ analyses: self._analyses,
35
+ steps: self._steps
36
+ }.delete_if { |_, v| v.nil? }
37
+ end
38
+
39
+ def event_collection(event_collection)
40
+ self._event_collection = event_collection
41
+ end
42
+
43
+ def analysis_type(analysis_type)
44
+ self._analysis_type = analysis_type
45
+ end
46
+
47
+ def timeframe(timeframe)
48
+ self._timeframe = timeframe
49
+ end
50
+
51
+ def target_property(target_property)
52
+ self._target_property = target_property
53
+ end
54
+
55
+ def group_by(group_by)
56
+ self._group_by = group_by
57
+ end
58
+
59
+ def interval(interval)
60
+ self._interval = interval
61
+ end
62
+
63
+ def filters(filters)
64
+ self._filters = filters
65
+ end
66
+
67
+ def steps(steps)
68
+ self._steps = steps
69
+ end
70
+
71
+ def analyses(analyses)
72
+ self._analyses = analyses
73
+ end
74
+
75
+ end
76
+
77
+ Pushpop::Job.register_plugin(Keen::PLUGIN_NAME, Keen)
78
+ end
@@ -0,0 +1,94 @@
1
+ require 'mail'
2
+
3
+ Mail.defaults do
4
+ delivery_method :smtp, { address: 'smtp.sendgrid.net',
5
+ port: 587,
6
+ domain: ENV['SENDGRID_DOMAIN'],
7
+ user_name: ENV['SENDGRID_USERNAME'],
8
+ password: ENV['SENDGRID_PASSWORD'],
9
+ authentication: 'plain',
10
+ enable_starttls_auto: true }
11
+ end
12
+
13
+ module Pushpop
14
+
15
+ class Sendgrid < Step
16
+
17
+ PLUGIN_NAME = 'sendgrid'
18
+
19
+ attr_accessor :_from
20
+ attr_accessor :_to
21
+ attr_accessor :_subject
22
+ attr_accessor :_body
23
+ attr_accessor :_preview
24
+
25
+ def run(last_response=nil, step_responses=nil)
26
+
27
+ self.configure(last_response, step_responses)
28
+
29
+ # print the message if its just a preview
30
+ return print_preview if self._preview
31
+
32
+ _to = self._to
33
+ _from = self._from
34
+ _subject = self._subject
35
+ _body = self._body
36
+
37
+ Mail.deliver do
38
+ to _to
39
+ from _from
40
+ subject _subject
41
+ text_part do
42
+ body _body
43
+ end
44
+ html_part do
45
+ content_type 'text/html; charset=UTF-8'
46
+ body _body
47
+ end
48
+ end
49
+ end
50
+
51
+ def configure(last_response=nil, step_responses=nil)
52
+ self.instance_exec(last_response, step_responses, &block)
53
+ end
54
+
55
+ def from(from)
56
+ self._from = from
57
+ end
58
+
59
+ def to(to)
60
+ self._to = to
61
+ end
62
+
63
+ def subject(subject)
64
+ self._subject = subject
65
+ end
66
+
67
+ def preview(preview)
68
+ self._preview = preview
69
+ end
70
+
71
+ def body(*args)
72
+ if args.length == 1
73
+ self._body = args.first
74
+ else
75
+ self._body = template *args
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def print_preview
82
+ puts <<MESSAGE
83
+ To: #{self._to}
84
+ From: #{self._from}
85
+ Subject: #{self._subject}
86
+
87
+ #{self._body}
88
+ MESSAGE
89
+ end
90
+
91
+ end
92
+
93
+ Pushpop::Job.register_plugin(Sendgrid::PLUGIN_NAME, Sendgrid)
94
+ end
@@ -0,0 +1,52 @@
1
+ require 'twilio-ruby'
2
+
3
+ TWILIO_SID = ENV['TWILIO_SID']
4
+ TWILIO_AUTH_TOKEN = ENV['TWILIO_AUTH_TOKEN']
5
+ TWILIO_FROM = ENV['TWILIO_FROM']
6
+
7
+ module Pushpop
8
+
9
+ class Twilio < Step
10
+
11
+ PLUGIN_NAME = 'twilio'
12
+
13
+ attr_accessor :_from
14
+ attr_accessor :_to
15
+ attr_accessor :_body
16
+
17
+ def run(last_response=nil, step_responses=nil)
18
+
19
+ self.configure(last_response, step_responses)
20
+
21
+ _to = self._to
22
+ _from = self._from || TWILIO_FROM
23
+ _body = self._body
24
+
25
+ client = ::Twilio::REST::Client.new(TWILIO_SID, TWILIO_AUTH_TOKEN)
26
+
27
+ client.account.messages.create(
28
+ from: _from,
29
+ to: _to,
30
+ body: _body )
31
+ end
32
+
33
+ def configure(last_response=nil, step_responses=nil)
34
+ self.instance_exec(last_response, step_responses, &block)
35
+ end
36
+
37
+ def from(from)
38
+ self._from = from
39
+ end
40
+
41
+ def to(to)
42
+ self._to = to
43
+ end
44
+
45
+ def body(body)
46
+ self._body = body
47
+ end
48
+
49
+ end
50
+
51
+ Pushpop::Job.register_plugin(Twilio::PLUGIN_NAME, Twilio)
52
+ end
data/lib/pushpop.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'logger'
2
+ require 'clockwork'
3
+ require 'pushpop/version'
4
+ require 'pushpop/job'
5
+ require 'pushpop/step'
6
+
7
+ # require all plugins
8
+ Dir["#{File.expand_path('../plugins/*', __FILE__)}.rb"].each { |file|
9
+ require file
10
+ }
11
+
12
+ module Pushpop
13
+ class << self
14
+ cattr_accessor :logger
15
+ cattr_accessor :jobs
16
+
17
+ # for jobs and steps
18
+ def random_name
19
+ (0...8).map { (65 + rand(26)).chr }.join
20
+ end
21
+
22
+ self.jobs = []
23
+
24
+ def add_job(name=nil, &block)
25
+ self.jobs.push(Job.new(name, &block))
26
+ self.jobs.last
27
+ end
28
+
29
+ def run
30
+ self.jobs.map &:run
31
+ end
32
+
33
+ def schedule
34
+ self.jobs.map &:schedule
35
+ end
36
+ end
37
+ end
38
+
39
+ # add into main
40
+ def job(name=nil, &block)
41
+ Pushpop.add_job(name, &block)
42
+ end
43
+
44
+ Pushpop.logger = lambda {
45
+ logger = Logger.new($stdout)
46
+ if ENV['DEBUG']
47
+ logger.level = Logger::DEBUG
48
+ elsif ENV['RACK_ENV'] == 'test'
49
+ logger.level = Logger::FATAL
50
+ else
51
+ logger.level = Logger::INFO
52
+ end
53
+ logger
54
+ }.call
55
+
@@ -0,0 +1,95 @@
1
+ module Pushpop
2
+
3
+ class Job
4
+
5
+ class << self
6
+
7
+ cattr_accessor :plugins
8
+ self.plugins = {}
9
+
10
+ def register_plugin(name, klass)
11
+ self.plugins ||= {}
12
+ self.plugins[name.to_s] = klass
13
+ end
14
+
15
+ end
16
+
17
+ attr_accessor :name
18
+ attr_accessor :every_duration
19
+ attr_accessor :every_options
20
+ attr_accessor :steps
21
+
22
+ def initialize(name=nil, &block)
23
+ self.name = name || Pushpop.random_name
24
+ self.steps = []
25
+ self.every_options = {}
26
+ self.instance_eval(&block)
27
+ end
28
+
29
+ def every(duration, options={})
30
+ self.every_duration = duration
31
+ self.every_options = options
32
+ end
33
+
34
+ def step(name=nil, plugin=nil, &block)
35
+ if plugin
36
+
37
+ plugin_klass = self.class.plugins[plugin]
38
+ raise "No plugin configured for #{plugin}" unless plugin_klass
39
+
40
+ self.add_step(plugin_klass.new(name, plugin, &block))
41
+ else
42
+ self.add_step(Step.new(name, plugin, &block))
43
+ end
44
+ end
45
+
46
+ def add_step(step)
47
+ self.steps.push(step)
48
+ end
49
+
50
+ def schedule
51
+ Clockwork.manager.every(every_duration, name, every_options) do
52
+ run
53
+ end
54
+ end
55
+
56
+ def run
57
+
58
+ # track the last response, and all responses
59
+ last_response = nil
60
+ step_responses = {}
61
+
62
+ self.steps.each do |step|
63
+
64
+ # track the last_response and all responses
65
+ last_response = step.run(last_response, step_responses)
66
+ step_responses[step.name] = last_response
67
+
68
+ # abort unless this step returned truthily
69
+ return unless last_response
70
+ end
71
+
72
+ # log responses in debug
73
+ Pushpop.logger.info("#{name}: #{step_responses}")
74
+
75
+ # return the last response and all responses
76
+ [last_response, step_responses]
77
+ end
78
+
79
+ def method_missing(method, *args, &block)
80
+ plugin_class = self.class.plugins[method.to_s]
81
+
82
+ name = args[0]
83
+ plugin = method.to_s
84
+
85
+ if plugin_class
86
+ step(name, plugin, &block)
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+