person.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import celery
  2. import json
  3. import pagure
  4. import rdflib
  5. from .. import activitypub
  6. from .. import model
  7. from .. import settings
  8. from . import broker
  9. from . import broker_url
  10. from . import database_session
  11. log = celery.utils.log.get_task_logger(__name__)
  12. log.setLevel(settings.LOG_LEVEL)
  13. @broker.task
  14. def handle_incoming_activity(person_id, activity):
  15. """
  16. A person has received a new Activity in its INBOX. This task is scheduled
  17. in order to triage the activity and decide how the actor should react to it.
  18. """
  19. activity = activitypub.Document(activity)
  20. with database_session() as (pagure_db, forgefed_db):
  21. person = pagure_db.query(model.Person) \
  22. .filter(model.Person.id == person_id) \
  23. .one_or_none()
  24. # If the person doesn't exist, it means it was deleted after it received
  25. # an Activity but before the Activity was handled.
  26. if not person:
  27. log.info('Actor {} doesn\'t exist. Incoming Activity will be ignored.'.format(person.local_uri))
  28. return
  29. # DONE
  30. if activity['type'] == 'Accept' \
  31. and activity.node('object')['type'] == 'Follow' \
  32. and activity['object']['actor'] == person.local_uri \
  33. and activity['object']['id'] == activity['actor']:
  34. """
  35. We have received a response to our Follow request.
  36. """
  37. log.debug('Actor {} has accepted the Follow request by {}'.format(activity['actor'], person.local_uri))
  38. if activity['type'] == 'Accept' \
  39. and activity.node('object')['type'] == 'Offer' \
  40. and activity['object']['actor'] == person.local_uri \
  41. and activity['object']['object']['type'] == 'Ticket' \
  42. and 'result' in activity \
  43. and activity['actor'] == activity['object']['to']:
  44. """
  45. We have received a response to our Offer(Ticket) request.
  46. """
  47. log.debug('The remote actor has accepted the Ticket offer.')
  48. ticket = activity.node('object').node('object')
  49. # Remember that our local Ticket is a view of a remote Ticket
  50. forgefed_db.add(database.SameAs(
  51. local_uri = ticket['id'],
  52. remote_uri = activity['result']))
  53. log.debug('The ticket {} was accepted. A new ticket was created at {}'.format(ticket['id'], activity['result']))
  54. if activity['type'] == 'Create' \
  55. and activity.node('object')['type'] == 'Note' \
  56. and 'context' in activity['object']:
  57. """
  58. Somebody has created a new Note for a Ticket or a MergeRequest.
  59. """
  60. log.debug('Somebody has Created a new Note.')
  61. model.test_or_set_remote_comment(pagure_db, forgefed_db, activity['object']['id'])
  62. # DONE
  63. if activity['type'] == 'Follow' \
  64. and activity['object'] == person.local_uri:
  65. """
  66. Somebody has Followed this actor..
  67. """
  68. # Check if the remote actor is already following the local actor
  69. if forgefed_db.query(
  70. forgefed_db.query(database.Collection) \
  71. .filter(database.Collection.uri == person.followers_uri) \
  72. .filter(database.Collection.item == activity['actor']) \
  73. .exists()
  74. ).scalar():
  75. log.info('Actor {} is already following {}. Will ignore Follow request.'.format(person.local_uri, activity['actor']))
  76. return
  77. # Add the remote object to our followers collection
  78. forgefed_db.add(database.Collection(uri = person.followers_uri, item = activity['actor']))
  79. # Commit before accepting the Activity because we want the new
  80. # follower in the Followers collection before sending out the
  81. # Accept Activity.
  82. forgefed_db.commit()
  83. # Automatically accept Follow requests.
  84. person.accept(activity)
  85. if activity['type'] == 'Resolve' \
  86. and activity.node('object')['type'] == 'Ticket':
  87. """
  88. We've been notified that somebody has resolved a remote Ticket.
  89. """
  90. # Check if we have any local object representing the remote Ticket,
  91. # in which case we will update our local copy.
  92. ticket = forgefed_db.query(database.SameAs) \
  93. .filter(database.SameAs.remote_uri == activity['object']['id']) \
  94. .one_or_none()
  95. if not ticket:
  96. log.debug('The Ticket {} is not cached locally.'.format(activity['object']['id']))
  97. return
  98. log.debug('Ticket resolved: {}'.format(activity['object']['id']))
  99. #-----------
  100. # Edit the pagure Issue object
  101. pagure.lib.query.edit_issue(
  102. session=pagure_db,
  103. issue=ticket,
  104. user=actor.username,
  105. status='Closed')