billymeltdown-twitter 0.3.8.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,25 +5,37 @@ module Twitter
5
5
  class NoAccounts < StandardError; end
6
6
 
7
7
  def output_tweets(collection, options={})
8
- options.reverse_merge!({
8
+ options = {
9
9
  :cache => false,
10
10
  :since_prefix => '',
11
- :empty_msg => 'Nothing new since your last check.'
12
- })
11
+ :empty_msg => 'Nothing new since your last check.',
12
+ :reverse => false
13
+ }.merge(options)
14
+
13
15
  if collection.size > 0
14
16
  justify = collection.collect { |s| s.user.screen_name }.max { |a,b| a.length <=> b.length }.length rescue 0
15
17
  indention = ' ' * (justify + 3)
16
18
  say("\n#{indention}#{collection.size} new tweet(s) found.\n\n")
19
+ collection.reverse! if options[:reverse]
17
20
  collection.each do |s|
18
21
  Tweet.create_from_tweet(current_account, s) if options[:cache]
22
+
19
23
  occurred_at = Time.parse(s.created_at).strftime('On %b %d at %l:%M%P')
20
24
  formatted_time = '-' * occurred_at.length + "\n#{indention}#{occurred_at}"
21
25
  formatted_name = s.user.screen_name.rjust(justify + 1)
22
26
  formatted_msg = ''
23
- s.text.split(' ').in_groups_of(6, false) { |row| formatted_msg += row.join(' ') + "\n#{indention}" }
24
- say "#{CGI::unescapeHTML(formatted_name)}: #{CGI::unescapeHTML(formatted_msg)}#{formatted_time}\n\n"
27
+
28
+ s.text.split(' ').each_with_index do |word, idx|
29
+ formatted_msg += "#{word} "
30
+
31
+ sixth_word = idx != 0 && idx % 6 == 0
32
+ formatted_msg += "\n#{indention}" if sixth_word
33
+ end
34
+
35
+ say "#{CGI::unescapeHTML(formatted_name)}: #{CGI::unescapeHTML(formatted_msg)}\n#{indention}#{formatted_time}\n\n"
25
36
  end
26
- Configuration["#{options[:since_prefix]}_since_id"] = collection.first.id
37
+
38
+ Configuration["#{options[:since_prefix]}_since_id"] = options[:reverse] ? collection.last.id : collection.first.id
27
39
  else
28
40
  say(options[:empty_msg])
29
41
  end
@@ -35,7 +47,7 @@ module Twitter
35
47
 
36
48
  def current_account
37
49
  @current_account ||= Account.active
38
- raise Account.count == 0 ? NoAccounts : NoActiveAccount if @current_account.blank?
50
+ raise Account.count == 0 ? NoAccounts : NoActiveAccount if @current_account.nil?
39
51
  @current_account
40
52
  end
41
53
 
@@ -44,7 +56,7 @@ module Twitter
44
56
  if File.exists?(tweet_file)
45
57
  say '.twitter file found, attempting import...'
46
58
  config = YAML::load(File.read(tweet_file))
47
- if !config['email'].blank? && !config['password'].blank?
59
+ if !config['email'].nil? && !config['password'].nil?
48
60
  Account.add(:username => config['email'], :password => config['password'])
49
61
  say 'Account imported'
50
62
  block.call if block_given?
@@ -11,7 +11,7 @@ module Twitter
11
11
 
12
12
  def initialize(q=nil)
13
13
  clear
14
- containing(q) unless q.blank?
14
+ containing(q) if q && q.strip != ''
15
15
  end
16
16
 
17
17
  def from(user)
@@ -59,6 +59,12 @@ module Twitter
59
59
  self
60
60
  end
61
61
 
62
+ # Which page of results to fetch
63
+ def page(num)
64
+ @query[:page] = num
65
+ self
66
+ end
67
+
62
68
  # Only searches tweets since a given id.
63
69
  # Recommended to use this when possible.
64
70
  def since(since_id)
@@ -83,7 +89,7 @@ module Twitter
83
89
  # If you want to get results do something other than iterate over them.
84
90
  def fetch
85
91
  @query[:q] = @query[:q].join(' ')
86
- self.class.get('/search.json', {:query => @query})
92
+ SearchResultInfo.new_from_hash(self.class.get('/search.json', {:query => @query}))
87
93
  end
88
94
 
89
95
  def each
@@ -91,4 +97,5 @@ module Twitter
91
97
  @result['results'].each { |r| yield r }
92
98
  end
93
99
  end
94
- end
100
+ end
101
+
@@ -0,0 +1,83 @@
1
+ module Twitter
2
+ class SearchResult < Hash
3
+
4
+ # Creates an easier to work with hash from
5
+ # one with string-based keys
6
+ def self.new_from_hash(hash)
7
+ new.merge!(hash)
8
+ end
9
+
10
+ def created_at
11
+ self['created_at']
12
+ end
13
+
14
+ def created_at=(val)
15
+ self['created_at'] = val
16
+ end
17
+
18
+ def from_user
19
+ self['from_user']
20
+ end
21
+
22
+ def from_user=(val)
23
+ self['from_user'] = val
24
+ end
25
+
26
+ def from_user_id
27
+ self['from_user_id']
28
+ end
29
+
30
+ def from_user_id=(val)
31
+ self['from_user_id'] = val
32
+ end
33
+
34
+ def id
35
+ self['id']
36
+ end
37
+
38
+ def id=(val)
39
+ self['id'] = val
40
+ end
41
+
42
+ def iso_language_code
43
+ self['iso_language_code']
44
+ end
45
+
46
+ def iso_language_code=(val)
47
+ self['iso_language_code'] = val
48
+ end
49
+
50
+ def profile_image_url
51
+ self['profile_image_url']
52
+ end
53
+
54
+ def profile_image_url=(val)
55
+ self['profile_image_url'] = val
56
+ end
57
+
58
+ def text
59
+ self['text']
60
+ end
61
+
62
+ def text=(val)
63
+ self['text'] = val
64
+ end
65
+
66
+ def to_user
67
+ self['to_user']
68
+ end
69
+
70
+ def to_user=(val)
71
+ self['to_user'] = val
72
+ end
73
+
74
+ def to_user_id
75
+ self['to_user_id']
76
+ end
77
+
78
+ def to_user_id=(val)
79
+ self['to_user_id'] = val
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,82 @@
1
+ module Twitter
2
+ class SearchResultInfo < Hash
3
+
4
+ # Creates an easier to work with hash from
5
+ # one with string-based keys
6
+ def self.new_from_hash(hash)
7
+ i = new
8
+ i.merge!(hash)
9
+ search_results = []
10
+ i.results.each do |r|
11
+ search_results << SearchResult.new_from_hash(r)
12
+ end
13
+ i.results = search_results
14
+ i
15
+ end
16
+
17
+ def completed_in
18
+ self['completed_in']
19
+ end
20
+
21
+ def completed_in=(val)
22
+ self['completed_in'] = val
23
+ end
24
+
25
+ def max_id
26
+ self['max_id']
27
+ end
28
+
29
+ def max_id=(val)
30
+ self['max_id'] = val
31
+ end
32
+
33
+ def next_page
34
+ self['next_page']
35
+ end
36
+
37
+ def next_page=(val)
38
+ self['next_page'] = val
39
+ end
40
+
41
+ def page
42
+ self['page']
43
+ end
44
+
45
+ def page=(val)
46
+ self['page'] = val
47
+ end
48
+
49
+ def refresh_url
50
+ self['refresh_url']
51
+ end
52
+
53
+ def refresh_url=(val)
54
+ self['refresh_url'] = val
55
+ end
56
+
57
+ def results_per_page
58
+ self['results_per_page']
59
+ end
60
+
61
+ def results_per_page=(val)
62
+ self['results_per_page'] = val
63
+ end
64
+
65
+ def since_id
66
+ self['since_id']
67
+ end
68
+
69
+ def since_id=(val)
70
+ self['since_id'] = val
71
+ end
72
+
73
+ def results
74
+ self['results']
75
+ end
76
+
77
+ def results=(val)
78
+ self['results'] = val
79
+ end
80
+
81
+ end
82
+ end
@@ -1,9 +1,3 @@
1
1
  module Twitter #:nodoc:
2
- module VERSION #:nodoc:
3
- MAJOR = 0
4
- MINOR = 3
5
- TINY = 8
6
-
7
- STRING = [MAJOR, MINOR, TINY].join('.')
8
- end
2
+ Version = '0.4.2'
9
3
  end
data/spec/base_spec.rb CHANGED
@@ -16,7 +16,11 @@ describe "Twitter::Base" do
16
16
  lambda { @base.timeline(:fakeyoutey) }.should raise_error(Twitter::UnknownTimeline)
17
17
  end
18
18
 
19
- it "should default to friends timeline"
19
+ it "should default to friends timeline" do
20
+ @base.should_receive(:call).with("friends_timeline", {:auth=>true, :args=>{}, :since=>nil})
21
+ @base.should_receive(:statuses)
22
+ @base.timeline
23
+ end
20
24
 
