jekyll-recker 1.6.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e0cc3d6cafa2518fb5819ad8cc4a6db7ecf88e214b0e998468f521d0ec19a37
4
- data.tar.gz: e623e1c53b62d3ccf0a55ac572ef0fc4257e03cdf7faf543baa1f5ce7d0a40ed
3
+ metadata.gz: 15d0b79e8f6f9370433856ad0d89a1ae7996d0900644739fa915bd5f155e60c9
4
+ data.tar.gz: 630418f988d9e17ac451be9932aa6e3f881cb71a37570b7d4e70bd3f1b629477
5
5
  SHA512:
6
- metadata.gz: b45d3daae8d8af21c963a412d8430dce81bafaff270a35ca94444b01e74a7d4bd25e422a3ac9afb958bb3693cd7359d4bab70a07776d1da7c3637a38d633eed7
7
- data.tar.gz: 4f6aadcd49f0b0d71232ab67c361d3aac1e5a91887272d39e826e3300afa8e0cf872b2154f6e5371dda74a5fd8ea9ac928bd7a2acc6b98357be2e87b75d25903
6
+ metadata.gz: 141f627ae47682e8cd42320cd522693e33f01970f8f229c7394f26d66e1a13284ac1f73f8ac90fc4361093dccef209698a89ea168be299b9fae264efe6106523
7
+ data.tar.gz: 9563f420e21f8a343c409521b06065c5d36f8aad3f503303511e913ec37b1d15ee476819bcffa1ccf4a6c8781b6c1da8d52b474c25dbc007a68e3d27395412aa
@@ -2,7 +2,7 @@
2
2
  {%- if include.url %}
3
3
  <a href="{{ include.url }}">
4
4
  {%- endif %}
5
- <img alt="{{ alt | default: include.filename }}" src="{{ site.baseurl }}assets/images/{{ include.filename }}"/>
5
+ <img alt="{{ include.alt | default: include.filename }}" src="{{ site.baseurl }}assets/images/{{ include.filename }}"/>
6
6
  {%- if include.url %}
7
7
  </a>
8
8
  {%- endif %}
@@ -2,23 +2,19 @@
2
2
 
3
3
  require 'jekyll'
4
4
 
5
- module Jekyll
6
- # Recker
7
- module Recker
8
- require 'jekyll_recker/logger.rb'
9
- require 'jekyll_recker/mixins.rb'
5
+ # jekyll-recker
6
+ #
7
+ # The greatest jekyll plugin in the world
8
+ module JekyllRecker
9
+ autoload :Configuration, 'jekyll_recker/configuration.rb'
10
+ autoload :Mixins, 'jekyll_recker/mixins.rb'
11
+ autoload :Shell, 'jekyll_recker/shell.rb'
12
+ autoload :Social, 'jekyll_recker/social.rb'
13
+ autoload :VERSION, 'jekyll_recker/version.rb'
10
14
 
11
- require 'jekyll_recker/commands.rb'
12
- require 'jekyll_recker/configuration.rb'
13
- require 'jekyll_recker/error.rb'
14
- require 'jekyll_recker/facebook.rb'
15
- require 'jekyll_recker/filters.rb'
16
- require 'jekyll_recker/generators.rb'
17
- require 'jekyll_recker/shell.rb'
18
- require 'jekyll_recker/slack.rb'
19
- require 'jekyll_recker/tags.rb'
20
- require 'jekyll_recker/twitter.rb'
21
- require 'jekyll_recker/version.rb'
22
- require 'jekyll_recker/words.rb'
23
- end
15
+ # Eager loads!
16
+ require 'jekyll_recker/commands.rb'
17
+ require 'jekyll_recker/filters.rb'
18
+ require 'jekyll_recker/generators.rb'
19
+ require 'jekyll_recker/tags.rb'
24
20
  end
@@ -1,34 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- # Commands
6
- module Commands
7
- # Share
8
- class Share < Jekyll::Command
9
- include Mixins::Logging
3
+ module JekyllRecker
4
+ # Commands
5
+ module Commands
6
+ # Share
7
+ class Share < Jekyll::Command
8
+ include Mixins::Logging
10
9
 
11
- def self.init_with_program(prog)
12
- prog.command(:share) do |c|
13
- c.syntax 'share'
14
- c.description 'Share latest post with each configured backend'
15
- c.option 'dry', '-d', '--dry', 'perform dry run'
16
- c.action { |args, opts| action(args, opts) }
17
- end
10
+ def self.init_with_program(prog)
11
+ prog.command(:share) do |c|
12
+ c.syntax 'share'
13
+ c.description 'Share latest post with each configured backend'
14
+ c.option 'dry', '-d', '--dry', 'perform dry run'
15
+ c.action { |args, opts| action(args, opts) }
18
16
  end
17
+ end
19
18
 
20
- def self.action(args, options)
21
- if args.empty? || args.include?('slack')
22
- Recker::Slack.share(dry: options['dry'])
23
- elsif args.empty? || args.include?('twitter')
24
- Recker::Twitter.share(dry: options['dry'])
25
- # elsif args.empty? || args.include?('facebook')
26
- # Recker::Facebook.share(dry: options['dry'])
27
- end
28
- rescue ReckerError => e
29
- logger.error e.message
30
- exit 1
31
- end
19
+ def self.action(args, options)
20
+ JekyllRecker::Social.action(args, options)
21
+ rescue Error => e
22
+ logger.error e.message
23
+ exit 1
32
24
  end
33
25
  end
34
26
  end
@@ -1,39 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- # Configuration
6
- module Configuration
7
- def self.jekyll
8
- @jekyll ||= Jekyll.configuration
9
- end
3
+ module JekyllRecker
4
+ # Configuration
5
+ module Configuration
6
+ def self.jekyll
7
+ @jekyll ||= Jekyll.configuration
8
+ end
10
9
 
11
- def self.recker
12
- jekyll.fetch('recker', {})
13
- end
10
+ def self.recker
11
+ jekyll.fetch('recker', {})
12
+ end
14
13
 
15
- def self.facebook
16
- recker.fetch('facebook', {})
17
- end
14
+ def self.facebook
15
+ recker.fetch('facebook', {})
16
+ end
18
17
 
19
- def self.twitter
20
- recker.fetch('twitter', {})
21
- end
18
+ def self.twitter
19
+ recker.fetch('twitter', {})
20
+ end
22
21
 
23
- def self.slack
24
- recker.fetch('slack', {})
25
- end
22
+ def self.slack
23
+ recker.fetch('slack', {})
24
+ end
26
25
 
27
- def self.site
28
- @site = Jekyll::Site.new(jekyll)
29
- @site.reset
30
- @site.read
31
- @site
32
- end
26
+ def self.site
27
+ @site = Jekyll::Site.new(jekyll)
28
+ @site.reset
29
+ @site.read
30
+ @site
31
+ end
33
32
 
34
- def self.latest_post
35
- @latest_post ||= site.posts.docs.last
36
- end
33
+ def self.latest_post
34
+ @latest_post ||= site.posts.docs.last
37
35
  end
38
36
  end
39
37
  end
@@ -1,15 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- # Filters
6
- module Filters
7
- # Converts a date object to standard Uhh Yeah Dude format.
8
- def uyd_date(date)
9
- date.strftime('%A, %B %d %Y')
10
- end
3
+ module JekyllRecker
4
+ # Filters
5
+ module Filters
6
+ # Converts a date object to standard Uhh Yeah Dude format.
7
+ def uyd_date(date)
8
+ date.strftime('%A, %B %d %Y')
9
+ end
10
+
11
+ # Adds commas to a number
12
+ def pretty(num)
13
+ num.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
11
14
  end
12
15
  end
13
16
  end
14
17
 
15
- Liquid::Template.register_filter(Jekyll::Recker::Filters)
18
+ Liquid::Template.register_filter(JekyllRecker::Filters)
@@ -1,111 +1,152 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- module Generators
6
- # Stats Module
7
- #
8
- # Functions for stats generators.
9
- # @abstract
10
- module Stats
11
- include Mixins::Logging
12
- include Jekyll::Filters
13
-
14
- def key
15
- self.class.const_get(:KEY)
3
+ require 'mini_magick'
4
+ require 'fastimage'
5
+
6
+ module JekyllRecker
7
+ module Generators
8
+ # Image Resize Generator
9
+ class ImageResize < Jekyll::Generator
10
+ include Mixins::Logging
11
+
12
+ def generate(site)
13
+ @site = site
14
+ logger.info 'checking images'
15
+ resizeable_images.each do |f, d|
16
+ logger.info "resizing #{f} to fit #{d}"
17
+ image = MiniMagick::Image.new(f)
18
+ image.resize d
16
19
  end
20
+ end
17
21
 
18
- def generate(site)
19
- @site = site
20
- logger.info "crunching stats.#{key}"
21
- @site.data['stats'] ||= {}
22
- @site.data['stats'][key] = crunch
23
- end
22
+ def image?(file)
23
+ ['.jpg', 'jpeg', '.png', '.svg'].include? File.extname(file)
24
+ end
24
25
 
25
- def crunch
26
- raise NotImplementedError, '#crunch not implemented!'
27
- end
26
+ def too_big?(width, height)
27
+ width > 800 || height > 800
28
+ end
28
29
 
29
- # Calculates the average of a list of numbers.
30
- #
31
- # @param [Array<Numeric>] numlist list of numbers to be averaged.
32
- # @return [Numeric] rounded, calculated average of numlist.
33
- def average(numlist)
34
- calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
35
- calc.round
36
- end
30
+ def images
31
+ @site.static_files.collect(&:path).select { |f| image?(f) }
32
+ end
37
33
 
38
- # Calculates the total of a list of numbers.
39
- #
40
- # @param [Array<Numeric>] numlist list of numbers to be totaled.
41
- # @return [Numeric] calculated total of numlist.
42
- def total(numlist)
43
- numlist.inject(0) { |sum, x| sum + x }
34
+ def resizeable_images
35
+ with_sizes = images.map { |f| [f, FastImage.size(f)].flatten }
36
+ with_sizes.select! { |f| too_big?(f[1], f[2]) }
37
+ with_sizes.map do |f, w, h|
38
+ dimensions = if w > h
39
+ '800x600'
40
+ else
41
+ '600x800'
42
+ end
43
+ [f, dimensions]
44
44
  end
45
+ end
46
+ end
45
47
 
46
- def entries
47
- @site.posts.docs.select(&:published?)
48
- end
48
+ # Stats Module
49
+ #
50
+ # Functions for stats generators.
51
+ # @abstract
52
+ module Stats
53
+ include Mixins::Logging
54
+ include Jekyll::Filters
55
+
56
+ def key
57
+ self.class.const_get(:KEY)
49
58
  end
50
59
 
51
- # Post Count Generator
52
- class PostCount < Jekyll::Generator
53
- include Stats
60
+ def generate(site)
61
+ @site = site
62
+ logger.info "crunching stats.#{key}"
63
+ @site.data['stats'] ||= {}
64
+ @site.data['stats'][key] = crunch
65
+ end
54
66
 
55
- KEY = 'posts'
67
+ def crunch
68
+ raise NotImplementedError, '#crunch not implemented!'
69
+ end
56
70
 
57
- def crunch
58
- entries.count.pretty
59
- end
71
+ # Calculates the average of a list of numbers.
72
+ #
73
+ # @param [Array<Numeric>] numlist list of numbers to be averaged.
74
+ # @return [Numeric] rounded, calculated average of numlist.
75
+ def average(numlist)
76
+ calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
77
+ calc.round
78
+ end
79
+
80
+ # Calculates the total of a list of numbers.
81
+ #
82
+ # @param [Array<Numeric>] numlist list of numbers to be totaled.
83
+ # @return [Numeric] calculated total of numlist.
84
+ def total(numlist)
85
+ numlist.inject(0) { |sum, x| sum + x }
60
86
  end
61
87
 
62
- # Word Count Generator
63
- class Words < Jekyll::Generator
64
- include Stats
88
+ def entries
89
+ @site.posts.docs.select(&:published?)
90
+ end
91
+ end
65
92
 
66
- KEY = 'words'
93
+ # Post Count Generator
94
+ class PostCount < Jekyll::Generator
95
+ include Stats
67
96
 
68
- def crunch
69
- total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
70
- {
71
- 'average' => average(total_counts).pretty,
72
- 'total' => total(total_counts).pretty
73
- }
74
- end
97
+ KEY = 'posts'
98
+
99
+ def crunch
100
+ entries.count
75
101
  end
102
+ end
76
103
 
77
- # Streak Count Generator
78
- class Streaks < Jekyll::Generator
79
- include Stats
104
+ # Word Count Generator
105
+ class Words < Jekyll::Generator
106
+ include Stats
80
107
 
