123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- import celery
- import json
- import pagure
- import rdflib
- from .. import activitypub
- from .. import model
- from .. import settings
- from . import broker
- from . import broker_url
- from . import database_session
- log = celery.utils.log.get_task_logger(__name__)
- log.setLevel(settings.LOG_LEVEL)
- @broker.task
- def handle_pagure_signal(topic, message):
- """
- This task receives notifications from Pagure about events that happen on
- the instance, creates a new activity, and schedules their delivery.
- """
-
- log.debug('New notification from Pagure: ' + topic)
- log.debug(json.dumps(message, indent=4, sort_keys=True))
-
- with database_session() as (pagure_db, forgefed_graph):
-
- if topic == 'issue.new':
- # A user has created a new issue
-
- person = pagure_db \
- .query(model.Person) \
- .filter(model.Person.user == message['issue']['user']['name']) \
- .one_or_none()
-
- project = pagure_db \
- .query(model.Projects) \
- .filter(model.Projects.id == message['project']['id']) \
- .one_or_none()
-
- issue = pagure_db \
- .query(pagure.lib.model.Issue) \
- .filter(pagure.lib.model.Issue.id == message['issue']['id'],
- pagure.lib.model.Issue.project_id == message['project']['id']) \
- .one_or_none()
-
- # This should never raise an error otherwise there's a bug in Pagure
- assert person and issue and project, \
- 'User or or project doesn\'t exist.'
-
- tracker_url = project.uri + '/issues'
-
- # Check if this tracker is only used to interact with a remote one
- remote_tracker = forgefed_graph.value(rdflib.URIRef(tracker_url),
- rdflib.OWL.sameAs)
-
- if not remote_tracker:
- log.debug('Not a remote tracker. Nothing to send.')
-
- if remote_tracker:
- log.debug('Sending new issue to remote tracker...')
-
- ticket = pagure_db \
- .query(model.Ticket) \
- .filter(model.Ticket.id == issue.id,
- model.Ticket.project_id == issue.project_id) \
- .one_or_none()
-
- # Offer a new ticket to the remote tracker
- person.offer(ticket.jsonld, to=remote_tracker)
-
- if topic == 'issue.comment.added':
- # A user has commented on an issue
-
- # The Pagure notification contains *all* the comments of the issue
- # in an ordered list, so we extract the last one from the list of
- # comments.
- comment = pagure_db \
- .query(model.TicketComment) \
- .filter(model.TicketComment.id == message['issue']['comments'][-1]['id']) \
- .one_or_none()
-
- person = pagure_db \
- .query(model.Person) \
- .filter(model.Person.id == comment.user.id) \
- .one_or_none()
-
- project = pagure_db \
- .query(model.Projects) \
- .filter(model.Projects.id == message['project']['id']) \
- .one_or_none()
-
- # Our local ticket
- ticket = pagure_db \
- .query(model.Ticket) \
- .filter(model.Ticket.id == message['issue']['id'],
- model.Ticket.project_id == message['project']['id']) \
- .one_or_none()
-
- tracker_url = project.uri + '/issues'
-
- # Check if this tracker is only used to interact with a remote one
- remote_tracker = forgefed_graph.value(rdflib.URIRef(tracker_url),
- rdflib.OWL.sameAs)
-
- if remote_tracker:
- log.debug('Sending new comment to remote tracker...')
-
- assert ticket.remote_uri, 'Ticket not linked to remote ticket.'
-
- # Notify the remote tracker about the new comment
- person.create(comment.jsonld, to=remote_tracker)
-
- else:
- log.debug('Not a remote tracker. Will send new comment to tracker followers '
- + 'and watchers.')
-
- # Retrieve the pagure "watchlist"
- watchlist = pagure.lib.query.get_watch_list(pagure_db, ticket)
- actors = []
-
- for username in watchlist:
- actor = pagure_db \
- .query(model.Person) \
- .filter(model.Person.user == username) \
- .one_or_none()
-
- actors.append(actor.uri)
-
- # Send the Activity
- person.create(comment.jsonld, to=actors)
-
- if topic == 'issue.edit':
- # A user has edited an issue
-
- # The Ticket that was modified
- ticket = pagure_db \
- .query(model.Ticket) \
- .filter(model.Ticket.id == message['issue']['id'],
- model.Ticket.project_id == message['project']['id']) \
- .one_or_none()
-
- # The user that edited the Ticket
- person = pagure_db \
- .query(model.Person) \
- .filter(model.Person.user == message['agent']) \
- .one_or_none()
-
- project = pagure_db \
- .query(model.Projects) \
- .filter(model.Projects.id == message['project']['id']) \
- .one_or_none()
-
- # Let's fetch the JSONLD object of the Ticket that has been edited
- ticket_jsonld = activitypub.fetch(ticket.uri)
-
- # Let's replace the fields that have changed
- if 'status' in message['fields']:
- status = message['fields']['status'].upper()
-
- if status == 'CLOSED':
- ticket_jsonld['status'] = 'Closed'
-
- if status == 'OPEN':
- ticket_jsonld['status'] = 'Open'
-
- if 'content' in message['fields']:
- ticket_jsonld['content'] = content
-
- # If the user has edited the Ticket of a remote tracker, we just
- # send the Activity to the tracker
- if ticket.is_remote:
- log.debug('Local user has edited the remote Ticket {}'.format(ticket_jsonld['id']))
-
- person.update(ticket_jsonld, to=project.uri)
-
- # otherwise we send the Activity to the Tickets' watchlist
- else:
- log.debug('Local user has edited the local Ticket {}'.format(ticket_jsonld['id']))
-
- # Retrieve the pagure "watchlist"
- watchlist = pagure.lib.query.get_watch_list(pagure_db, ticket)
- actors = []
-
- for username in watchlist:
- actor = pagure_db \
- .query(model.Person) \
- .filter(model.Person.user == username) \
- .one_or_none()
-
- actors.append(actor.uri)
-
- # Send the Activity
- person.update(ticket_jsonld, to=actors)
-
|