21
25
  it "should be able to retrieve friends timeline" do
22
26
  data = open(File.dirname(__FILE__) + '/fixtures/friends_timeline.xml').read
@@ -50,6 +54,12 @@ describe "Twitter::Base" do
50
54
  @base.friends(:lite => true).size.should == 15
51
55
  end
52
56
 
57
+ it "should be able to get friend ids" do
58
+ data = open(File.dirname(__FILE__) + '/fixtures/friend_ids.xml').read
59
+ @base.should_receive(:request).and_return(Hpricot::XML(data))
60
+ @base.friend_ids.size.should == 8
61
+ end
62
+
53
63
  it "should be able to get friends for another user" do
54
64
  data = open(File.dirname(__FILE__) + '/fixtures/friends_for.xml').read
55
65
  @base.should_receive(:request).and_return(Hpricot::XML(data))
@@ -66,17 +76,25 @@ describe "Twitter::Base" do
66
76
  timeline.first.name.should == 'Blaine Cook'
67
77
  end
68
78
 
79
+ it "should be able to get follower ids" do
80
+ data = open(File.dirname(__FILE__) + '/fixtures/follower_ids.xml').read
81
+ @base.should_receive(:request).and_return(Hpricot::XML(data))
82
+ @base.follower_ids.size.should == 8
83
+ end
84
+
69
85
  it "should be able to create a friendship" do
70
86
  data = open(File.dirname(__FILE__) + '/fixtures/friendship_created.xml').read
71
87
  @base.should_receive(:request).and_return(Hpricot::XML(data))
72
88
  user = @base.create_friendship('jnunemaker')
73
89
  end
74
90
 
75
- it "should bomb if friendship already exists" #do
76
- # data = open(File.dirname(__FILE__) + '/fixtures/friendship_already_exists.xml').read
77
- # @base.should_receive(:request).and_return(Hpricot::XML(data))
78
- # lambda { @base.create_friendship('billymeltdown') }.should raise_error(Twitter::AlreadyFollowing)
79
- #end
91
+ it "should bomb if friendship already exists" do
92
+ data = open(File.dirname(__FILE__) + '/fixtures/friendship_already_exists.xml').read
93
+ response = Net::HTTPForbidden.new("1.1", '403', '')
94
+ response.stub!(:body).and_return(data)
95
+ @base.should_receive(:response).and_return(response)
96
+ lambda { @base.create_friendship('billymeltdown') }.should raise_error(Twitter::AlreadyFollowing)
97
+ end
80
98
  end
81
99
 
82
100
  it "should be able to get single status" do
@@ -118,4 +136,4 @@ describe "Twitter::Base" do
118
136
  @base.rate_limit_status.remaining_hits.should == 5
119
137
  end
120
138
  end
121
- end
139
+ end
@@ -8,6 +8,10 @@ def say(str)
8
8
  puts str
9
9
  end
10
10
 
11
+ class Tweet < OpenStruct
12
+ attr_accessor :id
13
+ end
14
+
11
15
  describe Twitter::CLI::Helpers do
12
16
  include Twitter::CLI::Helpers
13
17
 
@@ -15,21 +19,31 @@ describe Twitter::CLI::Helpers do
15
19
  before do
16
20
  Configuration.stub!(:[]=).and_return(true)