81
- KEY = 'days'
108
+ KEY = 'words'
82
109
 
83
- def crunch
84
- streaks.take(1).map do |count, dates|
85
- {
86
- 'days' => count.pretty,
87
- 'start' => dates[0],
88
- 'end' => dates[1]
89
- }
90
- end.first
91
- end
110
+ def crunch
111
+ total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
112
+ {
113
+ 'average' => average(total_counts),
114
+ 'total' => total(total_counts)
115
+ }
116
+ end
117
+ end
92
118
 
93
- private
94
-
95
- def streaks
96
- _streaks = []
97
- entry_dates.slice_when do |prev, curr|
98
- curr != prev - 1
99
- end.each do |dates|
100
- first, last = dates.minmax
101
- _streaks << [(last - first).to_i, [first, last]]
102
- end
103
- _streaks
104
- end
119
+ # Streak Count Generator
120
+ class Streaks < Jekyll::Generator
121
+ include Stats
122
+
123
+ KEY = 'days'
105
124
 
106
- def entry_dates
107
- entries.collect(&:date).map { |t| Date.new(t.year, t.month, t.day) }.sort.reverse
125
+ def crunch
126
+ streaks.take(1).map do |count, dates|
127
+ {
128
+ 'days' => count,
129
+ 'start' => dates[0],
130
+ 'end' => dates[1]
131
+ }
132
+ end.first
133
+ end
134
+
135
+ private
136
+
137
+ def streaks
138
+ _streaks = []
139
+ entry_dates.slice_when do |prev, curr|
140
+ curr != prev - 1
141
+ end.each do |dates|
142
+ first, last = dates.minmax
143
+ _streaks << [(last - first).to_i, [first, last]]
108
144
  end
145
+ _streaks
146
+ end
147
+
148
+ def entry_dates
149
+ entries.collect(&:date).map { |t| Date.new(t.year, t.month, t.day) }.sort.reverse
109
150
  end
110
151
  end
111
152
  end
@@ -1,28 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- module Mixins
6
- # Descendants
7
- module Descendants
8
- def self.included(base)
9
- base.extend(self)
10
- end
3
+ require 'logger'
11
4
 
12
- def descendants
13
- ObjectSpace.each_object(Class).select { |klass| klass < self }
14
- end
5
+ module JekyllRecker
6
+ module Mixins
7
+ # Introspection
8
+ #
9
+ # Adds functions which let the class see things about itself.
10
+ module Introspection
11
+ def self.included(base)
12
+ base.extend(self)
15
13
  end
16
14
 
17
- # Logging
18
- module Logging
19
- def self.included(base)
20
- base.extend(self)
21
- end
15
+ # Get the class instance
16
+ def class_name
17
+ self.class.name.split('::').last
18
+ end
19
+
20
+ # Get a list of all classes which inherit from this class
21
+ def descendants
22
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
23
+ end
24
+ end
25
+
26
+ # Logging
27
+ module Logging
28
+ def self.included(base)
29
+ base.extend(self)
30
+ end
22
31
 
23
- def logger
24
- Jekyll::Recker.logger
25
- end
32
+ def logger
33
+ @logger ||= Logger.new(
34
+ STDOUT,
35
+ formatter: proc { |_severity, _datetime, _progname, msg| "jekyll-recker: #{msg}\n" }
36
+ )
26
37
  end
27
38
  end
28
39
  end
@@ -2,13 +2,10 @@
2
2
 
3
3
  require 'open3'
4
4
 
5
- module Jekyll
6
- # Recker
7
- module Recker
8
- # ShellCommandFailed
9
- class ShellCommandFailed < ReckerError; end
10
-
11
- def self.shell(cmd)
5
+ module JekyllRecker
6
+ # Shell
7
+ module Shell
8
+ def self.run(cmd)
12
9
  out, err, status = Open3.capture3(cmd)
13
10
  return out if status.success?
14
11
 
@@ -22,7 +19,7 @@ module Jekyll
22
19
  #{err}
23
20
  ERROR
24
21
 
25
- raise ShellCommandFailed, msg
22
+ raise msg
26
23
  end
27
24
  end
28
25
  end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slack-notifier'
4
+ require 'twitter'
5
+
6
+ module JekyllRecker
7
+ module Social
8
+ def self.action(args, options)
9
+ args += %w[slack twitter] if args.empty?
10
+ Slack.share(dry: options['dry']) if args.include?('slack')
11
+ Twitter.share(dry: options['dry']) if args.include?('twitter')
12
+ end
13
+ # Backend
14
+ #
15
+ # Backend base class for social sharing backends.
16
+ # @abstract
17
+ class Share
18
+ include Mixins::Introspection
19
+ include Mixins::Logging
20
+
21
+ def self.share(dry: false)
22
+ backend = new(dry: dry)
23
+ logger.info "#{backend.name} - building configuration"
24
+ backend.configure!
25
+
26
+ logger.info "#{backend.name} - sharing \"#{backend.latest_title}\""
27
+ backend.post!
28
+ end
29
+
30
+ def initialize(dry: false)
31
+ @dry = dry
32
+ end
33
+
34
+ def dry?
35
+ @dry
36
+ end
37
+
38
+ def config
39
+ @config ||= JekyllRecker::Configuration.recker.fetch(config_key)
40
+ end
41
+
42
+ def config_key
43
+ class_name.downcase
44
+ end
45
+ alias name config_key
46
+
47
+ def post_body
48
+ url = File.join Configuration.jekyll['url'], latest.url
49
+ <<~BODY
50
+ #{latest.data['date'].strftime('%A, %B %-d %Y')}
51
+ #{latest.data['title']}
52
+ #{url}
53
+ BODY
54
+ end
55
+
56
+ def latest
57
+ @latest ||= Configuration.latest_post
58
+ end
59
+
60
+ def latest_title
61
+ latest.data['title']
62
+ end
63
+
64
+ def configure!
65
+ raise NotImplementedError
66
+ end
67
+
68
+ def post!
69
+ raise NotImplementedError
70
+ end
71
+ end
72
+
73
+ # Slack
74
+ #
75
+ # Slack social sharing backend
76
+ class Slack < Share
77
+ def configure!
78
+ @creds = {}
79
+ workspaces.each do |key, data|
80
+ webhook = ENV["SLACK_#{key.upcase}_WEBHOOK"] || extract_from_config(data)
81
+ if webhook.nil?
82
+ raise "cannot find slack webhook for #{key} workspace!"
83
+ end
84
+
85
+ @creds[key] = webhook
86
+ end
87
+ end
88
+
89
+ def post!
90
+ message_body = ::Slack::Notifier::Util::LinkFormatter.format(post_body)
91
+ workspaces.each do |key, config|
92
+ logger.info "posting to #{key} workspace"
93
+ if @dry
94
+ logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
95
+ else
96
+ ::Slack::Notifier.new(
97
+ @creds[key].strip,
98
+ channel: config.fetch('channel'),
99
+ username: config.fetch('username'),
100
+ icon_emoji: config.fetch('emoji')
101
+ ).post(text: message_body)
102
+ end
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def extract_from_config(data)
109
+ cmd = data['webhook_cmd']
110
+ return nil if cmd.nil?
111
+
112
+ Shell.run(cmd)
113
+ end
114
+
115
+ def workspaces
116
+ config.each
117
+ end
118
+ end
119
+
120
+ # Twitter
121
+ #
122
+ # Twitter social sharing backend
123
+ class Twitter < Share
124
+ def configure!
125
+ creds = extract_from_env || extract_from_config
126
+ raise 'cannot find twitter credentials!' if creds.nil?
127
+
128
+ @client = ::Twitter::REST::Client.new do |settings|
129
+ settings.consumer_key = creds['consumer_api_key']
130
+ settings.consumer_secret = creds['consumer_api_secret']
131
+ settings.access_token = creds['access_token']
132
+ settings.access_token_secret = creds['access_token_secret']
133
+ end
134
+ end
135
+
136
+ def post!
137
+ if dry?
138
+ logger.info('tweeting in dry mode, printing message')
139
+ logger.info("BEGIN TWEET\n#{post_body}END TWEET")
140
+ else
141
+ @client.update(post_body)
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ def extract_from_env
148
+ values = cred_fieldnames.map { |k| ENV["TWITTER_#{k.upcase}"] }
149
+
150
+ return nil if values.any? { |v| v.nil? || v.empty? }
151
+
152
+ Hash[cred_fieldnames.zip(values)]
153
+ end
154
+
155
+ def extract_from_config
156
+ values = cred_fieldnames.map do |k|
157
+ Shell.run(Configuration.twitter["#{k}_cmd"]).strip
158
+ end
159
+
160
+ return nil if values.any? { |v| v.nil? || v.empty? }
161
+
162
+ Hash[cred_fieldnames.zip(values)]
163
+ end
164
+
165
+ def cred_fieldnames
166
+ %w[
167
+ access_token_secret
168
+ access_token
169
+ consumer_api_key
170
+ consumer_api_secret
171
+ ]
172
+ end
173
+ end
174
+ end
175
+ end
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- module Tags
6
- # Returns the VERSION of the running jekyll-recker gem.
7
- class Version < Liquid::Tag
8
- def render(_context)
9
- VERSION
10
- end
3
+ module JekyllRecker
4
+ module Tags
5
+ # Returns the VERSION of the running jekyll-recker gem.
6
+ class Version < Liquid::Tag
7
+ def render(_context)
8
+ VERSION
11
9
  end
