lolcommits-mpv 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +13 -0
  4. data/.travis.yml +33 -0
  5. data/CHANGELOG +140 -0
  6. data/CONTRIBUTING +11 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +165 -0
  9. data/NOTES +17 -0
  10. data/README.md +100 -0
  11. data/Rakefile +77 -0
  12. data/bin/lolcommits +456 -0
  13. data/config/cucumber.yml +2 -0
  14. data/features/bugs.feature +58 -0
  15. data/features/lolcommits.feature +251 -0
  16. data/features/plugins.feature +37 -0
  17. data/features/step_definitions/lolcommits_steps.rb +123 -0
  18. data/features/support/env.rb +78 -0
  19. data/features/support/path_helpers.rb +39 -0
  20. data/lib/core_ext/class.rb +7 -0
  21. data/lib/lolcommits.rb +33 -0
  22. data/lib/lolcommits/capture_cygwin.rb +20 -0
  23. data/lib/lolcommits/capture_fake.rb +10 -0
  24. data/lib/lolcommits/capture_linux.rb +36 -0
  25. data/lib/lolcommits/capture_mac.rb +19 -0
  26. data/lib/lolcommits/capture_mac_animated.rb +71 -0
  27. data/lib/lolcommits/capture_windows.rb +20 -0
  28. data/lib/lolcommits/capturer.rb +14 -0
  29. data/lib/lolcommits/configuration.rb +210 -0
  30. data/lib/lolcommits/git_info.rb +31 -0
  31. data/lib/lolcommits/plugin.rb +83 -0
  32. data/lib/lolcommits/plugins/dot_com.rb +42 -0
  33. data/lib/lolcommits/plugins/lol_twitter.rb +125 -0
  34. data/lib/lolcommits/plugins/lolsrv.rb +72 -0
  35. data/lib/lolcommits/plugins/loltext.rb +73 -0
  36. data/lib/lolcommits/plugins/tranzlate.rb +113 -0
  37. data/lib/lolcommits/plugins/uploldz.rb +34 -0
  38. data/lib/lolcommits/runner.rb +117 -0
  39. data/lib/lolcommits/version.rb +3 -0
  40. data/lolcommits.gemspec +48 -0
  41. data/test/images/test_image.jpg +0 -0
  42. data/test/test_lolcommits.rb +70 -0
  43. data/vendor/ext/CommandCam/COPYING +674 -0
  44. data/vendor/ext/CommandCam/CommandCam.exe +0 -0
  45. data/vendor/ext/CommandCam/LICENSE +16 -0
  46. data/vendor/ext/imagesnap/ReadMeOrDont.rtf +117 -0
  47. data/vendor/ext/imagesnap/imagesnap +0 -0
  48. data/vendor/ext/videosnap/videosnap +0 -0
  49. data/vendor/fonts/Impact.ttf +0 -0
  50. metadata +397 -0
@@ -0,0 +1,31 @@
1
+ module Lolcommits
2
+ class GitInfo
3
+ include Methadone::CLILogging
4
+ attr_accessor :sha, :message, :repo_internal_path, :repo
5
+
6
+ def initialize
7
+ debug "GitInfo: attempting to read local repository"
8
+ g = Git.open('.')
9
+ debug "GitInfo: reading commits logs"
10
+ commit = g.log.first
11
+ debug "GitInfo: most recent commit is '#{commit}'"
12
+
13
+ self.message = commit.message.split("\n").first
14
+ self.sha = commit.sha[0..10]
15
+ self.repo_internal_path = g.repo.path
16
+ regex = /.*[:\/]([\w\-]*).git/
17
+ match = g.remote.url.match regex if g.remote.url
18
+ if match
19
+ self.repo = match[1]
20
+ elsif !g.repo.path.empty?
21
+ self.repo = g.repo.path.split(File::SEPARATOR)[-2]
22
+ end
23
+
24
+ debug "GitInfo: parsed the following values from commit:"
25
+ debug "GitInfo: \t#{self.message}"
26
+ debug "GitInfo: \t#{self.sha}"
27
+ debug "GitInfo: \t#{self.repo_internal_path}"
28
+ debug "GitInfo: \t#{self.repo}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,83 @@
1
+ module Lolcommits
2
+ class Plugin
3
+ include Methadone::CLILogging
4
+
5
+ attr_accessor :runner, :options
6
+
7
+ def initialize(runner)
8
+ debug "Initializing"
9
+ self.runner = runner
10
+ self.options = ['enabled']
11
+ end
12
+
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
20
+ end
21
+
22
+ def run
23
+ debug "base plugin, does nothing to anything"
24
+ end
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
31
+
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
55
+ else
56
+ puts "Missing #{self.class.name} config - configure with: lolcommits --config -p #{self.class.name}"
57
+ false
58
+ end
59
+ end
60
+
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'
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,42 @@
1
+ require 'httmultiparty'
2
+
3
+ module Lolcommits
4
+ class DotCom < Plugin
5
+
6
+ def initialize(runner)
7
+ super
8
+ self.options.concat(['api_key', 'api_secret', 'repo_id'])
9
+ end
10
+
11
+ def run
12
+ return unless valid_configuration?
13
+
14
+ t = Time.now.to_i.to_s
15
+ resp = HTTMultiParty.post('http://www.lolcommits.com/git_commits.json',
16
+ :body => {
17
+ :git_commit => {
18
+ :sha => self.runner.sha,
19
+ :repo_external_id => configuration['repo_id'],
20
+ :image => File.open(self.runner.main_image),
21
+ :raw => File.open(self.runner.snapshot_loc)
22
+ },
23
+
24
+ :key => configuration['api_key'],
25
+ :t => t,
26
+ :token => Digest::SHA1.hexdigest(configuration['api_secret'] + t)
27
+ }
28
+ )
29
+ end
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
41
+ end
42
+ end
@@ -0,0 +1,125 @@
1
+ require 'yaml'
2
+ require 'oauth'
3
+
4
+ # twitter gem currently spams stdout when activated, surpress warnings just during the inital require
5
+ original_verbose, $VERBOSE = $VERBOSE, nil # Supress warning messages.
6
+ require 'twitter'
7
+ $VERBOSE = original_verbose # activate warning messages again.
8
+
9
+ module Lolcommits
10
+ class LolTwitter < Plugin
11
+
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
37
+ end
38
+
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
46
+
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,
67
+ TWITTER_CONSUMER_SECRET,
68
+ :site => 'http://api.twitter.com',
69
+ :request_endpoint => 'http://api.twitter.com',
70
+ :sign_in => true)
71
+
72
+ request_token = consumer.get_request_token
73
+ rtoken = request_token.token
74
+ rsecret = request_token.secret
75
+
76
+ print "\n1) Please open this url in your browser to get a PIN for lolcommits:\n\n"
77
+ puts request_token.authorize_url
78
+ print "\n2) Enter PIN, then press enter: "
79
+ twitter_pin = STDIN.gets.strip.downcase.to_s
80
+
81
+ unless twitter_pin =~ TWITTER_PIN_REGEX
82
+ puts "\nERROR: '#{twitter_pin}' is not a valid Twitter Auth PIN"
83
+ return
84
+ end
85
+
86
+ begin
87
+ debug "Requesting Twitter OAuth Token with PIN: #{twitter_pin}"
88
+ OAuth::RequestToken.new(consumer, rtoken, rsecret)
89
+ access_token = request_token.get_access_token(:oauth_verifier => twitter_pin)
90
+ rescue OAuth::Unauthorized
91
+ puts "\nERROR: Twitter PIN Auth FAILED!"
92
+ return
93
+ end
94
+
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 }
99
+ end
100
+ end
101
+
102
+ def is_configured?
103
+ !configuration['enabled'].nil? &&
104
+ configuration['access_token'] &&
105
+ configuration['secret']
106
+ end
107
+
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'],
113
+ :oauth_token_secret => configuration['secret']
114
+ )
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'
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,72 @@
1
+ require "rest_client"
2
+ require "pp"
3
+ require "json"
4
+ require "logger"
5
+
6
+ module Lolcommits
7
+ class Lolsrv < Plugin
8
+
9
+ def initialize(runner)
10
+ super
11
+ self.options << 'server'
12
+ if self.runner
13
+ @logger = Logger.new(File.new(self.runner.config.loldir + "/lolsrv.log", "a+"))
14
+ end
15
+ end
16
+
17
+ def run
18
+ return unless valid_configuration?
19
+ fork { sync() }
20
+ end
21
+
22
+ def is_configured?
23
+ !configuration["enabled"].nil? && configuration["server"]
24
+ end
25
+
26
+ def sync
27
+ existing = get_existing_lols
28
+ unless existing.nil?
29
+ Dir[self.runner.config.loldir + "/*.{jpg,gif}"].each do |item|
30
+ sha = File.basename(item, ".*")
31
+ unless existing.include?(sha) || sha == "tmp_snapshot"
32
+ upload(item, sha)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def get_existing_lols
39
+ begin
40
+ lols = JSON.parse(
41
+ RestClient.get(configuration['server'] + "/lols"))
42
+ lols.map { |lol| lol["sha"] }
43
+ rescue => e
44
+ log_error(e, "ERROR: existing lols could not be retrieved #{e.class} - #{e.message}")
45
+ return nil
46
+ end
47
+ end
48
+
49
+ def upload(file, sha)
50
+ begin
51
+ RestClient.post(
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}")
58
+ return
59
+ end
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
71
+ end
72
+ end
@@ -0,0 +1,73 @@
1
+ module Lolcommits
2
+ class Loltext < Plugin
3
+
4
+ def initialize(runner)
5
+ super
6
+ @font_location = runner ? runner.font : nil
7
+ end
8
+
9
+ # enabled by default (if no configuration exists)
10
+ def is_enabled?
11
+ !is_configured? || super
12
+ end
13
+
14
+ def run
15
+ font_location = @font_location || File.join(Configuration::LOLCOMMITS_ROOT,
16
+ "vendor",
17
+ "fonts",
18
+ "Impact.ttf")
19
+
20
+ debug "Annotating image via MiniMagick"
21
+ image = MiniMagick::Image.open(self.runner.main_image)
22
+ image.combine_options do |c|
23
+ c.gravity 'SouthWest'
24
+ c.fill 'white'
25
+ c.stroke 'black'
26
+ c.strokewidth '2'
27
+ c.pointsize(self.runner.animate? ? '24' : '48')
28
+ c.interline_spacing '-9'
29
+ c.font font_location
30
+ c.annotate '0', clean_msg(self.runner.message)
31
+ end
32
+
33
+ image.combine_options do |c|
34
+ c.gravity 'NorthEast'
35
+ c.fill 'white'
36
+ c.stroke 'black'
37
+ c.strokewidth '2'
38
+ c.pointsize(self.runner.animate? ? '21' : '32')
39
+ c.font font_location
40
+ c.annotate '0', self.runner.sha
41
+ end
42
+
43
+ debug "Writing changed file to #{self.runner.main_image}"
44
+ image.write self.runner.main_image
45
+ end
46
+
47
+ def self.name
48
+ 'loltext'
49
+ end
50
+
51
+
52
+ private
53
+
54
+ # do whatever is required to commit message to get it clean and ready for imagemagick
55
+ def clean_msg(text)
56
+ wrapped_text = word_wrap text
57
+ escape_quotes wrapped_text
58
+ end
59
+
60
+ # conversion for quotation marks to avoid shell interpretation
61
+ # does not seem to be a safe way to escape cross-platform?
62
+ def escape_quotes(text)
63
+ text.gsub(/"/, "''")
64
+ end
65
+
66
+ # convenience method for word wrapping
67
+ # based on https://github.com/cmdrkeene/memegen/blob/master/lib/meme_generator.rb
68
+ def word_wrap(text, col = 27)
69
+ wrapped = text.gsub(/(.{1,#{col + 4}})(\s+|\Z)/, "\\1\n")
70
+ wrapped.chomp!
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,113 @@
1
+ # Adapted and expanded from https://github.com/rwtnorton/moar-lolspeak
2
+ # which was largely taken from an old Perl script and is sadly is not
3
+ # available via rubygems
4
+
5
+ module Lolspeak
6
+
7
+ LOL_DICTIONARY = {
8
+ /what/ => %w{wut whut},
9
+ /you\b/ => %w{yu yous yoo u yooz},
10
+ /cture/ => %w{kshur},
11
+ /ss\b/ => %w{s zz z},
12
+ /the\b/ => %w{teh},
13
+ /more/ => %w{moar},
14
+ /my/ => %w{mah mai},
15
+ /are/ => %w{is ar},
16
+ /eese/ => %w{eez},
17
+ /ph/ => %w{f},
18
+ /as\b/ => %w{az},
19
+ /seriously/ => %w{srsly},
20
+ /sion/ => %w{shun},
21
+ /just/ => %w{jus},
22
+ /ose\b/ => %w{oze},
23
+ /eady/ => %w{eddy},
24
+ /ome?\b/ => %w{um},
25
+ /of\b/ => %w{of ov of},
26
+ /uestion/ => %w{wesjun},
27
+ /want/ => %w{wants},
28
+ /ead\b/ => %w{edd},
29
+ /ck/ => %w{kk kkk},
30
+ /sion/ => %w{shun},
31
+ /cat|kitten|kitty/ => %w{kitteh kittehz cat fuzzeh fuzzyrumpus foozles fuzzbut fluffernutter beast mew},
32
+ /eak/ => %w{ekk},
33
+ /age/ => %w{uj},
34
+ /like/ => %w{likez liek licks},
35
+ /love/ => %w{lovez lub lubs luv lurve lurves},
36
+ /\bis\b/ => ['ar teh','ar'],
37
+ /nd\b/ => %w{n n'},
38
+ /who/ => %w{hoo},
39
+ /'/ => [''],
40
+ /ese\b/ => %w{eez},
41
+ /outh/ => %w{owf},
42
+ /scio/ => %w{shu},
43
+ /esque/ => %w{esk},
44
+ /ture/ => %w{chur},
45
+ /\btoo?\b/ => %w{to t 2 to t},
46
+ /tious/ => %w{shus},
47
+ /sure\b/ => %w{shur},
48
+ /tty\b/ => %w{tteh},
49
+ /were/ => %w{was},
50
+ /ok\b|okay/ => %w{kthxbye!},
51
+ /\ba\b/ => %w{uh},
52
+ /ym/ => %w{im},
53
+ /fish/ => %w{ghoti},
54
+ /thy\b/ => %w{fee},
55
+ /\wly\w/ => %w{li},
56
+ /que\w/ => %w{kwe},
57
+ /\both/ => %w{udd},
58
+ /though\b/ => %w{tho},
59
+ /(t|r|en)ough/ => %w{\1uff},
60
+ /ought/ => %w{awt},
61
+ /ease/ => %w{eez},
62
+ /ing\b/ => %w{in ins ng ing in'},
63
+ /have/ => ['haz', 'hav', 'haz a'],
64
+ /has/ => %w{haz gots},
65
+ /your/ => %w{yur ur yore yoar},
66
+ /ove\b/ => %w{oov ove uuv uv oove},
67
+ /for/ => %w{for 4 fr fur for foar},
68
+ /thank/ => %w{fank tank thx thnx},
69
+ /good/ => %w{gud goed guud gude gewd goot gut},
70
+ /really/ => %w{rly rily rilly rilleh},
71
+ /world/ => %w{wurrld whirld wurld wrld},
72
+ /i'?m\b/ => ['im', 'i yam', 'i iz'],
73
+ /(?!e)ight/ => %w{ite},
74
+ /(?!ues)tion/ => %w{shun},
75
+ /you'?re/ => %w{yore yr},
76
+ /er\b|are|ere/ => %w{r},
77
+ /y\b|ey\b/ => %w{eh},
78
+ /ea/ => %w{ee},
79
+ /can\si\s(?:ple(?:a|e)(?:s|z)e?)?\s?have\sa/ => ['i can haz'],
80
+ /(?:hello|\bhi\b|\bhey\b|howdy|\byo\b),?/ => ['oh hai,'],
81
+ /(?:god\b|allah|buddah?|diety|lord)/ => ['ceiling cat'],
82
+ }
83
+
84
+ def tranzlate(str)
85
+ lolstr = str.dup
86
+ LOL_DICTIONARY.each do |english, lolspeak|
87
+ #ghetto ruby1.8/1.9 agnostic version of choice vs sample
88
+ lolstr.gsub!(english, lolspeak.shuffle.first)
89
+ end
90
+
91
+ lolstr << '! kthxbye!' if rand(10) == 2
92
+ lolstr.gsub!(/(\?|!|,|\.)+/, '!')
93
+
94
+ lolstr.upcase
95
+ end
96
+ end
97
+
98
+ module Lolcommits
99
+ class Tranzlate < Plugin
100
+
101
+ extend Lolspeak
102
+
103
+ def run
104
+ debug "Commit message before: #{self.runner.message}"
105
+ self.runner.message = self.class.tranzlate(self.runner.message)
106
+ debug "Commit message after: #{self.runner.message}"
107
+ end
108
+
109
+ def self.name
110
+ 'tranzlate'
111
+ end
112
+ end
113
+ end