social_profile 0.2.1 → 0.2.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.
- checksums.yaml +4 -4
 - data/lib/social_profile/people/facebook.rb +23 -4
 - data/lib/social_profile/people/twitter.rb +50 -0
 - data/lib/social_profile/people/vkontakte.rb +186 -0
 - data/lib/social_profile/providers/odnoklassniki.rb +74 -0
 - data/lib/social_profile/version.rb +1 -1
 - data/lib/social_profile.rb +2 -0
 - data/social_profile.gemspec +3 -3
 - data/spec/mock_json/facebook/followers_5_0.json +34 -0
 - data/spec/mock_json/facebook/followers_5_10.json +35 -0
 - data/spec/mock_json/facebook/followers_5_15.json +26 -0
 - data/spec/mock_json/twitter/auth.json +1 -1
 - data/spec/mock_json/twitter/last_posts.json +4326 -0
 - data/spec/mock_json/vkontakte/comments_photos.json +707 -0
 - data/spec/mock_json/vkontakte/comments_post_655.json +42 -0
 - data/spec/mock_json/vkontakte/followers.json +187 -0
 - data/spec/mock_json/vkontakte/followers_20.json +127 -0
 - data/spec/mock_json/vkontakte/followers_20_2.json +67 -0
 - data/spec/mock_json/vkontakte/friends.json +1728 -0
 - data/spec/mock_json/vkontakte/last_posts.json +4279 -0
 - data/spec/mock_json/vkontakte/last_posts_2.json +2736 -0
 - data/spec/mock_json/vkontakte/last_posts_3.json +533 -0
 - data/spec/mock_json/vkontakte/likes_photo_290498375.json +24 -0
 - data/spec/mock_json/vkontakte/likes_post_655.json +14 -0
 - data/spec/mock_json/vkontakte/shares_post_3675.json +1373 -0
 - data/spec/people/facebook_spec.rb +25 -0
 - data/spec/people/twitter_spec.rb +21 -1
 - data/spec/people/vkontakte_spec.rb +95 -3
 - data/spec/spec_helper.rb +1 -1
 - metadata +47 -14
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9ff2a46cb1b8edb78c457fb204d2efac1035b642
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: e843f72028951caa385e61478566a2eda9ba31ae
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 889b1b58ae675301c69a86282700b552cae13d99f441bacf9b2d74c579e06110942fddaadd687a1f075420b9fc0436d5d953628be875fe7c2315db83245f00dc
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 9108fb8234539617a98bf26c94247515a10b32b7e804b697e365e5d6d45fd7048f944c990086815ebabec2ffd90e1c6c72b718ec0ea4b2f2ba354f0b4cbedc6f
         
     | 
| 
         @@ -70,11 +70,16 @@ module SocialProfile 
     | 
|
| 
       70 
70 
     | 
    
         
             
                  def last_post_by_days(days, options={})
         
     | 
| 
       71 
71 
     | 
    
         
             
                    date = (options[:date_end] || Time.now) - days.days
         
     | 
| 
       72 
72 
     | 
    
         
             
                    limit = options[:limit] || 100
         
     | 
| 
      
 73 
     | 
    
         
            +
                    max_iteration = options[:max_iteration] || 100
         
     | 
| 
      
 74 
     | 
    
         
            +
                    iteration = 0
         
     | 
| 
       73 
75 
     | 
    
         | 
| 
       74 
76 
     | 
    
         
             
                    posts = collection = last_posts(limit, options)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    return [] if posts.blank?
         
     | 
| 
      
 78 
     | 
    
         
            +
                    
         
     | 
| 
       75 
79 
     | 
    
         
             
                    last_created_time = posts.last.created_time
         
     | 
| 
       76 
80 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                    while last_created_time > date
         
     | 
| 
      
 81 
     | 
    
         
            +
                    while last_created_time > date && !last_created_time.blank? && iteration < max_iteration
         
     | 
| 
      
 82 
     | 
    
         
            +
                      iteration += 1
         
     | 
| 
       78 
83 
     | 
    
         
             
                      collection = collection.next
         
     | 
| 
       79 
84 
     | 
    
         
             
                      posts += collection
         
     | 
| 
       80 
85 
     | 
    
         
             
                      last_created_time = posts.last.created_time
         
     | 
| 
         @@ -86,15 +91,29 @@ module SocialProfile 
     | 
|
| 
       86 
91 
     | 
    
         
             
                  # Get all friends list
         
     | 
| 
       87 
92 
     | 
    
         
             
                  #
         
     | 
