hackershout 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.2@hackershout
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hackershout.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(/^spec\/(.*)_spec.rb/)
6
+ watch(/^lib\/(.*)\.rb/) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch(/^spec\/spec_helper.rb/) { "spec" }
8
+ end
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => :spec
11
+ task :test => [:spec]
data/Readme.md ADDED
@@ -0,0 +1,92 @@
1
+ #Hackershout
2
+
3
+ Shout your hackerness to the world!
4
+
5
+ Hackershout lets you promote your open-source work on the major Ruby (and geek
6
+ related) community blogs (Reddit, Hackernews and RubyFlow) via a nice command
7
+ line interface.
8
+
9
+ ##Install
10
+
11
+ $ gem install hackershout
12
+
13
+ ##Known caveats
14
+
15
+ Publishing to Reddit is not available yet.
16
+
17
+ ##Notes
18
+
19
+ Through hackershout you publish an **URL** and a **text**. To link the URL from
20
+ the text you just have to use the special `<link>` tag. Note that for certain
21
+ sites, such as RubyFlow, you _have to link_ the URL from the text, since there
22
+ is no separate URL field. Hackershout will omit the special tag where it
23
+ doesn't need it (for example, in Reddit).
24
+
25
+ You can add additional links with normal HTML `<a>` tags.
26
+
27
+ Given `http://rubygems.org/gems/my_gem` as an URL, an example of a message
28
+ would be:
29
+
30
+ Hey! I have released <link>some awesome open-source gem</link> that is
31
+ going to save the world. Check it out! You can also grab the source code on
32
+ <a href="http://github.com/me/my_gem">Github</a> if you want.
33
+
34
+ This will publish in Reddit like this:
35
+
36
+ URL: http://rubygems.org/gems/my_gem
37
+ TEXT: Hey! I have released some awesome open-source gem that is going to
38
+ save the world. Check it out! You can also grab the source code on
39
+ <a href="http://github.com/me/my_gem">Github</a> if you want.
40
+
41
+ And on RubyFlow (where there is no separate URL field) like this:
42
+
43
+ TEXT: Hey! I have released <a href="http://rubygems.org/gems/my_gem">some
44
+ awesome open-source gem</a> that is going to save the world. Check it out!
45
+ You can also grab the source code on <a href="http://github.com/me/my_gem">
46
+ Github</a> if you want.
47
+
48
+ ##Usage
49
+
50
+ $ hackershout
51
+
52
+ :: Welcome to hackershout! ::
53
+
54
+ Type the URL you want to share: http://rubygems.com/gems/my_gem
55
+ Enter a brief, descriptive title: Released MyGem 1.0!
56
+
57
+ Bear in mind that some services may require a more extended text aside from the title.
58
+ Type your message (two ENTERs to finish):
59
+ Hey! I have released <link>some awesome open-source gem</link> that is
60
+ going to save the world. Check it out! You can also grab the source code
61
+ on <a href="http://github.com/me/my_gem">Github</a> if you want.(enter)
62
+ (enter)
63
+ Type some tags separated by comma (i.e. ruby, rails, bdd): ruby, parsing
64
+
65
+ ...Got it! Now where would you want to spread the word?
66
+ Ruby Reddit (y/n)? y
67
+ Sorry, I don't have your Ruby Reddit credentials.
68
+ E-mail: my.email@gmail.com
69
+ Password: ********
70
+ Saved! You won't have to enter your credentials for Ruby Reddit again.
71
+ Hackernews (y/n)? y
72
+ RubyFlow (y/n)? n
73
+ Fine.
74
+ Posting to Ruby Reddit...........ok
75
+ Posting to Hackernews............ok
76
+
77
+ Done. Happy hacking! :)
78
+
79
+ ##Contribute!
80
+
81
+ * Fork the project.
82
+ * Make your feature addition or bug fix.
83
+ * Add specs for it. This is important so I don't break it in a future
84
+ version unintentionally.
85
+ * Commit, do not mess with rakefile, version, or history.
86
+ If you want to have your own version, that is fine but bump version
87
+ in a commit by itself I can ignore when I pull.
88
+ * Send me a pull request. Bonus points for topic branches.
89
+
90
+ ## Copyright
91
+
92
+ Copyright (c) 2011 Codegram. See LICENSE for details.
data/bin/hackershout ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $: << 'lib'
3
+ require 'hackershout'
4
+
5
+ Hackershout.run
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hackershout/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hackershout"
7
+ s.version = Hackershout::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Josep M. Bach", "Josep Jaume Rey", "Oriol Gual"]
10
+ s.email = ["info@codegram.com"]
11
+ s.homepage = "http://github.com/codegram/hackershout"
12
+ s.summary = %q{Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.}
13
+ s.description = %q{Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.}
14
+
15
+ s.rubyforge_project = "hackershout"
16
+
17
+ s.add_runtime_dependency 'nokogiri'
18
+ s.add_runtime_dependency 'mechanize'
19
+
20
+ s.add_development_dependency 'rspec', '~> 2.5.0'
21
+ s.add_development_dependency 'guard'
22
+ s.add_development_dependency 'guard-rspec'
23
+ s.add_development_dependency 'rb-fsevent'
24
+ s.add_development_dependency 'vcr'
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,83 @@
1
+ require 'hackershout/output'
2
+
3
+ module Hackershout
4
+ class Base
5
+ include Output
6
+
7
+ def initialize(options = {})
8
+ @url = options[:url]
9
+ @title = options[:title]
10
+ @message = options[:message]
11
+ @tags = options[:tags] || []
12
+ @providers = options[:providers] || []
13
+ end
14
+
15
+ def run
16
+ welcome_banner
17
+ @url = ask_for_url
18
+ @title = ask_for_title
19
+ @message = ask_for_message
20
+ @tags = ask_for_tags
21
+ providers_banner
22
+
23
+ @providers = ask_for_providers
24
+ post_to_providers
25
+ end
26
+
27
+ def welcome_banner
28
+ print ":: Welcome to hackershout! ::"
29
+ blank
30
+ end
31
+
32
+ def ask_for_url
33
+ print "Type the URL you want to share: "
34
+ gets.chomp.strip
35
+ end
36
+
37
+ def ask_for_title
38
+ print "Enter a brief, descriptive title: "
39
+ gets.chomp.strip
40
+ end
41
+
42
+ def ask_for_message
43
+ print "Bear in mind that some services may require a more extended text aside from the title."
44
+ print "Type your message (two ENTERs to finish): "
45
+ $/ = "\n\n"
46
+ gets.chomp.strip.tap do
47
+ # Restore EOM char
48
+ $/ = "\n"
49
+ end
50
+ end
51
+
52
+ def ask_for_tags
53
+ print "Type some tags separated by comma (i.e. ruby, rails, bdd): "
54
+ gets.chomp.strip.split(',').map(&:strip)
55
+ end
56
+
57
+ def providers_banner
58
+ print "...Got it! Now where would you want to spread the word?"
59
+ end
60
+
61
+ def ask_for_providers
62
+ Provider.list.keys.select do |provider|
63
+ Provider.wants?(provider)
64
+ end
65
+ end
66
+
67
+ def post_to_providers
68
+ print "Fine."
69
+ @providers.map do |provider|
70
+ eval("Provider::#{provider.capitalize}").new({
71
+ url: @url,
72
+ title: @title,
73
+ message: @message,
74
+ tags: @tags,
75
+ })
76
+ end.each do |provider|
77
+ provider.publish
78
+ end
79
+ puts "Done. Happy hacking! :)\n"
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,13 @@
1
+ module Hackershout
2
+ module Output
3
+
4
+ def print(str)
5
+ $stdout.print "\n" + str
6
+ end
7
+
8
+ def blank
9
+ print "\n"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ require 'mechanize'
2
+ require 'nokogiri'
3
+
4
+ Mechanize.html_parser = Nokogiri::HTML
5
+
6
+ module Hackershout
7
+ module Provider
8
+ class Base
9
+ attr_reader :agent
10
+
11
+ include Output
12
+
13
+ def initialize(options = {})
14
+ @name = self.class.name.split("::").last
15
+ @url = options[:url]
16
+ @title = options[:title]
17
+ @tags = options[:tags]
18
+ @message = options[:message]
19
+
20
+ creds = YAML.load(File.read(File.join(File.expand_path('~'), '.hackershoutrc')))[@name.downcase]
21
+ raise "Can't find credentials on ~/.hackershoutrc for #{@name}" unless creds
22
+
23
+ @login = creds["login"]
24
+ @password = creds["password"]
25
+ @agent = Mechanize.new
26
+ end
27
+
28
+ def publish
29
+ print "Posting to #{@name}..."
30
+ post unless ENV['NOSEND']
31
+ print "Posted to #{@name}!"
32
+ end
33
+
34
+ def post
35
+ raise NotImplementedError
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ module Hackershout
2
+ module Provider
3
+ class Hackernews < Base
4
+
5
+ URL = {
6
+ :login => 'http://news.ycombinator.com/submit'
7
+ }
8
+
9
+ def post
10
+ page = agent.get(URL[:login])
11
+ login_form = page.forms.first
12
+ login_form.u = @login
13
+ login_form.p = @password
14
+ page = login_form.submit
15
+ submit(page)
16
+ end
17
+
18
+ private
19
+
20
+ def submit(submit_page)
21
+ form = submit_page.forms.first
22
+ form.t = @title
23
+ form.u = @url
24
+ form.submit
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Hackershout
2
+ module Provider
3
+ class Reddit < Base
4
+
5
+ URL = {
6
+ :login => 'http://www.reddit.com/r/ruby/',
7
+ :submit => 'http://www.reddit.com/r/ruby/submit',
8
+ }
9
+
10
+ # Not logging in! :(
11
+ def post
12
+ raise NotImplementedError
13
+ page = agent.get(URL[:login])
14
+ login_form = page.forms_with(:action => 'http://www.reddit.com/r/ruby/post/login').first
15
+ login_form.user = @login
16
+ login_form.passwd = @password
17
+ page = login_form.submit
18
+ puts page.links_with(:text => 'logout').inspect
19
+ page = page.links_with(:text => 'Submit a link').first.click
20
+ puts page.inspect
21
+
22
+ rescue Mechanize::ResponseCodeError=>e
23
+ puts "#{@name} is unavailable for now. Please try in a few minutes. The server gave the following reason:"
24
+ puts e.inspect
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ module Hackershout
2
+ module Provider
3
+ class Rubyflow < Base
4
+
5
+ URL = {
6
+ :login => 'http://www.rubyflow.com/login'
7
+ }
8
+
9
+ def post
10
+ page = agent.get(URL[:login])
11
+ login_form = page.form_with(:action => '/session')
12
+ login_form.login = @login
13
+ login_form.password = @password
14
+ page = login_form.submit
15
+ page = page.link_with(:href => /items\/new/).click
16
+ submit(page)
17
+ end
18
+
19
+ private
20
+
21
+ def submit(submit_page)
22
+ form = submit_page.form_with(:action => '/items')
23
+ form['item[title]'] = @title
24
+ form['item[content]'] = process(@message)
25
+ form.submit
26
+ end
27
+
28
+ def process(message)
29
+ message.gsub!('<link>', "<a href=\"#{@url}\">")
30
+ message.gsub!('</link>', "</a>")
31
+ message
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+ module Hackershout
2
+ module Provider
3
+ class << self
4
+
5
+ include Output
6
+
7
+ def list
8
+ {
9
+ # :reddit => 'Ruby Reddit',
10
+ :hackernews => 'Hackernews',
11
+ :rubyflow => 'RubyFlow',
12
+ }
13
+ end
14
+
15
+ def wants?(provider)
16
+ name = list[provider]
17
+ print "\t#{name} (y/n)? "
18
+ return case gets.chomp
19
+ when 'y'
20
+ check_credentials_for(provider)
21
+ when 'n'
22
+ false
23
+ else
24
+ blank
25
+ print "I don't understand. Just type y for yes and n for no :)"
26
+ wants?(provider)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def check_credentials_for(provider)
33
+ credentials = if File.exists?(File.join(File.expand_path('~'), '.hackershoutrc'))
34
+ YAML.load(File.read(File.join(File.expand_path('~'), '.hackershoutrc')))
35
+ else
36
+ ask_for_credentials(provider)
37
+ end
38
+
39
+ if credentials[provider.to_s] &&
40
+ credentials[provider.to_s]["login"] &&
41
+ credentials[provider.to_s]["password"]
42
+ true
43
+ else
44
+ ask_for_credentials(provider)
45
+ end
46
+ end
47
+
48
+ def ask_for_credentials(provider)
49
+ print "Sorry, I don't have your #{list[provider]} credentials."
50
+ print "\tLogin: "
51
+ login = gets.chomp.strip
52
+ system('stty -echo')
53
+ print "\tPassword: "
54
+ password = gets.chomp.strip
55
+ system('stty echo')
56
+ File.open(File.join(File.expand_path('~'), '.hackershoutrc'), 'a') do |file|
57
+ file.write "\n#{provider}:"
58
+ file.write "\n login: #{login}"
59
+ file.write "\n password: #{password}"
60
+ file.write "\n"
61
+ end
62
+ { provider => { "login" => login, "password" => password } }
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ module Hackershout
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,15 @@
1
+ require 'hackershout/output'
2
+ require 'hackershout/provider'
3
+ require 'hackershout/provider/base'
4
+ require 'hackershout/provider/reddit'
5
+ require 'hackershout/provider/hackernews'
6
+ require 'hackershout/provider/rubyflow'
7
+ require 'hackershout/base'
8
+
9
+ module Hackershout
10
+ class << self
11
+ def run
12
+ Base.new.run
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ module Hackershout
4
+ describe Base do
5
+
6
+ describe ".run" do
7
+ before do
8
+ subject.stub(:welcome_banner)
9
+ subject.stub(:ask_for_url)
10
+ subject.stub(:ask_for_message)
11
+ subject.stub(:ask_for_title)
12
+ subject.stub(:ask_for_tags)
13
+ subject.stub(:providers_banner)
14
+ subject.stub(:ask_for_providers)
15
+ subject.stub(:post_to_providers)
16
+ end
17
+ it 'calls welcome banner' do
18
+ subject.should_receive(:welcome_banner)
19
+ subject.run
20
+ end
21
+ it 'calls ask_for_url' do
22
+ subject.should_receive(:ask_for_url)
23
+ subject.run
24
+ end
25
+ it 'calls ask_for_title' do
26
+ subject.should_receive(:ask_for_title)
27
+ subject.run
28
+ end
29
+ it 'calls ask_for_message' do
30
+ subject.should_receive(:ask_for_message)
31
+ subject.run
32
+ end
33
+ it 'calls ask_for_tags' do
34
+ subject.should_receive(:ask_for_tags)
35
+ subject.run
36
+ end
37
+ it 'calls providers_banner' do
38
+ subject.should_receive(:providers_banner)
39
+ subject.run
40
+ end
41
+ it 'calls ask_for_providers' do
42
+ subject.should_receive(:ask_for_providers)
43
+ subject.run
44
+ end
45
+ end
46
+
47
+ describe "#welcome_banner" do
48
+ it 'prints the welcome banner' do
49
+ subject.should_receive(:blank).any_number_of_times
50
+ subject.should_receive(:print).with(":: Welcome to hackershout! ::")
51
+ subject.welcome_banner
52
+ end
53
+ end
54
+
55
+ describe "#ask_for_url" do
56
+ it 'asks for the url and returns it' do
57
+ subject.should_receive(:print).with("Type the URL you want to share: ")
58
+ subject.should_receive(:gets).and_return ' http://rubygems.org/gems/my_gem '
59
+ subject.ask_for_url.should == 'http://rubygems.org/gems/my_gem'
60
+ end
61
+ end
62
+
63
+ describe "#ask_for_title" do
64
+ it 'asks for the title and returns it' do
65
+ subject.should_receive(:print).with("Enter a brief, descriptive title: ")
66
+ subject.should_receive(:gets).and_return ' Released my gem: a nifty gem to eradicate hunger! '
67
+ subject.ask_for_title.should == 'Released my gem: a nifty gem to eradicate hunger!'
68
+ end
69
+ end
70
+
71
+ describe "#ask_for_message" do
72
+ it 'asks for the message and returns it' do
73
+ subject.should_receive(:print).with("Bear in mind that some services may require a more extended text aside from the title.")
74
+ subject.should_receive(:print).with("Type your message (two ENTERs to finish): ")
75
+ subject.should_receive(:gets).and_return("""
76
+ Hey! I have released <link>some awesome open-source gem</link> that is
77
+ going to save the world.\nCheck it out! You can also grab the source code
78
+ on <a href=\"http://github.com/me/my_gem\">Github</a> if you want.
79
+
80
+ """)
81
+ subject.ask_for_message
82
+ end
83
+ end
84
+
85
+ describe "#ask_for_tags" do
86
+ it 'asks for the tags and returns them' do
87
+ subject.should_receive(:print).with("Type some tags separated by comma (i.e. ruby, rails, bdd): ")
88
+ subject.should_receive(:gets).and_return ' ruby , bdd, rails, parsing '
89
+ subject.ask_for_tags.should == %w( ruby bdd rails parsing )
90
+ end
91
+ end
92
+
93
+ describe "#providers_banner" do
94
+ it 'prints the providers banner' do
95
+ subject.should_receive(:print).with("...Got it! Now where would you want to spread the word?")
96
+ subject.providers_banner
97
+ end
98
+ end
99
+
100
+ describe "#ask_for_providers" do
101
+ it 'asks for providers' do
102
+ providers = [:reddit, :hackernews, :rubyflow]
103
+ Provider.stub_chain('list.keys').and_return providers
104
+ Provider.should_receive(:wants?).with(:reddit).and_return true
105
+ Provider.should_receive(:wants?).with(:hackernews).and_return false
106
+ Provider.should_receive(:wants?).with(:rubyflow).and_return true
107
+
108
+ subject.ask_for_providers.should == [:reddit, :rubyflow]
109
+ end
110
+ end
111
+
112
+ describe "#post_to_providers" do
113
+ it 'instantiates each provider and calls #publish on it' do
114
+ args = {
115
+ :url => 'http://rubygems.org/gems/my_gem',
116
+ :title => 'Released MyGem!',
117
+ :tags => ['ruby', 'bdd'],
118
+ :message => 'Hello!',
119
+ }
120
+ base = Base.new({:providers => [:reddit, :hackernews]}.update(args))
121
+ base.stub(:print)
122
+
123
+ hackernews = double :provider
124
+ reddit = double :provider
125
+
126
+ Provider::Hackernews.should_receive(:new).with(args).and_return hackernews
127
+ Provider::Reddit.should_receive(:new).with(args).and_return reddit
128
+
129
+ hackernews.should_receive(:publish)
130
+ reddit.should_receive(:publish)
131
+
132
+ base.post_to_providers
133
+ end
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ module Hackershout
4
+ module Provider
5
+ describe Base do
6
+
7
+ # Test only base class. Each provider only implements #post with pure Mechanize logic.
8
+
9
+ before do
10
+ File.stub(:read).and_return """
11
+ base:
12
+ login: my.email@gmail.com
13
+ password: mypassword
14
+ """
15
+ end
16
+
17
+ describe "#initialize" do
18
+ it 'reads the credentials and stores them' do
19
+ base = Base.new(:url => 'url',
20
+ :tags => ['my', 'tags'],
21
+ :message => 'message')
22
+
23
+ base.instance_variable_get(:@login).should eq('my.email@gmail.com')
24
+ base.instance_variable_get(:@password).should eq('mypassword')
25
+ base.instance_variable_get(:@agent).should be_a(Mechanize)
26
+ end
27
+ end
28
+
29
+ describe "#publish" do
30
+ it 'logs in and posts' do
31
+ base = Base.new(:url => 'url',
32
+ :tags => ['my', 'tags'],
33
+ :message => 'message')
34
+
35
+ base.should_receive(:post)
36
+
37
+ base.publish
38
+ end
39
+ end
40
+
41
+ it 'crap' do
42
+ File.stub(:read).and_return """
43
+ hackernews:
44
+ login: codegram
45
+ password: codgamerP90
46
+ """
47
+ Hackernews.new(:title => 'my title', :message => 'my message', :url => 'http://google.com').post
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ module Hackershout
4
+ describe Provider do
5
+
6
+ describe "#list" do
7
+ it 'returns a hash' do
8
+ subject.list.should == {
9
+ :reddit => 'Ruby Reddit',
10
+ :hackernews => 'Hackernews',
11
+ :rubyflow => 'RubyFlow',
12
+ }
13
+ end
14
+ end
15
+
16
+ describe "#wants?(provider)" do
17
+ before do
18
+ subject.should_receive(:print).with("\tRuby Reddit (y/n)? ")
19
+ end
20
+ context 'if the user wants to publish on a provider' do
21
+ it 'checks the credentials' do
22
+ subject.should_receive(:gets).and_return 'y'
23
+ subject.should_receive(:check_credentials_for).with(:reddit)
24
+ subject.wants?(:reddit)
25
+ end
26
+ end
27
+ context 'if the user doesn\'t want' do
28
+ it 'returns false' do
29
+ subject.should_receive(:gets).and_return 'n'
30
+ subject.wants?(:reddit).should be_false
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#check_credentials_for(provider)" do
36
+
37
+ context 'if the credentials exist' do
38
+ it 'returns true' do
39
+ File.stub(:read).and_return "reddit:\n login: my.email@gmail.com\n password: mypassword"
40
+ subject.should_not_receive(:ask_for_credentials)
41
+ subject.send(:check_credentials_for, :reddit).should be_true
42
+ end
43
+ end
44
+
45
+ context 'otherwise' do
46
+ it 'asks for them' do
47
+ File.stub(:read).and_return "hackernews:\n login: my.email@gmail.com\n password: mypassword"
48
+ subject.should_receive(:ask_for_credentials).with(:reddit)
49
+ subject.send(:check_credentials_for, :reddit)
50
+ end
51
+ end
52
+
53
+ context "if the file doesn't even exist" do
54
+ it 'asks for the credentials as well' do
55
+ File.stub(:read).and_raise Errno::ENOENT
56
+ subject.should_receive(:ask_for_credentials).with(:reddit)
57
+ subject.send(:check_credentials_for, :reddit)
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ describe "#ask_for_credentials(provider)" do
64
+ it 'asks for the credentials and saves them into ~/.hackershoutrc' do
65
+ subject.stub(:print)
66
+ file = double :file
67
+ subject.should_receive(:gets).and_return 'my.email@gmail.com'
68
+ subject.should_receive(:gets).and_return 'mypassword'
69
+ File.should_receive(:open).and_yield file
70
+
71
+ file.should_receive(:write).with "\nreddit:"
72
+ file.should_receive(:write).with "\n login: my.email@gmail.com"
73
+ file.should_receive(:write).with "\n password: mypassword"
74
+
75
+ subject.send(:ask_for_credentials, :reddit)
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hackershout do
4
+
5
+ describe ".run" do
6
+ it 'calls run on a new Base instance' do
7
+ Hackershout::Base.should_receive(:new).and_return(double(:base).tap { |b|
8
+ b.should_receive(:run)
9
+ })
10
+ subject.run
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec'
2
+ require 'hackershout'
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hackershout
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Josep M. Bach
13
+ - Josep Jaume Rey
14
+ - Oriol Gual
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-02-17 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: nokogiri
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: mechanize
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 2
58
+ - 5
59
+ - 0
60
+ version: 2.5.0
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: guard
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: guard-rspec
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ type: :development
88
+ version_requirements: *id005
89
+ - !ruby/object:Gem::Dependency
90
+ name: rb-fsevent
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ type: :development
101
+ version_requirements: *id006
102
+ - !ruby/object:Gem::Dependency
103
+ name: vcr
104
+ prerelease: false
105
+ requirement: &id007 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ type: :development
114
+ version_requirements: *id007
115
+ description: Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.
116
+ email:
117
+ - info@codegram.com
118
+ executables:
119
+ - hackershout
120
+ extensions: []
121
+
122
+ extra_rdoc_files: []
123
+
124
+ files:
125
+ - .gitignore
126
+ - .rspec
127
+ - .rvmrc
128
+ - Gemfile
129
+ - Guardfile
130
+ - Rakefile
131
+ - Readme.md
132
+ - bin/hackershout
133
+ - hackershout.gemspec
134
+ - lib/hackershout.rb
135
+ - lib/hackershout/base.rb
136
+ - lib/hackershout/output.rb
137
+ - lib/hackershout/provider.rb
138
+ - lib/hackershout/provider/base.rb
139
+ - lib/hackershout/provider/hackernews.rb
140
+ - lib/hackershout/provider/reddit.rb
141
+ - lib/hackershout/provider/rubyflow.rb
142
+ - lib/hackershout/version.rb
143
+ - spec/hackershout/base_spec.rb
144
+ - spec/hackershout/provider/base_spec.rb
145
+ - spec/hackershout/provider_spec.rb
146
+ - spec/hackershout_spec.rb
147
+ - spec/spec_helper.rb
148
+ has_rdoc: true
149
+ homepage: http://github.com/codegram/hackershout
150
+ licenses: []
151
+
152
+ post_install_message:
153
+ rdoc_options: []
154
+
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ segments:
163
+ - 0
164
+ version: "0"
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ segments:
171
+ - 0
172
+ version: "0"
173
+ requirements: []
174
+
175
+ rubyforge_project: hackershout
176
+ rubygems_version: 1.3.7
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.
180
+ test_files:
181
+ - spec/hackershout/base_spec.rb
182
+ - spec/hackershout/provider/base_spec.rb
183
+ - spec/hackershout/provider_spec.rb
184
+ - spec/hackershout_spec.rb
185
+ - spec/spec_helper.rb