george 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: