jekyll-recker 1.6.0 → 1.11.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: 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