12
10
  end
13
11
  end
14
12
  end
15
13
 
16
- Liquid::Template.register_tag('recker_version', Jekyll::Recker::Tags::Version)
14
+ Liquid::Template.register_tag('recker_version', JekyllRecker::Tags::Version)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Recker
5
- VERSION = '1.6.0'
6
- end
3
+ module JekyllRecker
4
+ VERSION = '1.11.0'
7
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-recker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Recker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-28 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bump
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: fastimage
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: jekyll
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -109,7 +123,7 @@ dependencies:
109
123
  - !ruby/object:Gem::Version
110
124
  version: '3.8'
111
125
  - !ruby/object:Gem::Dependency
112
- name: koala
126
+ name: mini_magick
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -171,18 +185,13 @@ files:
171
185
  - lib/jekyll-recker.rb
172
186
  - lib/jekyll_recker/commands.rb
173
187
  - lib/jekyll_recker/configuration.rb
174
- - lib/jekyll_recker/error.rb
175
- - lib/jekyll_recker/facebook.rb
176
188
  - lib/jekyll_recker/filters.rb
177
189
  - lib/jekyll_recker/generators.rb
178
- - lib/jekyll_recker/logger.rb
179
190
  - lib/jekyll_recker/mixins.rb
180
191
  - lib/jekyll_recker/shell.rb
181
- - lib/jekyll_recker/slack.rb
192
+ - lib/jekyll_recker/social.rb
182
193
  - lib/jekyll_recker/tags.rb
183
- - lib/jekyll_recker/twitter.rb
184
194
  - lib/jekyll_recker/version.rb
185
- - lib/jekyll_recker/words.rb
186
195
  homepage: https://www.github.com/arecker/jekyll-recker/
187
196
  licenses:
