fake_friends 0.1.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa126944bb6f960473714414b4cb44a87ed8deef
4
- data.tar.gz: bc9568f7a519b8fd8f16585d12a60cc7953a2157
3
+ metadata.gz: 91c52fe6550cce6abc312dbfccd2743415889406
4
+ data.tar.gz: e1fda60d62b933d57fd7073f02239e0b48ad3a20
5
5
  SHA512:
6
- metadata.gz: f4647bda8cbefc8938ccbb4bcf80b644784cfb4852bd041a6894ea1ed8c3c02d1bdcad310cf8e6dd1633740d4fd0e2d606c62ee9665032518109b9cb14ec8b19
7
- data.tar.gz: 60ee89b9a857e5b7ca077cf18aee6be1f57256945e97296f81aa56e64f95cf562a5ccb8e649fbff36e59a79ce88afaefacf25507e5f37ca0350615f0280b2c7a
6
+ metadata.gz: 7fda149947ae5445946d3e0076291e85be64afd91cbca5256a28141463ae8497ccf5e6ee2acd97782547c4ff65ef18a4c61a6a7e84648b2c5835a383ddb38b81
7
+ data.tar.gz: 47cb69a59f89ab1ba33c1edc85343513efc08260d1fb520bc04a7976ce890c99f3ba330645216e6e74f4c3100d107fd3a68e31d5f4b478198a0761beb958a29d
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # FakeFriends
2
2
 
