lolcommits 0.5.1 → 0.5.2.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|