billymeltdown-twitter 0.3.8.1 → 0.4.2

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.
@@ -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