| 
       88 
93 
     | 
    
         
             
                  def friends(options={})
         
     | 
| 
       89 
     | 
    
         
            -
                    limit = options[:limit] ||  
     | 
| 
      
 94 
     | 
    
         
            +
                    limit = options[:limit] || 5000
         
     | 
| 
       90 
95 
     | 
    
         
             
                    user.friends(:limit => limit)
         
     | 
| 
       91 
96 
     | 
    
         
             
                  end
         
     | 
| 
       92 
97 
     | 
    
         | 
| 
       93 
98 
     | 
    
         
             
                  # Get all followers list
         
     | 
| 
       94 
99 
     | 
    
         
             
                  #
         
     | 
| 
       95 
100 
     | 
    
         
             
                  def followers(options={})
         
     | 
| 
       96 
     | 
    
         
            -
                    limit = options[:limit] ||  
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
      
 101 
     | 
    
         
            +
                    limit = options[:limit] || 5000
         
     | 
| 
      
 102 
     | 
    
         
            +
                    fetch_all = options[:fetch_all] || false
         
     | 
| 
      
 103 
     | 
    
         
            +
                    iteration = 0
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    _followers = collection = user.subscribers(:limit => limit)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    max_iteration = _followers.total_count / limit + 1
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    if fetch_all
         
     | 
| 
      
 109 
     | 
    
         
            +
                      while iteration < max_iteration
         
     | 
| 
      
 110 
     | 
    
         
            +
                        iteration += 1
         
     | 
| 
      
 111 
     | 
    
         
            +
                        collection = collection.next
         
     | 
| 
      
 112 
     | 
    
         
            +
                        _followers += collection
         
     | 
| 
      
 113 
     | 
    
         
            +
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                    _followers
         
     | 
| 
       98 
117 
     | 
    
         
             
                  end
         
     | 
| 
       99 
118 
     | 
    
         | 
| 
       100 
119 
     | 
    
         
             
                  protected
         
     | 
| 
         @@ -3,6 +3,7 @@ require "twitter" 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module SocialProfile
         
     | 
| 
       4 
4 
     | 
    
         
             
              module People
         
     | 
| 
       5 
5 
     | 
    
         
             
                class Twitter < Person
         
     | 
| 
      
 6 
     | 
    
         
            +
                  MAX_ATTEMPTS = 3
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
                  # Get friends count
         
     | 
| 
       8 
9 
     | 
    
         
             
                  def friends_count
         
     | 
| 
         @@ -12,6 +13,55 @@ module SocialProfile 
     | 
|
| 
       12 
13 
     | 
    
         
             
                  def fetch_friends_count
         
     | 
| 
       13 
14 
     | 
    
         
             
                    client.user.followers_count
         
     | 
| 
       14 
15 
     | 
    
         
             
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # Get last limited tweets from user_timeline, max 200 by query
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def last_posts(uid, options = {})
         
     | 
| 
      
 20 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 21 
     | 
    
         
            +
                      :count => 200, 
         
     | 
| 
      
 22 
     | 
    
         
            +
                      :exclude_replies => true, 
         
     | 
| 
      
 23 
     | 
    
         
            +
                      :trim_user => true,
         
     | 
| 
      
 24 
     | 
    
         
            +
                      :include_rts => false
         
     | 
| 
      
 25 
     | 
    
         
            +
                    }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    with_atterms do 
         
     | 
| 
      
 30 
     | 
    
         
            +
                      client.user_timeline(uid, params)  
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end     
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def get_all_tweets(uid, options = {})
         
     | 
| 
      
 35 
     | 
    
         
            +
                    collect_with_max_id do |max_id|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      options[:max_id] = max_id unless max_id.nil?
         
     | 
| 
      
 37 
     | 
    
         
            +
                      last_posts(uid, options)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def collect_with_max_id(collection=[], max_id=nil, &block)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    response = yield(max_id)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    collection += response
         
     | 
| 
      
 44 
     | 
    
         
            +
                    response.empty? ? collection.flatten : collect_with_max_id(collection, response.last.id - 1, &block)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def with_atterms
         
     | 
| 
      
 48 
     | 
    
         
            +
                    num_attempts = 0
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 51 
     | 
    
         
            +
                      num_attempts += 1
         
     | 
| 
      
 52 
     | 
    
         
            +
                      yield if block_given?
         
     | 
| 
      
 53 
     | 
    
         
            +
                    rescue ::Twitter::Error::TooManyRequests => error
         
     | 
