social_profile 0.2.1 → 0.2.2

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: d44aa58dfddf32479ef916e66b88cb18006ddb01
4
- data.tar.gz: 02d418b320701c6378d5b3c773fb017e8a46c369
3
+ metadata.gz: 9ff2a46cb1b8edb78c457fb204d2efac1035b642
4
+ data.tar.gz: e843f72028951caa385e61478566a2eda9ba31ae
5
5
  SHA512:
6
- metadata.gz: ac9db1fcbd22aee01f98b9f67fca013253c461aba73b22989a0fc4b50a19b9d9631183b5ac14b45144294d435c2062e2a73d58614cd33344805229a115e3a614
7
- data.tar.gz: 7f30303b62b4f02700c4fb7832992e9ff7f4289ece4b2e011ef47f45810ecd34ec041a24fadf73d1a09e2aa24cc203c9f8e65f341a4ac61d9b9c6ede20b1c1fc
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] || 500000
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] || 500000
97
- user.subscribers(:limit => limit)
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
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module SocialProfile
3
- VERSION = "0.2.1"
3
+ VERSION = "0.2.2"
4
4
  end
@@ -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
 
@@ -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":4051,"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}
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}