mushy 0.2.6 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1f4610ff32999add5edef562475fff259d62961c020d10abec4e2bfbe64344f
4
- data.tar.gz: c0d2c08fdf345a28e7abfb9377309c1c1c3d09c0c38a28ca106e911da0bdb12f
3
+ metadata.gz: 49ce2c989b79318911d3941f9733d582a5911e9b7c31e73fb50bae29d63ee5e0
4
+ data.tar.gz: c9cff38e82362e8ec8299ae84884b1c1cfdc511f367c832697f6cb538143b505
5
5
  SHA512:
6
- metadata.gz: e7995542973e879c9dc1485182f74b2f648d37eb711b21017de11370a5839a0c92663d48fbcf1192781f121db1dddf0a367f68865a4761881306712fed37bbaa
7
- data.tar.gz: a89ff7d26708e89c7d64fc8486146a4b51bcbba9abe8ad824796c90f6bae217f1f6578f41ca5772a8f105ec13e8e60c9981673dffdc7e88477ce2a11afa23fc9
6
+ metadata.gz: ef122c23b39ef1ef6dbe3675b66f55840c243341403d5b22f31356c2d31b1dd9fdc66f6572ff6861cfb2ea2c43257c064ab8411e15f01da29a472d4612c8fa89
7
+ data.tar.gz: 79a7708ce3fda3f0081d00a767ccc588967a2cbc44f37e27363a769234eb43a1fc53a0e50e1fa74e245497304ee6185b3160a14cac2216c71e09d09ed632f31e
data/bin/mushy CHANGED
@@ -10,7 +10,8 @@ class MushyCLI < Thor
10
10
 
11
11
  desc "start FILE", "Run this workflow file."
12
12
  def start
13
- Mushy::Builder::Api.start file, values
13
+ v = values || {}
14
+ Mushy::Builder::Api.start file, v
14
15
  end
15
16
 
16
17
  desc "build FILE", 'Build a flow.'
@@ -1,3 +1,5 @@
1
+ require 'daemons'
2
+
1
3
  module Mushy
2
4
 
3
5
  module Builder
@@ -32,9 +34,34 @@ module Mushy
32
34
  file = "#{file}.json" unless file.downcase.end_with?('.json')
33
35
  flow = File.open(file).read
34
36
  flow = Mushy::Flow.parse flow
35
- flux = flow.fluxs.select { |x| x.type == 'Cli' }.first
36
37
 
37
- Mushy::Runner.new.start event, flux, flow
38
+ service_fluxes = flow.fluxs.select { |x| x.respond_to? :loop }
39
+
40
+ pwd = Dir.pwd
41
+
42
+ if service_fluxes.any?
43
+ calls = service_fluxes
44
+ .map { |s| { flux: s, proc: ->(e) do
45
+ Dir.chdir pwd
46
+ Mushy::Runner.new.start e, s, flow
47
+ end } }
48
+ .map { |p| ->() { p[:flux].loop &p[:proc] } }
49
+ .map { |x| ->() { loop &x } }
50
+ .map { |x| run_as_a_daemon &x }
51
+
52
+ puts calls.inspect
53
+
54
+ exit
55
+ end
56
+
57
+ cli_flux = flow.fluxs.select { |x| x.kind_of?(Mushy::Cli) }.first
58
+
59
+ Mushy::Runner.new.start event, cli_flux, flow
60
+ end
61
+
62
+ def self.run_as_a_daemon &block
63
+ #block.call
64
+ Daemons.call(&block).pid.pid
38
65
  end
39
66
 
40
67
  def self.get_flow file
@@ -68,6 +95,14 @@ module Mushy
68
95
  details[:config][:sort] = { type: 'text', shrink: true, description: 'Sort by this key.', default: '' }
69
96
  details[:config][:model] = { type: 'keyvalue', shrink: true, description: 'Reshape the outgoing events.', value: {}, default: {} }
70
97
 
98
+ details[:config][:error_strategy] = {
99
+ description: 'Error strategy. (return to return an event with "exception" returning the error, or ignore to ignore the exception)',
100
+ type: 'select',
101
+ options: ['', 'return', 'ignore'],
102
+ value: '',
103
+ shrink: true,
104
+ }
105
+
71
106
  details[:config]
72
107
  .select { |_, v| v[:type] == 'keyvalue' }
73
108
  .select { |_, v| v[:editors].nil? }
@@ -0,0 +1,30 @@
1
+ module Mushy
2
+
3
+ module DateParts
4
+
5
+ def self.parse now
6
+ {
7
+ year: nil,
8
+ month: nil,
9
+ day: nil,
10
+ hour: nil,
11
+ minute: :min,
12
+ second: :sec,
13
+ nanosecond: :nsec,
14
+ utc_offset: nil,
15
+ weekday: :wday,
16
+ day_of_month: :mday,
17
+ day_of_year: :yday,
18
+ string: :to_s,
19
+ epoch_integer: :to_i,
20
+ epoch_float: :to_f,
21
+ }.reduce({}) do |t, i|
22
+ method = i[1] || i[0]
23
+ t[i[0]] = now.send method
24
+ t
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
data/lib/mushy/flux.rb CHANGED
@@ -77,6 +77,10 @@ module Mushy
77
77
 
78
78
  returned_one_result ? results.first : results
79
79
 
80
+ rescue Exception => e
81
+ raise e if config[:error_strategy].to_s == ''
82
+ return [] if config[:error_strategy] == 'ignore'
83
+ { exception: e.message }
80
84
  end
81
85
 
82
86
  def standardize_these results
@@ -15,6 +15,7 @@ module Mushy
15
15
  directory: {
16
16
  description: 'The working directory in which the command will be run.',
17
17
  type: 'text',
18
+ shrink: true,
18
19
  value: '',
19
20
  },
20
21
  },
@@ -18,7 +18,7 @@ module Mushy
18
18
  description: 'Run this browser headless.',
19
19
  type: 'boolean',
20
20
  shrink: true,
21
- value: 'true',
21
+ value: '',
22
22
  },
23
23
  timeout: {
24
24
  description: 'The default timeout (in seconds) before closing the browser. Default is 5 seconds.',
@@ -90,7 +90,9 @@ module Mushy
90
90
 
91
91
  browser.headers.add get_the_headers_from(event, config)
92
92
 
93
+ the_start = Time.now
93
94
  browser.goto config[:url]
95
+ time = Time.now - the_start
94
96
 
95
97
  browser.execute(config[:execute]) if config[:execute]
96
98
 
@@ -102,6 +104,7 @@ module Mushy
102
104
  title: browser.frames[0].title,
103
105
  cookies: browser.cookies.all.map { |k, v| v.instance_variable_get('@attributes') },
104
106
  headers: browser.headers.get,
107
+ time: time,
105
108
  body: browser.body
106
109
  }
107
110
 