17
21
  @collection = [
18
- OpenStruct.new(
19
- :text => 'This is my long message that I want to see formatted ooooh so pretty with a few words on each line so it is easy to scan.',
22
+ Tweet.new(
23
+ :id => 1,
24
+ :text => 'This is my long message that I want to see formatted ooooh so pretty with a few words on each line so it is easy to scan.',
20
25
  :created_at => Time.mktime(2008, 5, 1, 10, 15, 00).strftime('%Y-%m-%d %H:%M:%S'),
21
- :user => OpenStruct.new(:screen_name => 'jnunemaker')
26
+ :user => OpenStruct.new(:screen_name => 'jnunemaker')
22
27
  ),
23
- OpenStruct.new(
24
- :text => 'This is my long message that I want to see formatted ooooh so pretty with a.',
28
+ Tweet.new(
29
+ :id => 2,
30
+ :text => 'This is my long message that I want to see formatted ooooh so pretty with a.',
25
31
  :created_at => Time.mktime(2008, 4, 1, 10, 15, 00).strftime('%Y-%m-%d %H:%M:%S'),
26
- :user => OpenStruct.new(:screen_name => 'danielmorrison')
32
+ :user => OpenStruct.new(:screen_name => 'danielmorrison')
27
33
  )
28
34
  ]
29
35
  end
30
36
 
31
37
  specify "should properly format" do
32
- output_tweets(@collection)
38
+ stdout_for {
39
+ output_tweets(@collection)
40
+ }.should match(/with a few words[\w\W]*with a\./)
41
+ end
42
+
43
+ specify 'should format in reverse' do
44
+ stdout_for {
45
+ output_tweets(@collection, :reverse => true)
46
+ }.should match(/with a\.[\w\W]*with a few words/)
33
47
  end
34
48
  end
35
49
  end
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ids>
3
+ <id>1192</id>
4
+ <id>750823</id>
5
+ <id>813198</id>
6
+ <id>10718</id>
7
+ <id>13046</id>
8
+ <id>79543</id>
9
+ <id>813775</id>
10
+ <id>681473</id>
11
+ </ids>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ids>
3
+ <id>1192</id>
4
+ <id>780561</id>
5
+ <id>10718</id>
6
+ <id>750823</id>
7
+ <id>643443</id>
8
+ <id>813198</id>
9
+ <id>13046</id>
10
+ <id>147093</id>
11
+ </ids>
12
+
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <hash>
3
+ <request>/friendships/create/billymeltdown.xml</request>
4
+ <error>Could not follow user: billymeltdown is already on your list.</error>
5
+ </hash>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <user>
3
+ <id>4243</id>
4
+ <name>John Nunemaker</name>
5
+ <screen_name>jnunemaker</screen_name>
6
+ <location>Indiana</location>
7
+ <description>Loves his wife, ruby, notre dame football and iu basketball</description>
8
+ <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/52619256/ruby_enterprise_shirt_normal.jpg</profile_image_url>
9
+ <url>http://addictedtonew.com</url>
10
+ <protected>false</protected>
11
+ <followers_count>363</followers_count>
12
+ </user>
@@ -0,0 +1,147 @@
1
+ --- !map:Twitter::SearchResultInfo
2
+ results:
3
+ - !map:Twitter::SearchResult
4
+ text: "@jqr - wow. just really looked at httparty for first time - sweet! - have you been using that a lot?"
5
+ to_user_id: 176589
6
+ to_user: jqr
7
+ from_user: baldwindavid
8
+ id: 1073680192
9
+ from_user_id: 804487
10
+ iso_language_code: en
11
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/67146299/before_400_normal.jpg
12
+ created_at: Tue, 23 Dec 2008 04:20:12 +0000
13
+ - !map:Twitter::SearchResult
14
+ text: the httparty gem rocks my socks. no better way to consume web services in ruby.
15
+ to_user_id:
16
+ from_user: mildmojo
17
+ id: 1073135700
18
+ from_user_id: 2090305
19
+ iso_language_code: en
20
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/65215459/appicon_normal.png
21
+ created_at: Mon, 22 Dec 2008 22:20:43 +0000
22
+ - !map:Twitter::SearchResult
23
+ text: It's an HTTParty and everyone is invited!
24
+ to_user_id:
25
+ from_user: mypheme
26
+ id: 1067975762
27
+ from_user_id: 3067473
28
+ iso_language_code: en
29
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/67872558/Picture_3_normal.png
30
+ created_at: Fri, 19 Dec 2008 22:09:23 +0000
31
+ - !map:Twitter::SearchResult
32
+ text: dans la famille des clients http,vous connaissiez curb, httparty, mais connaissiez-vous httpclient ? http://dev.ctor.org/httpclient/
33
+ to_user_id:
34
+ from_user: rubyfrance
35
+ id: 1064812719
36
+ from_user_id: 70780
37
+ iso_language_code: fr
38
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/51884877/twitter_normal.png
39
+ created_at: Thu, 18 Dec 2008 12:46:27 +0000
40
+ - !map:Twitter::SearchResult
41
+ text: "@jnunemaker have you ever seen httparty get a Net::HTTPServerException: 411 &quot;Length Required&quot; back?"
42
+ to_user_id: 19106
43
+ to_user: jnunemaker
44
+ from_user: techpickles
45
+ id: 1064375973
46
+ from_user_id: 22902
47
+ iso_language_code: en
48
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/64410494/Photo_9_normal.jpg
49
+ created_at: Thu, 18 Dec 2008 05:24:23 +0000
50
+ - !map:Twitter::SearchResult
51
+ text: playing with the tumblr api, httparty style
52
+ to_user_id:
53
+ from_user: techpickles
54
+ id: 1064355666
55
+ from_user_id: 22902
56
+ iso_language_code: en
57
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/64410494/Photo_9_normal.jpg
58
+ created_at: Thu, 18 Dec 2008 05:07:59 +0000
59
+ - !map:Twitter::SearchResult
60
+ text: Testing from HTTParty, awesome ruby gem that allows for easy access to APIs over http.
61
+ to_user_id:
62
+ from_user: simonreed
63
+ id: 1063822669
64
+ from_user_id: 63911
65
+ iso_language_code: en
66
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/53963586/fu_normal.jpg
67
+ created_at: Wed, 17 Dec 2008 23:21:34 +0000
68
+ - !map:Twitter::SearchResult
69
+ text: It's an HTTParty and everyone is invited!
70
+ to_user_id:
71
+ from_user: bernsno
72
+ id: 1063277742
73
+ from_user_id: 1495935
74
+ iso_language_code: en
75
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/63820805/me_normal.gif
76
+ created_at: Wed, 17 Dec 2008 18:25:31 +0000
77
+ - !map:Twitter::SearchResult
78
+ text: "[ruby] Using Context and Stump to HTTParty like a Wufoo"
79
+ to_user_id:
80
+ from_user: rubymentary
81
+ id: 1062068801
82
+ from_user_id: 474717
83
+ iso_language_code: en
84
+ profile_image_url: http://static.twitter.com/images/default_profile_normal.png
85
+ created_at: Wed, 17 Dec 2008 03:37:00 +0000
86
+ - !map:Twitter::SearchResult
87
+ text: "net/http\xE3\x81\xAEwrapper\xE3\x81\xA0\xE3\x81\xA3\xE3\x81\x9F\xE3\x80\x82\xE3\x80\x82\xE3\x80\x82 &gt; HTTParty re: http://ff.im/h1Dg"
88
+ to_user_id:
89
+ from_user: nahi
90
+ id: 1061821371
91
+ from_user_id: 36221
92
+ iso_language_code: "no"
93
+ profile_image_url: http://static.twitter.com/images/default_profile_normal.png
94
+ created_at: Wed, 17 Dec 2008 00:58:19 +0000
95
+ - !map:Twitter::SearchResult
96
+ text: Using HTTParty to wrap the Wufoo form submit API, as we are switching the Ordered List contact form to Wufoo.
97
+ to_user_id:
98
+ from_user: jnunemaker
99
+ id: 1061117717
100
+ from_user_id: 19106
101
+ iso_language_code: en
102
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/61024905/black250_normal.jpg
103
+ created_at: Tue, 16 Dec 2008 18:25:28 +0000
104
+ - !map:Twitter::SearchResult
105
+ text: Playing with HTTParty. Like it already. :)
106
+ to_user_id:
107
+ from_user: atog
108
+ id: 1058725999
109
+ from_user_id: 21795
110
+ iso_language_code: en
111
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/61430136/ikke_vierkant_normal.jpg
112
+ created_at: Mon, 15 Dec 2008 16:06:26 +0000
113
+ - !map:Twitter::SearchResult
114
+ text: HTTParty is like sweet candy...
115
+ to_user_id:
116
+ from_user: levicole
117
+ id: 1055553905
118
+ from_user_id: 111971
119
+ iso_language_code: en
120
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/24274692/Photo_2_normal.jpg
121
+ created_at: Sat, 13 Dec 2008 17:52:01 +0000
122
+ - !map:Twitter::SearchResult
123
+ text: "thinking httparty needs a bit of morph class generation magic: http://tinyurl.com/6774gz"
124
+ to_user_id:
125
+ from_user: delineator
126
+ id: 1054352107
127
+ from_user_id: 102024
128
+ iso_language_code: en
129
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/63867007/rob_64_64_normal.png
130
+ created_at: Fri, 12 Dec 2008 22:53:41 +0000
131
+ - !map:Twitter::SearchResult
132
+ text: To use HTTParty, or just net/http? I'm going to have to change some headers, which means digging around. Hrm.
133
+ to_user_id:
134
+ from_user: HibiscuS4
135
+ id: 1050622779
136
+ from_user_id: 8780
137
+ iso_language_code: en
138
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/60311231/Photo_9_normal.jpg
139
+ created_at: Thu, 11 Dec 2008 04:13:06 +0000
140
+ since_id: 0
141
+ max_id: 1078578631
142
+ refresh_url: ?since_id=1078578631&q=httparty
143
+ results_per_page: 15
144
+ next_page: ?page=2&max_id=1078578631&q=httparty
145
+ completed_in: 0.018799
146
+ page: 1
147
+ query: httparty