lolcommits 0.5.1 → 0.5.2.pre1
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 +15 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +1 -0
- data/CHANGELOG +13 -0
- data/README.md +29 -16
- data/bin/lolcommits +68 -15
- data/features/lolcommits.feature +40 -6
- data/features/plugins.feature +4 -4
- data/features/step_definitions/lolcommits_steps.rb +6 -0
- data/lib/lolcommits/configuration.rb +41 -35
- data/lib/lolcommits/plugin.rb +62 -19
- data/lib/lolcommits/plugins/dot_com.rb +14 -4
- data/lib/lolcommits/plugins/lol_twitter.rb +87 -65
- data/lib/lolcommits/plugins/lolsrv.rb +31 -32
- data/lib/lolcommits/plugins/loltext.rb +13 -34
- data/lib/lolcommits/plugins/tranzlate.rb +104 -9
- data/lib/lolcommits/plugins/uploldz.rb +13 -9
- data/lib/lolcommits/version.rb +1 -1
- data/lolcommits.gemspec +2 -1
- data/test/test_lolcommits.rb +39 -21
- metadata +25 -67
- data/lib/tranzlate/lolspeak.rb +0 -101
data/lib/lolcommits/plugin.rb
CHANGED
@@ -1,40 +1,83 @@
|
|
1
1
|
module Lolcommits
|
2
2
|
class Plugin
|
3
3
|
include Methadone::CLILogging
|
4
|
-
attr_accessor :default, :name, :runner, :options
|
5
4
|
|
6
|
-
|
7
|
-
config = runner.config.user_configuration
|
8
|
-
return Hash.new if config.nil?
|
9
|
-
config[self.name] || Hash.new
|
10
|
-
end
|
5
|
+
attr_accessor :runner, :options
|
11
6
|
|
12
7
|
def initialize(runner)
|
8
|
+
debug "Initializing"
|
13
9
|
self.runner = runner
|
14
10
|
self.options = ['enabled']
|
11
|
+
end
|
15
12
|
|
16
|
-
|
13
|
+
def execute
|
14
|
+
if is_enabled?
|
15
|
+
debug "I am enabled, about to run"
|
16
|
+
run
|
17
|
+
else
|
18
|
+
debug "Disabled, doing nothing for execution"
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
|
-
def
|
20
|
-
|
21
|
-
return self.default if enabled_config.nil? || enabled_config == ''
|
22
|
-
return enabled_config
|
22
|
+
def run
|
23
|
+
debug "base plugin, does nothing to anything"
|
23
24
|
end
|
24
25
|
|
26
|
+
def configuration
|
27
|
+
config = runner.config.read_configuration if runner
|
28
|
+
return Hash.new unless config
|
29
|
+
config[self.class.name] || Hash.new
|
30
|
+
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
# ask for plugin options
|
33
|
+
def configure_options!
|
34
|
+
puts "Configuring plugin: #{self.class.name}\n"
|
35
|
+
options.inject(Hash.new) do |acc, option|
|
36
|
+
print "#{option}: "
|
37
|
+
val = STDIN.gets.strip.downcase
|
38
|
+
if %w(true yes).include?(val)
|
39
|
+
val = true
|
40
|
+
elsif %(false no).include?(val)
|
41
|
+
val = false
|
42
|
+
end
|
43
|
+
acc.merge(option => val)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_enabled?
|
48
|
+
configuration['enabled'] == true
|
49
|
+
end
|
50
|
+
|
51
|
+
# check config is valid
|
52
|
+
def valid_configuration?
|
53
|
+
if is_configured?
|
54
|
+
true
|
30
55
|
else
|
31
|
-
|
56
|
+
puts "Missing #{self.class.name} config - configure with: lolcommits --config -p #{self.class.name}"
|
57
|
+
false
|
32
58
|
end
|
33
59
|
end
|
34
60
|
|
35
|
-
#
|
36
|
-
def
|
37
|
-
|
61
|
+
# empty plugin configuration
|
62
|
+
def is_configured?
|
63
|
+
!configuration.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
# uniform puts for plugins
|
67
|
+
# dont puts if the runner wants to be silent (stealth mode)
|
68
|
+
def puts(*args)
|
69
|
+
return if runner && runner.capture_stealth
|
70
|
+
super(args)
|
71
|
+
end
|
72
|
+
|
73
|
+
# uniform debug logging for plugins
|
74
|
+
def debug(msg)
|
75
|
+
super("Plugin: #{self.class.to_s}: " + msg)
|
76
|
+
end
|
77
|
+
|
78
|
+
# identifying plugin name (for config, listing)
|
79
|
+
def self.name
|
80
|
+
'plugin'
|
38
81
|
end
|
39
82
|
end
|
40
83
|
end
|
@@ -2,17 +2,17 @@ require 'httmultiparty'
|
|
2
2
|
|
3
3
|
module Lolcommits
|
4
4
|
class DotCom < Plugin
|
5
|
+
|
5
6
|
def initialize(runner)
|
6
7
|
super
|
7
|
-
|
8
|
-
self.name = 'dot_com'
|
9
|
-
self.default = false
|
10
8
|
self.options.concat(['api_key', 'api_secret', 'repo_id'])
|
11
9
|
end
|
12
10
|
|
13
11
|
def run
|
12
|
+
return unless valid_configuration?
|
13
|
+
|
14
14
|
t = Time.now.to_i.to_s
|
15
|
-
resp = HTTMultiParty.post('http://www.lolcommits.com/git_commits.json',
|
15
|
+
resp = HTTMultiParty.post('http://www.lolcommits.com/git_commits.json',
|
16
16
|
:body => {
|
17
17
|
:git_commit => {
|
18
18
|
:sha => self.runner.sha,
|
@@ -28,5 +28,15 @@ module Lolcommits
|
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
31
|
+
def is_configured?
|
32
|
+
!configuration['enabled'].nil? &&
|
33
|
+
configuration['api_key'] &&
|
34
|
+
configuration['api_secret'] &&
|
35
|
+
configuration['repo_id']
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.name
|
39
|
+
'dot_com'
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
@@ -3,101 +3,123 @@ require 'oauth'
|
|
3
3
|
|
4
4
|
# twitter gem currently spams stdout when activated, surpress warnings just during the inital require
|
5
5
|
original_verbose, $VERBOSE = $VERBOSE, nil # Supress warning messages.
|
6
|
-
|
7
|
-
$VERBOSE = original_verbose #
|
8
|
-
|
9
|
-
TWITTER_CONSUMER_KEY = 'qc096dJJCxIiqDNUqEsqQ'
|
10
|
-
TWITTER_CONSUMER_SECRET = 'rvjNdtwSr1H0TvBvjpk6c4bvrNydHmmbvv7gXZQI'
|
6
|
+
require 'twitter'
|
7
|
+
$VERBOSE = original_verbose # activate warning messages again.
|
11
8
|
|
12
9
|
module Lolcommits
|
13
|
-
|
14
10
|
class LolTwitter < Plugin
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
TWITTER_CONSUMER_KEY = 'qc096dJJCxIiqDNUqEsqQ'
|
13
|
+
TWITTER_CONSUMER_SECRET = 'rvjNdtwSr1H0TvBvjpk6c4bvrNydHmmbvv7gXZQI'
|
14
|
+
TWITTER_RETRIES = 2
|
15
|
+
TWITTER_PIN_REGEX = /^\d{4,}$/ # 4 or more digits
|
16
|
+
|
17
|
+
def run
|
18
|
+
return unless valid_configuration?
|
19
|
+
|
20
|
+
attempts = 0
|
21
|
+
|
22
|
+
begin
|
23
|
+
attempts += 1
|
24
|
+
tweet = build_tweet(self.runner.message)
|
25
|
+
puts "Tweeting: #{tweet}"
|
26
|
+
debug "--> Tweeting! (attempt: #{attempts}, tweet size: #{tweet.length} chars)"
|
27
|
+
if client.update_with_media(tweet, File.open(self.runner.main_image, 'r'))
|
28
|
+
puts "\t--> Tweet Sent!"
|
29
|
+
end
|
30
|
+
rescue Twitter::Error::InternalServerError,
|
31
|
+
Twitter::Error::BadRequest,
|
32
|
+
Twitter::Error::ClientError => e
|
33
|
+
debug "Tweet FAILED! #{e.class} - #{e.message}"
|
34
|
+
retry if attempts < TWITTER_RETRIES
|
35
|
+
puts "ERROR: Tweet FAILED! (after #{attempts} attempts) - #{e.message}"
|
36
|
+
end
|
20
37
|
end
|
21
38
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
39
|
+
def build_tweet(commit_message, tag = "#lolcommits")
|
40
|
+
available_commit_msg_size = max_tweet_size - (tag.length + 1)
|
41
|
+
if commit_message.length > available_commit_msg_size
|
42
|
+
commit_message = "#{commit_message[0..(available_commit_msg_size-3)]}..."
|
43
|
+
end
|
44
|
+
"#{commit_message} #{tag}"
|
45
|
+
end
|
26
46
|
|
27
|
-
|
47
|
+
def configure_options!
|
48
|
+
options = super
|
49
|
+
# ask user to configure tokens if enabling
|
50
|
+
if options['enabled'] == true
|
51
|
+
if auth_config = configure_auth!
|
52
|
+
options.merge!(auth_config)
|
53
|
+
else
|
54
|
+
# return nil if configure_auth failed
|
55
|
+
return
|
56
|
+
end
|
57
|
+
end
|
58
|
+
return options
|
59
|
+
end
|
60
|
+
|
61
|
+
def configure_auth!
|
62
|
+
puts "---------------------------"
|
63
|
+
puts "Need to grab twitter tokens"
|
64
|
+
puts "---------------------------"
|
65
|
+
|
66
|
+
consumer = OAuth::Consumer.new(TWITTER_CONSUMER_KEY,
|
28
67
|
TWITTER_CONSUMER_SECRET,
|
29
68
|
:site => 'http://api.twitter.com',
|
30
69
|
:request_endpoint => 'http://api.twitter.com',
|
31
70
|
:sign_in => true)
|
32
71
|
|
33
72
|
request_token = consumer.get_request_token
|
34
|
-
rtoken
|
35
|
-
rsecret
|
73
|
+
rtoken = request_token.token
|
74
|
+
rsecret = request_token.secret
|
36
75
|
|
37
|
-
|
76
|
+
print "\n1) Please open this url in your browser to get a PIN for lolcommits:\n\n"
|
38
77
|
puts request_token.authorize_url
|
39
|
-
|
78
|
+
print "\n2) Enter PIN, then press enter: "
|
79
|
+
twitter_pin = STDIN.gets.strip.downcase.to_s
|
40
80
|
|
41
|
-
|
42
|
-
|
43
|
-
twitter_pin = STDIN.gets.chomp
|
44
|
-
rescue
|
45
|
-
end
|
46
|
-
|
47
|
-
if (twitter_pin.nil?) || (twitter_pin.length == 0)
|
48
|
-
puts "\n\tERROR: Could not read PIN, auth fail"
|
81
|
+
unless twitter_pin =~ TWITTER_PIN_REGEX
|
82
|
+
puts "\nERROR: '#{twitter_pin}' is not a valid Twitter Auth PIN"
|
49
83
|
return
|
50
84
|
end
|
51
85
|
|
52
86
|
begin
|
87
|
+
debug "Requesting Twitter OAuth Token with PIN: #{twitter_pin}"
|
53
88
|
OAuth::RequestToken.new(consumer, rtoken, rsecret)
|
54
89
|
access_token = request_token.get_access_token(:oauth_verifier => twitter_pin)
|
55
|
-
rescue
|
56
|
-
puts "
|
90
|
+
rescue OAuth::Unauthorized
|
91
|
+
puts "\nERROR: Twitter PIN Auth FAILED!"
|
57
92
|
return
|
58
93
|
end
|
59
94
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def run
|
67
|
-
commit_msg = self.runner.message
|
68
|
-
available_commit_msg_size = 128
|
69
|
-
tweet_msg = commit_msg.length > available_commit_msg_size ? "#{commit_msg[0..(available_commit_msg_size-3)]}..." : commit_msg
|
70
|
-
tweet_text = "#{tweet_msg} #lolcommits"
|
71
|
-
puts "Tweeting: #{tweet_text}"
|
72
|
-
|
73
|
-
if configuration['access_token'].nil? || configuration['secret'].nil?
|
74
|
-
initial_twitter_auth()
|
75
|
-
end
|
76
|
-
|
77
|
-
if configuration['access_token'].nil? || configuration['secret'].nil?
|
78
|
-
puts "Missing Twitter Credentials - Skipping The Tweet"
|
79
|
-
return
|
95
|
+
if access_token.token && access_token.secret
|
96
|
+
print "\n3) Thanks! Twitter Auth Succeeded\n"
|
97
|
+
return { 'access_token' => access_token.token,
|
98
|
+
'secret' => access_token.secret }
|
80
99
|
end
|
100
|
+
end
|
81
101
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
102
|
+
def is_configured?
|
103
|
+
!configuration['enabled'].nil? &&
|
104
|
+
configuration['access_token'] &&
|
105
|
+
configuration['secret']
|
106
|
+
end
|
86
107
|
|
87
|
-
|
88
|
-
|
108
|
+
def client
|
109
|
+
@client ||= Twitter::Client.new(
|
110
|
+
:consumer_key => TWITTER_CONSUMER_KEY,
|
111
|
+
:consumer_secret => TWITTER_CONSUMER_SECRET,
|
112
|
+
:oauth_token => configuration['access_token'],
|
89
113
|
:oauth_token_secret => configuration['secret']
|
90
114
|
)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
puts "\t ! --> Tweet 500 Error - Tweet Not Posted"
|
100
|
-
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def max_tweet_size
|
118
|
+
139 - client.configuration.characters_reserved_per_media
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.name
|
122
|
+
'twitter'
|
101
123
|
end
|
102
124
|
end
|
103
125
|
end
|
@@ -4,42 +4,31 @@ require "json"
|
|
4
4
|
require "logger"
|
5
5
|
|
6
6
|
module Lolcommits
|
7
|
-
|
8
7
|
class Lolsrv < Plugin
|
9
8
|
|
10
|
-
SERVER = 'server'
|
11
|
-
|
12
9
|
def initialize(runner)
|
13
10
|
super
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
|
17
|
-
|
11
|
+
self.options << 'server'
|
12
|
+
if self.runner
|
13
|
+
@logger = Logger.new(File.new(self.runner.config.loldir + "/lolsrv.log", "a+"))
|
14
|
+
end
|
18
15
|
end
|
19
16
|
|
20
17
|
def run
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if configuration[SERVER].nil?
|
26
|
-
puts "Missing server configuration. Use lolcommits --config -p lolsrv"
|
27
|
-
return
|
28
|
-
end
|
18
|
+
return unless valid_configuration?
|
19
|
+
fork { sync() }
|
20
|
+
end
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
end
|
22
|
+
def is_configured?
|
23
|
+
!configuration["enabled"].nil? && configuration["server"]
|
33
24
|
end
|
34
25
|
|
35
26
|
def sync
|
36
27
|
existing = get_existing_lols
|
37
28
|
unless existing.nil?
|
38
|
-
Dir
|
39
|
-
|
40
|
-
|
41
|
-
sha = File.basename(item, '.*')
|
42
|
-
unless existing.include?(sha) || sha == 'tmp_snapshot'
|
29
|
+
Dir[self.runner.config.loldir + "/*.{jpg,gif}"].each do |item|
|
30
|
+
sha = File.basename(item, ".*")
|
31
|
+
unless existing.include?(sha) || sha == "tmp_snapshot"
|
43
32
|
upload(item, sha)
|
44
33
|
end
|
45
34
|
end
|
@@ -49,11 +38,10 @@ module Lolcommits
|
|
49
38
|
def get_existing_lols
|
50
39
|
begin
|
51
40
|
lols = JSON.parse(
|
52
|
-
RestClient.get(configuration[
|
41
|
+
RestClient.get(configuration['server'] + "/lols"))
|
53
42
|
lols.map { |lol| lol["sha"] }
|
54
|
-
rescue =>
|
55
|
-
|
56
|
-
@logger.info error.backtrace
|
43
|
+
rescue => e
|
44
|
+
log_error(e, "ERROR: existing lols could not be retrieved #{e.class} - #{e.message}")
|
57
45
|
return nil
|
58
46
|
end
|
59
47
|
end
|
@@ -61,13 +49,24 @@ module Lolcommits
|
|
61
49
|
def upload(file, sha)
|
62
50
|
begin
|
63
51
|
RestClient.post(
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
52
|
+
configuration["server"] + "/uplol",
|
53
|
+
:lol => File.new(file),
|
54
|
+
:sha => sha
|
55
|
+
)
|
56
|
+
rescue => e
|
57
|
+
log_error(e,"ERROR: Upload of lol #{sha} FAILED #{e.class} - #{e.message}")
|
69
58
|
return
|
70
59
|
end
|
71
60
|
end
|
61
|
+
|
62
|
+
def log_error(e, message)
|
63
|
+
debug message
|
64
|
+
@logger.info message
|
65
|
+
@logger.info e.backtrace
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.name
|
69
|
+
"lolsrv"
|
70
|
+
end
|
72
71
|
end
|
73
72
|
end
|
@@ -3,22 +3,21 @@ module Lolcommits
|
|
3
3
|
|
4
4
|
def initialize(runner)
|
5
5
|
super
|
6
|
-
|
7
6
|
@font_location = runner ? runner.font : nil
|
8
|
-
|
9
|
-
self.name = 'loltext'
|
10
|
-
self.default = true
|
11
7
|
end
|
12
8
|
|
13
|
-
|
14
|
-
|
9
|
+
# enabled by default (if no configuration exists)
|
10
|
+
def is_enabled?
|
11
|
+
!is_configured? || super
|
15
12
|
end
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
def run
|
15
|
+
font_location = @font_location || File.join(Configuration::LOLCOMMITS_ROOT,
|
16
|
+
"vendor",
|
17
|
+
"fonts",
|
18
|
+
"Impact.ttf")
|
20
19
|
|
21
|
-
|
20
|
+
debug "Annotating image via MiniMagick"
|
22
21
|
image = MiniMagick::Image.open(self.runner.main_image)
|
23
22
|
image.combine_options do |c|
|
24
23
|
c.gravity 'SouthWest'
|
@@ -41,34 +40,14 @@ module Lolcommits
|
|
41
40
|
c.annotate '0', self.runner.sha
|
42
41
|
end
|
43
42
|
|
44
|
-
|
43
|
+
debug "Writing changed file to #{self.runner.main_image}"
|
45
44
|
image.write self.runner.main_image
|
46
45
|
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# draw = Magick::Draw.new
|
52
|
-
# draw.font = File.join(Configuration::LOLCOMMITS_ROOT, "vendor", "fonts", "Impact.ttf")
|
53
|
-
|
54
|
-
# draw.fill = 'white'
|
55
|
-
# draw.stroke = 'black'
|
56
|
-
|
57
|
-
# draw.annotate(canvas, 0, 0, 0, 0, self.runner.sha) do
|
58
|
-
# self.gravity = NorthEastGravity
|
59
|
-
# self.pointsize = 32
|
60
|
-
# self.stroke_width = 2
|
61
|
-
# end
|
62
|
-
|
63
|
-
# draw.annotate(canvas, 0, 0, 0, 0, word_wrap(self.runner.message)) do
|
64
|
-
# self.gravity = SouthWestGravity
|
65
|
-
# self.pointsize = 48
|
66
|
-
# self.interline_spacing = -(48 / 5) if self.respond_to?(:interline_spacing)
|
67
|
-
# self.stroke_width = 2
|
68
|
-
# end
|
47
|
+
def self.name
|
48
|
+
'loltext'
|
49
|
+
end
|
69
50
|
|
70
|
-
# canvas.write(runner.main_image)
|
71
|
-
# end
|
72
51
|
|
73
52
|
private
|
74
53
|
|