@@ -0,0 +1,27 @@
1
+ module Mushy
2
+
3
+ class Document < Flux
4
+
5
+ def self.details
6
+ {
7
+ name: 'Document',
8
+ description: 'Create a multi-line document.',
9
+ config: {
10
+ document: {
11
+ description: 'The multi-line document you wish to create.',
12
+ type: 'textarea',
13
+ value: '',
14
+ },
15
+ },
16
+ }
17
+ end
18
+
19
+ def process event, config
20
+ {
21
+ document: config[:document],
22
+ }
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,86 @@
1
+ module Mushy
2
+
3
+ class GitLog < Bash
4
+
5
+ def self.details
6
+ {
7
+ name: 'GitLog',
8
+ description: 'Return git logs.',
9
+ config: {
10
+ directory: {
11
+ description: 'The working directory in which the command will be run.',
12
+ type: 'text',
13
+ shrink: true,
14
+ value: '',
15
+ },
16
+ after: {
17
+ description: 'Filter for commits after this',
18
+ type: 'text',
19
+ shrink: true,
20
+ value: '',
21
+ },
22
+ before: {
23
+ description: 'Filter for commits before this',
24
+ type: 'text',
25
+ shrink: true,
26
+ value: '',
27
+ },
28
+ author: {
29
+ description: 'Filter for commits by this author',
30
+ type: 'text',
31
+ shrink: true,
32
+ value: '',
33
+ },
34
+ committer: {
35
+ description: 'Filter for commits by this committer',
36
+ type: 'text',
37
+ shrink: true,
38
+ value: '',
39
+ },
40
+ },
41
+ }
42
+ end
43
+
44
+ def process event, config
45
+
46
+ config[:command] = 'git log'
47
+
48
+ if config[:directory].to_s != ''
49
+ config[:command] = "cd \"#{config[:directory]}\";#{config[:command]}"
50
+ end
51
+
52
+ [:after, :before, :author, :committer]
53
+ .select { |x| config[x].to_s != ''}
54
+ .each { |k| config[:command] = "#{config[:command]} --#{k}=\"#{config[k]}\"" }
55
+
56
+ result = super event, config
57
+
58
+ return result unless result[:success]
59
+
60
+ result[:text].split("\n\n").reduce([]) do |results, line|
61
+ if line.start_with? 'commit'
62
+ results << { message: line.sub('commit', 'commit:') }
63
+ else
64
+ results[-1][:message] = results[-1][:message] + "\nMessage: " + line.strip
65
+ end
66
+ results
67
+ end.map { |x| x[:message] }.map do |line|
68
+ line.split("\n").reduce({}) do |t, i|
69
+ segments = i.split ':'
70
+ key = segments.shift.strip.downcase.to_sym
71
+ t[key] = segments.map { |y| y.strip }.join ':'
72
+ t
73
+ end
74
+ end.map do |commit|
75
+ commit.tap do |x|
76
+ segments = x[:author].split '<'
77
+ x[:author_name] = segments.shift.strip
78
+ x[:author_email] = segments.join('').strip.gsub('>', '')
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,56 @@
1
+ require 'csv'
2
+
3
+ module Mushy
4
+
5
+ class Interval < Flux
6
+
7
+ def self.setup
8
+ {
9
+ seconds: ->(x) { x },
10
+ minutes: ->(x) { x * 60 },
11
+ hours: ->(x) { x * 60 * 60 },
12
+ days: ->(x) { x * 60 * 60 * 24 },
13
+ weeks: ->(x) { x * 60 * 60 * 24 * 7 },
14
+ }
15
+ end
16
+
17
+ def self.details
18
+ {
19
+ name: 'Interval',
20
+ description: 'Fire an event every X minutes.',
21
+ config: {},
22
+ }.tap do |c|
23
+ setup.keys.each do |key|
24
+ c[:config][key] = {
25
+ description: "#{key.to_s.capitalize} until the job is fired again.",
26
+ type: 'integer',
27
+ shrink: true,
28
+ value: '',
29
+ }
30
+ end
31
+ end
32
+ end
33
+
34
+ def loop &block
35
+ event = { time: time }
36
+ block.call event
37
+ sleep time
38
+ end
39
+
40
+ def time
41
+ the_time = self.class.setup.keys
42
+ .select { |x| config[x].to_s != '' }
43
+ .map { |x| self.class.setup[x].call(config[x].to_i) }
44
+ .sum
45
+
46
+ the_time > 0 ? the_time : 60
47
+ end
48
+
49
+ def process event, config
50
+ now = Time.now
51
+ Mushy::DateParts.parse now
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -6,30 +6,133 @@ module Mushy
6
6
  {
7
7
  name: 'Ls',
8
8
  description: 'Run the "ls" command.',
9
- config: {
10
- directory: {
11
- description: 'The working directory in which the command will be run.',
12
- type: 'text',
13
- value: '',
14
- },
15
- },
16
- }
9
+ config: Mushy::Bash.details[:config].tap { |c| c.delete :command },
10
+ }.tap do |c|
11
+ c[:config][:recursive] = {
12
+ description: 'Pull files recursively.',
13
+ type: 'boolean',
14
+ shrink: true,
15
+ value: '',
16
+ }
17
+ c[:config][:path] = {
18
+ description: 'Path, used to search for specific files.',
19
+ type: 'text',
20
+ shrink: true,
21
+ value: '',
22
+ }
23
+ end
17
24
  end
18
25
 
19
26
  def process event, config
27
+ arguments = build_the_arguments_from config
20
28
 
21
- config[:command] = 'ls'
22
-
29
+ config[:command] = build_the_command_from arguments
23
30
  result = super event, config
24
31
 
25
- return result unless result[:success]
32
+ things = turn_the_ls_output_to_events result, config, event
33
+ things
34
+ end
35
+
36
+ def build_the_command_from arguments
37
+ "ls #{arguments.join(' ')}"
38
+ end
39
+
40
+ def build_the_arguments_from config
41
+ arguments = ['-A', '-l', '--full-time', '-i']
42
+ arguments << '-R' if config[:recursive].to_s == 'true'
43
+ arguments << '-d' if config[:directory_only].to_s == 'true'
44
+ arguments << config[:path] if config[:path].to_s != ''
45
+ arguments
46
+ end
47
+
48
+ def turn_the_ls_output_to_events result, config, event
49
+
50
+ lines = result[:text].split("\n")
51
+
52
+ needs_special_work_for_path = config[:directory_only].to_s != 'true' &&
53
+ config[:path].to_s != '' &&
54
+ lines[0].start_with?('total ')
55
+
56
+ origin = config[:directory] || Dir.pwd
57
+ directory = needs_special_work_for_path ? '||DIRECTORY||' : origin
58
+
59
+ things = lines.map do |x|
60
+ segments = x.split ' '
61
+ result = if segments.count > 5
62
+ pull_file segments, directory
63
+ elsif segments.count == 1
64
+ dir_segments = segments[0].split("\/")
65
+
66
+ if dir_segments[0] == '.'
67
+ dir_segments[0] = origin
68
+ else
69
+ dir_segments.unshift origin
70
+ end
71
+
72
+ dir_segments[-1] = dir_segments[-1].sub ':', ''
73
+ directory = dir_segments.join("\/")
74
+ nil
75
+ else
76
+ nil
77
+ end
78
+ end.select { |x| x }
79
+
80
+ if needs_special_work_for_path
81
+ config[:directory_only] = true
82
+ special_name = process(event, config)[0][:name]
83
+ things.each do |x|
84
+ [:directory, :path].each do |key|
85
+ if x[key].include?('||DIRECTORY||')
86
+ x[key].sub!('||DIRECTORY||', File.join(Dir.pwd, special_name))
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ things
93
+ end
94
+
95
+ def pull_file segments, directory
96
+ result = {}
97
+
98
+ [:inode, :help, :hard_links, :owner, :group, :size].each do |key|
99
+ result[key] = segments.shift; x = segments.join ' '
100
+ end
101
+
102
+ result.tap do |r|
103
+ r[:date] = []
104
+ 3.times { r[:date] << segments.shift }
105
+ r[:date] = r[:date].join ' '
106
+ r[:date] = Time.parse r[:date]
107
+ end
108
+
109
+ result[:name] = segments.shift
110
+
111
+ result.tap do |r|
112
+ help_segments = r[:help].split ''
113
+ r[:type] = help_segments[0]
114
+ r[:owner_permission] = [1, 2, 3].map { |i| help_segments[i] }.reduce('') { |t, i| t + i }
115
+ r[:group_permission] = [4, 5, 6].map { |i| help_segments[i] }.reduce('') { |t, i| t + i }
116
+ r[:other_permission] = [7, 8, 9].map { |i| help_segments[i] }.reduce('') { |t, i| t + i }
117
+ r.delete :help
118
+ end
119
+
120
+ [:hard_links, :size].each { |x| result[x] = result[x].to_i }
121
+
122
+ result[:date] = Mushy::DateParts.parse result[:date]
123
+
124
+ result[:directory] = directory
26
125
 
