brookr-tootils 0.1.1

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jack Danger Canty
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,69 @@
1
+ Description:
2
+ A collection of useful Twitter Utilities
3
+ Tools:
4
+ Of primary interest is the graphing tool. It will determine if a
5
+ Twitter user has another user in thier 1st, 2nd or
6
+ 3rd degree of connections
7
+ Limitations:
8
+ Running 3rd degree checks on users that have a lot of followers/friends
9
+ will result in using all your available API hit. Twitter developer
10
+ account recommended!
11
+
12
+ Result: the graph method returns a hash of arrays, keyed off the degree of
13
+ separation. The value for each key an array of all the connections that exist
14
+ at that level. Each connection is described by a series of Twitter IDs
15
+ that are ordered by the flow of the connection.
16
+
17
+ Example:
18
+ tootil = Tootils.new(user, pass)
19
+ tootil.graph(sarahr, brookr)
20
+ - {1=>[[11146212, 11136022]], 2=>[], 3=>[]}
21
+ tootil.graph(sarahr, whitscott)
22
+ - {1=>[],
23
+ - 2=>
24
+ - [[11146212, 11136022, 9338922],
25
+ - [11146212, 14864296, 9338922],
26
+ - [11146212, 17785160, 9338922],
27
+ - [11146212, 6602252, 9338922],
28
+ - [11146212, 11136252, 9338922]],
29
+ - 3=>[]}
30
+
31
+ tootil.graph(sarahr, pop17)
32
+ - {1=>[],
33
+ - 2=>[],
34
+ - 3=>
35
+ - [[11146212, 11136022, 9338922, 74673],
36
+ - [11146212, 11136022, 813286, 74673],
37
+ - [11146212, 11136022, 5997662, 74673],
38
+ - [11146212, 11136022, 2874, 74673],
39
+ - [11146212, 11136022, 734493, 74673],
40
+ - [11146212, 14864296, 9338922, 74673],
41
+ - ...}
42
+
43
+ Author:
44
+ Brook Riggio
45
+ http://twitter.com/brookr
46
+
47
+ History:
48
+ 2009-07-16:
49
+ Version 0.1.1: "Gemified!"
50
+ – Thanks to @jackdanger for using technicalpickles-jeweler to set up the gem
51
+ 2009-07-15:
52
+ Version 0.1.0: "Layout the API"
53
+ – Renamed project Tootils, to make space for other utilities
54
+ – Totally refactored
55
+ – Graph now shows all connections between two users
56
+ – Consistent internal API
57
+ – Renamed links_to to graph
58
+ – Better data structure for graph results
59
+ 2009-05-26:
60
+ Version 0.0.2: "We might have something here"
61
+ – Now checks the 3rd degree as intended
62
+ – Various optimizations to reduce API hits
63
+ – Refactorings!
64
+
65
+ 2009-02-20:
66
+ Version 0.0.1: "Proof of concept"
67
+ – Checks first and second degree
68
+ – Uses lots of API hits
69
+ – But keeps track of those API hits used!
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "tootils"
8
+ gem.summary = %Q{Twitter Utilities}
9
+ gem.email = "gitcommit@6brand.com"
10
+ gem.homepage = "http://github.com/JackDanger/tootils"
11
+ gem.authors = ["Jack Danger Canty"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "tootils #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,115 @@
1
+ # See README for version history and usage
2
+ #
3
+
4
+ require 'rubygems'
5
+ require 'httparty'
6
+ require 'pp'
7
+ config = YAML::load(File.read(File.join(ENV['HOME'], '.twitter')))
8
+
9
+ module Tootils
10
+ class Tools
11
+ include HTTParty
12
+ base_uri 'twitter.com'
13
+ format :json
14
+
15
+ def initialize(user, pass)
16
+ @auth = {:username => user, :password => pass}
17
+ end
18
+
19
+ def options
20
+ options = { :basic_auth => @auth }
21
+ end
22
+
23
+ def self.remaining_hits
24
+ options = { :basic_auth => @auth }
25
+ get("/account/rate_limit_status.json", options)['remaining_hits']
26
+ end
27
+
28
+ def check_limit
29
+ if self.class.remaining_hits > 1
30
+ true
31
+ else
32
+ raise 'Over API rate limit!'
33
+ exit 2
34
+ end
35
+ end
36
+
37
+
38
+ def friends(user)
39
+ friends = self.class.get("/friends/ids/#{user.to_s}.json", options)
40
+ if friends["error"]
41
+ pp friends
42
+ return []
43
+ end unless friends.class == Array
44
+ friends
45
+ end
46
+
47
+ def followers(user)
48
+ followers = self.class.get("/followers/ids/#{user.to_s}.json", options)
49
+ if followers["error"]
50
+ pp followers
51
+ return []
52
+ end unless followers.class == Array
53
+ followers
54
+ end
55
+
56
+ def info(user)
57
+ info = self.class.get("/users/show/#{user.to_s}.json", options)
58
+ if info["error"]
59
+ pp info
60
+ return {}
61
+ end
62
+ info
63
+ end
64
+
65
+ # Our first twitter tool: Graphing connections from the first user to the second.
66
+ # This will check the first 3 degrees for links, and return a hash of connections
67
+ # found in each degree.
68
+ # Once any degree has a connection in it, additional degrees are not checked.
69
+ def graph(twit1, twit2)
70
+ twit1_id = info(twit1)['id']
71
+ twit1_friends = friends(twit1)
72
+ twit2_id = info(twit2)['id']
73
+ twit2_followers = followers(twit2)
74
+ # Start assuming there are no connections
75
+ graph = { 1 => [], 2 => [], 3 => [] }
76
+
77
+ if twit2_followers.include?(twit1_id)
78
+ graph[1] = [[twit1_id, twit2_id]]
79
+ end
80
+
81
+ return graph unless graph[1].empty?
82
+
83
+ # Check second degree: Are there friends of twit1 who are followers of twit2?
84
+ # Get an array of all connections.
85
+ for friend in (twit1_friends & twit2_followers)
86
+ graph[2] << [twit1_id, friend, twit2_id]
87
+ end
88
+ return graph unless graph[2].empty?
89
+
90
+ # Check the 3rd degree: This is where we really burn through API calls.
91
+ # We need to check friends of friends, or the followers of followers,
92
+ # which ever is fewer to save API hits
93
+ if twit1_friends.length < twit2_followers.length
94
+ for friend in twit1_friends
95
+ friends_of_friend = friends(friend)
96
+ deg3 = friends_of_friend & twit2_followers
97
+ # Add a connection for each friend of a friend who is a follower of twit2
98
+ for fof in deg3
99
+ graph[3] << [twit1_id, friend, fof, twit2_id]
100
+ end
101
+ end
102
+ else
103
+ for follower in twit2_followers
104
+ followers_of_follower = followers(follower)
105
+ deg3 = twit1_friends & followers_of_follower
106
+ # Add a connection for each follower of a follower who is a friend of twit1
107
+ for fof in deg3
108
+ graph[3] << [twit1_id, fof, follower, twit2_id]
109
+ end rescue pp "Can't get followers for #{follower}: #{info(follower)}"
110
+ end
111
+ end
112
+ return graph
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'tootils'
8
+
9
+ class Test::Unit::TestCase
10
+ include Tootils
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ class TootilsTest < Test::Unit::TestCase
4
+ should "build auth hash" do
5
+ assert !Tootils::Tools.new('user', 'pass').options.empty?
6
+ end
7
+
8
+ should "find first degree connections" do
9
+ assert !Tootils::Tools.new('user', 'pass').graph('brookr', 'jackdanger')[1].empty?
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brookr-tootils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Brook Riggio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: brookr@brookr.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README
30
+ - Rakefile
31
+ - VERSION
32
+ - lib/tootils.rb
33
+ - test/test_helper.rb
34
+ - test/tootils_test.rb
35
+ has_rdoc: false
36
+ homepage: http://github.com/brookr/tootils
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.2.0
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Twitter Utilities
61
+ test_files:
62
+ - test/test_helper.rb
63
+ - test/tootils_test.rb