ivanvc-pft 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Iván Valdés
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,25 @@
1
+ h1. pft!
2
+
3
+ A command line twitter client. It's intended to be as powerful as donkey.
4
+
5
+ h2. Requirements
6
+
7
+ * ruby
8
+ * rubyems
9
+ * Included in the gem:
10
+ ** twitter
11
+ ** choice (0.1.3.1)
12
+ ** highline
13
+ ** rspec
14
+
15
+ h2. Installation
16
+
17
+ Just hit
18
+
19
+ @gem install ivanvc-pft --source http://gems.github.com/@
20
+
21
+ Then you're ready to go. You should have the pft binary.
22
+
23
+ h2. Help
24
+
25
+ Use @pft -@ or @pft --help@
data/bin/pft ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'pft'
5
+ require 'choice'
6
+
7
+ Choice.options do
8
+ banner "Usage: #{File.basename(__FILE__)} [-adhrt] [message]"
9
+
10
+ header ''
11
+ header 'Configuration options:'
12
+
13
+ option :authorize do
14
+ short '-a'
15
+ long '--authorize'
16
+ desc "Associate your twitter account using OAuth"
17
+ default false
18
+ end
19
+
20
+ separator ''
21
+ separator 'Tweet options:'
22
+
23
+ option :dm do
24
+ short '-d'
25
+ long '--dm=USERNAME'
26
+ desc "Send a direct message to username"
27
+ default nil
28
+ end
29
+
30
+ option :reply do
31
+ short '-r'
32
+ long '--reply=USERNAME'
33
+ desc "Send a reply to username's last tweet"
34
+ default nil
35
+ end
36
+
37
+ option :rt do
38
+ short '-t'
39
+ long '--rt=USERNAME'
40
+ desc "Post a retweet of username's last tweet"
41
+ default nil
42
+ end
43
+
44
+ separator ''
45
+ separator 'Common options: '
46
+
47
+ option :help do
48
+ long '--help'
49
+ desc 'Show this message'
50
+ end
51
+
52
+ option :version do
53
+ short '-v'
54
+ long '--version'
55
+ desc 'Show version'
56
+ action do
57
+ puts "#{File.basename(__FILE__)} v#{Pft::Base.version}"
58
+ exit
59
+ end
60
+ end
61
+ end
62
+
63
+ Pft::Base.tweet(Choice.choices, Choice.rest) rescue puts $!
64
+ #CIJoe::Server.start(options[:host], options[:port], Choice.rest[0])
data/lib/pft/base.rb ADDED
@@ -0,0 +1,107 @@
1
+ module Pft
2
+ class Base
3
+ attr_accessor :oauth, :message, :configuration
4
+
5
+ def initialize(*args)
6
+ options = args.pop || {}
7
+ @oauth = Oauth.new
8
+ end
9
+
10
+ def reply_to(user, message)
11
+ user = get_user(user)
12
+ @oauth.client.update("@#{user.screen_name} #{message}", :in_reply_to_status_id => user.status.id)
13
+ message_for('reply', user)
14
+ end
15
+
16
+ def retweet(user)
17
+ user = get_user(user)
18
+ @oauth.client.update("RT @#{user.screen_name} #{user.status.text}")
19
+ message_for('retweet', user)
20
+ end
21
+
22
+ def direct_message(user, message)
23
+ user = get_user(user).screen_name
24
+ @oauth.client.direct_message_create(user, message)
25
+ message_for('direct message', user)
26
+ end
27
+
28
+ def get_user(user)
29
+ user = @oauth.client.user(user) rescue false
30
+ if !user || !user.status
31
+ raise "User or last tweet not found"
32
+ end
33
+ user
34
+ end
35
+
36
+ def parse_urls(message)
37
+ return message unless message.=~(/(?:http:\/\/|ftp:\/\/|https:\/\/|www\.|ftp\.[\w]+)(?:[\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])/)
38
+ parsed_message = ""
39
+ message.each(" ") do |word|
40
+ if word.=~(/(?:http:\/\/|ftp:\/\/|https:\/\/|www\.|ftp\.[\w]+)(?:[\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])/)
41
+ word = "#{TinyUrl.compact(word.delete(' '))} "
42
+ end
43
+ parsed_message << word
44
+ end
45
+ parsed_message
46
+ end
47
+
48
+ def message_for(type, user = nil)
49
+ "pft! successfully sent a #{type}#{" to #{user}" if user}"
50
+ end
51
+
52
+ def self.tweet(*options)
53
+ base = self.new
54
+ message = options.pop || []
55
+ message = base.parse_urls(message.join(" "))
56
+ options = options.pop || {}
57
+
58
+ if options[:authorize]
59
+ base.oauth.authorize
60
+ elsif options[:reply]
61
+ puts base.reply_to(options[:reply], message)
62
+ elsif options[:rt]
63
+ puts base.retweet(options[:rt])
64
+ elsif options[:dm]
65
+ puts base.direct_message(options[:dm], message)
66
+ elsif message.size > 0
67
+ base.oauth.client.update(message)
68
+ puts base.message_for('tweet')
69
+ else
70
+ raise "Please provide a message"
71
+ # class HighLine
72
+ # public :get_character
73
+ # end
74
+ # input = HighLine.new
75
+ # while (c = input.get_character) != ?\e do
76
+ # puts "You typed #{c.chr.inspect}"
77
+ # end
78
+ end
79
+ end
80
+
81
+ def self.version
82
+ "0.1"
83
+ end
84
+
85
+ def self.options(file=nil)
86
+ @@options ||= begin
87
+ @@file = File.expand_path(file || "~/.pftrc")
88
+ configuration = []
89
+ File.open(@@file).each do |line|
90
+ configuration << [$1.to_sym, $2.chomp] if line =~ /(\w+)=(.+)/
91
+ end rescue nil
92
+ Hash[*configuration.flatten]
93
+ end
94
+ end
95
+
96
+ def self.write_options
97
+ File.open(@@file, "w") do |f|
98
+ options.each { |key, value| f.puts "#{key}=#{value}" }
99
+ end
100
+ end
101
+
102
+ def self.input
103
+ @@input ||= IO.new(2,"r")
104
+ end
105
+
106
+ end
107
+ end
data/lib/pft/oauth.rb ADDED
@@ -0,0 +1,44 @@
1
+ module Pft
2
+ class Oauth
3
+ attr_accessor :key, :secret
4
+
5
+ def initialize(*args)
6
+ @key = "Imv819Ww77451xPcQ4Jxaw"
7
+ @secret = "MIcYaAqL62S2L3nLSasSu4YjMo1Mydeh46ItULi5Tc"
8
+ end
9
+
10
+ def client
11
+ @client ||= begin
12
+ client_token = Base.options[:token]
13
+ client_secret = Base.options[:secret]
14
+ if !client_secret || !client_token
15
+ raise "Please run it with -a"
16
+ end
17
+ oauth = Twitter::OAuth.new(@key, @secret)
18
+ oauth.authorize_from_access(client_token, client_secret)
19
+ Twitter::Base.new(oauth)
20
+ end
21
+ end
22
+
23
+ def authorize
24
+ puts "We are going to launch the brower, do you want to continue? [Y/n]"
25
+ authorize = Base.input.gets.chomp
26
+ raise "Cannot authorize the account" if authorize.downcase == "n"
27
+ consumer = OAuth::Consumer.new(@key, @secret, {:site => 'http://twitter.com'})
28
+ request_token = consumer.get_request_token
29
+ system "open #{request_token.authorize_url}"
30
+ puts "Please enter the provided PIN:"
31
+ pin = Base.input.gets.chomp
32
+ access_token = request_token.get_access_token(:oauth_verifier => pin) rescue false
33
+ if access_token
34
+ Base.options[:token] = access_token.token
35
+ Base.options[:secret] = access_token.secret
36
+ Base.write_options
37
+ puts "Great we're done! You can now ridicolous tweet from pft!@"
38
+ else
39
+ raise "The PIN provided is incorrect"
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ module Pft
2
+ class TinyUrl
3
+
4
+ def self.compact(url)
5
+ Net::HTTP.start('is.gd', 80) do |http|
6
+ short_url = http.get("/api.php?longurl=#{url}")
7
+ short_url.body if short_url.value
8
+ end
9
+ rescue
10
+ url
11
+ end
12
+
13
+ end
14
+ end
data/lib/pft.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'twitter'
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'highline/import'
6
+
7
+ require File.dirname(__FILE__) + '/pft/base'
8
+ require File.dirname(__FILE__) + '/pft/oauth'
9
+ require File.dirname(__FILE__) + '/pft/tiny_url'
data/spec/base_spec.rb ADDED
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/../lib/pft.rb'
2
+
3
+ describe "Pft::Base" do
4
+
5
+ it "should raise an error with no arguments" do
6
+ lambda { Pft::Base.tweet.should_not }.should raise_error("Please provide a message")
7
+ end
8
+
9
+ it "should respond with the version" do
10
+ Pft::Base.version
11
+ end
12
+
13
+ it "should open not default configuration file" do
14
+ File.stub!(:open).and_return(["token=test"])
15
+ Pft::Base.options("blah")[:token].should eql("test")
16
+ end
17
+
18
+ end
19
+
20
+ describe "Pft::Base instance" do
21
+
22
+ before(:each) do
23
+ @pft = Pft::Base.new
24
+ end
25
+
26
+ it "should have a oauth client" do
27
+ @pft.oauth.should_not be_nil
28
+ end
29
+
30
+ describe "handling no such user error" do
31
+
32
+ it "should raise it if the user is invalid when posting a reply" do
33
+ lambda { @pft.reply_to('123123wjas8duas8d', 'blah') }.should raise_error("User or last tweet not found")
34
+ end
35
+
36
+ it "should raise it if the user is invalid when posting a direct message" do
37
+ lambda { @pft.direct_message('123123wjas8duas8d', 'blah') }.should raise_error("User or last tweet not found")
38
+ end
39
+
40
+ it "should raise it if the user is invalid when posting a retweet" do
41
+ lambda { @pft.retweet('123123wjas8duas8d') }.should raise_error("User or last tweet not found")
42
+ end
43
+
44
+ end
45
+
46
+ it "should print confirmation message" do
47
+ @pft.message_for('test').should == "pft! successfully sent a test"
48
+ end
49
+
50
+ it "should print confirmation message with an user" do
51
+ @pft.message_for('test', 'testo').should == "pft! successfully sent a test to testo"
52
+ end
53
+
54
+ it "should handle urls" do
55
+ original_text = "testing http://www.example.com/blaaaaaaaaaaaaaaaaaaaaaaaah a"
56
+ @pft.parse_urls(original_text).should_not == original_text
57
+ end
58
+
59
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../lib/pft.rb'
2
+
3
+ describe "Pft::OAuth" do
4
+
5
+ before(:each) do
6
+ @pft_oauth = Pft::Oauth.new
7
+ end
8
+
9
+ it "should have a key and a secret" do
10
+ @pft_oauth.key.should_not be_nil
11
+ @pft_oauth.secret.should_not be_nil
12
+ end
13
+
14
+ it "should ask you to allow oauth client" do
15
+ Pft::Base.stub!(:options).and_return({})
16
+ lambda { @pft_oauth.client }.should raise_error("Please run it with -a")
17
+ end
18
+
19
+ it "should not ask you to allow oauth client" do
20
+ Pft::Base.stub!(:options).and_return({:token => "aaa", :secret => "bbb"})
21
+ lambda { @pft_oauth.client }.should_not raise_error("Please run it with -a")
22
+ end
23
+
24
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../lib/pft.rb'
2
+
3
+ describe "Pft::TinyUrl" do
4
+
5
+ it "should shorten one url" do
6
+ url = "http://example.org/1234567/abcdef/gtr"
7
+ shorten = Pft::TinyUrl.compact(url)
8
+ shorten.should_not == url
9
+ end
10
+
11
+ it "should not short one bad formated url" do
12
+ url = "http://example.org/123334/3 "
13
+ shorten = Pft::TinyUrl.compact(url)
14
+ shorten.should == url
15
+ end
16
+
17
+ it "should not short a non url" do
18
+ url = "test"
19
+ shorten = Pft::TinyUrl.compact(url)
20
+ shorten.should == url
21
+ end
22
+
23
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ivanvc-pft
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - "Iv\xC3\xA1n Vald\xC3\xA9s"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-27 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: twitter
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.6.15
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: ivanvc-choice
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.3.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: highline
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.5.1
44
+ version:
45
+ description: pft is a simple command line twitter client.
46
+ email: iv@nvald.es
47
+ executables:
48
+ - pft
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README.textile
53
+ - LICENSE
54
+ files:
55
+ - bin/pft
56
+ - lib/pft.rb
57
+ - lib/pft/base.rb
58
+ - lib/pft/tiny_url.rb
59
+ - lib/pft/oauth.rb
60
+ - spec/base_spec.rb
61
+ - spec/oauth_spec.rb
62
+ - spec/tiny_url_spec.rb
63
+ - README.textile
64
+ - LICENSE
65
+ has_rdoc: false
66
+ homepage: http://github.com/ivanvc/pft
67
+ licenses:
68
+ post_install_message: pft! this is ridiculous
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.3.5
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: pft is a command line twitter client.
92
+ test_files: []
93
+