27
- result[:text].split("\n").map do |x|
28
- {
29
- name: x,
30
- }
126
+ if result[:type] == 'd' && result[:directory] == result[:name]
127
+ result[:path] = result[:directory]
128
+ name_segments = result[:name].split "\/"
129
+ result[:name] = name_segments.pop
130
+ result[:directory] = name_segments.join "\/"
131
+ else
132
+ result[:path] = File.join result[:directory], result[:name]
31
133
  end
32
134
 
135
+ result
33
136
  end
34
137
 
35
138
  end
@@ -0,0 +1,26 @@
1
+ module Mushy
2
+
3
+ class Print < Flux
4
+
5
+ def self.details
6
+ {
7
+ name: 'Print',
8
+ description: 'Print output to the screen.',
9
+ config: {
10
+ message: {
11
+ description: 'The message to display',
12
+ type: 'text',
13
+ value: '',
14
+ },
15
+ }
16
+ }
17
+ end
18
+
19
+ def process event, config
20
+ puts config[:message]
21
+ {}
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,31 @@
1
+ module Mushy
2
+
3
+ class Pwd < Bash
4
+
5
+ def self.details
6
+ {
7
+ name: 'Pwd',
8
+ description: 'Run the "pwd" command.',
9
+ config: Mushy::Bash.details[:config].tap { |c| c.delete :command },
10
+ }
11
+ end
12
+
13
+ def process event, config
14
+
15
+ config[:command] = 'pwd'
16
+
17
+ result = super event, config
18
+
19
+ return result unless result[:success]
20
+
21
+ pwd = result[:text].to_s.strip
22
+
23
+ {
24
+ pwd: Mushy::Ls.new.process({}, { path: pwd, directory_only: true })[0]
25
+ }
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -7,11 +7,10 @@ module Mushy
7
7
  details['name'] = 'Screenshot'
8
8
  details['description'] = 'Take a screenshot of the browser.'
9
9
 