| 
      
 54 
     | 
    
         
            +
                      if num_attempts <= MAX_ATTEMPTS
         
     | 
| 
      
 55 
     | 
    
         
            +
                        # NOTE: Your process could go to sleep for up to 15 minutes but if you
         
     | 
| 
      
 56 
     | 
    
         
            +
                        # retry any sooner, it will almost certainly fail with the same exception.
         
     | 
| 
      
 57 
     | 
    
         
            +
                        sleep error.rate_limit.reset_in
         
     | 
| 
      
 58 
     | 
    
         
            +
                        retry
         
     | 
| 
      
 59 
     | 
    
         
            +
                      else
         
     | 
| 
      
 60 
     | 
    
         
            +
                        raise
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                        
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
       15 
65 
     | 
    
         | 
| 
       16 
66 
     | 
    
         
             
                  protected
         
     | 
| 
       17 
67 
     | 
    
         | 
| 
         @@ -33,12 +33,198 @@ module SocialProfile 
     | 
|
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
                    counters["friends"].to_i + counters["followers"].to_i
         
     | 
| 
       35 
35 
     | 
    
         
             
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  # Get last limited posts from user_timeline, max 100 by query
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #
         
     | 
| 
      
 39 
     | 
    
         
            +
                  def last_posts(options = {})
         
     | 
| 
      
 40 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 41 
     | 
    
         
            +
                      :owner_id => user.identifier,
         
     | 
| 
      
 42 
     | 
    
         
            +
                      :count => 100, 
         
     | 
| 
      
 43 
     | 
    
         
            +
                      :filter => "owner", 
         
     | 
| 
      
 44 
     | 
    
         
            +
                      :offset => 0
         
     | 
| 
      
 45 
     | 
    
         
            +
                    }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    fetch_all_method_items_with_days("wall.get", params)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  # Get last posts by N days from user_timeline
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #
         
     | 
| 
      
 54 
     | 
    
         
            +
                  def last_post_by_days(days, options = {})
         
     | 
| 
      
 55 
     | 
    
         
            +
                    options = { :days => days }.merge(options)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    last_posts(options)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end      
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  # Get object likes (post, comment, photo, audio, video, note, photo_comment, video_comment, topic_comment, sitepage)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #
         
     | 
| 
      
 62 
     | 
    
         
            +
                  def object_likes(uid, options = {})
         
     | 
| 
      
 63 
     | 
    
         
            +
                    fetch_all = options.delete(:fetch_all)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 66 
     | 
    
         
            +
                      :owner_id => user.identifier,
         
     | 
| 
      
 67 
     | 
    
         
            +
                      :count => 1000, 
         
     | 
| 
      
 68 
     | 
    
         
            +
                      :type => "post", 
         
     | 
| 
      
 69 
     | 
    
         
            +
                      :item_id => uid,
         
     | 
| 
      
 70 
     | 
    
         
            +
                      :offset => 0
         
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
      
 72 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    
         
     | 
| 
      
 74 
     | 
    
         
            +
                    if fetch_all
         
     | 
| 
      
 75 
     | 
    
         
            +
                      return fetch_all_method_items("likes.getList", params)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                    user.likes.getList(params)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  # Get post comments
         
     | 
| 
      
 83 
     | 
    
         
            +
                  #
         
     | 
| 
      
 84 
     | 
    
         
            +
                  def post_comments(uid, options = {})
         
     | 
| 
      
 85 
     | 
    
         
            +
                    fetch_all = options.delete(:fetch_all)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 88 
     | 
    
         
            +
                      :owner_id => user.identifier,
         
     | 
| 
      
 89 
     | 
    
         
            +
                      :count => 100, 
         
     | 
| 
      
 90 
     | 
    
         
            +
                      :preview_length => 0, 
         
     | 
| 
      
 91 
     | 
    
         
            +
                      :need_likes => 1,
         
     | 
| 
      
 92 
     | 
    
         
            +
                      :post_id => uid,
         
     | 
| 
      
 93 
     | 
    
         
            +
                      :offset => 0
         
     | 
| 
      
 94 
     | 
    
         
            +
                    }
         
     | 
| 
      
 95 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                    if fetch_all
         
     | 
| 
      
 98 
     | 
    
         
            +
                      return fetch_all_method_items("wall.getComments", params)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                    user.wall.getComments(params)  
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  # Get post shares
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #
         
     | 
| 
      
 106 
     | 
    
         
            +
                  def post_shares(uid, options = {})
         
     | 
| 
      
 107 
     | 
    
         
            +
                    fetch_all = options.delete(:fetch_all)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 110 
     | 
    
         
            +
                      :owner_id => user.identifier,
         
     | 
| 
      
 111 
     | 
    
         
            +
                      :count => 1000, 
         
     | 
| 
      
 112 
     | 
    
         
            +
                      :post_id => uid,
         
     | 
| 
      
 113 
     | 
    
         
            +
                      :offset => 0
         
     | 
| 
      
 114 
     | 
    
         
            +
                    }
         
     | 
| 
      
 115 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    if fetch_all
         
     | 
| 
      
 118 
     | 
    
         
            +
                      return fetch_all_method_items("wall.getReposts", params)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                    user.wall.getReposts(params)  
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  # Get all photos comments
         
     | 
| 
      
 125 
     | 
    
         
            +
                  #
         
     | 
| 
      
 126 
     | 
    
         
            +
                  def photos_comments(options = {})
         
     | 
| 
      
 127 
     | 
    
         
            +
                    params = { 
         
     | 
| 
      
 128 
     | 
    
         
            +
                      :owner_id => user.identifier,
         
     | 
| 
      
 129 
     | 
    
         
            +
                      :count => 100, 
         
     | 
| 
      
 130 
     | 
    
         
            +
                      :need_likes => 1,
         
     | 
| 
      
 131 
     | 
    
         
            +
                      :offset => 0
         
     | 
| 
      
 132 
     | 
    
         
            +
                    }
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    params.merge!(options)
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    fetch_all_method_items_with_days("photos.getAllComments", params)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  # Get all photos comments by days
         
     | 
| 
      
 140 
     | 
    
         
            +
                  #
         
     | 
| 
      
 141 
     | 
    
         
            +
                  def photos_comments_by_days(days, options = {})
         
     | 
| 
      
 142 
     | 
    
         
            +
                    options = { :days => days }.merge(options)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                    photos_comments(options)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  # Get all friends list
         
     | 
| 
      
 148 
     | 
    
         
            +
                  #
         
     | 
| 
      
 149 
     | 
    
         
            +
                  def friends(options={})
         
     | 
| 
      
 150 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 151 
     | 
    
         
            +
                      :count => 5000,
         
     | 
| 
      
 152 
     | 
    
         
            +
                      :offset => 0,
         
     | 
| 
      
 153 
     | 
    
         
            +
                      :fields => "domain"
         
     | 
| 
      
 154 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                    fetch_all_method_items(:fetch_friends, options)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  # Get all followers list
         
     | 
| 
      
 160 
     | 
    
         
            +
                  #
         
     | 
| 
      
 161 
     | 
    
         
            +
                  def followers(options={})
         
     | 
| 
      
 162 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 163 
     | 
    
         
            +
                      :count => 1000,
         
     | 
| 
      
 164 
     | 
    
         
            +
                      :offset => 0,
         
     | 
| 
      
 165 
     | 
    
         
            +
                      :fields => "screen_name"
         
     | 
| 
      
 166 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                    fetch_all_method_items(:fetch_followers, options)
         
     | 
| 
      
 169 
     | 
    
         
            +
                  end
         
     | 
| 
       36 
170 
     | 
    
         | 
| 
       37 
171 
     | 
    
         
             
                  protected
         
     | 
| 
       38 
172 
     | 
    
         | 
| 
       39 
173 
     | 
    
         
             
                    def user
         
     | 
| 
       40 
174 
     | 
    
         
             
                      @user ||= ::Vkontakte::App::User.new(uid, :access_token => access_token)
         
     | 
| 
       41 
175 
     | 
    
         
             
                    end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                    def fetch_all_method_items(name, options)
         
     | 
| 
      
 178 
     | 
    
         
            +
                      methods = name.to_s.split(".")
         
     | 
| 
      
 179 
     | 
    
         
            +
                      response = methods.size == 2 ? user.send(methods[0]).send(methods[1], options) : user.send(name, options)
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                      _items = response["items"]
         
     | 
| 
      
 182 
     | 
    
         
            +
                      return [] if _items.blank?
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                      iteration = (response["count"].to_i / _items.size.to_f).ceil
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                      iteration.times do |index|
         
     | 
| 
      
 187 
     | 
    
         
            +
                        next if index == 0
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                        options[:offset] += options[:count]
         
     | 
| 
      
 190 
     | 
    
         
            +
                        _items += (methods.size == 2 ? user.send(methods[0]).send(methods[1], options) : user.send(name, options))["items"]
         
     | 
| 
      
 191 
     | 
    
         
            +
                      end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                      _items
         
     | 
| 
      
 194 
     | 
    
         
            +
                    end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                    def fetch_all_method_items_with_days(name, options)
         
     | 
| 
      
 197 
     | 
    
         
            +
                      days = options.delete(:days)
         
     | 
| 
      
 198 
     | 
    
         
            +
                      date_end = options.delete(:date_end)
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                      methods = name.to_s.split(".")
         
     | 
| 
      
 201 
     | 
    
         
            +
                      response = methods.size == 2 ? user.send(methods[0]).send(methods[1], options) : user.send(name, options)
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                      return [] if response.blank? || !response.is_a?(Hash)
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                      _items = response["items"]
         
     | 
| 
      
 206 
     | 
    
         
            +
                      return [] if _items.blank?
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                      if days
         
     | 
| 
      
 209 
     | 
    
         
            +
                        date = (date_end || Time.now) - days.days
         
     | 
| 
      
 210 
     | 
    
         
            +
                        iteration = (response["count"].to_i / _items.size.to_f).ceil
         
     | 
| 
      
 211 
     | 
    
         
            +
                        last_date = _items.last ? Time.at(_items.last["date"].to_i).to_datetime : nil
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                        iteration.times do |index|
         
     | 
| 
      
 214 
     | 
    
         
            +
                          next if index == 0
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                          options[:offset] += options[:count]
         
     | 
| 
      
 217 
     | 
    
         
            +
                          _items += (methods.size == 2 ? user.send(methods[0]).send(methods[1], options) : user.send(name, options))["items"]
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                          last_date = _items.last ? Time.at(_items.last["date"].to_i).to_datetime : nil
         
     | 
| 
      
 220 
     | 
    
         
            +
                          break if last_date.blank? || last_date < date
         
     | 
| 
      
 221 
     | 
    
         
            +
                        end if !last_date.blank? && last_date > date
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                        return _items.select { |item| Time.at(item["date"].to_i).to_datetime > date }
         
     | 
| 
      
 224 
     | 
    
         
            +
                      end
         
     | 
| 
      
 225 
     | 
    
         
            +
                      
         
     | 
| 
      
 226 
     | 
    
         
            +
                      _items
         
     | 
| 
      
 227 
     | 
    
         
            +
                    end
         
     | 
| 
       42 
228 
     | 
    
         
             
                end
         
     | 
| 
       43 
229 
     | 
    
         | 
| 
       44 
230 
     | 
    
         
             
                class Album
         
     | 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SocialProfile
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Providers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Odnoklassniki < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def picture_url
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @picture_url ||= begin
         
     | 
| 
      
 9 
     | 
    
         
            +
                      url = info('image').gsub("photoType=4", "photoType=3")
         
     | 
| 
      
 10 
     | 
    
         
            +
                      check_url(url)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def profile_url
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @profile_url ||= begin
         
     | 
| 
      
 16 
     | 
    
         
            +
                      urls = info('urls')
         
     | 
| 
      
 17 
     | 
    
         
            +
                      urls.nil? ? nil : urls['Odnoklassniki']
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # 0 - unknown
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # 1 - female
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # 2 - male
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # Возвращаемые значения: 1 - женский, 2 - мужской, 0 - без указания пола. 
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def gender
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @gender ||= case extra('raw_info')['gender']
         
     | 
| 
      
 27 
     | 
    
         
            +
                      when 'male' then 2
         
     | 
| 
      
 28 
     | 
    
         
            +
                      when 'female' then 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                      else 0
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def birthday
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @birthday ||= begin
         
     | 
| 
      
 35 
     | 
    
         
            +
                      Date.strptime(extra('raw_info')['birthday'],'%m/%d/%Y')
         
     | 
| 
      
 36 
     | 
    
         
            +
                    rescue Exception => e
         
     | 
| 
      
 37 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def city_name
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @city_name ||= begin
         
     | 
| 
      
 43 
     | 
    
         
            +
                      location('city')
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def location?
         
     | 
| 
      
 48 
     | 
    
         
            +
                    raw_info? && extra('raw_info')['location'] && extra('raw_info')['location'].is_a?(Hash)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  def location(key)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    if location? && Utils.exists?(extra('raw_info')['location'][key])
         
     | 
| 
      
 53 
     | 
    
         
            +
                      extra('raw_info')['location'][key]
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  
         
     | 
| 
      
 57 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 58 
     | 
    
         
            +
                  
         
     | 
| 
      
 59 
     | 
    
         
            +
                    def check_url(url)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      response = Utils.head(url, :follow_redirects => false)
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                      if response.code == 302 && response.headers['location']
         
     | 
