george 0.1.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.
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ = +george+
2
+
3
+ George is your helpful tea maker, gem installer and vim tutor. +george+ is a
4
+ command-line program for sending tweets to George.
5
+
6
+
7
+ == Usage
8
+
9
+ Install +george+ and authorize it to post to Twitter. This pops up the Twitter
10
+ auth flow in your browser.
11
+
12
+ gem install george
13
+ george install
14
+
15
+ Then send tweets to George! Commands are of the form:
16
+
17
+ george COMMAND ARGUMENT
18
+
19
+ For example:
20
+
21
+ george make tea
22
+ george help django
23
+ george judge whisky
24
+ george gem mirror
25
+
26
+ You can also use George's favourite editor to compose your own tweet:
27
+
28
+ george vim
29
+
30
+
31
+ == License
32
+
33
+ Copyright (c) 2013 /dev/fort Cohort 7
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
36
+ this software and associated documentation files (the 'Software'), to deal in
37
+ the Software without restriction, including without limitation the rights to use,
38
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
39
+ Software, and to permit persons to whom the Software is furnished to do so,
40
+ subject to the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be included in all
43
+ copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
47
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
48
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
49
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
50
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51
+
data/bin/george ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/george', __FILE__)
4
+ George.run(ARGV)
5
+
data/config/anna.vim ADDED
@@ -0,0 +1,27 @@
1
+ " Hi Anna,
2
+ "
3
+ " I thought it would be fun to carry on reminding you that you're awesome
4
+ " at vim, but sadly it's not practical for me to sit at your desk giving you
5
+ " a thumbs up every few minutes. The good news is that I can easily be replaced
6
+ " with a very small vim script.
7
+ "
8
+ " Enjoy,
9
+ " George
10
+ "
11
+ " P.S. When this gets annoying you should delete the "source anna.vim" line
12
+ " from your ~/.vimrc file.
13
+
14
+
15
+ let g:annas_awesomeness = 0
16
+ autocmd InsertLeave * call AnnaWasAwesome()
17
+
18
+ function! AnnaWasAwesome()
19
+ let g:annas_awesomeness = g:annas_awesomeness + 1
20
+
21
+ if (g:annas_awesomeness > 50)
22
+ silent !open "http://georgebrock.com/images/thumbsup.gif"
23
+ redraw!
24
+ let g:annas_awesomeness = 0
25
+ endif
26
+ endfunction
27
+
@@ -0,0 +1,10 @@
1
+ ---
2
+ twitter_username: georgebrock
3
+ consumer_key: oMU5kOPVvKTf4aMHrlrg
4
+ consumer_secret: 4gRVEZdm6bV3vutBEMBbMIAFQwXCaowWukfHSShcA
5
+ provider_site: https://api.twitter.com
6
+ request_token_url: https://api.twitter.com/oauth/request_token
7
+ authorize_url: https://api.twitter.com/oauth/authorize
8
+ access_token_url: https://api.twitter.com/oauth/access_token
9
+ callback_url: http://0.0.0.0:4180/authenticate
10
+
data/lib/george.rb ADDED
@@ -0,0 +1,107 @@
1
+ require 'childprocess'
2
+ require 'erb'
3
+ require 'json'
4
+ require 'twitter'
5
+ require 'yaml'
6
+
7
+ class George
8
+ ROOT = File.expand_path('../..', __FILE__)
9
+ LIB = ROOT + '/lib/george'
10
+ CONFIG_PATH = ROOT + '/config/twitter.yml'
11
+ ANNA_VIM = ROOT + '/config/anna.vim'
12
+ TEMPLATE_PATH = ROOT + '/templates'
13
+
14
+ CALLBACK_PATH = '/authenticate'
15
+ DEFAULT_PORT = 4180
16
+ DOTFILE_PATH = File.expand_path('~/.georgerc')
17
+ SCRATCH_PATH = File.expand_path('~/.GEORGE_TWEET')
18
+
19
+ autoload :Config, LIB + '/config'
20
+ autoload :OAuthClient, LIB + '/oauth_client'
21
+
22
+ def self.run(argv)
23
+ new.run(argv)
24
+ end
25
+
26
+ def config
27
+ @config ||= Config.new(CONFIG_PATH)
28
+ end
29
+
30
+ def run(argv)
31
+ command = argv.first
32
+ __send__(command, *argv[1..-1])
33
+ exit 0
34
+ rescue => e
35
+ $stderr.puts(e.message)
36
+ exit 1
37
+ end
38
+
39
+ def install(*args)
40
+ client = OAuthClient.new(config)
41
+ client.boot
42
+ credentials = client.get_oauth_credentials
43
+ File.open(DOTFILE_PATH, 'w') { |f| f.write(JSON.dump(credentials)) }
44
+ end
45
+
46
+ def vim(*args)
47
+ File.open(SCRATCH_PATH, 'w') do |f|
48
+ f.write "# Compose your tweet in George's favourite editor!\n"
49
+ end
50
+ vim = ChildProcess.build('vim', '-u', ANNA_VIM, SCRATCH_PATH)
51
+ vim.io.inherit!
52
+ vim.start
53
+ sleep 0.01 until vim.exited?
54
+ message = File.read(SCRATCH_PATH).split("\n").delete_if { |l| l =~ /^\s*#/ }.join("\n")
55
+
56
+ post_to_twitter(message)
57
+ ensure
58
+ File.unlink(SCRATCH_PATH)
59
+ end
60
+
61
+ Dir.entries(TEMPLATE_PATH).grep(/\.yml$/).each do |n|
62
+ undef_method File.basename(n, '.yml') rescue nil
63
+ end
64
+
65
+ def method_missing(name, *args)
66
+ template_path = File.join(TEMPLATE_PATH, "#{name}.yml")
67
+ raise "Not a valid command: `george #{name}`" unless File.file?(template_path)
68
+
69
+ templates = YAML.load_file(template_path)
70
+ thing = args.first
71
+ messages = (templates['custom'][thing] || []) + templates['generic']
72
+ template = messages[rand(messages.size)]
73
+ message = ERB.new(template).result(binding)
74
+
75
+ post_to_twitter(message)
76
+ end
77
+
78
+ def post_to_twitter(message)
79
+ message.strip!
80
+ return if message == ''
81
+ tweet = "@#{twitter_username} #{message}"
82
+ if ENV['DEBUG']
83
+ puts tweet
84
+ else
85
+ twitter.update(tweet)
86
+ end
87
+ end
88
+
89
+ def twitter
90
+ unless File.file?(DOTFILE_PATH)
91
+ raise "Please run `george install` to authenticate with Twitter"
92
+ end
93
+
94
+ credentials = JSON.parse(File.read(DOTFILE_PATH))
95
+ Twitter::Client.new(
96
+ :consumer_key => config.consumer_key,
97
+ :consumer_secret => config.consumer_secret,
98
+ :oauth_token => credentials['token'],
99
+ :oauth_token_secret => credentials['secret']
100
+ )
101
+ end
102
+
103
+ def twitter_username
104
+ ENV['GEORGE_USERNAME'] || config.twitter_username
105
+ end
106
+ end
107
+
@@ -0,0 +1,16 @@
1
+ class George
2
+ class Config
3
+
4
+ def initialize(path)
5
+ @data = YAML.load_file(path)
6
+ end
7
+
8
+ def method_missing(name)
9
+ name = name.to_s
10
+ return nil unless @data.include?(name)
11
+ ENV['GEORGE_' + name.upcase] || @data[name]
12
+ end
13
+
14
+ end
15
+ end
16
+
@@ -0,0 +1,117 @@
1
+ require 'base64'
2
+ require 'oauth'
3
+ require 'rack'
4
+ require 'webrick'
5
+
6
+ class George
7
+ class OAuthClient
8
+
9
+ DEFAULT_COMMANDS = {
10
+ /(mingw|mswin|windows|cygwin)/i => ['cmd', '/C', 'start', '/b'],
11
+ /(darwin|mac os)/i => ['open'],
12
+ /(linux|bsd|aix|solaris)/i => ['xdg-open']
13
+ }
14
+
15
+ GIF_PATH = File.join(TEMPLATE_PATH, 'thumbsup.gif')
16
+
17
+ RESPONSE_BODY = <<-HTML
18
+ <!doctype html>
19
+ <html>
20
+ <head>
21
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
22
+ <title>Tea is on its way!</title>
23
+ <style type="text/css">
24
+ body {
25
+ background: #fff;
26
+ color: #666;
27
+ font: 18px/1.5 FreeSans, Helvetica, Arial, sans-serif;
28
+ }
29
+
30
+ section {
31
+ width: 400px;
32
+ margin: 40px auto;
33
+ }
34
+
35
+ img {
36
+ display: block;
37
+ width: 360px;
38
+ border: 10px solid #eee;
39
+ }
40
+
41
+ h1 {
42
+ font-weight: normal;
43
+ font-size: 2.4em;
44
+ margin: 0.6em 0 0.4em;
45
+ }
46
+ </style>
47
+ </head>
48
+ <body>
49
+
50
+ <section>
51
+ <img alt="Thumbs up!" src="data:image/gif;base64,#{ Base64.encode64(File.read(GIF_PATH)).gsub(/[\s\n\r\t]/, '') }">
52
+
53
+ <h1>Tea is on its way!</h1>
54
+
55
+ <p>You&rsquo;re authorized to post to Twitter. Close this window and
56
+ return to your terminal.</p>
57
+ </section>
58
+
59
+ </body>
60
+ </html>
61
+ HTML
62
+
63
+ def initialize(config)
64
+ @config = config
65
+ @client = OAuth::Consumer.new(
66
+ config.consumer_key,
67
+ config.consumer_secret,
68
+ :site => config.provider_site
69
+ )
70
+ end
71
+
72
+ def boot
73
+ @server_thread = Thread.new do
74
+ handler = Rack::Handler.get('webrick')
75
+ handler.run(self, :Port => DEFAULT_PORT,
76
+ :AccessLog => [],
77
+ :Logger => WEBrick::Log::new(nil, 0))
78
+ end
79
+ end
80
+
81
+ def authorize_url
82
+ @request_token.authorize_url(:oauth_callback => @config.callback_url)
83
+ end
84
+
85
+ def get_oauth_credentials
86
+ @request_token = @client.get_request_token(:oauth_callback => @config.callback_url)
87
+ launch_browser(authorize_url)
88
+ sleep 1 until @oauth_credentials
89
+ @oauth_credentials
90
+ end
91
+
92
+ def launch_browser(url)
93
+ os = RbConfig::CONFIG['host_os']
94
+ key = DEFAULT_COMMANDS.keys.find { |key| os =~ key }
95
+ argv = DEFAULT_COMMANDS[key] + [url]
96
+
97
+ @browser = ChildProcess.build(*argv)
98
+ @browser.start
99
+ end
100
+
101
+ def call(env)
102
+ return [404, {}, []] unless env['PATH_INFO'] == CALLBACK_PATH
103
+
104
+ params = Rack::Request.new(env).params
105
+ @access_token = @request_token.get_access_token(:oauth_verifier => params['oauth_verifier'])
106
+
107
+ @oauth_credentials = {
108
+ 'token' => @access_token.token,
109
+ 'secret' => @access_token.secret
110
+ }
111
+
112
+ [200, {'Content-Type' => 'text/html'}, [RESPONSE_BODY]]
113
+ end
114
+
115
+ end
116
+ end
117
+
data/templates/gem.yml ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ generic:
3
+ - George, can you send me the <%= thing %>.gem file, please?
4
+
5
+ custom:
6
+ rails:
7
+ - "SystemStackError due to #lol_ruby"
8
+ - What the fuck Rails? What the actual fuck?
9
+ - Bet you could do this in Django in 5 mins.
10
+ - Because RAILS MAGIC... MAGIC!
11
+
12
+ benice:
13
+ - You're awesome. Fucking awesome!
14
+ - The bank of George was the Best Bank Ever.
15
+ - Next time George, next time.
16
+ - Beer's on me.
17
+ - Cookie? Omnomnom coooooookie.
18
+ - I miss you George. Then I get over it.
19
+ - Lets go crazy, I'll buy YOU a coffee!... Can you lend me some money?
20
+ - I miss working with you and that level of ridiculousness.
@@ -0,0 +1,25 @@
1
+ ---
2
+ generic:
3
+ - Help, George, I don't understand <%= thing %>.
4
+ - Can you pair with me on <%= thing %>?
5
+ - Help me, George, you're my only hope.
6
+ - I need some emergency leftover <%= thing %>.
7
+ - Can you help me fix my own stupidity?
8
+ - Oops.
9
+ - TO THE WHITEBOARD!
10
+ - Coax me back, George.
11
+
12
+ custom:
13
+ code:
14
+ - What does this JavaScripts do?
15
+ - Can you send me the Nokogiri gem?
16
+ - What's that? Variadic Ruby methods cause stack overflows? Cool story, bro.
17
+ - Wait, what? That function takes a callback of a callback of a moose?
18
+ - GEORGE! You changed some settings and broke the build again.
19
+ - I've got some batshit insane Varnish config problem can you help?
20
+ - There is a more pleasant way of doing that.
21
+ - Not all spans are bad, m'kay.
22
+ - The JS fadey zoomy thingy isn't ajax whooshy, why not?
23
+ vim:
24
+ - I just entered normal mode.
25
+
@@ -0,0 +1,14 @@
1
+ ---
2
+ generic:
3
+ - With the judging eyes, the judgiiiiing
4
+ - Yeah, I know it's crazy, I just met you, I'll judge you maybe
5
+ - It's all wrong!
6
+
7
+ custom:
8
+ whisky:
9
+ - Melancholy. The MELANCHOLY. Balls :(
10
+ - Want some coke with your whisky?
11
+ - Mazz may have ruined everything but you ruined my mum.
12
+ stockholm:
13
+ - You're getting Stockholm Syndrome from living in Stockholm.
14
+
@@ -0,0 +1,18 @@
1
+ ---
2
+ generic:
3
+ - George. George. George. George. George. George. George. George. George. George.
4
+ - Please may I have some <%= thing %>?
5
+ - Isn't it time you had some <%= thing %>?
6
+ - git fetch george
7
+ - Thanks George! Thorge.
8
+ - Something something <%= thing %>.
9
+
10
+ custom:
11
+ tea:
12
+ - Are you putting the kettle on? I'd love one.
13
+ - You wouldn't want the world to discover your EVIL ALIEN IDENTITY NOW, RIGHT?
14
+ - Is that "Fifty Shades of Earl Grey" you're reading?
15
+ - Milk and no sugar for me, please.
16
+ - It's two pots, one George!
17
+ supertrain:
18
+ - George, it's time. Get your bag. Supertrain is here.
Binary file
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: george
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - James Coglan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: childprocess
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: oauth
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.4.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: twitter
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 4.0.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 4.0.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: rack
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description:
79
+ email: jcoglan@gmail.com
80
+ executables:
81
+ - george
82
+ extensions: []
83
+ extra_rdoc_files:
84
+ - README.rdoc
85
+ files:
86
+ - README.rdoc
87
+ - bin/george
88
+ - config/twitter.yml
89
+ - config/anna.vim
90
+ - lib/george.rb
91
+ - lib/george/oauth_client.rb
92
+ - lib/george/config.rb
93
+ - templates/thumbsup.gif
94
+ - templates/help.yml
95
+ - templates/judge.yml
96
+ - templates/gem.yml
97
+ - templates/make.yml
98
+ homepage: http://github.com/jcoglan/george
99
+ licenses: []
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --main
103
+ - README.rdoc
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.23
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Makes you tea, helps you code
124
+ test_files: []
125
+ has_rdoc: