Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Showing with 0 additions and 5,378 deletions.
  1. +0 −68 Manifest
  2. +0 −84 README
  3. +0 −42 Rakefile
  4. +0 −14 bin/twitter
  5. +0 −15 examples/blocks.rb
  6. +0 −29 examples/direct_messages.rb
  7. +0 −20 examples/favorites.rb
  8. +0 −25 examples/friends_followers.rb
  9. +0 −13 examples/friendships.rb
  10. +0 −7 examples/identica_timeline.rb
  11. +0 −8 examples/location.rb
  12. +0 −60 examples/oauth.rb
  13. +0 −9 examples/posting.rb
  14. +0 −27 examples/replies.rb
  15. +0 −18 examples/search.rb
  16. +0 −27 examples/sent_messages.rb
  17. +0 −34 examples/timeline.rb
  18. +0 −27 examples/twitter.rb
  19. +0 −13 examples/verify_credentials.rb
  20. +0 −38 lib/twitter.rb
  21. +0 −284 lib/twitter/base.rb
  22. +0 −334 lib/twitter/cli.rb
  23. +0 −9 lib/twitter/cli/config.rb
  24. +0 −109 lib/twitter/cli/helpers.rb
  25. +0 −13 lib/twitter/cli/migrations/20080722194500_create_accounts.rb
  26. +0 −16 lib/twitter/cli/migrations/20080722194508_create_tweets.rb
  27. +0 −9 lib/twitter/cli/migrations/20080722214605_add_account_id_to_tweets.rb
  28. +0 −13 lib/twitter/cli/migrations/20080722214606_create_configurations.rb
  29. +0 −33 lib/twitter/cli/models/account.rb
  30. +0 −13 lib/twitter/cli/models/configuration.rb
  31. +0 −20 lib/twitter/cli/models/tweet.rb
  32. +0 −22 lib/twitter/direct_message.rb
  33. +0 −43 lib/twitter/easy_class_maker.rb
  34. +0 −32 lib/twitter/oauth.rb
  35. +0 −19 lib/twitter/rate_limit_status.rb
  36. +0 −101 lib/twitter/search.rb
  37. +0 −83 lib/twitter/search_result.rb
  38. +0 −82 lib/twitter/search_result_info.rb
  39. +0 −22 lib/twitter/status.rb
  40. +0 −38 lib/twitter/user.rb
  41. +0 −3  lib/twitter/version.rb
  42. +0 −139 spec/base_spec.rb
  43. +0 −49 spec/cli/helper_spec.rb
  44. +0 −35 spec/direct_message_spec.rb
  45. +0 −11 spec/fixtures/follower_ids.xml
  46. +0 −706 spec/fixtures/followers.xml
  47. +0 −12 spec/fixtures/friend_ids.xml
  48. +0 −609 spec/fixtures/friends.xml
  49. +0 −584 spec/fixtures/friends_for.xml
  50. +0 −192 spec/fixtures/friends_lite.xml
  51. +0 −66 spec/fixtures/friends_timeline.xml
  52. +0 −5 spec/fixtures/friendship_already_exists.xml
  53. +0 −12 spec/fixtures/friendship_created.xml
  54. +0 −148 spec/fixtures/public_timeline.xml
  55. +0 −7 spec/fixtures/rate_limit_status.xml
  56. +0 −147 spec/fixtures/search_result_info.yml
  57. +0 −1  spec/fixtures/search_results.json
  58. +0 −25 spec/fixtures/status.xml
  59. +0 −38 spec/fixtures/user.xml
  60. +0 −465 spec/fixtures/user_timeline.xml
  61. +0 −100 spec/search_spec.rb
  62. +0 −1  spec/spec.opts
  63. +0 −23 spec/spec_helper.rb
  64. +0 −40 spec/status_spec.rb
  65. +0 −42 spec/user_spec.rb
  66. +0 −45 twitter.gemspec