3
- A simple [ruby gem](https://rubygems.org/gems/fake_friends) to generate consistent and realistic fake user data for demoing social networking apps (e.g., user names match their avatars, fake posts are pulled from actual Twitter posts rather than lorem text, etc).
3
+ A simple [ruby gem](https://rubygems.org/gems/fake_friends) to generate consistent and realistic fake user data for demoing social networking apps (e.g., user names match their avatars, fake posts are pulled from actual Twitter posts rather than lorem text, etc), modeled on the popular [Faker](https://github.com/stympy/faker) gem.
4
+
5
+ ## Release Notes
6
+ 0.1.6 December 2, 2013 (152 KB) Adds tests in RSpec
7
+ 0.1.5 November 26, 2013 (148 KB) Inital release
4
8
 
5
9
  ## Installation
6
10
 
@@ -24,7 +28,7 @@ Or install it yourself as: `$ gem install fake_friends`
24
28
  * `#name`
25
29
  * `#description`
26
30
  * `#avatar_url(size)`
27
- `size`: requested size of image. Available in 128, 64, 48, and 24 px.
31
+ `size`: requested size of image. Available in 128, 73, 48, and 24 px.
28
32
  Returns a url to an image in the closest available size.
29
33
  * `#url`
30
34
  * `#posts`
@@ -42,7 +46,7 @@ to return an array of 5 `FakeFriend` objects.
42
46
  returns the fifth user in the library and assigns it to `user`.
43
47
 
44
48
  `user.avatar_url(size)` pulls an avatar from uiFaces.com, where Twitter users have contributed their profile photos.
45
- The available sizes (in pixels) are 128, 64, 48, and 24. The method will choose the image closest in size
49
+ The available sizes (in pixels) are 128, 73, 48, and 24. The method will choose the image closest in size
46
50
  to the requested `size`.
47
51
 
48
52
  `user.url` returns a hash with an `:expanded` url (e.g. `http://www.google.com`) and a `:display` url (e.g. `google.com`).
@@ -57,14 +61,12 @@ The library currently holds 101 users with associated status updates. Associated
57
61
  ## Source
58
62
  Images come from user contributions on uiFaces.com.
59
63
  Posts are non-retweet tweets from the associated twitter profiles (all public).
60
-
61
64
  Many thanks to these users for their contributions.
62
65
 
63
66
 
64
67
  ## Future work
65
68
 
66
- A hundred users should be enough for most demoing needs, but a method to fetch new user
67
- data right from the FakeFriends class may be added in future.
69
+ A hundred users should be enough for most demoing needs, but a class method to fetch fresh data from the Twitter API may be added in future.
68
70
 
69
71
  ## Contributing
70
72
 
@@ -0,0 +1,142 @@
1
+ require 'twitter'
2
+ require 'yaml'
3
+
4
+ class TweetFetcher
5
+ attr_reader :twitter_client, :number_of_users, :max_posts_per_user,
6
+ :avail_users, :output_file_rel_path, :fake_friends
7
+
8
+ def initialize(opt={ users: 100, max_posts_per_user: 50,
9
+ user_list: 'usernames.yml',
10
+ output_file: '../lib/fake_friends/users.yml' } )
11
+
12
+ @number_of_users = opt[:users]
13
+ @max_posts_per_user = opt[:max_posts_per_user]
14
+ @output_file_rel_path = opt[:output_file]
15
+ @avail_users = YAML.load_file(opt[:user_list])
16
+
17
+ @fake_friends = {} # users to be stored as FakeFriend objects
18
+ @twitter_client = initialize_twitter_api_client
19
+ end
20
+
21
+ # ---
22
+ # prompts for twitter api credentials and returns a client
23
+ # ---
24
+ def initialize_twitter_api_client
25
+ puts 'Enter your Twitter API credentials (get some @ dev.twitter.com).'
26
+
27
+ Twitter::REST::Client.new do |config|
28
+ print 'consumer key: '
29
+ config.consumer_key = gets.chomp
30
+ print 'consumer secret: '
31
+ config.consumer_secret = gets.chomp
32
+ print 'oauth token: '
33
+ config.oauth_token = gets.chomp
34
+ print 'oauth token secret: '
35
+ config.oauth_token_secret = gets.chomp
36
+ end
37
+ end
38
+
39
+ # ---
40
+ # returns array of non-retweet tweets, each as a hash containing
41
+ # the tweet's with :time of creation and :text
42
+ # ---
43
+ def posts(twitter_username, count)
44
+ options = { count: count, exclude_replies: true }
45
+ twitter_client.user_timeline(twitter_username, options)
46
+ .delete_if{ |t| t.retweeted || (t.text =~ /^RT\s@/) } # remove retweets
47
+ .map { |tweet| { time: tweet.created_at, text: tweet.text } }
48
+ end
49
+
50
+ # ---
51
+ # Fetches users and their tweets, iteratively saves them to file as YAML
52
+ # ---
53
+ def fetch_users_and_their_tweets
54
+ users = avail_users.sample( number_of_users )
55
+
56
+ puts ""
57
+ users.each_with_index do |username, user_num|
58
+ fake_friends[username] = create_user_hash_for username
59
+ update_output_file_with username, user_num
60
+ end
61
+
62
+ puts "Finished fetching users and tweets"
63
+ end
64
+
65
+ # ---
66
+ # For a given Twitter user, returns a hash with the following strings:
67
+ # name, location, description, url[:expanded], url[:display], image url
68
+ # and an array containing the desired number of tweets
69
+ # ---
70
+ def create_user_hash_for(u)
71
+ ## Ensure user exists and tweets are public
72
+ if twitter_client.user?(u)
73
+ unless twitter_client.user(u).protected?
74
+
75
+ user = twitter_client.user(u) # load user
76
+ posts = posts(u, max_posts_per_user) # fetch 100 posts
77
+
78
+ begin # get expanded url if it exists
79
+ expanded_url = user.attrs[:entities][:url][:urls].first[:expanded_url]
80
+ rescue
81
+ expanded_url = nil
82
+ end
83
+
84
+ begin # get display url if it exists
85
+ display_url = user.attrs[:entities][:url][:urls].first[:display_url]
86
+ rescue
87
+ display_url = nil
88
+ end
89
+
90
+ {
91
+ name: user.name, location: user.location,
92
+ description: user.description,
93
+ url: { expanded: expanded_url, display: display_url },
94
+ image: user.profile_image_url, posts: posts
95
+ }
96
+ end
97
+ end
98
+ end
99
+
100
+ # ---
101
+ # Updates the ouput file with YAML for the array of
102
+ # users in its current state
103
+ # ---
104
+ def update_output_file_with(user, number)
105
+ File.open(output_file_rel_path, 'w') do |f|
106
+ f.write(fake_friends.to_yaml)
107
+ end
108
+
109
+ puts "fetched and saved user #{number+1}: #{user}"
110
+
111
+ if number_of_users <= 75
112
+ # small number fetched in batches, rest every 15th user
113
+ countdown_minutes(15) if (number+1 % 15 == 0)
114
+ else
115
+ # large number fetched at slow, steady pace
116
+ countdown_minutes(1)
117
+ end
118
+ end
119
+
120
+ # ---
121
+ # Displays a countdown timer on the command line
122
+ # for the given number of minutes
123
+ # ---
124
+ def countdown_minutes(min)
125
+ puts "taking a #{min}-minute power nap to stay within Twitter API rate limits..."
126
+
127
+ clock =<<-SHELL
128
+ MIN=#{min}
129
+ for i in $(seq $(($MIN*60)) -1 1);
130
+ do
131
+ printf "\r%02d:%02d:%02d" $((i/3600)) $(( (i/60)%60)) $((i%60));
132
+ sleep 1;
133
+ done
134
+ SHELL
135
+
136
+ system(clock)
137
+ puts ""
138
+ end
139
+ end
140
+
141
+ twitter_api = TweetFetcher.new
142
+ twitter_api.fetch_users_and_their_tweets
data/fake_friends.gemspec CHANGED
@@ -20,11 +20,11 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  # TO BE ADDED
23
- # spec.add_runtime_dependency "twitter", "~> 4.8.1"
23
+ # spec.add_runtime_dependency "twitter", "~> 5.2.0"
24
24
 
25
- spec.add_development_dependency "twitter", "~> 4.8.1"
26
- spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "twitter", "~> 5.2.0"
26
+ spec.add_development_dependency "rspec", "~> 2.14.1"
27
27
 
28
- spec.add_development_dependency "bundler", "~> 1.3"
29
- spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "bundler", "~> 1.3.5"
29
+ spec.add_development_dependency "rake", "~> 10.1.0"
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module FalseFriends
2
- VERSION = "0.1.6"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/fake_friends.rb CHANGED
@@ -61,7 +61,7 @@ module FakeFriends
61
61
  # avatar_url(size)
62
62
  # returns the user's uiFaces url in the closest available size
63
63
  def avatar_url(size)
64
- valid_sizes = [128, 64, 48, 24]
64
+ valid_sizes = [128, 73, 48, 24]
65
65
  size = valid_sizes.min { |a,b| (size-a).abs <=> (size-b).abs }
66
66
  "https://s3.amazonaws.com/uifaces/faces/twitter/#{username}/#{size}.jpg"
67
67
  end
@@ -3,11 +3,7 @@ include FakeFriends
3
3
 
4
4
  describe FakeFriend do
5
5
 
6
- # it { should respond_to(:gather).with(1).argument }
7
- # it { should respond_to(:find_by).with(1).argument }
8
-
9
6
  describe "::gather" do
10
-
11
7
  context "with valid input" do
12
8
  let(:users){ FakeFriend.gather(5) }
13
9
 
@@ -16,12 +12,12 @@ describe FakeFriend do
16
12
  expect(users).to be_composed_of FakeFriend
17
13
  end
18
14
 
19
- it "returns the requested number objects" do
15
+ it "returns the requested number of FakeFriends" do
20
16
  expect(users.count).to be 5
21
17
  end
22
18
 
23
19
  it "does not return duplicates" do
24
- expect(users.uniq.count).to be users.count
20
+ expect(users.count).to be users.map(&:username).uniq.count
25
21
  end
26
22
  end
27
23
 
@@ -35,6 +31,7 @@ describe FakeFriend do
35
31
  end
36
32
  end
37
33
 
34
+
38
35
  describe "::find_by" do
39
36
  context "with valid input (by id)" do
40
37
  let(:user){ FakeFriend.find_by(id: 1) }
@@ -72,4 +69,4 @@ describe FakeFriend do
72
69
  end
73
70
  end
74
71
  end
75
- end
72
+ end
data/spec/spec_helper.rb CHANGED
@@ -11,10 +11,10 @@ end
11
11
 
12
12
  RSpec::Matchers.define :be_composed_of do |expected_type|
13
13
  match do |actual|
14
- actual.all?{|u| u.is_a? expected_type} == true
14
+ actual.all?{|u| u.is_a? expected_type}
15
15
  end
16
16
 
17
17
  failure_message_for_should do |actual|
18
- "expected that #{actual.class} would be composed of #{expected_type}s"
18
+ "expected #{actual.class} to be composed of #{expected_type}s"
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fake_friends
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Romer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-02 00:00:00.000000000 Z
11
+ date: 2013-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: twitter
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 4.8.1
19
+ version: 5.2.0
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 4.8.1
26
+ version: 5.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 2.14.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 2.14.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '1.3'
47
+ version: 1.3.5
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '1.3'
54
+ version: 1.3.5
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 10.1.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 10.1.0
69
69
  description: A simple fake user generator
70
70
  email:
71
71
  - jake@jakeromer.com
@@ -79,7 +79,7 @@ files:
79
79
  - LICENSE.txt
80
80
  - README.md
81
81
  - Rakefile
82
- - dev/pull_from_twitter.rb
82
+ - dev/fetch_from_twitter.rb
83
83
  - dev/usernames.yml
84
84
  - fake_friends.gemspec
85
85
  - lib/fake_friends.rb
@@ -1,116 +0,0 @@
1
- require 'twitter'
2
- require 'yaml'
3
-
4
- # TODO: Method to pull a user from Twitter directly into FakeFriend.find_by(username)
5
-
6
- puts 'Enter your Twitter API credentials (get some @ dev.twitter.com).'
7
- print 'consumer key: '
8
- twitter_cons_key = gets.chomp
9
- print 'consumer secret: '
10
- twitter_cons_sec = gets.chomp
11
- print 'oauth token: '
12
- twitter_auth_tok = gets.chomp
13
- print 'oauth token secret: '
14
- twitter_auth_sec = gets.chomp
15
-
16
- Twitter.configure do |config|
17
- config.consumer_key = twitter_cons_key
18
- config.consumer_secret = twitter_cons_sec
19
- config.oauth_token = twitter_auth_tok
20
- config.oauth_token_secret = twitter_auth_sec
21
- end
22
-
23
- # returns array of non-retweets with time and text
24
- def posts(twitter_username, count)
25
- options = { count: count, exclude_replies: true }
26
-
27
- Twitter.user_timeline(twitter_username, options)
28
- .delete_if{ |t| t.retweeted || (t.text =~ /^RT\s@/) } # remove retweets
29
- .map do |tweet|
30
- { time: tweet.created_at, text: tweet.text }
31
- end
32
- end
33
-
34
-
35
- number_of_users_to_pull = 100
36
- number_of_posts_to_pull = 50
37
-
38
- usernames = 'usernames.yml'
39
- users = File.open(usernames, 'r'){|file| YAML.load(file, usernames) }
40
- users = users.sample(number_of_users_to_pull)
41
- friends = {}
42
-
43
- users.each_with_index do |u, i|
44
- ## Ensure user exists and tweets are public
45
- if Twitter.user?(u)
46
- unless Twitter.user(u).protected?
47
-
48
- # load user
49
- user = Twitter.user(u)
50
-
51
- # pull 100 posts
52
- posts = posts(u, number_of_posts_to_pull)
53
-
54
- # get urls if they exist
55
- begin
56
- expanded_url = user.attrs[:entities][:url][:urls].first[:expanded_url]
57
- rescue
58
- expanded_url = nil
59
- end
60
-
61
- begin
62
- display_url = user.attrs[:entities][:url][:urls].first[:display_url]
63
- rescue
64
- display_url = nil
65
- end
66
-
67
- # populate friends hash
68
- friends[u] = {
69
- name: user.name,
70
- location: user.location,
71
- description: user.description,
72
- url: { expanded: expanded_url, display: display_url },
73
- image: user.profile_image_url,
74
- posts: posts
75
- }
76
- end
77
- end
78
-
79
- # write to file as yaml
80
- users_lib = '../lib/fake_friends/users.yml'
81
- File.open(users_lib, 'w'){|f| f.write(friends.to_yaml) }
82
- puts "loaded #{i+1}: #{u}"
83
-
84
- if number_of_users_to_pull <= 75
85
- # Twitter API limit: 15 per 15 minutes
86
- if (i+1 % 15 == 0)
87
- puts "taking a 15-minute power nap to stay within Twitter API rate limits..."
88
-
89
- clock =<<-SHELL
90
- MIN=15
91
- for i in $(seq $(($MIN*60)) -1 1);
92
- do
93
- printf "\r%02d:%02d:%02d" $((i/3600)) $(( (i/60)%60)) $((i%60));
94
- sleep 1;
95
- done
96
- SHELL
97
-
98
- system(clock)
99
- puts ""
100
- end
101
- else
102
- puts "taking a 1-minute power nap to stay within Twitter API rate limits..."
103
-
104
- clock =<<-SHELL
105
- MIN=1
106
- for i in $(seq $(($MIN*60)) -1 1);
107
- do
108
- printf "\r%02d:%02d:%02d" $((i/3600)) $(( (i/60)%60)) $((i%60));
109
- sleep 1;
110
- done
111
- SHELL
112
-
113
- system(clock)
114
- puts ""
115
- end
116
- end