lolcommits 0.9.2 → 0.9.3.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +6 -0
  3. data/CHANGELOG.md +243 -105
  4. data/CONTRIBUTING.md +2 -2
  5. data/README.md +10 -3
  6. data/bin/lolcommits +9 -16
  7. data/features/step_definitions/lolcommits_steps.rb +0 -1
  8. data/features/support/env.rb +0 -1
  9. data/features/support/path_helpers.rb +0 -1
  10. data/lib/core_ext/mini_magick/utilities.rb +0 -1
  11. data/lib/lolcommits.rb +16 -16
  12. data/lib/lolcommits/backends/git_info.rb +0 -1
  13. data/lib/lolcommits/backends/installation_git.rb +0 -1
  14. data/lib/lolcommits/backends/installation_mercurial.rb +0 -1
  15. data/lib/lolcommits/backends/mercurial_info.rb +0 -1
  16. data/lib/lolcommits/capturer.rb +0 -1
  17. data/lib/lolcommits/capturer/capture_cygwin.rb +0 -1
  18. data/lib/lolcommits/capturer/capture_fake.rb +0 -1
  19. data/lib/lolcommits/capturer/capture_linux.rb +0 -1
  20. data/lib/lolcommits/capturer/capture_linux_animated.rb +0 -1
  21. data/lib/lolcommits/capturer/capture_mac.rb +0 -1
  22. data/lib/lolcommits/capturer/capture_mac_animated.rb +0 -1
  23. data/lib/lolcommits/capturer/capture_windows.rb +0 -1
  24. data/lib/lolcommits/cli/fatals.rb +0 -8
  25. data/lib/lolcommits/cli/launcher.rb +0 -1
  26. data/lib/lolcommits/cli/process_runner.rb +0 -2
  27. data/lib/lolcommits/cli/timelapse_gif.rb +0 -1
  28. data/lib/lolcommits/configuration.rb +10 -7
  29. data/lib/lolcommits/gem_plugin.rb +46 -0
  30. data/lib/lolcommits/installation.rb +0 -1
  31. data/lib/lolcommits/platform.rb +0 -1
  32. data/lib/lolcommits/plugin/base.rb +110 -0
  33. data/lib/lolcommits/plugin/dot_com.rb +50 -0
  34. data/lib/lolcommits/plugin/lol_flowdock.rb +69 -0
  35. data/lib/lolcommits/plugin/lol_hipchat.rb +124 -0
  36. data/lib/lolcommits/plugin/lol_protonet.rb +68 -0
  37. data/lib/lolcommits/plugin/lol_slack.rb +68 -0
  38. data/lib/lolcommits/plugin/lol_tumblr.rb +129 -0
  39. data/lib/lolcommits/plugin/lol_twitter.rb +176 -0
  40. data/lib/lolcommits/plugin/lol_yammer.rb +84 -0
  41. data/lib/lolcommits/plugin/lolsrv.rb +58 -0
  42. data/lib/lolcommits/plugin/loltext.rb +190 -0
  43. data/lib/lolcommits/plugin/term_output.rb +55 -0
  44. data/lib/lolcommits/{plugins → plugin}/tranzlate.rb +14 -15
  45. data/lib/lolcommits/plugin/uploldz.rb +65 -0
  46. data/lib/lolcommits/plugin_manager.rb +48 -0
  47. data/lib/lolcommits/runner.rb +4 -5
  48. data/lib/lolcommits/test_helpers/fake_io.rb +20 -0
  49. data/lib/lolcommits/test_helpers/git_repo.rb +44 -0
  50. data/lib/lolcommits/vcs_info.rb +0 -1
  51. data/lib/lolcommits/version.rb +2 -2
  52. data/lolcommits.gemspec +2 -2
  53. data/test/lolcommits_test.rb +1 -2
  54. data/test/plugins_test.rb +7 -8
  55. metadata +22 -19
  56. data/lib/core_ext/class.rb +0 -8
  57. data/lib/lolcommits/plugin.rb +0 -123
  58. data/lib/lolcommits/plugins/dot_com.rb +0 -51
  59. data/lib/lolcommits/plugins/lol_flowdock.rb +0 -70
  60. data/lib/lolcommits/plugins/lol_hipchat.rb +0 -125
  61. data/lib/lolcommits/plugins/lol_protonet.rb +0 -69
  62. data/lib/lolcommits/plugins/lol_slack.rb +0 -69
  63. data/lib/lolcommits/plugins/lol_tumblr.rb +0 -129
  64. data/lib/lolcommits/plugins/lol_twitter.rb +0 -176
  65. data/lib/lolcommits/plugins/lol_yammer.rb +0 -85
  66. data/lib/lolcommits/plugins/lolsrv.rb +0 -58
  67. data/lib/lolcommits/plugins/loltext.rb +0 -184
  68. data/lib/lolcommits/plugins/term_output.rb +0 -54
  69. data/lib/lolcommits/plugins/uploldz.rb +0 -66
@@ -0,0 +1,50 @@
1
+ require 'httmultiparty'
2
+
3
+ module Lolcommits
4
+ module Plugin
5
+ class DotCom < Base
6
+ BASE_URL = 'http://lolcommits-dot-com.herokuapp.com'.freeze
7
+
8
+ def initialize(runner)
9
+ super
10
+ options.concat(%w(api_key api_secret repo_id))
11
+ end
12
+
13
+ def run_postcapture
14
+ t = Time.now.to_i.to_s
15
+ HTTMultiParty.post(
16
+ "#{BASE_URL}/git_commits.json",
17
+ body: {
18
+ git_commit: {
19
+ sha: runner.sha,
20
+ repo_external_id: configuration['repo_id'],
21
+ image: File.open(runner.main_image),
22
+ raw: File.open(runner.snapshot_loc)
23
+ },
24
+
25
+ key: configuration['api_key'],
26
+ t: t,
27
+ token: Digest::SHA1.hexdigest(configuration['api_secret'] + t)
28
+ }
29
+ )
30
+ rescue => e
31
+ log_error(e, "ERROR: HTTMultiParty POST FAILED #{e.class} - #{e.message}")
32
+ end
33
+
34
+ def configured?
35
+ !configuration['enabled'].nil? &&
36
+ configuration['api_key'] &&
37
+ configuration['api_secret'] &&
38
+ configuration['repo_id']
39
+ end
40
+
41
+ def self.name
42
+ 'dot_com'
43
+ end
44
+
45
+ def self.runner_order
46
+ :postcapture
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,69 @@
1
+ require 'rest_client'
2
+
3
+ module Lolcommits
4
+ module Plugin
5
+ class LolFlowdock < Base
6
+ ENDPOINT_URL = 'api.flowdock.com/flows/'.freeze
7
+ RETRY_COUNT = 2
8
+
9
+ def self.name
10
+ 'flowdock'
11
+ end
12
+
13
+ def self.runner_order
14
+ :postcapture
15
+ end
16
+
17
+ def configured?
18
+ !configuration['access_token'].nil?
19
+ end
20
+
21
+ def configure
22
+ print "Open the URL below and issue a token for your user (Personal API token):\n"
23
+ print "https://flowdock.com/account/tokens\n"
24
+ print "Enter the generated token below, then press enter: \n"
25
+ code = gets.to_s.strip
26
+ print "Enter the machine name of the flow you want to post to from this repo.\n"
27
+ print "Go to https://www.flowdock.com/account and click Flows, then click the flow, then get the machine name from the URL:\n"
28
+ flow = gets.to_s.strip.downcase
29
+ print "Enter the name of the organization for this Flowdock account.\n"
30
+ organization = gets.to_s.strip.downcase
31
+
32
+ {
33
+ 'access_token' => code,
34
+ 'flow' => flow,
35
+ 'organization' => organization
36
+ }
37
+ end
38
+
39
+ def configure_options!
40
+ options = super
41
+ if options['enabled']
42
+ config = configure
43
+ options.merge!(config)
44
+ end
45
+ options
46
+ end
47
+
48
+ def run_postcapture
49
+ retries = RETRY_COUNT
50
+ begin
51
+
52
+ endpoint = 'https://' + configuration['access_token'] + '@' + ENDPOINT_URL + configuration['organization'] + '/' + configuration['flow'] + '/messages'
53
+ response = RestClient.post(
54
+ endpoint,
55
+ event: 'file',
56
+ content: File.new(runner.main_image)
57
+ )
58
+ debug response
59
+ rescue => e
60
+ retries -= 1
61
+ retry if retries > 0
62
+ puts "Posting to flowdock failed - #{e.message}"
63
+ puts 'Try running config again:'
64
+ puts "\tlolcommits --config --plugin flowdock"
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,124 @@
1
+ module Lolcommits
2
+ module Plugin
3
+ class LolHipchat < Base
4
+ def configure_options!
5
+ options = super
6
+ options.merge! configure_auth_options if options['enabled']
7
+ options
8
+ end
9
+
10
+ def configure_auth_options
11
+ puts '-' * 50
12
+ puts ' Lolcommits HipChat Plugin Configuration'
13
+ puts '-' * 50
14
+
15
+ puts '1.) I need your Team Name '
16
+ puts 'teamname as in teamname.hipchat.com, without .hipchat.com'
17
+ print 'Your Teamname: '
18
+ teamname = gets.to_s.strip
19
+ puts "2.) We need a Authentication Token, get yours at https://#{teamname}.hipchat.com/account/api"
20
+ puts 'make sure to select scope "Send Message"'
21
+ print 'Your auth_token: '
22
+ token = gets.to_s.strip
23
+ puts '3.) Which Room should be we post to?'
24
+ puts 'can be a id or name'
25
+ print 'Your Room: '
26
+ room = gets.to_s.strip
27
+
28
+ {
29
+ 'api_token' => token,
30
+ 'api_team' => teamname,
31
+ 'api_room' => room
32
+ }
33
+ end
34
+
35
+ def run_postcapture
36
+ http = Net::HTTP.new(api_url.host, api_url.port)
37
+ # http.set_debug_output $stderr # nice for debugging, never ever release with it
38
+ http.start do |connection|
39
+ header = { 'Content-Type' => 'multipart/related; boundary=0123456789ABLEWASIEREISAWELBA9876543210' }
40
+ data = [message_part, picture_part].map do |part|
41
+ "--0123456789ABLEWASIEREISAWELBA9876543210\r\n#{part}"
42
+ end.join('') << '--0123456789ABLEWASIEREISAWELBA9876543210--'
43
+ connection.post("#{api_url.path}?#{api_url.query}", data, header)
44
+ end
45
+ end
46
+
47
+ def message_part
48
+ [
49
+ 'Content-Type: application/json; charset=UTF-8',
50
+ 'Content-Disposition: attachment; name="metadata"',
51
+ '',
52
+ message_json,
53
+ ''
54
+ ].join "\r\n"
55
+ end
56
+
57
+ def message_json
58
+ { message: message }.to_json.force_encoding('utf-8')
59
+ end
60
+
61
+ def picture_part
62
+ mime_type = MIME::Types.type_for(picture.path)[0] || MIME::Types['application/octet-stream'][0]
63
+ [
64
+ format('Content-Type: %s', mime_type.simplified),
65
+ format('Content-Disposition: attachment; name="file"; filename="%s"', picture.path),
66
+ '',
67
+ "#{picture.read} ",
68
+ ''
69
+ ].join "\r\n"
70
+ end
71
+
72
+ def picture
73
+ @picture ||= File.new(runner.main_image)
74
+ end
75
+
76
+ def api_url
77
+ URI(format('http://%{api_team}.hipchat.com/v2/room/%{api_room}/share/file?auth_token=%{api_token}', symbolized_configuration))
78
+ end
79
+
80
+ def symbolized_configuration
81
+ @symbolized_configuration ||= configuration.each_with_object({}) { |(k, v), obj| obj[k.to_sym] = v }
82
+ end
83
+
84
+ def message
85
+ "commited some #{random_adjective} #{random_object} to #{runner.vcs_info.repo}@#{runner.sha} (#{runner.vcs_info.branch}) "
86
+ end
87
+
88
+ def random_object
89
+ objects = %w(screws bolts exceptions errors cookies)
90
+
91
+ objects.sample
92
+ end
93
+
94
+ def random_adjective
95
+ adjectives = %w(adaptable adventurous affable affectionate agreeable ambitious amiable amicable amusing brave \
96
+ bright broad-minded calm careful charming communicative compassionate conscientious considerate \
97
+ convivial courageous courteous creative decisive determined diligent diplomatic discreet dynamic \
98
+ easygoing emotional energetic enthusiastic exuberant fair-minded faithful fearless forceful \
99
+ frank friendly funny generous gentle good gregarious hard-working helpful honest humorous \
100
+ imaginative impartial independent intellectual intelligent intuitive inventive kind loving loyal \
101
+ modest neat nice optimistic passionate patient persistent pioneering philosophical placid plucky \
102
+ polite powerful practical pro-active quick-witted quiet rational reliable reserved resourceful \
103
+ romantic self-confident self-disciplined sensible sensitive shy sincere sociable straightforward \
104
+ sympathetic thoughtful tidy tough unassuming understanding versatile warmhearted willing witty)
105
+ adjectives.sample
106
+ end
107
+
108
+ def configured?
109
+ super &&
110
+ configuration['api_token'] &&
111
+ configuration['api_team'] &&
112
+ configuration['api_room']
113
+ end
114
+
115
+ def self.name
116
+ 'hipchat'
117
+ end
118
+
119
+ def self.runner_order
120
+ :postcapture
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,68 @@
1
+ require 'rest_client'
2
+
3
+ module Lolcommits
4
+ module Plugin
5
+ class LolProtonet < Base
6
+ def initialize(runner)
7
+ super
8
+ options.concat(%w(api_token api_endpoint))
9
+ end
10
+
11
+ def run_postcapture
12
+ debug "Posting capture to #{configuration['endpoint']}"
13
+ RestClient.post(
14
+ api_url,
15
+ {
16
+ files: [File.new(runner.main_image)],
17
+ message: message
18
+ },
19
+ 'X-Protonet-Token' => configuration['api_token']
20
+ )
21
+ end
22
+
23
+ def api_url
24
+ configuration['api_endpoint']
25
+ end
26
+
27
+ def message
28
+ "commited some #{random_adjective} #{random_object} to #{runner.vcs_info.repo}@#{runner.sha} (#{runner.vcs_info.branch}) "
29
+ end
30
+
31
+ def random_object
32
+ objects = %w(screws bolts exceptions errors cookies)
33
+
34
+ objects.sample
35
+ end
36
+
37
+ def random_adjective
38
+ adjectives = [
39
+ 'awesome', 'great', 'interesting', 'cool', 'EPIC', 'gut', 'good', 'pansy',
40
+ 'powerful', 'boring', 'quirky', 'untested', 'german', 'iranian', 'neutral', 'crazy', 'well tested',
41
+ 'jimmy style', 'nasty', 'bibliographical (we received complaints about the original wording)',
42
+ 'bombdiggidy', 'narly', 'spiffy', 'smashing', 'xing style',
43
+ 'leo apotheker style', 'black', 'white', 'yellow', 'shaggy', 'tasty', 'mind bending', 'JAY-Z',
44
+ 'Kanye (the best ever)', '* Toby Keith was here *', 'splendid', 'stupendulous',
45
+ '(freedom fries!)', '[vote RON PAUL]', '- these are not my glasses -', 'typical pansy',
46
+ '- ze goggles zey do nothing! -', 'almost working', 'legen- wait for it -', '-dairy!',
47
+ ' - Tavonius would be proud of this - ', 'Meg FAILMAN!', '- very brofessional of you -',
48
+ 'heartbleeding', 'juciy', 'supercalifragilisticexpialidocious', 'failing', 'loving'
49
+ ]
50
+ adjectives.sample
51
+ end
52
+
53
+ def configured?
54
+ !configuration['enabled'].nil? &&
55
+ configuration['api_token'] &&
56
+ configuration['api_endpoint']
57
+ end
58
+
59
+ def self.name
60
+ 'lolprotonet'
61
+ end
62
+
63
+ def self.runner_order
64
+ :postcapture
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,68 @@
1
+ require 'rest_client'
2
+
3
+ module Lolcommits
4
+ module Plugin
5
+ class LolSlack < Base
6
+ ENDPOINT_URL = 'https://slack.com/api/files.upload'.freeze
7
+ RETRY_COUNT = 2
8
+
9
+ def self.name
10
+ 'slack'
11
+ end
12
+
13
+ def self.runner_order
14
+ :postcapture
15
+ end
16
+
17
+ def configured?
18
+ !configuration['access_token'].nil?
19
+ end
20
+
21
+ def configure
22
+ print "Open the URL below and issue a token for your user:\n"
23
+ print "https://api.slack.com/web\n"
24
+ print "Enter the generated token below, then press enter: (e.g. xxxx-xxxxxxxxx-xxxx) \n"
25
+ code = gets.to_s.strip
26
+ print "Enter a comma-seperated list of channel IDs to post images in, then press enter: (e.g. C1234567890,C1234567890)\n"
27
+ print "NOTE: you must use channel IDs (not channel names). Grab them from here; https://api.slack.com/methods/channels.list/test\n"
28
+ channels = gets.to_s.strip
29
+
30
+ { 'access_token' => code,
31
+ 'channels' => channels }
32
+ end
33
+
34
+ def configure_options!
35
+ options = super
36
+ if options['enabled']
37
+ config = configure
38
+ options.merge!(config)
39
+ end
40
+ options
41
+ end
42
+
43
+ def run_postcapture
44
+ retries = RETRY_COUNT
45
+ begin
46
+
47
+ response = RestClient.post(
48
+ ENDPOINT_URL,
49
+ file: File.new(runner.main_image),
50
+ token: configuration['access_token'],
51
+ filetype: 'jpg',
52
+ filename: runner.sha,
53
+ title: runner.message + "[#{runner.vcs_info.repo}]",
54
+ channels: configuration['channels']
55
+ )
56
+
57
+ debug response
58
+ rescue => e
59
+ retries -= 1
60
+ retry if retries > 0
61
+ puts "Posting to slack failed - #{e.message}"
62
+ puts 'Try running config again:'
63
+ puts "\tlolcommits --config --plugin slack"
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,129 @@
1
+ require 'yaml'
2
+ require 'oauth'
3
+ require 'webrick'
4
+ require 'cgi'
5
+ require 'tumblr_client'
6
+
7
+ module Lolcommits
8
+ module Plugin
9
+ class LolTumblr < Base
10
+ TUMBLR_API_ENDPOINT = 'https://www.tumblr.com'.freeze
11
+ TUMBLR_CONSUMER_KEY = '2FtMEDpEPkxjoUdkpHh42h9wqTu9IVS7Ra0QyNZGixdCvhllN2'.freeze
12
+ TUMBLR_CONSUMER_SECRET = 'qWuvxgFUR2YyWKtbWOkDTMAiBEbj7ZGaNLaNQPba0PI1N4JpBs'.freeze
13
+
14
+ def run_postcapture
15
+ puts 'Posting to Tumblr'
16
+ r = client.photo(configuration['tumblr_name'], data: runner.main_image)
17
+ if r.key?('id')
18
+ puts "\t--> Post successful!"
19
+ else
20
+ puts "Tumblr post FAILED! #{r}"
21
+ end
22
+ rescue Faraday::Error => e
23
+ puts "Tumblr post FAILED! #{e.message}"
24
+ end
25
+
26
+ def configure_options!
27
+ options = super
28
+ # ask user to configure tokens if enabling
29
+ if options['enabled']
30
+ auth_config = configure_auth!
31
+ return unless auth_config
32
+ options = options.merge(auth_config).merge(configure_tumblr_name)
33
+ end
34
+ options
35
+ end
36
+
37
+ def configure_auth!
38
+ puts '---------------------------'
39
+ puts 'Need to grab tumblr tokens'
40
+ puts '---------------------------'
41
+
42
+ request_token = oauth_consumer.get_request_token(exclude_callback: true)
43
+ print "\n1) Please open this url in your browser to authorize lolcommits:\n\n"
44
+ puts request_token.authorize_url
45
+ print "\n2) Launching a local server to complete the OAuth authentication process:\n\n"
46
+ begin
47
+ server = WEBrick::HTTPServer.new Port: 3000
48
+ server.mount_proc '/', server_callback(server)
49
+ server.start
50
+ debug "Requesting Tumblr OAuth Token with verifier: #{@verifier}"
51
+ access_token = request_token.get_access_token(oauth_verifier: @verifier)
52
+ rescue Errno::EADDRINUSE
53
+ puts "\nERROR You have something running on port 3000. Please turn it off to complete the authorization process"
54
+ return
55
+ rescue OAuth::Unauthorized
56
+ puts "\nERROR: Tumblr OAuth verification faile!"
57
+ return
58
+ end
59
+ return unless access_token.token && access_token.secret
60
+ puts ''
61
+ puts '------------------------------'
62
+ puts 'Thanks! Tumblr Auth Succeeded'
63
+ puts '------------------------------'
64
+
65
+ {
66
+ 'access_token' => access_token.token,
67
+ 'secret' => access_token.secret
68
+ }
69
+ end
70
+
71
+ def configure_tumblr_name
72
+ print "\n3) What's your tumblr name? (i.e. 'http://[THIS PART HERE].tumblr.com'): "
73
+ { 'tumblr_name' => gets.strip }
74
+ end
75
+
76
+ def configured?
77
+ !configuration['enabled'].nil? &&
78
+ configuration['access_token'] &&
79
+ configuration['secret']
80
+ end
81
+
82
+ def client
83
+ @client ||= Tumblr.new(
84
+ consumer_key: TUMBLR_CONSUMER_KEY,
85
+ consumer_secret: TUMBLR_CONSUMER_SECRET,
86
+ oauth_token: configuration['access_token'],
87
+ oauth_token_secret: configuration['secret']
88
+ )
89
+ end
90
+
91
+ def oauth_consumer
92
+ @oauth_consumer ||= OAuth::Consumer.new(
93
+ TUMBLR_CONSUMER_KEY,
94
+ TUMBLR_CONSUMER_SECRET,
95
+ site: TUMBLR_API_ENDPOINT,
96
+ request_endpoint: TUMBLR_API_ENDPOINT,
97
+ http_method: :get
98
+ )
99
+ end
100
+
101
+ def config_with_default(key, default = nil)
102
+ if configuration[key]
103
+ configuration[key].strip.empty? ? default : configuration[key]
104
+ else
105
+ default
106
+ end
107
+ end
108
+
109
+ def self.name
110
+ 'tumblr'
111
+ end
112
+
113
+ def self.runner_order
114
+ :postcapture
115
+ end
116
+
117
+ protected
118
+
119
+ def server_callback(server)
120
+ proc do |req, res|
121
+ q = CGI.parse req.request_uri.query
122
+ @verifier = q['oauth_verifier'][0]
123
+ server.stop
124
+ res.body = 'Lolcommits authorization complete!'
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end