188
197
  - GPLv3
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Recker
5
- # ReckerError
6
- class ReckerError < StandardError; end
7
- end
8
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'koala'
4
-
5
- module Jekyll
6
- module Recker
7
- # Facebook Client
8
- class Facebook
9
- include Mixins::Logging
10
-
11
- def self.share(dry: false)
12
- client = new(dry: dry)
13
- logger.info 'discovering credentials'
14
- client.discover_credentials!
15
- logger.info "sharing #{client.latest.data['title']}"
16
- client.post_latest!
17
- end
18
-
19
- def initialize(dry: false)
20
- @dry = dry
21
- end
22
-
23
- def discover_credentials!
24
- @creds = extract_from_env || extract_from_config
25
- raise ReckerError, 'cannot find facebook credentials!' if @creds.nil?
26
-
27
- set_credentials!
28
- end
29
-
30
- def post_latest!
31
- if @dry
32
- logger.info('posting in dry mode, printing message')
33
- logger.info("BEGIN POST\n#{post_body.strip}\nEND POST")
34
- else
35
- @graph.put_connections("me", "feed", message: "I am writing on my wall!")
36
- end
37
- end
38
-
39
- def latest
40
- Configuration.latest_post
41
- end
42
-
43
- private
44
-
45
- def post_body
46
- url = File.join Configuration.jekyll['url'], latest.url
47
- <<~POST
48
- #{latest.data['date'].strftime('%A, %B %-d %Y')}
49
- #{latest.data['title']}
50
- #{url}
51
- POST
52
- end
53
-
54
- def set_credentials!
55
- Koala.configure do |config|
56
- config.access_token = @creds['access_token']
57
- # config.app_access_token = @creds['app_access_token']
58
- config.app_id = @creds['app_id']
59
- config.app_secret = @creds['app_secret']
60
- end
61
- @client = Koala::Facebook::API.new(@creds['access_token'])
62
- end
63
-
64
- def extract_from_env
65
- values = cred_fieldnames.map { |k| ENV["FACEBOOK_#{k.upcase}"] }
66
-
67
- return nil if values.any? { |v| v.nil? || v.empty? }
68
-
69
- Hash[cred_fieldnames.zip(values)]
70
- end
71
-
72
- def extract_from_config
73
- values = cred_fieldnames.map do |k|
74
- cmd = Configuration.facebook.fetch("#{k}_cmd", '').strip
75
- if cmd.empty?
76
- nil
77
- else
78
- Recker.shell(Configuration.facebook["#{k}_cmd"]).strip
79
- end
80
- end
81
-
82
- return nil if values.any? { |v| v.nil? || v.empty? }
83
-
84
- Hash[cred_fieldnames.zip(values)]
85
- end
86
-
87
- def cred_fieldnames
88
- # app_access_token
89
- %w[
90
- access_token
91
- app_id
92
- app_secret
93
- ]
94
- end
95
- end
96
- end
97
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'logger'
4
-
5
- module Jekyll
6
- # Recker
7
- module Recker
8
- def self.logger
9
- @logger ||= make_logger
10
- end
11
-
12
- def self.make_logger
13
- logger = Logger.new(STDOUT)
14
- logger.formatter = proc do |_severity, _datetime, _progname, msg|
15
- "jekyll-recker: #{msg}\n"
16
- end
17
- logger
18
- end
19
- end
20
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'slack-notifier'
4
-
5
- module Jekyll
6
- # Recker
7
- module Recker
8
- # Slack
9
- class Slack
10
- include Jekyll::Recker::Mixins::Logging
11
-
12
- def self.share(dry: false)
13
- each_in_config(dry: dry) do |client|
14
- logger.info "#{client.key}: discovering webhook"
15
- client.discover_webhook!
16
- logger.info "#{client.key}: posting #{client.latest.data['title']}"
17
- client.post_latest!
18
- end
19
- end
20
-
21
- def self.each_in_config(dry: false)
22
- Configuration.slack.map do |key, body|
23
- yield new(key, body, dry: dry)
24
- end
25
- end
26
-
27
- attr_reader :key
28
-
29
- def initialize(config_key, config_body, dry: false)
30
- @key = config_key
31
- @data = config_body
32
- @webhook = nil
33
- @dry = dry
34
- end
35
-
36
- def discover_webhook!
37
- @webhook = ENV["SLACK_#{@key.upcase}_WEBHOOK"] || extract_from_config
38
- raise ReckerError, 'cannot find slack credentials!' if @webhook.nil?
39
- end
40
-
41
- def latest
42
- @latest ||= Configuration.latest_post
43
- end
44
-
45
- def post_latest!
46
- if @dry
47
- logger.info('postign in dry mode, printing message')
48
- logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
49
- else
50
- ::Slack::Notifier.new(
51
- @webhook.strip,
52
- channel: @data.fetch('channel'),
53
- username: @data.fetch('username'),
54
- icon_emoji: @data.fetch('emoji')
55
- ).post(text: message_body)
56
- end
57
- end
58
-
59
- private
60
-
61
- def message_body
62
- url = File.join Configuration.jekyll['url'], latest.url
63
- body = <<~MSG
64
- #{latest.data['date'].strftime('%A, %B %-d %Y')}
65
- #{latest.data['title']}
66
- #{url}
67
- MSG
68
- ::Slack::Notifier::Util::LinkFormatter.format(body)
69
- end
70
-
71
- def extract_from_config
72
- cmd = @data['webhook_cmd']
73
- return nil if cmd.nil?
74
-
75
- Recker.shell(cmd)
76
- end
77
- end
78
- end
79
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'twitter'
4
-
5
- module Jekyll
6
- module Recker
7
- # Twitter Client
8
- class Twitter
9
- include Mixins::Logging
10
-
11
- def self.share(dry: false)
12
- client = new(dry: dry)
13
- logger.info 'discovering credentials'
14
- client.discover_credentials!
15
- logger.info "tweeting #{client.latest.data['title']}"
16
- client.post_latest!
17
- end
18
-
19
- def initialize(dry: false)
20
- @dry = dry
21
- end
22
-
23
- def discover_credentials!
24
- @creds = extract_from_env || extract_from_config
25
- raise ReckerError, 'cannot find twitter credentials!' if @creds.nil?
26
-
27
- set_credentials!
28
- end
29
-
30
- def post_latest!
31
- if @dry
32
- logger.info('tweeting in dry mode, printing message')
33
- logger.info("BEGIN TWEET\n#{tweet_body.strip}\nEND TWEET")
34
- else
35
- @client.update(tweet_body)
36
- end
37
- end
38
-
39
- def latest
40
- Configuration.latest_post
41
- end
42
-
43
- private
44
-
45
- def tweet_body
46
- url = File.join Configuration.jekyll['url'], latest.url
47
- <<~TWEET
48
- #{latest.data['date'].strftime('%A, %B %-d %Y')}
49
- #{latest.data['title']}
50
- #{url}
51
- TWEET
52
- end
53
-
54
- def set_credentials!
55
- @client ||= ::Twitter::REST::Client.new do |settings|
56
- settings.consumer_key = @creds['consumer_api_key']
57
- settings.consumer_secret = @creds['consumer_api_secret']
58
- settings.access_token = @creds['access_token']
59
- settings.access_token_secret = @creds['access_token_secret']
60
- end
61
- end
62
-
63
- def extract_from_env
64
- values = cred_fieldnames.map { |k| ENV["TWITTER_#{k.upcase}"] }
65
-
66
- return nil if values.any? { |v| v.nil? || v.empty? }
67
-
68
- Hash[cred_fieldnames.zip(values)]
69
- end
70
-
71
- def extract_from_config
72
- values = cred_fieldnames.map do |k|
73
- Recker.shell(Configuration.twitter["#{k}_cmd"]).strip
74
- end
75
-
76
- return nil if values.any? { |v| v.nil? || v.empty? }
77
-
78
- Hash[cred_fieldnames.zip(values)]
79
- end
80
-
81
- def cred_fieldnames
82
- %w[
83
- access_token_secret
84
- access_token
85
- consumer_api_key
86
- consumer_api_secret
87
- ]
88
- end
89
- end
90
- end
91
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Recker
5
- # Words
6
- module Words
7
- def self.array_to_and_list(array)
8
- case array.length
9
- when 0
10
- ''
11
- when 1
12
- array.first
13
- when 2
14
- "#{array.first} and #{array.last}"
15
- else
16
- array[0...-1].join(', ') + ", and #{array.last}"
17
- end
18
- end
19
-
20
- def self.and_list_to_array(str)
21
- str = str.gsub(' and ', ', ')
22
- str.split(',').map(&:strip).reject(&:empty?)
23
- end
24
-
25
- def self.prettify_number(number)
26
- number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
27
- end
28
-
29
- def self.prettify_path(path, home = nil)
30
- home ||= File.expand_path('~/')
31
- path.sub(home, '~')
32
- end
33
-
34
- def self.to_word_list(str)
35
- str.split(' ')
36
- end
37
-
38
- def self.to_weighted_list(arr)
39
- arr.uniq.map do |word|
40
- [word, arr.count(word)]
41
- end
42
- end
43
- end
44
- end
45
- end
46
-
47
- # Array extensions
48
- class Array
49
- def to_and_list
50
- Jekyll::Recker::Words.array_to_and_list(self)
51
- end
52
-
53
- def to_weighted_list
54
- Jekyll::Recker::Words.to_weighted_list(self)
55
- end
56
- end
57
-
58
- # Integer extensions
59
- class Integer
60
- def pretty
61
- Jekyll::Recker::Words.prettify_number(self)
62
- end
63
- end
64
-
65
- # String extensions
66
- class String
67
- def words
68
- Jekyll::Recker::Words.to_word_list(self)
69
- end
70
-
71
- def word_count
72
- Jekyll::Recker::Words.to_word_list(self).count
73
- end
74
-
75
- def pretty_path(home = nil)
76
- Jekyll::Recker::Words.prettify_path(self, home)
77
- end
78
-
79
- def to_and_array
80
- Jekyll::Recker::Words.and_list_to_array(self)
81
- end
82
- end