| 
      
 63 
     | 
    
         
            +
                        [response.headers['location']].flatten.first
         
     | 
| 
      
 64 
     | 
    
         
            +
                      else
         
     | 
| 
      
 65 
     | 
    
         
            +
                        url
         
     | 
| 
      
 66 
     | 
    
         
            +
                      end
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  
         
     | 
| 
      
 69 
     | 
    
         
            +
                    def raw_info?
         
     | 
| 
      
 70 
     | 
    
         
            +
                      extra('raw_info') && extra('raw_info').is_a?(Hash)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/social_profile.rb
    CHANGED
    
    | 
         @@ -11,6 +11,7 @@ module SocialProfile 
     | 
|
| 
       11 
11 
     | 
    
         
             
                autoload :Vkontakte, "social_profile/providers/vkontakte"
         
     | 
| 
       12 
12 
     | 
    
         
             
                autoload :Twitter, "social_profile/providers/twitter"
         
     | 
| 
       13 
13 
     | 
    
         
             
                autoload :Instagram, "social_profile/providers/instagram"
         
     | 
| 
      
 14 
     | 
    
         
            +
                autoload :Odnoklassniki, "social_profile/providers/odnoklassniki"
         
     | 
| 
       14 
15 
     | 
    
         
             
              end
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
              module People
         
     | 
| 
         @@ -27,6 +28,7 @@ module SocialProfile 
     | 
|
| 
       27 
28 
     | 
    
         
             
                  when "vkontakte" then Providers::Vkontakte
         
     | 
| 
       28 
29 
     | 
    
         
             
                  when "twitter" then Providers::Twitter
         
     | 
| 
       29 
30 
     | 
    
         
             
                  when "instagram" then Providers::Instagram
         
     | 
| 
      
 31 
     | 
    
         
            +
                  when "odnoklassniki" then Providers::Odnoklassniki
         
     | 
| 
       30 
32 
     | 
    
         
             
                  else Providers::Base
         
     | 
| 
       31 
33 
     | 
    
         
             
                end
         
     | 
| 
       32 
34 
     | 
    
         | 
    
        data/social_profile.gemspec
    CHANGED
    
    | 
         @@ -21,9 +21,9 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       21 
21 
     | 
    
         
             
              spec.add_development_dependency "bundler", "~> 1.3"
         
     | 
| 
       22 
22 
     | 
    
         
             
              spec.add_development_dependency "rake"
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
              spec.add_dependency "fb_graph"
         
     | 
| 
       25 
     | 
    
         
            -
              spec.add_dependency "vkontakte"
         
     | 
| 
       26 
     | 
    
         
            -
              spec.add_dependency "twitter"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_dependency "fb_graph", '~> 2.7.16'
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_dependency "vkontakte", '~> 0.0.6'
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_dependency "twitter", '~> 5.11.0'
         
     | 
| 
       27 
27 
     | 
    
         
             
              spec.add_dependency "httpclient"
         
     | 
| 
       28 
28 
     | 
    
         
             
              spec.add_dependency "multi_json"
         
     | 
| 
       29 
