Skip to content

Commit 4d32457

Browse files
committed
add optional activity kwarg to Source.get_*; move Facebook.get_rsvp to Source
the requested object in get_* can sometimes be extracted from the optional activity, which avoids an unnecessary API call. moved Facebook.get_rsvp to Source because it was entirely AS based and didn't have anything facebook-specific. TODO: move Instagram.get_comment to Source for the same reason.
1 parent f0b1381 commit 4d32457

9 files changed

+185
-80
lines changed

granary/facebook.py

+9-19
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,15 @@ def get_event(self, event_id, owner_id=None):
474474

475475
return self.event_to_activity(event)
476476

477-
def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
477+
def get_comment(self, comment_id, activity_id=None, activity_author_id=None,
478+
activity=None):
478479
"""Returns an ActivityStreams comment object.
479480
480481
Args:
481482
comment_id: string comment id
482483
activity_id: string activity id, optional
483484
activity_author_id: string activity author id, optional
485+
activity: activity object (optional)
484486
"""
485487
try:
486488
resp = self.urlopen(API_COMMENT % comment_id)
@@ -493,13 +495,14 @@ def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
493495

494496
return self.comment_to_object(resp, post_author_id=activity_author_id)
495497

496-
def get_share(self, activity_user_id, activity_id, share_id):
498+
def get_share(self, activity_user_id, activity_id, share_id, activity=None):
497499
"""Returns an ActivityStreams share activity object.
498500
499501
Args:
500502
activity_user_id: string id of the user who posted the original activity
501503
activity_id: string activity id
502504
share_id: string id of the share object
505+
activity: activity object (optional)
503506
"""
504507
orig_id = '%s_%s' % (activity_user_id, activity_id)
505508

@@ -522,20 +525,6 @@ def get_share(self, activity_user_id, activity_id, share_id):
522525
with util.ignore_http_4xx_error():
523526
return self.share_to_object(self.urlopen(API_OBJECT % (user_id, obj_id)))
524527

525-
def get_rsvp(self, activity_user_id, event_id, user_id):
526-
"""Returns an ActivityStreams RSVP activity object.
527-
528-
Args:
529-
activity_user_id: string id of the user who posted the event. unused.
530-
event_id: string event id
531-
user_id: string user id
532-
"""
533-
event = self.urlopen(API_EVENT % event_id)
534-
for field in RSVP_FIELDS:
535-
for rsvp in event.get(field, {}).get('data', []):
536-
if rsvp.get('id') == user_id:
537-
return self.rsvp_to_object(rsvp, type=field, event=event)
538-
539528
def get_albums(self, user_id=None):
540529
"""Fetches and returns a user's photo albums.
541530
@@ -549,7 +538,7 @@ def get_albums(self, user_id=None):
549538
return [self.album_to_object(a) for a in self.urlopen(url, _as=list)]
550539

551540
def get_reaction(self, activity_user_id, activity_id, reaction_user_id,
552-
reaction_id):
541+
reaction_id, activity=None):
553542
"""Fetches and returns a reaction.
554543
555544
Args:
@@ -558,11 +547,12 @@ def get_reaction(self, activity_user_id, activity_id, reaction_user_id,
558547
reaction_user_id: string id of the user who reacted
559548
reaction_id: string id of the reaction. one of:
560549
'love', 'wow', 'haha', 'sad', 'angry'
550+
activity: activity object (optional)
561551
"""
562552
if '_' not in reaction_id: # handle just name of reaction type
563553
reaction_id = '%s_%s_by_%s' % (activity_id, reaction_id, reaction_user_id)
564-
return super(Facebook, self).get_reaction(activity_user_id, activity_id,
565-
reaction_user_id, reaction_id)
554+
return super(Facebook, self).get_reaction(
555+
activity_user_id, activity_id, reaction_user_id, reaction_id, activity=activity)
566556

567557
def create(self, obj, include_link=source.OMIT_LINK,
568558
ignore_formatting=False):

granary/flickr.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,15 @@ def user_to_actor(self, resp):
439439

440440
return self.postprocess_object(obj)
441441

442-
def get_comment(self, comment_id, activity_id, activity_author_id=None):
442+
def get_comment(self, comment_id, activity_id, activity_author_id=None,
443+
activity=None):
443444
"""Returns an ActivityStreams comment object.
444445
445446
Args:
446447
comment_id: string comment id
447448
activity_id: string activity id, required
448449
activity_author_id: string activity author id, ignored
450+
activity: activity object (optional)
449451
"""
450452
resp = self.call_api_method('flickr.photos.comments.getList', {
451453
'photo_id': activity_id,

granary/googleplus.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,15 @@ def set_comments(req_id, resp, exc, activity=None):
188188
cache.set_multi(cache_updates)
189189
return response
190190

191-
def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
191+
def get_comment(self, comment_id, activity_id=None, activity_author_id=None,
192+
activity=None):
192193
"""Returns an ActivityStreams comment object.
193194
194195
Args:
195196
comment_id: string comment id
196197
activity_id: string activity id, optional
197198
activity_author_id: string activity author id. Ignored.
199+
activity: activity object (optional)
198200
"""
199201
# https://developers.google.com/+/api/latest/comments
200202
call = self.auth_entity.api().comments().get(commentId=comment_id)

granary/instagram.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -291,28 +291,30 @@ def _scrape(self, user_id=None, activity_id=None, cookie=None,
291291
resp['actor'] = actor
292292
return resp
293293

294-
def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
294+
def get_comment(self, comment_id, activity_id=None, activity_author_id=None,
295+
activity=None):
295296
"""Returns an ActivityStreams comment object.
296297
297298
Args:
298299
comment_id: string comment id
299300
activity_id: string activity id, required
300301
activity_author_id: string activity author id. Ignored.
302+
activity: activity object, optional. Avoids fetching the activity.
301303
"""
302-
activities = self.get_activities(activity_id=activity_id)
303-
if activities:
304+
if not activity:
305+
activity = self._get_activity(None, activity_id)
306+
if activity:
304307
tag_id = self.tag_uri(comment_id)
305-
for reply in activities[0].get('object', {}).get('replies', {}).get('items', []):
308+
for reply in activity.get('object', {}).get('replies', {}).get('items', []):
306309
if reply.get('id') == tag_id:
307310
return reply
308311

309-
def get_share(self, activity_user_id, activity_id, share_id):
312+
def get_share(self, activity_user_id, activity_id, share_id, activity=None):
310313
"""Not implemented. Returns None. Resharing isn't a feature of Instagram.
311314
"""
312315
return None
313316

314-
def create(self, obj, include_link=source.OMIT_LINK,
315-
ignore_formatting=False):
317+
def create(self, obj, include_link=source.OMIT_LINK, ignore_formatting=False):
316318
"""Creates a new comment or like.
317319
318320
Args:

granary/source.py

+50-24
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ def get_event(self, event_id):
312312
"""
313313
raise NotImplementedError()
314314

315-
def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
315+
def get_comment(self, comment_id, activity_id=None, activity_author_id=None,
316+
activity=None):
316317
"""Returns an ActivityStreams comment object.
317318
318319
Subclasses should override this.
@@ -322,10 +323,11 @@ def get_comment(self, comment_id, activity_id=None, activity_author_id=None):
322323
activity_id: string activity id, optional
323324
activity_author_id: string activity author id, optional. Needed for some
324325
sources (e.g. Facebook) to construct the comment permalink.
326+
activity: activity object, optional. May avoid an API call if provided.
325327
"""
326328
raise NotImplementedError()
327329

328-
def get_like(self, activity_user_id, activity_id, like_user_id):
330+
def get_like(self, activity_user_id, activity_id, like_user_id, activity=None):
329331
"""Returns an ActivityStreams 'like' activity object.
330332
331333
Default implementation that fetches the activity and its likes, then
@@ -336,14 +338,14 @@ def get_like(self, activity_user_id, activity_id, like_user_id):
336338
activity_user_id: string id of the user who posted the original activity
337339
activity_id: string activity id
338340
like_user_id: string id of the user who liked the activity
341+
activity: activity object, optional. May avoid an API call if provided.
339342
"""
340-
activities = self.get_activities(user_id=activity_user_id,
341-
activity_id=activity_id,
342-
fetch_likes=True)
343-
return self._get_tag(activities, 'like', like_user_id)
343+
if not activity:
344+
activity = self._get_activity(activity_user_id, activity_id, fetch_likes=True)
345+
return self._get_tag(activity, 'like', like_user_id)
344346

345347
def get_reaction(self, activity_user_id, activity_id, reaction_user_id,
346-
reaction_id):
348+
reaction_id, activity=None):
347349
"""Returns an ActivityStreams 'reaction' activity object.
348350
349351
Default implementation that fetches the activity and its reactions, then
@@ -355,33 +357,45 @@ def get_reaction(self, activity_user_id, activity_id, reaction_user_id,
355357
activity_id: string activity id
356358
reaction_user_id: string id of the user who reacted
357359
reaction_id: string id of the reaction
360+
activity: activity object, optional. May avoid an API call if provided.
358361
"""
359-
activities = self.get_activities(user_id=activity_user_id,
360-
activity_id=activity_id)
361-
return self._get_tag(activities, 'react', reaction_user_id, reaction_id)
362+
if not activity:
363+
activity = self._get_activity(activity_user_id, activity_id)
364+
return self._get_tag(activity, 'react', reaction_user_id, reaction_id)
362365

363-
def get_share(self, activity_user_id, activity_id, share_id):
366+
def get_share(self, activity_user_id, activity_id, share_id, activity=None):
364367
"""Returns an ActivityStreams 'share' activity object.
365368
366369
Args:
367370
activity_user_id: string id of the user who posted the original activity
368371
activity_id: string activity id
369372
share_id: string id of the share object or the user who shared it
373+
activity: activity object, optional. May avoid an API call if provided.
370374
"""
371-
activities = self.get_activities(user_id=activity_user_id,
372-
activity_id=activity_id,
373-
fetch_shares=True)
374-
return self._get_tag(activities, 'share', share_id)
375+
if not activity:
376+
activity = self._get_activity(activity_user_id, activity_id, fetch_shares=True)
377+
return self._get_tag(activity, 'share', share_id)
375378

376-
def get_rsvp(self, activity_user_id, event_id, user_id):
377-
"""Returns an ActivityStreams 'rsvp-*' activity object.
379+
def get_rsvp(self, activity_user_id, event_id, user_id, event=None):
380+
"""Returns an ActivityStreams RSVP activity object.
378381
379382
Args:
380-
activity_user_id: string id of the user who posted the original activity
383+
activity_user_id: string id of the user who posted the event. unused.
381384
event_id: string event id
382-
user_id: string id of the user who RSVPed
385+
user_id: string user id
386+
event: AS event activity (optional)
383387
"""
384-
raise NotImplementedError()
388+
user_tag_id = self.tag_uri(user_id)
389+
if not event:
390+
event = self.get_event(event_id)
391+
if not event:
392+
return None
393+
394+
for rsvp in self.get_rsvps_from_event(event['object']):
395+
for field in 'actor', 'object':
396+
id = rsvp.get(field, {}).get('id')
397+
if id and user_id == util.parse_tag_uri(id)[1]:
398+
return rsvp
385399

386400
def user_to_actor(self, user):
387401
"""Converts a user to an actor.
@@ -398,15 +412,21 @@ def user_to_actor(self, user):
398412
"""
399413
raise NotImplementedError()
400414

401-
def _get_tag(self, activities, verb, user_id, tag_id=None):
402-
if not activities:
415+
def _get_activity(self, user_id, activity_id, **kwargs):
416+
activities = self.get_activities(user_id=user_id, activity_id=activity_id,
417+
**kwargs)
418+
if activities:
419+
return activities[0]
420+
421+
def _get_tag(self, activity, verb, user_id, tag_id=None):
422+
if not activity:
403423
return None
404424

405425
user_tag_id = self.tag_uri(user_id)
406426
if tag_id:
407427
tag_id = self.tag_uri(tag_id)
408428

409-
for tag in activities[0].get('object', {}).get('tags', []):
429+
for tag in activity.get('object', {}).get('tags', []):
410430
author = tag.get('author', {})
411431
if (tag.get('verb') == verb and
412432
(not tag_id or tag_id == tag.get('id')) and
@@ -634,20 +654,26 @@ def get_rsvps_from_event(event):
634654
return []
635655
domain, event_id = parsed
636656
url = event.get('url')
657+
author = event.get('author')
637658

638659
rsvps = []
639660
for verb, field in RSVP_TO_EVENT.items():
640661
for actor in event.get(field, []):
641662
rsvp = {'objectType': 'activity',
642663
'verb': verb,
643-
'actor': actor,
664+
'object' if verb == 'invite' else 'actor': actor,
644665
'url': url,
645666
}
667+
646668
if event_id and 'id' in actor:
647669
_, actor_id = util.parse_tag_uri(actor['id'])
648670
rsvp['id'] = util.tag_uri(domain, '%s_rsvp_%s' % (event_id, actor_id))
649671
if url:
650672
rsvp['url'] = '#'.join((url, actor_id))
673+
674+
if verb == 'invite' and author:
675+
rsvp['actor'] = author
676+
651677
rsvps.append(rsvp)
652678

653679
return rsvps

0 commit comments

Comments
 (0)