pushpop 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+