activity_mapper 0.1.0
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.
- data/README.textile +211 -0
- data/lib/activity_mapper.rb +35 -0
- data/lib/activity_mapper/activity_data_mapper.rb +93 -0
- data/lib/activity_mapper/connector.rb +71 -0
- data/lib/activity_mapper/lexicon.txt +92662 -0
- data/lib/activity_mapper/linguistics.rb +147 -0
- data/lib/activity_mapper/service_module.rb +194 -0
- data/lib/activity_mapper/service_modules.rb +4 -0
- data/lib/activity_mapper/service_modules/delicious.rb +41 -0
- data/lib/activity_mapper/service_modules/flickr.rb +59 -0
- data/lib/activity_mapper/service_modules/twitter.rb +57 -0
- data/lib/activity_mapper/service_modules/wakoopa.rb +350 -0
- data/lib/activity_mapper/service_modules/youtube.rb +63 -0
- data/lib/extensions/uri.rb +42 -0
- data/spec/connector_mock.rb +49 -0
- data/spec/data/delicious_ac8fdf9b4e304b150bf198b42a1cb1b4.json +1 -0
- data/spec/data/delicious_ee55656e0f69242ccf02c3eb0f97b296.json +1 -0
- data/spec/data/flickr_2b826afe2906894197d92f7a41c2785c. +1 -0
- data/spec/data/flickr_3c25cf51d174ee4bb2d8673e294ce4c0.json +196 -0
- data/spec/data/flickr_482967b550afd05993ec4256fa1de388.json +229 -0
- data/spec/data/flickr_54c4b36bea4e2b14c783e5c50cba8544.json +9 -0
- data/spec/data/flickr_848ea91c1a903d0347d1029bf863132a. +1 -0
- data/spec/data/flickr_bcb82142f3d6998cabab3c82fba15ced.json +141 -0
- data/spec/data/flickr_e9d78058938c7c845a8de3a2c3526c61. +1 -0
- data/spec/data/twitter_227e1ca72a2ba08a1b03be2cd64b681e.json +274 -0
- data/spec/data/twitter_5dd0884137bf193d55d446619ec65c7e.json +1 -0
- data/spec/data/twitter_dd694fe9ebda58a84f92a859fb1cb79c.json +1 -0
- data/spec/data/wakoopa_1a8b94baf4eed4fd0e7ac39dc2f53059.json +1 -0
- data/spec/data/youtube_050e71a038359cc8ff7e00161e687b4e.json +1 -0
- data/spec/data/youtube_6d895fb0245f47b9e4fcc868d1f91674.json +1 -0
- data/spec/data/youtube_a92042581e44f9d3da548e2c7a89849c.json +1 -0
- data/spec/data/youtube_bf7b648ff8720edb1db951b7b9a474c4.json +1 -0
- data/spec/data/zemanta_suggest_for_tweet_response.xml +405 -0
- data/spec/models.rb +114 -0
- data/spec/service_modules/delicious_spec.rb +32 -0
- data/spec/service_modules/flickr_spec.rb +43 -0
- data/spec/service_modules/twitter_spec.rb +44 -0
- data/spec/service_modules/wakoopa_spec.rb +35 -0
- data/spec/service_modules/youtube_spec.rb +47 -0
- data/spec/spec_helper.rb +8 -0
- metadata +130 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
module ActivityMapper
|
3
|
+
|
4
|
+
class TwitterServiceModule < ServiceModule
|
5
|
+
ACTIVITY_MAP = {
|
6
|
+
nil => {
|
7
|
+
'activity.occurred_at' => 'created_at',
|
8
|
+
'activity.native_id' => 'id',
|
9
|
+
'activity_object.native_id' => 'id',
|
10
|
+
'activity.caption' => 'text',
|
11
|
+
'activity_object.title' => 'text',
|
12
|
+
'activity_object.body' => 'text'
|
13
|
+
}
|
14
|
+
}
|
15
|
+
ACCEPTED_HOSTS = [/twitter\.com/]
|
16
|
+
|
17
|
+
# TODO use this data:
|
18
|
+
# user.name
|
19
|
+
# user.description
|
20
|
+
# user.location
|
21
|
+
# user.url
|
22
|
+
def create_or_update_summary!(options = {})
|
23
|
+
attributes = {}
|
24
|
+
attributes[:username] = @profile.username || self.class.username_from_url(@profile.url)
|
25
|
+
|
26
|
+
mapper = ActivityDataMapper.new(ACTIVITY_MAP)
|
27
|
+
mapper.fetch!("http://twitter.com/statuses/user_timeline/#{attributes[:username]}.json", :format => :json)
|
28
|
+
tweets = mapper.data
|
29
|
+
|
30
|
+
attributes[:avatar_url] = tweets.blank? ? nil : tweets.first['user']['profile_image_url']
|
31
|
+
attributes[:native_user_id] = tweets.first['user']['id'].to_i
|
32
|
+
@profile.update_attributes(attributes)
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO use this data:
|
36
|
+
# tweet.favorited
|
37
|
+
# tweet.source # = what application was used to tweet (Wakoopa?)
|
38
|
+
# (tweet.in_reply_to_screen_name)
|
39
|
+
# (tweet.in_reply_to_status_id)
|
40
|
+
def aggregate_activity!(options = {})
|
41
|
+
mapper = ActivityDataMapper.new(ACTIVITY_MAP)
|
42
|
+
mapper.fetch!("http://twitter.com/statuses/user_timeline/#{@profile.username}.json", :format => :json)
|
43
|
+
mapper.map!
|
44
|
+
mapper.entries.sort! { |e2,e1|
|
45
|
+
e1['activity.occurred_at'] <=> e2['activity.occurred_at']
|
46
|
+
}
|
47
|
+
mapper.entries.each do |entry|
|
48
|
+
entry['activity_object.url'] = entry['activity.url'] = "http://twitter.com/#{@profile.username}/status/#{entry['activity.native_id']}"
|
49
|
+
break if Activity.exists?(@profile.user_id, entry)
|
50
|
+
create_activity(entry, ActivityObjectType::STATUS, ActivityVerb::POST) do |activity, activity_object|
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,350 @@
|
|
1
|
+
|
2
|
+
module ActivityMapper
|
3
|
+
|
4
|
+
class WakoopaServiceModule < ServiceModule
|
5
|
+
ACTIVITY_MAP = {
|
6
|
+
nil => {
|
7
|
+
'activity.occurred_at' => 'software/last_active_at',
|
8
|
+
'activity.caption' => 'software/name',
|
9
|
+
'activity_object.native_id' => 'software/id',
|
10
|
+
'activity_object.title' => 'software/name',
|
11
|
+
'activity_object.body' => 'category/name',
|
12
|
+
'activity_object.url' => 'software/complete_url',
|
13
|
+
'media.thumbnail_url' => 'software/complete_icon_url',
|
14
|
+
'rating_summary.rater_count' => 'software/num_users',
|
15
|
+
'rating_summary.view_count' => 'software/active_seconds'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ACCEPTED_HOSTS = [/wakoopa\.com/]
|
19
|
+
|
20
|
+
# most_used
|
21
|
+
|
22
|
+
# Available data:
|
23
|
+
# software: active-seconds
|
24
|
+
# software: created-at
|
25
|
+
# software: description
|
26
|
+
# software: id *
|
27
|
+
# software: name *
|
28
|
+
# software: num-users
|
29
|
+
# software: updated-at
|
30
|
+
# software: url *
|
31
|
+
# software: complete-url
|
32
|
+
# software: complete-icon-url
|
33
|
+
# software: complete-thumb-url
|
34
|
+
# software: developer: id
|
35
|
+
# software: developer: name
|
36
|
+
# software: developer: complete-url
|
37
|
+
# software: category: description *
|
38
|
+
# software: category: id
|
39
|
+
# software: category: name
|
40
|
+
# software: category: complete-url
|
41
|
+
# software: os-types
|
42
|
+
# activity["most_used"].each do |software|
|
43
|
+
#
|
44
|
+
# occurred_at = DateTime.parse(software['created_at']).to_time
|
45
|
+
#
|
46
|
+
# next if Activity.exists?(self.user_id, software['category']['description'], occurred_at)
|
47
|
+
#
|
48
|
+
# activity = Activity.create(
|
49
|
+
# :service_profile => self,
|
50
|
+
# :user_id => self.user_id,
|
51
|
+
# :native_id => software['id'].to_i,
|
52
|
+
# :activity_verb_id => ActivityVerb::MOST_USED.id,
|
53
|
+
# :url => software['complete_url'],
|
54
|
+
# :occurred_at => occurred_at # UTC OK
|
55
|
+
# )
|
56
|
+
#
|
57
|
+
# activity.object = ActivityObject.create(
|
58
|
+
# :title => software['name'],
|
59
|
+
# :body => software['category']['description'],
|
60
|
+
# :url => activity.url,
|
61
|
+
# :native_id => activity.native_id,
|
62
|
+
# :activity_object_type_id => ActivityObjectType::STATUS.id
|
63
|
+
# )
|
64
|
+
#
|
65
|
+
# activity.save
|
66
|
+
# end
|
67
|
+
|
68
|
+
# comments
|
69
|
+
|
70
|
+
# Available data:
|
71
|
+
# created-at
|
72
|
+
# id
|
73
|
+
# text
|
74
|
+
# owner: active-seconds
|
75
|
+
# owner: country
|
76
|
+
# owner: created-at
|
77
|
+
# owner: id
|
78
|
+
# owner: name
|
79
|
+
# owner: updated-at
|
80
|
+
# owner: username
|
81
|
+
# owner: complete-url
|
82
|
+
# owner: complete-icon-url
|
83
|
+
# owner: complete-thumb-url
|
84
|
+
# owner: os-types
|
85
|
+
|
86
|
+
|
87
|
+
# TODO use this data:
|
88
|
+
# None, the Wakoopa API calls assume you know the user already and doesn't explicitly provide this data
|
89
|
+
|
90
|
+
# TO DO: implement these fields
|
91
|
+
|
92
|
+
# contacts
|
93
|
+
# NB in de JSON call hebben ze het ineens over user ipv contact
|
94
|
+
# Hiermee haal je de eerste 10 contacts/users binnen
|
95
|
+
|
96
|
+
# Available data
|
97
|
+
# contact: active-seconds
|
98
|
+
# contact: country
|
99
|
+
# contact: created-at
|
100
|
+
# contact: id
|
101
|
+
# contact: name
|
102
|
+
# contact: updated-at
|
103
|
+
# contact: username
|
104
|
+
# contact: complete-url
|
105
|
+
# contact: complete-icon-url
|
106
|
+
# contact: complete-thumb-url
|
107
|
+
# contact: os-types
|
108
|
+
|
109
|
+
# teams
|
110
|
+
# Alleen 1e 10 teams
|
111
|
+
|
112
|
+
# Available data
|
113
|
+
# team: active seconds
|
114
|
+
# team: created-at
|
115
|
+
# team: description
|
116
|
+
# team: id
|
117
|
+
# team: name
|
118
|
+
# team: num-users
|
119
|
+
# team: complete-url
|
120
|
+
|
121
|
+
def create_or_update_summary!(options = {})
|
122
|
+
#softwares = WakoopaConnector.most_used_for(attributes[:username]) # Gebeurt er nog wat met softwares? Nee, niet echt :]
|
123
|
+
# avatar not (yet) available in the API calls
|
124
|
+
# native_user_id not (yet) available in the API calls
|
125
|
+
@profile.update_attributes(:username => self.class.username_from_url(@profile.url))
|
126
|
+
end
|
127
|
+
|
128
|
+
# TODO: since this is a summary, this should be done on create! and update! Need to implement recent activity here
|
129
|
+
# TODO use this data:
|
130
|
+
# software.complete_icon_url
|
131
|
+
# software.complete_thumb_url
|
132
|
+
# software.category
|
133
|
+
# software.num_users
|
134
|
+
# software.developer
|
135
|
+
# software.url
|
136
|
+
# software.active_seconds
|
137
|
+
def aggregate_activity!(options = {})
|
138
|
+
# most_used_softwares = WakoopaConnector.most_used_for(username)
|
139
|
+
# attributes = attributes_or_url.is_a?(Hash) ? attributes_or_url : {:username => username_from_url(attributes_or_url)}
|
140
|
+
#activities = WakoopaConnector.get_all_activity_for(username)
|
141
|
+
#activities.each { |activity,data| aggregate_for_activity(activity,data) }
|
142
|
+
|
143
|
+
mapper = ActivityDataMapper.new(ACTIVITY_MAP)
|
144
|
+
mapper.fetch!("http://api.wakoopa.com/#{@profile.username}/recently_used.json",
|
145
|
+
:format => :json,
|
146
|
+
:strip_callback => true
|
147
|
+
)
|
148
|
+
mapper.map!
|
149
|
+
mapper.entries.each do |entry|
|
150
|
+
next if Activity.exists?(@profile.user_id, entry)
|
151
|
+
create_activity(entry, ActivityObjectType::SOFTWARE, ActivityVerb::RECENTLY_USED)
|
152
|
+
end
|
153
|
+
|
154
|
+
=begin
|
155
|
+
data.each do |software|
|
156
|
+
|
157
|
+
occurred_at = (software['software']['created_at'])
|
158
|
+
|
159
|
+
next if Activity.exists?(self.user_id, software['software']['name'], occurred_at)
|
160
|
+
|
161
|
+
activity = Activity.create(
|
162
|
+
:service_profile => self,
|
163
|
+
:user_id => self.user_id,
|
164
|
+
:native_id => software['software']['id'].to_i,
|
165
|
+
:activity_verb_id => ActivityVerb::RECENTLY_USED.id,
|
166
|
+
:url => software['software']['complete_url'],
|
167
|
+
:occurred_at => occurred_at # UTC OK
|
168
|
+
)
|
169
|
+
|
170
|
+
body = (software['software']['category'].class == NilClass) ? "" : software['software']['category']['description']
|
171
|
+
|
172
|
+
activity.object = ActivityObject.create(
|
173
|
+
:title => software['software']['name'],
|
174
|
+
:body => body,
|
175
|
+
:url => activity.url,
|
176
|
+
:native_id => activity.native_id,
|
177
|
+
:activity_object_type_id => ActivityObjectType::STATUS.id
|
178
|
+
)
|
179
|
+
|
180
|
+
activity.save
|
181
|
+
end
|
182
|
+
=end
|
183
|
+
|
184
|
+
end
|
185
|
+
=begin
|
186
|
+
def aggregate_for_activity(activity,data)
|
187
|
+
case activity
|
188
|
+
when "recently_used"
|
189
|
+
recently_used(data)
|
190
|
+
when "newly_used"
|
191
|
+
newly_used(data)
|
192
|
+
when "comments"
|
193
|
+
comments(data)
|
194
|
+
when "reviews"
|
195
|
+
reviews(data)
|
196
|
+
else puts "error"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def recently_used(data)
|
201
|
+
# Available data is the same as for most_used.
|
202
|
+
data.each do |software|
|
203
|
+
|
204
|
+
occurred_at = (software['software']['created_at'])
|
205
|
+
|
206
|
+
next if Activity.exists?(self.user_id, software['software']['name'], occurred_at)
|
207
|
+
|
208
|
+
activity = Activity.create(
|
209
|
+
:service_profile => self,
|
210
|
+
:user_id => self.user_id,
|
211
|
+
:native_id => software['software']['id'].to_i,
|
212
|
+
:activity_verb_id => ActivityVerb::RECENTLY_USED.id,
|
213
|
+
:url => software['software']['complete_url'],
|
214
|
+
:occurred_at => occurred_at # UTC OK
|
215
|
+
)
|
216
|
+
|
217
|
+
body = (software['software']['category'].class == NilClass) ? "" : software['software']['category']['description']
|
218
|
+
|
219
|
+
activity.object = ActivityObject.create(
|
220
|
+
:title => software['software']['name'],
|
221
|
+
:body => body,
|
222
|
+
:url => activity.url,
|
223
|
+
:native_id => activity.native_id,
|
224
|
+
:activity_object_type_id => ActivityObjectType::STATUS.id
|
225
|
+
)
|
226
|
+
|
227
|
+
activity.save
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def newly_used(data)
|
232
|
+
# Available data is the same as for most_used.
|
233
|
+
data.each do |software|
|
234
|
+
# occurred_at = DateTime.parse(software['software']['updated_at']).to_time
|
235
|
+
# JSON converter automatically makes it into a time
|
236
|
+
occurred_at = software['software']['updated_at'] # Is this the proper field?
|
237
|
+
|
238
|
+
next if Activity.exists?(self.user_id, software['software']['name'], occurred_at)
|
239
|
+
|
240
|
+
activity = Activity.create(
|
241
|
+
:service_profile => self,
|
242
|
+
:user_id => self.user_id,
|
243
|
+
:native_id => software['software']['id'].to_i,
|
244
|
+
:activity_verb_id => ActivityVerb::NEWLY_USED.id,
|
245
|
+
:url => software['software']['complete_url'],
|
246
|
+
:occurred_at => occurred_at # UTC OK
|
247
|
+
)
|
248
|
+
|
249
|
+
body = (software['software']['category'].class == NilClass) ? "" : software['software']['category']['description']
|
250
|
+
|
251
|
+
activity.object = ActivityObject.create(
|
252
|
+
:title => software['software']['name'],
|
253
|
+
:body => body,
|
254
|
+
:url => activity.url,
|
255
|
+
:native_id => activity.native_id,
|
256
|
+
:activity_object_type_id => ActivityObjectType::STATUS.id
|
257
|
+
)
|
258
|
+
|
259
|
+
activity.save
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# COMMENTS
|
264
|
+
# NB Get the 10 most recent comments. This can be adjusted to [1..30]
|
265
|
+
|
266
|
+
# Available data:
|
267
|
+
# created-at *
|
268
|
+
# id *
|
269
|
+
# text *
|
270
|
+
# owner: active-seconds
|
271
|
+
# owner: country
|
272
|
+
# owner: created-at
|
273
|
+
# owner: id
|
274
|
+
# owner: name
|
275
|
+
# owner: updated-at
|
276
|
+
# owner: username
|
277
|
+
# owner: complete-url
|
278
|
+
# owner: complete-icon-url
|
279
|
+
# owner: complete-thumb-url
|
280
|
+
# owner: os-types
|
281
|
+
def comments(data)
|
282
|
+
data.each do |comment|
|
283
|
+
# JSON converter automatically makes it into a time
|
284
|
+
occurred_at = comment['user_comment']['created_at']
|
285
|
+
|
286
|
+
next if Activity.exists?(self.user_id, comment['user_comment']['text'], occurred_at)
|
287
|
+
|
288
|
+
activity = Activity.create(
|
289
|
+
:service_profile => self,
|
290
|
+
:user_id => self.user_id,
|
291
|
+
:native_id => comment['user_comment']['id'].to_i,
|
292
|
+
:activity_verb_id => ActivityVerb::COMMENT.id,
|
293
|
+
:url => "http://wakoopa.com/#{username}/comments?page=1",
|
294
|
+
:occurred_at => occurred_at # UTC OK
|
295
|
+
)
|
296
|
+
|
297
|
+
activity.object = ActivityObject.create(
|
298
|
+
:title => comment['user_comment']['text'],
|
299
|
+
:body => comment['user_comment']['text'],
|
300
|
+
:url => activity.url,
|
301
|
+
:native_id => activity.native_id,
|
302
|
+
:activity_object_type_id => ActivityObjectType::STATUS.id
|
303
|
+
)
|
304
|
+
|
305
|
+
activity.save
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
# REVIEWS
|
311
|
+
|
312
|
+
# Available data: same as most_used, plus:
|
313
|
+
# created-at *
|
314
|
+
# id *
|
315
|
+
# rating TO DO
|
316
|
+
# text *
|
317
|
+
def reviews(data)
|
318
|
+
|
319
|
+
data.each do |review|
|
320
|
+
|
321
|
+
occurred_at = review['review']['created_at']
|
322
|
+
|
323
|
+
next if Activity.exists?(self.user_id, review['review']['text'], occurred_at)
|
324
|
+
|
325
|
+
activity = Activity.create(
|
326
|
+
:service_profile => self,
|
327
|
+
:user_id => self.user_id,
|
328
|
+
:native_id => review['review']['id'].to_i,
|
329
|
+
:activity_verb_id => ActivityVerb::REVIEW.id,
|
330
|
+
:url => review['review']['software']['complete_url'] + "/review/#{review['id']}",
|
331
|
+
:occurred_at => occurred_at # UTC OK
|
332
|
+
)
|
333
|
+
|
334
|
+
activity.object = ActivityObject.create(
|
335
|
+
:title => review['review']['text'],
|
336
|
+
:body => review['review']['text'],
|
337
|
+
:url => activity.url,
|
338
|
+
:native_id => activity.native_id,
|
339
|
+
:activity_object_type_id => ActivityObjectType::STATUS.id
|
340
|
+
)
|
341
|
+
|
342
|
+
activity.save
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
=end
|
347
|
+
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
module ActivityMapper
|
3
|
+
|
4
|
+
class YoutubeServiceModule < ServiceModule
|
5
|
+
ACTIVITY_MAP = {
|
6
|
+
'feed/entry' => {
|
7
|
+
'activity.occurred_at' => 'published/$t',
|
8
|
+
'activity.caption' => 'title/$t',
|
9
|
+
'activity_object.title' => 'title/$t',
|
10
|
+
'activity_object.body' => 'media$group/media$description/$t',
|
11
|
+
'activity_object.url' => 'media$group/media$player/url',
|
12
|
+
'activity.url' => 'media$group/media$player/url',
|
13
|
+
'media.thumbnail_url' => 'media$group/media$thumbnail[0]/url',
|
14
|
+
'media.embed_url' => 'media$group/media$content[0]/url',
|
15
|
+
'media.duration' => 'media$group/yt$duration/seconds',
|
16
|
+
'rating_summary.rater_count' => 'gd$rating/numRaters',
|
17
|
+
'rating_summary.min' => 'gd$rating/min',
|
18
|
+
'rating_summary.max' => 'gd$rating/max',
|
19
|
+
'rating_summary.average' => 'gd$rating/average',
|
20
|
+
'rating_summary.view_count' => 'yt$statistics/viewCount',
|
21
|
+
'rating_summary.favorite_count' => 'yt$statistics/favoriteCount'
|
22
|
+
}
|
23
|
+
}
|
24
|
+
ACCEPTED_HOSTS = [/youtube\.com/]
|
25
|
+
|
26
|
+
# TODO use this data:
|
27
|
+
# user view statistics
|
28
|
+
def create_or_update_summary!(options = {})
|
29
|
+
@profile.update_attributes(:username => self.class.username_from_url(@profile.url))
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO use this data
|
33
|
+
# native id (need to somehow encode this to a big ass number: eg: dyMVZqJk8s4)
|
34
|
+
# media.categories
|
35
|
+
# media.keywords
|
36
|
+
# media.credit
|
37
|
+
# (media.uploader)
|
38
|
+
def aggregate_activity!(options = {})
|
39
|
+
mapper = ActivityDataMapper.new(ACTIVITY_MAP)
|
40
|
+
|
41
|
+
mapper.fetch!(
|
42
|
+
"http://gdata.youtube.com/feeds/api/users/#{@profile.username}/uploads?v=2&alt=json",
|
43
|
+
:format => :json
|
44
|
+
)
|
45
|
+
mapper.map!
|
46
|
+
mapper.entries.each do |entry|
|
47
|
+
next if Activity.exists?(@profile.user_id, entry)
|
48
|
+
create_activity(entry, ActivityObjectType::VIDEO, ActivityVerb::POST)
|
49
|
+
end
|
50
|
+
|
51
|
+
mapper.fetch!(
|
52
|
+
"http://gdata.youtube.com/feeds/api/users/#{@profile.username}/favorites?v=2&alt=json",
|
53
|
+
:format => :json
|
54
|
+
)
|
55
|
+
mapper.map!
|
56
|
+
mapper.entries.each do |entry|
|
57
|
+
next if Activity.exists?(@profile.user_id, entry)
|
58
|
+
create_activity(entry, ActivityObjectType::VIDEO, ActivityVerb::FAVORITE)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|