29 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            {
         
     | 
| 
      
 2 
     | 
    
         
            +
              "data": [
         
     | 
| 
      
 3 
     | 
    
         
            +
                {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  "name": "Sergey Kochergan", 
         
     | 
| 
      
 5 
     | 
    
         
            +
                  "id": "100002162037770"
         
     | 
| 
      
 6 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 7 
     | 
    
         
            +
                {
         
     | 
| 
      
 8 
     | 
    
         
            +
                  "name": "Lyudmila  Bublik", 
         
     | 
| 
      
 9 
     | 
    
         
            +
                  "id": "100006720518271"
         
     | 
| 
      
 10 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 11 
     | 
    
         
            +
                {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  "name": "Victoria Zhurbas", 
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "id": "1425672521"
         
     | 
| 
      
 14 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 15 
     | 
    
         
            +
                {
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "name": "Марина Николаева", 
         
     | 
| 
      
 17 
     | 
    
         
            +
                  "id": "100002446576144"
         
     | 
| 
      
 18 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 19 
     | 
    
         
            +
                {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "name": "Alex Filatov", 
         
     | 
| 
      
 21 
     | 
    
         
            +
                  "id": "1198544135"
         
     | 
| 
      
 22 
     | 
    
         
            +
                }
         
     | 
| 
      
 23 
     | 
    
         
            +
              ], 
         
     | 
| 
      
 24 
     | 
    
         
            +
              "paging": {
         
     | 
| 
      
 25 
     | 
    
         
            +
                "cursors": {
         
     | 
| 
      
 26 
     | 
    
         
            +
                  "after": "MTE5ODU0NDEzNQ==", 
         
     | 
| 
      
 27 
     | 
    
         
            +
                  "before": "MTAwMDAyMTYyMDM3Nzcw"
         
     | 
| 
      
 28 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 29 
     | 
    
         
            +
                "next": "https://graph.facebook.com/v1.0/100000730417342/subscribers?limit=5&after=MTE5ODU0NDEzNQ=="
         
     | 
| 
      
 30 
     | 
    
         
            +
              }, 
         
     | 
| 
      
 31 
     | 
    
         
            +
              "summary": {
         
     | 
| 
      
 32 
     | 
    
         
            +
                "total_count": 14
         
     | 
| 
      
 33 
     | 
    
         
            +
              }
         
     | 
| 
      
 34 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            {
         
     | 
| 
      
 2 
     | 
    
         
            +
              "data": [
         
     | 
| 
      
 3 
     | 
    
         
            +
                {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  "name": "Max Solomianyi", 
         
     | 
| 
      
 5 
     | 
    
         
            +
                  "id": "100000419905855"
         
     | 
| 
      
 6 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 7 
     | 
    
         
            +
                {
         
     | 
| 
      
 8 
     | 
    
         
            +
                  "name": "Олег Гардаш", 
         
     | 
| 
      
 9 
     | 
    
         
            +
                  "id": "100001535481251"
         
     | 
| 
      
 10 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 11 
     | 
    
         
            +
                {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  "name": "Oleg  Pavlov", 
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "id": "100004742075897"
         
     | 
| 
      
 14 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 15 
     | 
    
         
            +
                {
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "name": "Тепли Викна", 
         
     | 
| 
      
 17 
     | 
    
         
            +
                  "id": "100003304746675"
         
     | 
| 
      
 18 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 19 
     | 
    
         
            +
                {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "name": "Rashed  Mohammad", 
         
     | 
| 
      
 21 
     | 
    
         
            +
                  "id": "100004427467621"
         
     | 
| 
      
 22 
     | 
    
         
            +
                }
         
     | 
| 
      
 23 
     | 
    
         
            +
              ], 
         
     | 
| 
      
 24 
     | 
    
         
            +
              "paging": {
         
     | 
| 
      
 25 
     | 
    
         
            +
                "cursors": {
         
     | 
| 
      
 26 
     | 
    
         
            +
                  "after": "MTAwMDA0NDI3NDY3NjIx", 
         
     | 
| 
      
 27 
     | 
    
         
            +
                  "before": "MTAwMDAwNDE5OTA1ODU1"
         
     | 
| 
      
 28 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 29 
     | 
    
         
            +
                "previous": "https://graph.facebook.com/v1.0/100000730417342/subscribers?limit=5&before=MTAwMDAwNDE5OTA1ODU1", 
         
     | 
| 
      
 30 
     | 
    
         
            +
                "next": "https://graph.facebook.com/v1.0/100000730417342/subscribers?limit=5&after=MTAwMDA0NDI3NDY3NjIx"
         
     | 
| 
      
 31 
     | 
    
         
            +
              }, 
         
     | 
| 
      
 32 
     | 
    
         
            +
              "summary": {
         
     | 
| 
      
 33 
     | 
    
         
            +
                "total_count": 14
         
     | 
| 
      
 34 
     | 
    
         
            +
              }
         
     | 
| 
      
 35 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            {
         
     | 
| 
      
 2 
     | 
    
         
            +
              "data": [
         
     | 
| 
      
 3 
     | 
    
         
            +
                {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  "name": "Zyazyaveka Ad Critic", 
         
     | 
| 
      
 5 
     | 
    
         
            +
                  "id": "100001860144695"
         
     | 
| 
      
 6 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 7 
     | 
    
         
            +
                {
         
     | 
| 
      
 8 
     | 
    
         
            +
                  "name": "Aleksandr Mykoliuk", 
         
     | 
| 
      
 9 
     | 
    
         
            +
                  "id": "1043306710"
         
     | 
| 
      
 10 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 11 
     | 
    
         
            +
                {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  "name": "Solmaz Fooladi", 
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "id": "1413023193"
         
     | 
| 
      
 14 
     | 
    
         
            +
                }
         
     | 
| 
      
 15 
     | 
    
         
            +
              ], 
         
     | 
| 
      
 16 
     | 
    
         
            +
              "paging": {
         
     | 
| 
      
 17 
     | 
    
         
            +
                "cursors": {
         
     | 
| 
      
 18 
     | 
    
         
            +
                  "after": "MTQxMzAyMzE5Mw==", 
         
     | 
| 
      
 19 
     | 
    
         
            +
                  "before": "MTAwMDAxODYwMTQ0Njk1"
         
     | 
| 
      
 20 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 21 
     | 
    
         
            +
                "previous": "https://graph.facebook.com/v1.0/100000730417342/subscribers?limit=5&before=MTAwMDAxODYwMTQ0Njk1"
         
     | 
| 
      
 22 
     | 
    
         
            +
              }, 
         
     | 
| 
      
 23 
     | 
    
         
            +
              "summary": {
         
     | 
| 
      
 24 
     | 
    
         
            +
                "total_count": 14
         
     | 
| 
      
 25 
     | 
    
         
            +
              }
         
     | 
| 
      
 26 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            {"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"","description":"May contain forward-looking statements.","url":"https:\/\/t.co\/L2xIBazMPf","entities":{"url":{"urls":[{"url":"https:\/\/t.co\/L2xIBazMPf","expanded_url":"https:\/\/github.com\/sferik","display_url":"github.com\/sferik","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count": 
     | 
| 
      
 1 
     | 
    
         
            +
            {"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"","description":"May contain forward-looking statements.","url":"https:\/\/t.co\/L2xIBazMPf","entities":{"url":{"urls":[{"url":"https:\/\/t.co\/L2xIBazMPf","expanded_url":"https:\/\/github.com\/sferik","display_url":"github.com\/sferik","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":69,"friends_count":361,"listed_count":238,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":8976,"utc_offset":3600,"time_zone":"Berlin","geo_enabled":true,"verified":false,"statuses_count":13844,"lang":"en","status":{"created_at":"Wed Mar 19 00:50:35 +0000 2014","id":446086297866993665,"id_str":"446086297866993665","text":"RT @AntonWSJ: Okean Elzy, #Ukraine's biggest rock band, performed in Berlin tonight amid many \"Glory to Ukraine!\" chants http:\/\/t.co\/dkIF8X\u2026","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Tue Mar 18 23:56:08 +0000 2014","id":446072592227909632,"id_str":"446072592227909632","text":"Okean Elzy, #Ukraine's biggest rock band, performed in Berlin tonight amid many \"Glory to Ukraine!\" chants http:\/\/t.co\/dkIF8XvFyw","source":"\u003ca href=\"http:\/\/www.apple.com\" rel=\"nofollow\"\u003eiOS\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":4,"favorite_count":2,"entities":{"hashtags":[{"text":"Ukraine","indices":[12,20]}],"symbols":[],"urls":[],"user_mentions":[],"media":[{"id":446072592047538176,"id_str":"446072592047538176","indices":[107,129],"media_url":"http:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","url":"http:\/\/t.co\/dkIF8XvFyw","display_url":"pic.twitter.com\/dkIF8XvFyw","expanded_url":"http:\/\/twitter.com\/AntonWSJ\/status\/446072592227909632\/photo\/1","type":"photo","sizes":{"medium":{"w":600,"h":450,"resize":"fit"},"large":{"w":1024,"h":768,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"small":{"w":340,"h":255,"resize":"fit"}}}]},"favorited":true,"retweeted":true,"possibly_sensitive":false,"lang":"en"},"retweet_count":4,"favorite_count":0,"entities":{"hashtags":[{"text":"Ukraine","indices":[26,34]}],"symbols":[],"urls":[],"user_mentions":[{"screen_name":"AntonWSJ","name":"Anton Troianovski","id":76773876,"id_str":"76773876","indices":[3,12]}],"media":[{"id":446072592047538176,"id_str":"446072592047538176","indices":[139,140],"media_url":"http:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","url":"http:\/\/t.co\/dkIF8XvFyw","display_url":"pic.twitter.com\/dkIF8XvFyw","expanded_url":"http:\/\/twitter.com\/AntonWSJ\/status\/446072592227909632\/photo\/1","type":"photo","sizes":{"medium":{"w":600,"h":450,"resize":"fit"},"large":{"w":1024,"h":768,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"small":{"w":340,"h":255,"resize":"fit"}}}]},"favorited":true,"retweeted":true,"possibly_sensitive":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/7505382\/1385736840","profile_link_color":"0084B4","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false,"suspended":false,"needs_phone_verification":false}
         
     |