10
- details[:config][:path] = {
11
- description: 'The path of the file to save.',
12
- type: 'text',
13
- value: 'picture.jpg',
14
- }
10
+ details[:config].merge!(Mushy::WriteFile.file_saving_config.tap do |x|
11
+ x[x.keys.first][:value] = 'file.jpg'
12
+ end)
13
+
15
14
  details[:config][:quality] = {
16
15
  description: 'The quality of the image, a value beteen 0-100. Only applies to jpg.',
17
16
  type: 'integer',
@@ -33,15 +32,19 @@ module Mushy
33
32
  the_result = input[:result]
34
33
  the_config = input[:config]
35
34
 
35
+ file = Mushy::WriteFile.get_file_from config
36
36
  options = {
37
- path: the_config[:path],
37
+ path: file,
38
38
  full: ['true', ''].include?(the_config[:full].to_s),
39
39
  quality: (the_config[:quality].to_s == '' ? '100' : the_config[:quality]).to_i
40
40
  }
41
41
 
42
42
  the_browser.screenshot options
43
43
 
44
- options
44
+ the_result[:options] = options
45
+ the_result[:file] = Mushy::Ls.new.process({}, { path: file })[0]
46
+
47
+ the_result
45
48
 
46
49
  end
47
50
 
@@ -6,34 +6,46 @@ module Mushy
6
6
  {
7
7
  name: 'WriteFile',
8
8
  description: 'Write a file.',
9
- config: {
10
- name: {
11
- description: 'The name of the file.',
12
- type: 'text',
13
- value: 'file.csv',
14
- },
15
- directory: {
16
- description: 'The directory in which to write the file. Leave blank for the current directory.',
17
- type: 'text',
18
- value: '',
19
- },
20
- data: {
21
- description: 'The text to write. You can use Liquid templating here to pull data from the event, or write hardcoded data.',
22
- type: 'text',
23
- value: '{{data}}',
24
- },
25
- },
9
+ config: file_saving_config.merge({
10
+ data: {
11
+ description: 'The text to write. You can use Liquid templating here to pull data from the event, or write hardcoded data.',
12
+ type: 'text',
13
+ value: '{{data}}',
14
+ },
15
+ }),
26
16
  }
27
17
  end
28
18
 
29
- def process event, config
30
- file = config[:name]
19
+ def self.file_saving_config
20
+ {
21
+ name: {
22
+ description: 'The name of the file.',
23
+ type: 'text',
24
+ value: 'file.csv',
25
+ },
26
+ directory: {
27
+ description: 'The directory in which to write the file. Leave blank for the current directory.',
28
+ shrink: true,
29
+ type: 'text',
30
+ value: '',
31
+ },
32
+ }
33
+ end
31
34
 
35
+ def self.get_file_from config
36
+ file = config[:name]
32
37
  file = File.join(config[:directory], file) if config[:directory].to_s != ''
38
+ file
39
+ end
40
+
41
+ def process event, config
42
+ file = self.class.get_file_from config
33
43
 
34
44
  File.open(file, 'w') { |f| f.write config[:data] }
35
45
 
36
- {}
46
+ {
47
+ file: Mushy::Ls.new.process({}, { path: file })[0]
48
+ }
37
49
  end
38
50
 
39
51
  end
data/mushy.gemspec CHANGED
@@ -4,7 +4,7 @@ require 'mushy/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'mushy'
7
- s.version = '0.2.6'
7
+ s.version = '0.5.0'
8
8
  s.date = '2020-11-23'
9
9
  s.summary = 'Process streams of work using common modules.'
10
10
  s.description = 'This tool assists in the creation and processing of workflows.'
@@ -25,4 +25,5 @@ Gem::Specification.new do |s|
25
25
  s.add_runtime_dependency 'nokogiri'
26
26
  s.add_runtime_dependency 'faraday'
27
27
  s.add_runtime_dependency 'pony'
28
+ s.add_runtime_dependency 'daemons'
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mushy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Cauthon
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: daemons
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: This tool assists in the creation and processing of workflows.
140
154
  email: darren@cauthon.com
141
155
  executables:
@@ -150,6 +164,7 @@ files:
150
164
  - lib/mushy/builder/dark.rb
151
165
  - lib/mushy/builder/index.rb
152
166
  - lib/mushy/builder/vue.rb
167
+ - lib/mushy/date_parts.rb
153
168
  - lib/mushy/event.rb
154
169
  - lib/mushy/flow.rb
155
170
  - lib/mushy/flux.rb
@@ -158,13 +173,18 @@ files:
158
173
  - lib/mushy/fluxs/build_csv.rb
159
174
  - lib/mushy/fluxs/cli.rb
160
175
  - lib/mushy/fluxs/collection.rb
176
+ - lib/mushy/fluxs/document.rb
161
177
  - lib/mushy/fluxs/environment.rb
162
178
  - lib/mushy/fluxs/filter.rb
163
179
  - lib/mushy/fluxs/format.rb
164
180
  - lib/mushy/fluxs/get.rb
181
+ - lib/mushy/fluxs/git_log.rb
182
+ - lib/mushy/fluxs/interval.rb
165
183
  - lib/mushy/fluxs/ls.rb
166
184
  - lib/mushy/fluxs/parse_html.rb
167
185
  - lib/mushy/fluxs/pdf.rb
186
+ - lib/mushy/fluxs/print.rb
187
+ - lib/mushy/fluxs/pwd.rb
168
188
  - lib/mushy/fluxs/read_csv.rb
169
189
  - lib/mushy/fluxs/read_file.rb
170
190
  - lib/mushy/fluxs/screenshot.rb