View
68 Manifest
@@ -1,68 +0,0 @@
-bin/twitter
-examples/blocks.rb
-examples/direct_messages.rb
-examples/favorites.rb
-examples/friends_followers.rb
-examples/friendships.rb
-examples/identica_timeline.rb
-examples/location.rb
-examples/posting.rb
-examples/replies.rb
-examples/search.rb
-examples/sent_messages.rb
-examples/timeline.rb
-examples/twitter.rb
-examples/verify_credentials.rb
-History
-lib/twitter/base.rb
-lib/twitter/cli/config.rb
-lib/twitter/cli/helpers.rb
-lib/twitter/cli/migrations/20080722194500_create_accounts.rb
-lib/twitter/cli/migrations/20080722194508_create_tweets.rb
-lib/twitter/cli/migrations/20080722214605_add_account_id_to_tweets.rb
-lib/twitter/cli/migrations/20080722214606_create_configurations.rb
-lib/twitter/cli/models/account.rb
-lib/twitter/cli/models/configuration.rb
-lib/twitter/cli/models/tweet.rb
-lib/twitter/cli.rb
-lib/twitter/direct_message.rb
-lib/twitter/easy_class_maker.rb
-lib/twitter/rate_limit_status.rb
-lib/twitter/search.rb
-lib/twitter/search_result.rb
-lib/twitter/search_result_info.rb
-lib/twitter/status.rb
-lib/twitter/user.rb
-lib/twitter/version.rb
-lib/twitter.rb
-License
-Manifest
-Rakefile
-README
-spec/base_spec.rb
-spec/cli/helper_spec.rb
-spec/direct_message_spec.rb
-spec/fixtures/follower_ids.xml
-spec/fixtures/followers.xml
-spec/fixtures/friend_ids.xml
-spec/fixtures/friends.xml
-spec/fixtures/friends_for.xml
-spec/fixtures/friends_lite.xml
-spec/fixtures/friends_timeline.xml
-spec/fixtures/friendship_already_exists.xml
-spec/fixtures/friendship_created.xml
-spec/fixtures/public_timeline.xml
-spec/fixtures/rate_limit_status.xml
-spec/fixtures/search_result_info.yml
-spec/fixtures/search_results.json
-spec/fixtures/status.xml
-spec/fixtures/user.xml
-spec/fixtures/user_timeline.xml
-spec/search_spec.rb
-spec/spec.opts
-spec/spec_helper.rb
-spec/status_spec.rb
-spec/user_spec.rb
-website/css/common.css
-website/images/terminal_output.png
-website/index.html
View
84 README
@@ -1,84 +0,0 @@
-= addicted to twitter
-
-... a sweet little diddy that helps you twitter your life away
-
-== Install
-
-sudo gem install twitter will work just fine. For command line use, you'll need a few other gems: sudo gem install main highline activerecord sqlite3-ruby
-
-== Examples
-
- Twitter::Base.new('your email', 'your password').update('watching veronica mars')
-
- # or you can use post
- Twitter::Base.new('your email', 'your password').post('post works too')
-
- puts "Public Timeline", "=" * 50
- Twitter::Base.new('your email', 'your password').timeline(:public).each do |s|
- puts s.text, s.user.name
- puts
- end
-
- puts '', "Friends Timeline", "=" * 50
- Twitter::Base.new('your email', 'your password').timeline.each do |s|
- puts s.text, s.user.name
- puts
- end
-
- puts '', "Friends", "=" * 50
- Twitter::Base.new('your email', 'your password').friends.each do |u|
- puts u.name, u.status.text
- puts
- end
-
- puts '', "Followers", "=" * 50
- Twitter::Base.new('your email', 'your password').followers.each do |u|
- puts u.name, u.status.text
- puts
- end
-
-== Search Examples
-
- Twitter::Search.new('httparty').each { |r| puts r.inspect }
- Twitter::Search.new('httparty').from('jnunemaker').each { |r| puts r.inspect }
- Twitter::Search.new.from('jnunemaker').to('oaknd1').each { |r| puts r.inspect }
-
-
-== Command Line Use
-
-Note: If you want to use twitter from the command line be sure that sqlite3 and the sqlite3-ruby gem are installed. I removed the sqlite3-ruby gem as a dependency because you shouldn't need that to just use the API wrapper. Eventually I'll move the CLI interface into another gem.
-
- $ twitter
-
-Will give you a list of all the commands. You can get the help for each command by running twitter [command] -h.
-
-The first thing you'll want to do is install the database so your account(s) can be stored.
-
- $ twitter install
-
-You can always uninstall twitter like this:
-
- $ twitter uninstall
-
-Once the twitter database is installed and migrated, you can add accounts like this:
-
- $ twitter add
- Add New Account:
- Username: jnunemaker
- Password (won't be displayed):
- Account added.
-
-You can also list all the accounts you've added.
-
- $ twitter list
- Account List
- * jnunemaker
- snitch_test
-
-The * means denotes the account that will be used when posting, befriending, defriending, following, leaving or viewing a timeline.
-
-To post using the account marked with the *, simply type the following:
-
- $ twitter post "releasing my new twitter gem"
-
-That is about it. You can do pretty much anything that you can do with twitter from the command line interface.
View
42 Rakefile
@@ -1,42 +0,0 @@
-ProjectName = 'twitter'
-WebsitePath = "jnunemaker@rubyforge.org:/var/www/gforge-projects/#{ProjectName}"
-
-require 'rubygems'
-require 'rake'
-require 'echoe'
-require 'spec/rake/spectask'
-require "lib/#{ProjectName}/version"
-
-Echoe.new(ProjectName, Twitter::Version) do |p|
- p.description = "a command line interface for twitter, also a library which wraps the twitter api"
- p.url = "http://#{ProjectName}.rubyforge.org"
- p.author = "John Nunemaker"
- p.email = "nunemaker@gmail.com"
- p.extra_deps = [['oauth', '>= 0.3.2'], ['hpricot', '>= 0.6'], ['activesupport', '>= 2.1'], ['httparty', '>= 0.2.4']]
- p.need_tar_gz = false
- p.docs_host = WebsitePath
-end
-
-desc 'Upload website files to rubyforge'
-task :website do
- sh %{rsync -av website/ #{WebsitePath}}
- Rake::Task['website_docs'].invoke
-end
-
-task :website_docs do
- Rake::Task['redocs'].invoke
- sh %{rsync -av doc/ #{WebsitePath}/docs}
-end
-
-desc 'Preps the gem for a new release'
-task :prepare do
- %w[manifest build_gemspec].each do |task|
- Rake::Task[task].invoke
- end
-end
-
-Rake::Task[:default].prerequisites.clear
-task :default => :spec
-Spec::Rake::SpecTask.new do |t|
- t.spec_files = FileList["spec/**/*_spec.rb"]
-end
View
14 bin/twitter
@@ -1,14 +0,0 @@
-#!/usr/bin/env ruby
-
-# if we have stdin, let's prepend it to the message for post
-if ARGV[0] && ARGV[0] == 'post' && !STDIN.tty?
- ARGV[1] = "#{STDIN.read}#{ARGV[1]}"
-end
-
-# if we have stdin, let's prepend it to the message for d
-if ARGV[0] && ARGV[0] == 'd' && !STDIN.tty?
- ARGV[2] = "#{STDIN.read}#{ARGV[2]}"
-end
-
-require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'twitter'))
-require 'twitter/cli'
View
15 examples/blocks.rb
@@ -1,15 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'BLOCK CREATE'
-puts twitter.block('project_rockne').name
-puts
-puts
-
-puts 'BLOCK DESTROY'
-puts twitter.block('project_rockne').name
-puts
-puts
View
29 examples/direct_messages.rb
@@ -1,29 +0,0 @@
-require 'rubygems'
-require 'activesupport'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'SINCE'
-twitter.direct_messages(:since => Time.now - 5.day).each do |s|
- puts "- #{s.id} #{s.text}"
-end
-puts
-puts
-
-# puts 'SINCE_ID'
-# twitter.direct_messages(:since_id => 33505386).each do |s|
-# puts "- #{s.text}"
-# end
-# puts
-# puts
-#
-# puts 'PAGE'
-# twitter.direct_messages(:page => 1).each do |s|
-# puts "- #{s.text}"
-# end
-# puts
-# puts
-
-# puts twitter.destroy_direct_message(34489057).inspect
View
20 examples/favorites.rb
@@ -1,20 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'CREATE'
-puts twitter.create_favorite(865416114).text
-puts
-puts
-
-puts 'FAVORITES'
-twitter.favorites.each { |f| puts f.text }
-puts
-puts
-
-puts 'DESTROY'
-puts twitter.destroy_favorite(865416114).text
-puts
-puts
View
25 examples/friends_followers.rb
@@ -1,25 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts "FRIENDS"
-twitter.friends.each { |f| puts f.name }
-puts
-puts
-
-puts "FRIENDS FOR"
-twitter.friends_for('orderedlist', :lite => true).each { |f| puts f.name }
-puts
-puts
-
-puts "FOLLOWERS"
-twitter.followers(:lite => true).each { |f| puts f.name }
-puts
-puts
-
-puts "FOLLOWERS FOR"
-twitter.followers_for('orderedlist', :lite => true).each { |f| puts f.name }
-puts
-puts
View
13 examples/friendships.rb
@@ -1,13 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts twitter.create_friendship('orderedlist').name
-puts twitter.follow('orderedlist').name
-puts twitter.leave('orderedlist').name
-puts twitter.destroy_friendship('orderedlist').name
-
-puts twitter.friendship_exists?('jnunemaker', 'orderedlist').inspect
-puts twitter.friendship_exists?('jnunemaker', 'ze').inspect
View
7 examples/identica_timeline.rb
@@ -1,7 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-identica = Twitter::Base.new(config['email'], config['password'], :api_host => 'identi.ca/api')
-
-identica.timeline(:public).each { |s| puts s.text, s.user.name, '' }
View
8 examples/location.rb
@@ -1,8 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts twitter.update_location('Hollywood, CA').location
-puts twitter.update_delivery_device('none')
View
60 examples/oauth.rb
@@ -1,60 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-require 'pp'
-
-class ConfigStore
- attr_reader :file
-
- def initialize(file)
- @file = file
- end
-
- def load
- @config ||= YAML::load(open(file))
- self
- end
-
- def [](key)
- load
- @config[key]
- end
-
- def []=(key, value)
- @config[key] = value
- end
-
- def update(c={})
- @config.merge!(c)
- save
- end
-
- def save
- File.open(file, 'w') { |f| f.write(YAML.dump(@config)) }
- end
-end
-
-config = ConfigStore.new("#{ENV['HOME']}/.twitter")
-oauth = Twitter::OAuth.new(config['token'], config['secret'])
-
-if config['atoken'] && config['asecret']
- oauth.authorize_from_access(config['atoken'], config['asecret'])
- puts oauth.access_token.get("/statuses/friends_timeline.json")
-
-elsif config['rtoken'] && config['rsecret']
- oauth.authorize_from_request(config['rtoken'], config['rsecret'])
- puts oauth.access_token.get("/statuses/friends_timeline.json")
-
- config.update({
- 'atoken' => oauth.access_token.token,
- 'asecret' => oauth.access_token.secret,
- 'rtoken' => nil,
- 'rsecret' => nil,
- })
-else
- config.update({
- 'rtoken' => oauth.request_token.token,
- 'rsecret' => oauth.request_token.secret,
- })
-
- # authorize in browser
- %x(open #{oauth.request_token.authorize_url})
-end
View
9 examples/posting.rb
@@ -1,9 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-puts twitter.post("This is a test from the example file").inspect
-
-# sending a direct message
-# puts twitter.d('jnunemaker', 'this is a test').inspect
View
27 examples/replies.rb
@@ -1,27 +0,0 @@
-require 'rubygems'
-require 'activesupport'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'SINCE'
-twitter.replies(:since => Time.now - 5.day).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'SINCE_ID'
-twitter.replies(:since_id => 863081345).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'PAGE'
-twitter.replies(:page => 1).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
View
18 examples/search.rb
@@ -1,18 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-
-Twitter::Search.new('httparty').each { |r| puts r.inspect,'' }
-Twitter::Search.new('httparty').page(2).each { |r| puts r.inspect, '' }
-
-# search = Twitter::Search.new
-# search.from('jnunemaker').to('oaknd1').each { |r| puts r.inspect, '' }
-# pp search.result
-# search.clear
-
-# search.from('jnunemaker').to('oaknd1').since(814529437).containing('milk').each { |r| puts r.inspect, '' }
-# search.clear
-#
-# search.geocode('40.757929', '-73.985506', '50mi').containing('holland').each { |r| puts r.inspect, '' }
-# search.clear
-
-# pp search.from('jnunemaker').fetch()
View
27 examples/sent_messages.rb
@@ -1,27 +0,0 @@
-require 'rubygems'
-require 'activesupport'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'SINCE'
-twitter.sent_messages(:since => Time.now - 5.day).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'SINCE_ID'
-twitter.sent_messages(:since_id => 33505386).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'PAGE'
-twitter.sent_messages(:page => 1).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
View
34 examples/timeline.rb
@@ -1,34 +0,0 @@
-require 'rubygems'
-require 'activesupport'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts 'SINCE'
-twitter.timeline(:user, :since => Time.now - 1.day).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'SINCE_ID'
-twitter.timeline(:user, :since_id => 865547074).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'COUNT'
-twitter.timeline(:user, :count => 1).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
-
-puts 'PAGE'
-twitter.timeline(:user, :page => 1).each do |s|
- puts "- #{s.text}"
-end
-puts
-puts
View
27 examples/twitter.rb
@@ -1,27 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-puts "Public Timeline", "=" * 50
-Twitter::Base.new(config['email'], config['password']).timeline(:public).each do |s|
- puts s.text, s.user.name
- puts
-end
-
-puts '', "Friends Timeline", "=" * 50
-Twitter::Base.new(config['email'], config['password']).timeline.each do |s|
- puts s.text, s.user.name
- puts
-end
-
-puts '', "Friends", "=" * 50
-Twitter::Base.new(config['email'], config['password']).friends.each do |u|
- puts u.name, u.status.text
- puts
-end
-
-puts '', "Followers", "=" * 50
-Twitter::Base.new(config['email'], config['password']).followers.each do |u|
- puts u.name, u.status.text
- puts
-end
View
13 examples/verify_credentials.rb
@@ -1,13 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
-config = YAML::load(open(ENV['HOME'] + '/.twitter'))
-
-twitter = Twitter::Base.new(config['email'], config['password'])
-
-puts twitter.verify_credentials
-
-begin
- Twitter::Base.new('asdf', 'foobar').verify_credentials
-rescue => error
- puts error.message
-end
View
38 lib/twitter.rb
@@ -1,38 +0,0 @@
-require 'uri'
-require 'cgi'
-require 'net/http'
-require 'yaml'
-require 'time'
-require 'rubygems'
-
-gem 'hpricot'
-require 'hpricot'
-
-gem 'oauth'
-require 'oauth'
-
-$:.unshift(File.dirname(__FILE__))
-require 'twitter/version'
-require 'twitter/easy_class_maker'
-require 'twitter/oauth'
-require 'twitter/base'
-require 'twitter/user'
-require 'twitter/search'
-require 'twitter/status'
-require 'twitter/direct_message'
-require 'twitter/rate_limit_status'
-require 'twitter/search_result_info'
-require 'twitter/search_result'
-
-module Twitter
- class Unavailable < StandardError; end
- class CantConnect < StandardError; end
- class BadResponse < StandardError; end
- class UnknownTimeline < ArgumentError; end
- class RateExceeded < StandardError; end
- class CantFindUsers < ArgumentError; end
- class AlreadyFollowing < StandardError; end
- class CantFollowUser < StandardError; end
-
- SourceName = 'twittergem'
-end
View
284 lib/twitter/base.rb
@@ -1,284 +0,0 @@
-# This is the base class for the twitter library. It makes all the requests
-# to twitter, parses the xml (using hpricot) and returns ruby objects to play with.
-#
-# For complete documentation on the options, check out the twitter api docs.
-# http://groups.google.com/group/twitter-development-talk/web/api-documentation
-module Twitter
- class Base
- # Initializes the configuration for making requests to twitter
- # Twitter example:
- # Twitter.new('email/username', 'password')
- #
- # Identi.ca example:
- # Twitter.new('email/username', 'password', :api_host => 'identi.ca/api')
- def initialize(email, password, options={})
- @api_host = options.delete(:api_host) || 'twitter.com'
- @config, @config[:email], @config[:password] = options, email, password
- @proxy_host = options[:proxy_host]
- @proxy_port = options[:proxy_port]
- end
-
- # Returns an array of statuses for a timeline; Defaults to your friends timeline.
- def timeline(which=:friends, options={})
- raise UnknownTimeline unless [:friends, :public, :user].include?(which)
- auth = which.to_s.include?('public') ? false : true
- statuses(call("#{which}_timeline", :auth => auth, :since => options[:since], :args => parse_options(options)))
- end
-
- # Returns an array of users who are in your friends list
- def friends(options={})
- users(call(:friends, {:args => parse_options(options)}))
- end
-
- # Returns an array of users who are friends for the id or username passed in
- def friends_for(id, options={})
- friends(options.merge({:id => id}))
- end
-
- # Returns an array of user ids who are friends for the account or the option id/username passed in
- def friend_ids(id_or_screenname = nil)
- path = id_or_screenname ? "friends/ids/#{id_or_screenname}.xml" : "friends/ids.xml"
- doc = request(path, :auth => true)
- (doc/:id).inject([]) {|ids, id| ids << id.innerHTML; ids}
- end
-
- # Returns an array of users who are following you
- def followers(options={})
- users(call(:followers, {:args => parse_options(options)}))
- end
-
- def followers_for(id, options={})
- followers(options.merge({:id => id}))
- end
-
- # Returns an array of user ids who are followers for the account or the option id/username passed in
- def follower_ids(id_or_screenname = nil)
- path = id_or_screenname ? "followers/ids/#{id_or_screenname}.xml" : "followers/ids.xml"
- doc = request(path, :auth => true)
- (doc/:id).inject([]) {|ids, id| ids << id.innerHTML; ids}
- end
-
- # Returns a single status for a given id
- def status(id)
- statuses(call("show/#{id}")).first
- end
-
- # returns all the profile information and the last status for a user
- def user(id_or_screenname)
- users(request("users/show/#{id_or_screenname}.xml", :auth => true)).first
- end
-
- # Returns an array of statuses that are replies
- def replies(options={})
- statuses(call(:replies, :since => options[:since], :args => parse_options(options)))
- end
-
- # Destroys a status by id
- def destroy(id)
- call("destroy/#{id}")
- end
-
- def rate_limit_status
- RateLimitStatus.new_from_xml request("account/rate_limit_status.xml", :auth => true)
- end
-
- # waiting for twitter to correctly implement this in the api as it is documented
- def featured
- users(call(:featured))
- end
-
- # Returns an array of all the direct messages for the authenticated user
- def direct_messages(options={})
- doc = request(build_path('direct_messages.xml', parse_options(options)), {:auth => true, :since => options[:since]})
- (doc/:direct_message).inject([]) { |dms, dm| dms << DirectMessage.new_from_xml(dm); dms }
- end
- alias :received_messages :direct_messages
-
- # Returns direct messages sent by auth user
- def sent_messages(options={})
- doc = request(build_path('direct_messages/sent.xml', parse_options(options)), {:auth => true, :since => options[:since]})
- (doc/:direct_message).inject([]) { |dms, dm| dms << DirectMessage.new_from_xml(dm); dms }
- end
-
- # destroys a give direct message by id if the auth user is a recipient
- def destroy_direct_message(id)
- DirectMessage.new_from_xml(request("direct_messages/destroy/#{id}.xml", :auth => true, :method => :post))
- end
-
- # Sends a direct message <code>text</code> to <code>user</code>
- def d(user, text)
- DirectMessage.new_from_xml(request('direct_messages/new.xml', :auth => true, :method => :post, :form_data => {'text' => text, 'user' => user}))
- end
-
- # Befriends id_or_screenname for the auth user
- def create_friendship(id_or_screenname)
- users(request("friendships/create/#{id_or_screenname}.xml", :auth => true, :method => :post)).first
- end
-
- # Defriends id_or_screenname for the auth user
- def destroy_friendship(id_or_screenname)
- users(request("friendships/destroy/#{id_or_screenname}.xml", :auth => true, :method => :post)).first
- end
-
- # Returns true if friendship exists, false if it doesn't.
- def friendship_exists?(user_a, user_b)
- doc = request(build_path("friendships/exists.xml", {:user_a => user_a, :user_b => user_b}), :auth => true)
- doc.at('friends').innerHTML == 'true' ? true : false
- end
-
- # Updates your location and returns Twitter::User object
- def update_location(location)
- users(request(build_path('account/update_location.xml', {'location' => location}), :auth => true, :method => :post)).first
- end
-
- # Updates your deliver device and returns Twitter::User object
- def update_delivery_device(device)
- users(request(build_path('account/update_delivery_device.xml', {'device' => device}), :auth => true, :method => :post)).first
- end
-
- # Turns notifications by id_or_screenname on for auth user.
- def follow(id_or_screenname)
- users(request("notifications/follow/#{id_or_screenname}.xml", :auth => true, :method => :post)).first
- end
-
- # Turns notifications by id_or_screenname off for auth user.
- def leave(id_or_screenname)
- users(request("notifications/leave/#{id_or_screenname}.xml", :auth => true, :method => :post)).first
- end
-
- # Returns the most recent favorite statuses for the autenticating user
- def favorites(options={})
- statuses(request(build_path('favorites.xml', parse_options(options)), :auth => true))
- end
-
- # Favorites the status specified by id for the auth user
- def create_favorite(id)
- statuses(request("favorites/create/#{id}.xml", :auth => true, :method => :post)).first
- end
-
- # Un-favorites the status specified by id for the auth user
- def destroy_favorite(id)
- statuses(request("favorites/destroy/#{id}.xml", :auth => true, :method => :post)).first
- end
-
- # Blocks the user specified by id for the auth user
- def block(id)
- users(request("blocks/create/#{id}.xml", :auth => true, :method => :post)).first
- end
-
- # Unblocks the user specified by id for the auth user
- def unblock(id)
- users(request("blocks/destroy/#{id}.xml", :auth => true, :method => :post)).first
- end
-
- # Posts a new update to twitter for auth user.
- def post(status, options={})
- form_data = {'status' => status}
- form_data.merge!({'source' => options[:source]}) if options[:source]
- form_data.merge!({'in_reply_to_status_id' => options[:in_reply_to_status_id]}) if options[:in_reply_to_status_id]
- Status.new_from_xml(request('statuses/update.xml', :auth => true, :method => :post, :form_data => form_data))
- end
- alias :update :post
-
- # Verifies the credentials for the auth user.
- # raises Twitter::CantConnect on failure.
- def verify_credentials
- users(request('account/verify_credentials.xml', :auth => true)).first
- end
-
- private
- # Converts an hpricot doc to an array of statuses
- def statuses(doc)
- (doc/:status).inject([]) { |statuses, status| statuses << Status.new_from_xml(status); statuses }
- end
-
- # Converts an hpricot doc to an array of users
- def users(doc)
- (doc/:user).inject([]) { |users, user| users << User.new_from_xml(user); users }
- end
-
- # Calls whatever api method requested that deals with statuses
- #
- # ie: call(:public_timeline, :auth => false)
- def call(method, options={})
- options = { :auth => true, :args => {} }.merge(options)
- # Following line needed as lite=false doesn't work in the API: http://tinyurl.com/yo3h5d
- options[:args].delete(:lite) unless options[:args][:lite]
- args = options.delete(:args)
- request(build_path("statuses/#{method.to_s}.xml", args), options)
- end
-
- def response(path, options={})
- uri = URI.parse("http://#{@api_host}")
-
- begin
- response = Net::HTTP::Proxy(@proxy_host, @proxy_port).start(uri.host, uri.port) do |http|
- klass = Net::HTTP.const_get options[:method].to_s.downcase.capitalize
- req = klass.new("#{uri.path}/#{path}", options[:headers])
- req.basic_auth(@config[:email], @config[:password]) if options[:auth]
- if options[:method].to_s == 'post' && options[:form_data]
- req.set_form_data(options[:form_data])
- end
- http.request(req)
- end
- rescue => error
- raise CantConnect, error.message
- end
- end
-
- # Makes a request to twitter.
- def request(path, options={})
- options = {
- :headers => { "User-Agent" => @config[:email] },
- :method => :get,
- }.merge(options)
-
- unless options[:since].nil?
- since = options[:since].kind_of?(Date) ? options[:since].strftime('%a, %d-%b-%y %T GMT') : options[:since].to_s
- options[:headers]["If-Modified-Since"] = since
- end
-
- handle_response!(response(path, options))
- end
-
- def handle_response!(response)
- if %w[200 304].include?(response.code)
- response = parse(response.body)
- raise RateExceeded if (response/:hash/:error).text =~ /Rate limit exceeded/
- response
- elsif response.code == '503'
- raise Unavailable, response.message
- elsif response.code == '401'
- raise CantConnect, 'Authentication failed. Check your username and password'
- elsif response.code == '403'
- error_message = (parse(response.body)/:hash/:error).text
- raise CantFindUsers, error_message if error_message =~ /Could not find both specified users/
- raise AlreadyFollowing, error_message if error_message =~ /already on your list/
- raise CantFollowUser, "Response code #{response.code}: #{response.message} #{error_message}"
- else
- raise CantConnect, "Twitter is returning a #{response.code}: #{response.message}"
- end
- end
-
- # Given a path and a hash, build a full path with the hash turned into a query string
- def build_path(path, options)
- unless options.nil?
- query = options.inject('') { |str, h| str += "#{CGI.escape(h[0].to_s)}=#{CGI.escape(h[1].to_s)}&"; str }
- path += "?#{query}"
- end
-
- path
- end
-
- # Tries to get all the options in the correct format before making the request
- def parse_options(options)
- options[:since] = options[:since].kind_of?(Date) ? options[:since].strftime('%a, %d-%b-%y %T GMT') : options[:since].to_s if options[:since]
- options
- end
-
- # Converts a string response into an Hpricot xml element.
- def parse(response)
- Hpricot.XML(response || '')
- end
- end
-end
View
334 lib/twitter/cli.rb
@@ -1,334 +0,0 @@
-require 'rubygems'
-
-gem 'main'
-gem 'highline'
-gem 'activerecord'
-gem 'sqlite3-ruby'
-
-require 'main'
-require 'highline/import'
-require 'activerecord'
-require 'sqlite3'
-
-HighLine.track_eof = false
-CLI_ROOT = File.expand_path(File.join(File.dirname(__FILE__), 'cli'))
-require CLI_ROOT + '/config'
-require CLI_ROOT + '/helpers'
-Dir[CLI_ROOT + '/models/*.rb'].each { |m| require m }
-
-include Twitter::CLI::Helpers
-
-Main {
- def run
- puts "twitter [command] --help for usage instructions."
- puts "The available commands are: \n install, uninstall, add, remove, list, change, post, befriend, defriend, follow, leave, d and timeline."
- end
-
- mode 'install' do
- description 'Creates the sqlite3 database and runs the migrations.'
- def run
- migrate
- attempt_import
- say 'Twitter installed.'
- end
- end
-
- mode 'uninstall' do
- description 'Removes the sqlite3 database. There is no undo for this.'
- def run
- FileUtils.rm(Twitter::CLI::Config[:database]) if File.exists?(Twitter::CLI::Config[:database])
- say 'Twitter gem uninstalled.'
- end
- end
-
- mode 'add' do
- description 'Adds a new twitter account to the database. Prompts for username and password.'
- argument('username', 'u') {
- optional
- description 'optional username'
- }
- argument('password', 'p') {
- optional
- description 'optional password'
- }
-
- def run
- account = Hash.new
- say "Add New Account:"
-
- # allows optional username arg
- if params['username'].given?
- account[:username] = params['username'].value
- else
- account[:username] = ask('Username: ') do |q|
- q.validate = /\S+/
- end
- end
-
- # allows optional password arg
- if params['password'].given?
- account[:password] = params['password'].value
- else
- account[:password] = ask("Password (won't be displayed): ") do |q|
- q.echo = false
- q.validate = /\S+/
- end
- end
-
- do_work do
- base(account[:username], account[:password]).verify_credentials
- Account.add(account)
- say 'Account added.'
- end
- end
- end
-
- mode 'remove' do
- description 'Removes a twitter account from the database. If username provided it removes that username else it prompts with list and asks for which one you would like to remove.'
- argument( 'username' ) {
- optional
- description 'username of account you would like to remove'
- }
-
- def run
- do_work do
- if params['username'].given?
- account = Account.find_by_username(params['username'].value)
- else
- Account.find(:all, :order => 'username').each do |a|
- say "#{a.id}. #{a}"
- end
- account_id = ask 'Account to remove (enter number): ' do |q|
- q.validate = /\d+/
- end
- end
-
- begin
- account = account_id ? Account.find(account_id) : account
- account_name = account.username
- account.destroy
- Account.set_current(Account.first) if Account.new_active_needed?
- say "#{account_name} has been removed.\n"
- rescue ActiveRecord::RecordNotFound
- say "ERROR: Account could not be found. Try again. \n"
- end
- end
- end
- end
-
- mode 'list' do
- description 'Lists all the accounts that have been added and puts a * by the current one that is used for posting, etc.'
- def run
- do_work do
- if Account.count == 0
- say 'No accounts have been added.'
- else
- say 'Account List'
- Account.find(:all, :order => 'username').each do |a|
- say a
- end
- end
- end
- end
- end
-
- mode 'change' do
- description 'Changes the current account being used for posting etc. to the username provided. If no username is provided, a list is presented and you can choose the account from there.'
- argument( 'username' ) {
- optional
- description 'username of account you would like to switched to'
- }
-
- def run
- do_work do
- if params['username'].given?
- new_current = Account.find_by_username(params['username'].value)
- else
- Account.find(:all, :order => 'username').each do |a|
- say "#{a.id}. #{a}"
- end
- new_current = ask 'Change current account to (enter number): ' do |q|
- q.validate = /\d+/
- end
- end
-
- begin
- current = Account.set_current(new_current)
- say "#{current} is now the current account.\n"
- rescue ActiveRecord::RecordNotFound
- say "ERROR: Account could not be found. Try again. \n"
- end
- end
- end
- end
-
- mode 'post' do
- description "Posts a message to twitter using the current account. The following are all valid examples from the command line:
- $ twitter post 'my update'
- $ twitter post my update with quotes
- $ echo 'my update from stdin' | twitter post"
- def run
- do_work do
- post = ARGV.size > 1 ? ARGV.join(" ") : ARGV.shift
- say "Sending twitter update"
- finished, status = false, nil
- progress_thread = Thread.new { until finished; print "."; $stdout.flush; sleep 0.5; end; }
- post_thread = Thread.new(binding()) do |b|
- status = base.post(post, :source => Twitter::SourceName)
- finished = true
- end
- post_thread.join
- progress_thread.join
- say "Got it! New tweet created at: #{status.created_at}\n"
- end
- end
- end
-
- mode 'befriend' do
- description "Allows you to add a user as a friend"
- argument('username') {
- required
- description 'username or id of twitterrer to befriend'
- }
-
- def run
- do_work do
- username = params['username'].value
- base.create_friendship(username)
- say "#{username} has been added as a friend. follow notifications with 'twitter follow #{username}'"
- end
- end
- end
-
- mode 'defriend' do
- description "Allows you to remove a user from being a friend"
- argument('username') {
- required
- description 'username or id of twitterrer to defriend'
- }
-
- def run
- do_work do
- username = params['username'].value
- base.destroy_friendship(username)
- say "#{username} has been removed from your friends"
- end
- end
- end
-
- mode 'follow' do
- description "Allows you to add notifications for a user (aka Follow Them)"
- argument('username') {
- required
- description 'username or id of twitterrer to follow'
- }
-
- def run
- do_work do
- username = params['username'].value
- base.follow(username)
- say "You are now following notifications from #{username}"
- end
- end
- end
-
- mode 'leave' do
- description "Allows you to turn off notifications for a user"
- argument('username') {
- required
- description 'username or id of twitterrer to leave'
- }
-
- def run
- do_work do
- username = params['username'].value
- base.leave(username)
- say "You are no longer following notifications from #{username}"
- end
- end
- end
-
- mode 'd' do
- description "Allows you to direct message a user. The following are all valid examples from the command line:
- $ twitter d jnunemaker 'yo homeboy'
- $ twitter d jnunemaker yo homeboy
- $ echo 'yo homeboy' | twitter d jnunemaker"
- argument('username') {
- required
- description 'username or id of twitterrer to direct message'
- }
-
- def run
- do_work do
- username = params['username'].value
- post = ARGV.size > 1 ? ARGV.join(" ") : ARGV.shift
- base.d(username, post)
- say "Direct message sent to #{username}"
- end
- end
- end
-
- mode 'timeline' do
- description "Allows you to view your timeline, your friends or the public one"
- argument( 'timeline' ) {
- description 'the timeline you wish to see (friends, public, me)'
- default 'friends'
- }
- option('force', 'f') {
- description "Ignore since_id and show first page of results even if there aren't new ones"
- }
- option('reverse', 'r') {
- description 'Reverse the output so the oldest tweets are at the top'
- }
-
- def run
- do_work do
- timeline = params['timeline'].value == 'me' ? 'user' : params['timeline'].value
- options, since_id = {}, Configuration["#{timeline}_since_id"]
- options[:since_id] = since_id if !since_id.nil? && !params['force'].given?
- reverse = params['reverse'].given? ? true : false
- cache = [:friends, :user].include?(timeline)
- collection = base.timeline(timeline.to_sym, options)
- output_tweets(collection, {:cache => cache, :since_prefix => timeline, :reverse => reverse})
- end
- end
- end
-
- mode 'replies' do
- description 'Allows you to view all @replies sent to you'
- option('force', 'f') {
- description "Ignore since_id and show first page of replies even if there aren't new ones"
- }
-
- def run
- do_work do
- options, since_id = {}, Configuration["replies_since_id"]
- options[:since_id] = since_id if !since_id.nil? && !params['force'].given?
- collection = base.replies(options)
- output_tweets(collection, {:since_prefix => 'replies'})
- end
- end
- end
-
- mode 'clear_config' do
- def run
- do_work do
- count = Configuration.count
- Configuration.destroy_all
- say("#{count} configuration entries cleared.")
- end
- end
- end
-
- mode 'open' do
- description 'Opens the given twitter user in a browser window'
- argument('username') {
- required
- description "username or id of twitterrer who's page you would like to see"
- }
-
- def run
- `open http://twitter.com/#{params['username'].value}`
- end
- end
-}
View
9 lib/twitter/cli/config.rb
@@ -1,9 +0,0 @@
-module Twitter
- module CLI
- Config = {
- :adapter => 'sqlite3',
- :database => File.join(ENV['HOME'], '.twitter.db'),
- :timeout => 5000
- }
- end
-end
View
109 lib/twitter/cli/helpers.rb
@@ -1,109 +0,0 @@
-module Twitter
- module CLI
- module Helpers
- class NoActiveAccount < StandardError; end
- class NoAccounts < StandardError; end
-
- def output_tweets(collection, options={})
- options = {
- :cache => false,
- :since_prefix => '',
- :empty_msg => 'Nothing new since your last check.',
- :reverse => false
- }.merge(options)
-
- if collection.size > 0
- justify = collection.collect { |s| s.user.screen_name }.max { |a,b| a.length <=> b.length }.length rescue 0
- indention = ' ' * (justify + 3)
- say("\n#{indention}#{collection.size} new tweet(s) found.\n\n")
- collection.reverse! if options[:reverse]
- collection.each do |s|
- Tweet.create_from_tweet(current_account, s) if options[:cache]
-
- occurred_at = Time.parse(s.created_at).strftime('On %b %d at %l:%M%P')
- formatted_time = '-' * occurred_at.length + "\n#{indention}#{occurred_at}"
- formatted_name = s.user.screen_name.rjust(justify + 1)
- formatted_msg = ''
-
- s.text.split(' ').each_with_index do |word, idx|
- formatted_msg += "#{word} "
-
- sixth_word = idx != 0 && idx % 6 == 0
- formatted_msg += "\n#{indention}" if sixth_word
- end
-
- say "#{CGI::unescapeHTML(formatted_name)}: #{CGI::unescapeHTML(formatted_msg)}\n#{indention}#{formatted_time}\n\n"
- end
-
- Configuration["#{options[:since_prefix]}_since_id"] = options[:reverse] ? collection.last.id : collection.first.id
- else
- say(options[:empty_msg])
- end
- end
-
- def base(username=current_account.username, password=current_account.password)
- @base ||= Twitter::Base.new(username, password)
- end
-
- def current_account
- @current_account ||= Account.active
- raise Account.count == 0 ? NoAccounts : NoActiveAccount if @current_account.nil?
- @current_account
- end
-
- def attempt_import(&block)
- tweet_file = File.join(ENV['HOME'], '.twitter')
- if File.exists?(tweet_file)
- say '.twitter file found, attempting import...'
- config = YAML::load(File.read(tweet_file))
- if !config['email'].nil? && !config['password'].nil?
- Account.add(:username => config['email'], :password => config['password'])
- say 'Account imported'
- block.call if block_given?
- true
- else
- say "Either your username or password were blank in your .twitter file so I could not import. Use 'twitter add' to add an account."
- false
- end
- end
- end
-
- def do_work(&block)
- connect
- begin
- block.call
- rescue Twitter::RateExceeded
- say("Twitter says you've been making too many requests. Wait for a bit and try again.")
- rescue Twitter::Unavailable
- say("Twitter is unavailable right now. Try again later.")
- rescue Twitter::CantConnect => msg
- say("Can't connect to twitter because: #{msg}")
- rescue Twitter::CLI::Helpers::NoActiveAccount
- say("You have not set an active account. Use 'twitter change' to set one now.")
- rescue Twitter::CLI::Helpers::NoAccounts
- unless attempt_import { block.call }
- say("You have not created any accounts. Use 'twitter add' to create one now.")
- end
- end
- end
-
- def connect
- ActiveRecord::Base.logger = Logger.new('/tmp/twitter_ar_logger.log')
- ActiveRecord::Base.establish_connection(Twitter::CLI::Config)
- ActiveRecord::Base.connection
- end
-
- def migrate
- connect
- ActiveRecord::Migrator.migrate("#{CLI_ROOT}/migrations/")
- end
-
- def connect_and_migrate
- say('Attempting to establish connection...')
- connect
- say('Connection established...migrating database...')
- migrate
- end
- end
- end
-end
View
13 lib/twitter/cli/migrations/20080722194500_create_accounts.rb
@@ -1,13 +0,0 @@
-class CreateAccounts < ActiveRecord::Migration
- def self.up
- create_table :accounts do |t|
- t.string :username, :password
- t.boolean :current
- t.timestamps
- end
- end
-
- def self.down
- drop_table :accounts
- end
-end
View
16 lib/twitter/cli/migrations/20080722194508_create_tweets.rb
@@ -1,16 +0,0 @@
-class CreateTweets < ActiveRecord::Migration
- def self.up
- create_table :tweets do |t|
- t.datetime :occurred_at
- t.boolean :truncated, :favorited, :user_protected, :default => false
- t.integer :twitter_id, :user_id, :in_reply_to_status_id, :in_reply_to_user_id, :user_followers_count
- t.text :body
- t.string :source, :user_name, :user_screen_name, :user_location, :user_description, :user_profile_image_url, :user_url
- t.timestamps
- end
- end
-
- def self.down
- drop_table :tweets
- end
-end
View
9 lib/twitter/cli/migrations/20080722214605_add_account_id_to_tweets.rb
@@ -1,9 +0,0 @@
-class AddAccountIdToTweets < ActiveRecord::Migration
- def self.up
- add_column :tweets, :account_id, :integer
- end
-
- def self.down
- remove_column :tweets, :account_id
- end
-end
View
13 lib/twitter/cli/migrations/20080722214606_create_configurations.rb
@@ -1,13 +0,0 @@
-class CreateConfigurations < ActiveRecord::Migration
- def self.up
- create_table :configurations do |t|
- t.string :key
- t.text :data
- t.timestamps
- end
- end
-
- def self.down
- drop_table :accounts
- end
-end
View
33 lib/twitter/cli/models/account.rb
@@ -1,33 +0,0 @@
-class Account < ActiveRecord::Base
- named_scope :current, :conditions => {:current => true}
-
- has_many :tweets, :dependent => :destroy
-
- def self.add(hash)
- username = hash.delete(:username)
- account = find_or_initialize_by_username(username)
- account.attributes = hash
- account.save
- set_current(account) if new_active_needed?
- end
-
- def self.active
- current.first
- end
-
- def self.set_current(account_or_id)
- account = account_or_id.is_a?(Account) ? account_or_id : find(account_or_id)
- account.update_attribute :current, true
- Account.update_all "current = 0", "id != #{account.id}"
- account
- end
-
- def self.new_active_needed?
- self.current.count == 0 && self.count > 0
- end
-
- def to_s
- "#{current? ? '*' : ' '} #{username}"
- end
- alias to_str to_s
-end
View
13 lib/twitter/cli/models/configuration.rb
@@ -1,13 +0,0 @@
-class Configuration < ActiveRecord::Base
- serialize :data
-
- def self.[](key)
- key = find_by_key(key.to_s)
- key.nil? ? nil : key.data
- end
-
- def self.[]=(key, data)
- c = find_or_create_by_key(key.to_s)
- c.update_attribute :data, data
- end
-end
View
20 lib/twitter/cli/models/tweet.rb
@@ -1,20 +0,0 @@
-class Tweet < ActiveRecord::Base
- belongs_to :account
-
- def self.create_from_tweet(account, s)
- tweet = account.tweets.find_or_initialize_by_twitter_id(s.id)
- tweet.body = s.text
- tweet.occurred_at = s.created_at
-
- %w[truncated favorited in_reply_to_status_id in_reply_to_user_id source].each do |m|
- tweet.send("#{m}=", s.send(m))
- end
-
- %w[id followers_count name screen_name location description
- profile_image_url url protected].each do |m|
- tweet.send("user_#{m}=", s.user.send(m))
- end
- tweet.save!
- tweet
- end
-end
View
22 lib/twitter/direct_message.rb
@@ -1,22 +0,0 @@
-module Twitter
- class DirectMessage
- include EasyClassMaker
-
- attributes :id, :text, :sender_id, :recipient_id, :created_at, :sender_screen_name, :recipient_screen_name
-
- class << self
- # Creates a new status from a piece of xml
- def new_from_xml(xml)
- DirectMessage.new do |d|
- d.id = (xml).at('id').innerHTML
- d.text = (xml).get_elements_by_tag_name('text').innerHTML
- d.sender_id = (xml).at('sender_id').innerHTML
- d.recipient_id = (xml).at('recipient_id').innerHTML
- d.created_at = (xml).at('created_at').innerHTML
- d.sender_screen_name = (xml).at('sender_screen_name').innerHTML
- d.recipient_screen_name = (xml).at('recipient_screen_name').innerHTML
- end
- end
- end
- end
-end
View
43 lib/twitter/easy_class_maker.rb
@@ -1,43 +0,0 @@
-# This is pretty much just a macro for creating a class that allows
-# using a block to initialize stuff and to define getters and setters
-# really quickly.
-module Twitter
- module EasyClassMaker
-
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- # creates the attributes class variable and creates each attribute's accessor methods
- def attributes(*attrs)
- @@attributes = attrs
- @@attributes.each { |a| attr_accessor a }
- end
-
- # read method for attributes class variable
- def self.attributes; @@attributes end
- end
-
- # allows for any class that includes this to use a block to initialize
- # variables instead of assigning each one seperately
- #
- # Example:
- #
- # instead of...
- #
- # s = Status.new
- # s.foo = 'thing'
- # s.bar = 'another thing'
- #
- # you can ...
- #
- # Status.new do |s|
- # s.foo = 'thing'
- # s.bar = 'another thing'
- # end
- def initialize
- yield self if block_given?
- end
- end
-end
View
32 lib/twitter/oauth.rb
@@ -1,32 +0,0 @@
-module Twitter
- class OAuth
- attr_reader :token, :secret
-
- def initialize(ctoken, csecret)
- @ctoken, @csecret = ctoken, csecret
- end
-
- def request_token
- @request_token ||= consumer.get_request_token
- end
-
- def authorize_from_request(rtoken, rsecret)
- request_token = ::OAuth::RequestToken.new(consumer, rtoken, rsecret)
- access_token = request_token.get_access_token
- @atoken, @asecret = access_token.token, access_token.secret
- end
-
- def access_token
- @access_token ||= ::OAuth::AccessToken.new(consumer, @atoken, @asecret)
- end
-
- def authorize_from_access(atoken, asecret)
- @atoken, @asecret = atoken, asecret
- end
-
- private
- def consumer
- @consumer ||= ::OAuth::Consumer.new(@ctoken, @csecret, {:site => 'http://twitter.com'})
- end
- end
-end
View
19 lib/twitter/rate_limit_status.rb
@@ -1,19 +0,0 @@
-module Twitter
- class RateLimitStatus
- include EasyClassMaker
-
- attributes :reset_time_in_seconds, :reset_time, :remaining_hits, :hourly_limit
-
- class << self
- # Creates a new rate limi status from a piece of xml
- def new_from_xml(xml)
- RateLimitStatus.new do |s|
- s.reset_time_in_seconds = xml.at('reset-time-in-seconds').inner_html.to_i
- s.reset_time = Time.parse xml.at('reset-time').inner_html
- s.remaining_hits = xml.at('remaining-hits').inner_html.to_i
- s.hourly_limit = xml.at('hourly-limit').inner_html.to_i
- end
- end
- end
- end
-end
View
101 lib/twitter/search.rb
@@ -1,101 +0,0 @@
-gem 'httparty'
-require 'httparty'
-
-module Twitter
- class Search
- include HTTParty
- include Enumerable
- base_uri 'search.twitter.com'
-
- attr_reader :result, :query
-
- def initialize(q=nil)
- clear
- containing(q) if q && q.strip != ''
- end
-
- def from(user)
- @query[:q] << "from:#{user}"
- self
- end
-
- def to(user)
- @query[:q] << "to:#{user}"
- self
- end
-
- def referencing(user)
- @query[:q] << "@#{user}"
- self
- end
- alias :references :referencing
- alias :ref :referencing
-
- def containing(word)
- @query[:q] << "#{word}"
- self
- end
- alias :contains :containing
-
- # adds filtering based on hash tag ie: #twitter
- def hashed(tag)
- @query[:q] << "##{tag}"
- self
- end
-
- # lang must be ISO 639-1 code ie: en, fr, de, ja, etc.
- #
- # when I tried en it limited my results a lot and took
- # out several tweets that were english so i'd avoid
- # this unless you really want it
- def lang(lang)
- @query[:lang] = lang
- self
- end
-
- # Limits the number of results per page
- def per_page(num)
- @query[:rpp] = num
- self
- end
-
- # Which page of results to fetch
- def page(num)
- @query[:page] = num
- self
- end
-
- # Only searches tweets since a given id.
- # Recommended to use this when possible.
- def since(since_id)
- @query[:since_id] = since_id
- self
- end
-
- # Search tweets by longitude, latitude and a given range.
- # Ranges like 25km and 50mi work.
- def geocode(long, lat, range)
- @query[:geocode] = [long, lat, range].join(',')
- self
- end
-
- # Clears all the query filters to make a new search
- def clear
- @query = {}
- @query[:q] = []
- self
- end
-
- # If you want to get results do something other than iterate over them.
- def fetch
- @query[:q] = @query[:q].join(' ')
- SearchResultInfo.new_from_hash(self.class.get('/search.json', {:query => @query}))
- end
-
- def each
- @result = fetch()
- @result['results'].each { |r| yield r }
- end
- end
-end
-
View
83 lib/twitter/search_result.rb
@@ -1,83 +0,0 @@
-module Twitter
- class SearchResult < Hash
-
- # Creates an easier to work with hash from
- # one with string-based keys
- def self.new_from_hash(hash)
- new.merge!(hash)
- end
-
- def created_at
- self['created_at']
- end
-
- def created_at=(val)
- self['created_at'] = val
- end
-
- def from_user
- self['from_user']
- end
-
- def from_user=(val)
- self['from_user'] = val
- end
-
- def from_user_id
- self['from_user_id']
- end
-
- def from_user_id=(val)
- self['from_user_id'] = val
- end
-
- def id
- self['id']
- end
-
- def id=(val)
- self['id'] = val
- end
-
- def iso_language_code
- self['iso_language_code']
- end
-
- def iso_language_code=(val)
- self['iso_language_code'] = val
- end
-
- def profile_image_url
- self['profile_image_url']
- end
-
- def profile_image_url=(val)
- self['profile_image_url'] = val
- end
-
- def text
- self['text']
- end
-
- def text=(val)
- self['text'] = val
- end
-
- def to_user
- self['to_user']
- end
-
- def to_user=(val)
- self['to_user'] = val
- end
-
- def to_user_id
- self['to_user_id']
- end
-
- def to_user_id=(val)
- self['to_user_id'] = val
- end
-
- end
-end
View
82 lib/twitter/search_result_info.rb
@@ -1,82 +0,0 @@
-module Twitter
- class SearchResultInfo < Hash
-
- # Creates an easier to work with hash from
- # one with string-based keys
- def self.new_from_hash(hash)
- i = new
- i.merge!(hash)
- search_results = []
- i.results.each do |r|
- search_results << SearchResult.new_from_hash(r)
- end
- i.results = search_results
- i
- end
-
- def completed_in
- self['completed_in']
- end
-
- def completed_in=(val)
- self['completed_in'] = val
- end
-
- def max_id
- self['max_id']
- end
-
- def max_id=(val)
- self['max_id'] = val
- end
-
- def next_page
- self['next_page']
- end
-
- def next_page=(val)
- self['next_page'] = val
- end
-
- def page
- self['page']
- end
-
- def page=(val)
- self['page'] = val
- end
-
- def refresh_url
- self['refresh_url']
- end
-
- def refresh_url=(val)
- self['refresh_url'] = val
- end
-
- def results_per_page
- self['results_per_page']
- end
-
- def results_per_page=(val)
- self['results_per_page'] = val
- end
-
- def since_id
- self['since_id']
- end
-
- def since_id=(val)
- self['since_id'] = val
- end
-
- def results
- self['results']
- end
-
- def results=(val)
- self['results'] = val
- end
-
- end
-end
View
22 lib/twitter/status.rb
@@ -1,22 +0,0 @@
-module Twitter
- class Status
- include EasyClassMaker
-
- attributes :created_at, :id, :text, :user, :source, :truncated, :in_reply_to_status_id, :in_reply_to_user_id, :favorited
-
- # Creates a new status from a piece of xml
- def self.new_from_xml(xml)
- s = new
- s.id = (xml).at('id').innerHTML
- s.created_at = (xml).at('created_at').innerHTML
- s.text = (xml).get_elements_by_tag_name('text').innerHTML
- s.source = (xml).at('source').innerHTML
- s.truncated = (xml).at('truncated').innerHTML == 'false' ? false : true
- s.favorited = (xml).at('favorited').innerHTML == 'false' ? false : true
- s.in_reply_to_status_id = (xml).at('in_reply_to_status_id').innerHTML
- s.in_reply_to_user_id = (xml).at('in_reply_to_user_id').innerHTML
- s.user = User.new_from_xml(xml.at('user')) if (xml).at('user')
- s
- end
- end
-end
View
38 lib/twitter/user.rb
@@ -1,38 +0,0 @@
-module Twitter
- class User
- include EasyClassMaker
-
- attributes :id, :name, :screen_name, :status, :location, :description, :url,
- :profile_image_url, :profile_background_color, :profile_text_color, :profile_link_color,
- :profile_sidebar_fill_color, :profile_sidebar_border_color, :friends_count, :followers_count,
- :favourites_count, :statuses_count, :utc_offset , :protected, :created_at
-
- # Creates a new user from a piece of xml
- def self.new_from_xml(xml)
- u = new
- u.id = (xml).at('id').innerHTML
- u.name = (xml).at('name').innerHTML
- u.screen_name = (xml).at('screen_name').innerHTML
- u.location = (xml).at('location').innerHTML
- u.description = (xml).at('description').innerHTML
- u.url = (xml).at('url').innerHTML
- u.profile_image_url = (xml).at('profile_image_url').innerHTML
-
- # optional, not always present
- u.created_at = (xml).at('created_at').innerHTML if (xml).at('created_at')
- u.profile_background_color = (xml).at('profile_background_color').innerHTML if (xml).at('profile_background_color')
- u.profile_text_color = (xml).at('profile_text_color').innerHTML if (xml).at('profile_text_color')
- u.profile_link_color = (xml).at('profile_link_color').innerHTML if (xml).at('profile_link_color')
- u.profile_sidebar_fill_color = (xml).at('profile_sidebar_fill_color').innerHTML if (xml).at('profile_sidebar_fill_color')
- u.profile_sidebar_border_color = (xml).at('profile_sidebar_border_color').innerHTML if (xml).at('profile_sidebar_border_color')
- u.friends_count = (xml).at('friends_count').innerHTML if (xml).at('friends_count')
- u.followers_count = (xml).at('followers_count').innerHTML if (xml).at('followers_count')
- u.favourites_count = (xml).at('favourites_count').innerHTML if (xml).at('favourites_count')
- u.statuses_count = (xml).at('statuses_count').innerHTML if (xml).at('statuses_count')
- u.utc_offset = (xml).at('utc_offset').innerHTML if (xml).at('utc_offset')
- u.protected = (xml).at('protected').innerHTML == 'false' ? false : true if (xml).at('protected')
- u.status = Status.new_from_xml(xml.at('status')) if (xml).at('status')
- u
- end
- end
-end
View
3  lib/twitter/version.rb
@@ -1,3 +0,0 @@
-module Twitter #:nodoc:
- Version = '0.4.4'
-end
View
139 spec/base_spec.rb
@@ -1,139 +0,0 @@
-require File.dirname(__FILE__) + '/spec_helper.rb'
-
-describe "Twitter::Base" do
- before do
- @base = Twitter::Base.new('foo', 'bar')
- end
-
- describe "being initialized" do
- it "should require email and password" do
- lambda { Twitter::Base.new }.should raise_error(ArgumentError)
- end
- end
-
- describe "timelines" do
- it "should bomb if given invalid timeline" do
- lambda { @base.timeline(:fakeyoutey) }.should raise_error(Twitter::UnknownTimeline)
- end
-
- it "should default to friends timeline" do
- @base.should_receive(:call).with("friends_timeline", {:auth=>true, :args=>{}, :since=>nil})
- @base.should_receive(:statuses)
- @base.timeline
- end
-
- it "should be able to retrieve friends timeline" do
- data = open(File.dirname(__FILE__) + '/fixtures/friends_timeline.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.timeline(:friends).size.should == 3
- end
-
- it "should be able to retrieve public timeline" do
- data = open(File.dirname(__FILE__) + '/fixtures/public_timeline.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.timeline(:public).size.should == 6
- end
-
- it "should be able to retrieve user timeline" do
- data = open(File.dirname(__FILE__) + '/fixtures/user_timeline.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.timeline(:user).size.should == 19
- end
- end
-
- describe "friends and followers" do
- it "should be able to get friends" do
- data = open(File.dirname(__FILE__) + '/fixtures/friends.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.friends.size.should == 25
- end
-
- it "should be able to get friends without latest status" do
- data = open(File.dirname(__FILE__) + '/fixtures/friends_lite.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.friends(:lite => true).size.should == 15
- end
-
- it "should be able to get friend ids" do
- data = open(File.dirname(__FILE__) + '/fixtures/friend_ids.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.friend_ids.size.should == 8
- end
-
- it "should be able to get friends for another user" do
- data = open(File.dirname(__FILE__) + '/fixtures/friends_for.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- timeline = @base.friends_for(20)
- timeline.size.should == 24
- timeline.first.name.should == 'Jack Dorsey'
- end
-
- it "should be able to get followers" do
- data = open(File.dirname(__FILE__) + '/fixtures/followers.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- timeline = @base.followers
- timeline.size.should == 29
- timeline.first.name.should == 'Blaine Cook'
- end
-
- it "should be able to get follower ids" do
- data = open(File.dirname(__FILE__) + '/fixtures/follower_ids.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.follower_ids.size.should == 8
- end
-
- it "should be able to create a friendship" do
- data = open(File.dirname(__FILE__) + '/fixtures/friendship_created.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- user = @base.create_friendship('jnunemaker')
- end
-
- it "should bomb if friendship already exists" do
- data = open(File.dirname(__FILE__) + '/fixtures/friendship_already_exists.xml').read
- response = Net::HTTPForbidden.new("1.1", '403', '')
- response.stub!(:body).and_return(data)
- @base.should_receive(:response).and_return(response)
- lambda { @base.create_friendship('billymeltdown') }.should raise_error(Twitter::AlreadyFollowing)
- end
- end
-
- it "should be able to get single status" do
- data = open(File.dirname(__FILE__) + '/fixtures/status.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.status(803478581).created_at.should == 'Sun May 04 23:36:14 +0000 2008'
- end
-
- it "should be able to get single user" do
- data = open(File.dirname(__FILE__) + '/fixtures/user.xml').read
- @base.should_receive(:request).and_return(Hpricot::XML(data))
- @base.user('4243').name.should == 'John Nunemaker'
- end
-
- describe "rate limit status" do
- before do
- @data = open(File.dirname(__FILE__) + '/fixtures/rate_limit_status.xml').read
- @base.stub!(:request).and_return(Hpricot::XML(@data))
- end
-
- it "should request the status" do
- @base.should_receive(:request).and_return(Hpricot::XML(@data))
- @base.rate_limit_status
- end
-
- it "should have an hourly limit" do
- @base.rate_limit_status.hourly_limit.should == 20
- end
-
- it "should have a reset time in seconds" do
- @base.rate_limit_status.reset_time_in_seconds.should == 1214757610
- end
-
- it "should have a reset time" do
- @base.rate_limit_status.reset_time.should == Time.parse('2008-06-29T16:40:10+00:00')
- end
-
- it "should have remaining hits" do
- @base.rate_limit_status.remaining_hits.should == 5
- end
- end
-end
View
49 spec/cli/helper_spec.rb
@@ -1,49 +0,0 @@
-require 'ostruct'
-require File.dirname(__FILE__) + '/../spec_helper.rb'
-require File.dirname(__FILE__) + '/../../lib/twitter/cli/helpers'