Esempio n. 1
0
def remove_wire_items():
    data = get_json_or_400()
    assert data.get('items')

    items_service = get_resource_service('items')
    versions_service = get_resource_service('items_versions')

    ids = []
    for doc in items_service.get_from_mongo(
            req=None, lookup={'_id': {
                '$in': data['items']
            }}):
        ids.append(doc['_id'])
        ids.extend(doc.get('ancestors') or [])

    if not ids:
        flask.abort(404, gettext('Not found'))

    docs = list(doc for doc in items_service.get_from_mongo(
        req=None, lookup={'_id': {
            '$in': ids
        }}))

    for doc in docs:
        items_service.on_delete(doc)

    items_service.delete({'_id': {'$in': ids}})

    for doc in docs:
        items_service.on_deleted(doc)
        versions_service.on_item_deleted(doc)

    push_notification('items_deleted', ids=ids)

    return flask.jsonify(), 200
Esempio n. 2
0
def notify_agenda_topic_matches(item, users_dict):
    topics = get_agenda_notification_topics(item, users_dict)

    topic_matches = [t['_id'] for t in topics]

    if topic_matches:
        push_notification('topic_matches', item=item, topics=topic_matches)
        send_topic_notification_emails(item, topics, topic_matches, users_dict)
Esempio n. 3
0
def notify_topic_matches(item, users_dict, companies_dict):
    topics = get_notification_topics()

    topic_matches = superdesk.get_resource_service('wire_search'). \
        get_matching_topics(item['_id'], topics, users_dict, companies_dict)

    if topic_matches:
        push_notification('topic_matches', item=item, topics=topic_matches)
        send_topic_notification_emails(item, topics, topic_matches, users_dict)
Esempio n. 4
0
    def set_delivery(self, wire_item):
        if not wire_item.get('coverage_id'):
            return

        def is_delivery_validated(coverage, item):
            latest_delivery = get_latest_available_delivery(coverage)
            if not latest_delivery or not item.get('rewrite_sequence'):
                return True

            if item.get('rewrite_sequence', 0) >= latest_delivery.get('sequence_no', 0) \
                    or item.get('firstpublished') >= latest_delivery.get('publish_time'):
                return True

            return False

        query = {
            'bool': {
                'must': [
                    {'nested': {
                        'path': 'coverages',
                        'query': {
                            'bool': {
                                'must': [
                                    {'term': {'coverages.coverage_id': wire_item['coverage_id']}}
                                ]
                            }
                        },
                    }}
                ],
            }
        }

        agenda_items = self.get_items_by_query(query)
        for item in agenda_items:
            wire_item.setdefault('agenda_id', item['_id'])
            wire_item.setdefault('agenda_href', url_for('agenda.item', _id=item['_id']))
            coverages = item['coverages']
            for coverage in coverages:
                if coverage['coverage_id'] == wire_item['coverage_id'] and is_delivery_validated(coverage, item):
                    coverage['delivery_id'] = wire_item['guid']
                    coverage['delivery_href'] = url_for_wire(None, _external=False, section='wire.item',
                                                             _id=wire_item['guid'])
                    self.system_update(item['_id'], {'coverages': coverages}, item)

                    # Notify agenda to update itself with new details of coverage
                    self.enhance_coverage_with_wire_details(coverage, wire_item)
                    push_notification('new_item', _items=[item])

                    self.notify_new_coverage(item, wire_item)
                    break
        return agenda_items
Esempio n. 5
0
    def _send_notification(section, users_ids):
        if not users_ids:
            return

        app.data.insert('notifications', [{
            'item': item['_id'],
            'user': user
        } for user in users_ids])

        push_notification('history_matches',
                          item=item,
                          users=users_ids,
                          section=section)
        send_user_notification_emails(item, users_ids, users_dict, section)
Esempio n. 6
0
def notify_new_item(item, check_topics=True):
    if not item or item.get('type') == 'composite':
        return

    user_dict = get_user_dict()
    user_ids = [u['_id'] for u in user_dict.values()]

    company_dict = get_company_dict()
    company_ids = [c['_id'] for c in company_dict.values()]

    push_notification('new_item', item=item['_id'])

    if check_topics:
        if item.get('type') == 'text':
            notify_wire_topic_matches(item, user_dict, company_dict)
        else:
            notify_agenda_topic_matches(item, user_dict)

    notify_user_matches(item, user_dict, company_dict, user_ids, company_ids)
Esempio n. 7
0
 def notify_agenda_update(self, update, agenda, events_only=False):
     if agenda:
         user_dict = get_user_dict()
         company_dict = get_company_dict()
         notify_user_ids = filter_active_users(agenda.get('watches', []), user_dict, company_dict, events_only)
         users = [user_dict[str(user_id)] for user_id in notify_user_ids]
         for user in users:
             app.data.insert('notifications', [{
                 'item': agenda['_id'],
                 'user': user['_id']
             }])
             send_agenda_notification_email(
                 user,
                 agenda,
                 agenda_notifications[update]['message'],
                 agenda_notifications[update]['subject'],
             )
         push_notification('agenda_update',
                           item=agenda,
                           users=notify_user_ids)
Esempio n. 8
0
def notify_user_matches(item, users_dict, companies_dict, user_ids,
                        company_ids):

    related_items = item.get('ancestors', [])
    related_items.append(item['_id'])

    history_users = get_history_users(related_items, user_ids, company_ids)
    bookmark_users = superdesk.get_resource_service('wire_search'). \
        get_matching_bookmarks(related_items, users_dict, companies_dict)

    history_users.extend(bookmark_users)
    history_users = list(set(history_users))

    if history_users:
        for user in history_users:
            app.data.insert('notifications', [{
                'item': item['_id'],
                'user': user
            }])
        push_notification('history_matches', item=item, users=history_users)
        send_user_notification_emails(item, history_users, users_dict)
Esempio n. 9
0
def notify_new_item(item, check_topics=True):
    if item.get('type') == 'composite':
        return

    lookup = {'is_enabled': True}
    all_users = list(query_resource('users', lookup=lookup, max_results=200))
    user_ids = [u['_id'] for u in all_users]
    users_dict = {str(user['_id']): user for user in all_users}

    all_companies = list(
        query_resource('companies', lookup=lookup, max_results=200))
    company_ids = [c['_id'] for c in all_companies]
    companies_dict = {
        str(company['_id']): company
        for company in all_companies
    }

    push_notification('new_item', item=item['_id'])

    if check_topics:
        notify_topic_matches(item, users_dict, companies_dict)
    notify_user_matches(item, users_dict, companies_dict, user_ids,
                        company_ids)
Esempio n. 10
0
    def notify_agenda_update(self, update_agenda, original_agenda, item=None, events_only=False,
                             related_planning_removed=None, coverage_updated=None):
        agenda = deepcopy(update_agenda)
        if agenda and original_agenda.get('state') != WORKFLOW_STATE.KILLED:
            user_dict = get_user_dict()
            company_dict = get_company_dict()
            coverage_watched = None
            for c in (original_agenda.get('coverages') or []):
                if len(c.get('watches') or []) > 0:
                    coverage_watched = True
                    break

            notify_user_ids = filter_active_users(original_agenda.get('watches', []),
                                                  user_dict,
                                                  company_dict,
                                                  events_only)

            users = [user_dict[str(user_id)] for user_id in notify_user_ids]
            # Only one push-notification
            push_notification('agenda_update',
                              item=agenda,
                              users=notify_user_ids)

            if len(notify_user_ids) == 0 and not coverage_watched:
                return

            def get_detailed_coverage(cov):
                plan = next((p for p in (agenda.get('planning_items') or []) if p['guid'] == cov.get('planning_id')),
                            None)
                if plan and plan.get('state') != WORKFLOW_STATE.KILLED:
                    detail_cov = next((c for c in (plan.get('coverages') or [])
                                       if c.get('coverage_id') == cov.get('coverage_id')), None)
                    if detail_cov:
                        detail_cov['watches'] = cov.get('watches')

                    return detail_cov

                original_cov = next((c for c in original_agenda.get('coverages') if
                                    c['coverage_id'] == cov['coverage_id']), cov)
                cov['watches'] = original_cov.get('watches') or []
                return cov

            def fill_all_coverages(skip_coverages=[], cancelled=False, use_original_agenda=False):
                fill_list = coverage_updates['unaltered_coverages'] if not cancelled else \
                        coverage_updates['cancelled_coverages']
                for coverage in (agenda if not use_original_agenda else original_agenda).get('coverages') or []:
                    if not next((s for s in skip_coverages if s.get('coverage_id') == coverage.get('coverage_id')),
                                None):
                        detailed_coverage = get_detailed_coverage(coverage)
                        if detailed_coverage:
                            fill_list.append(detailed_coverage)

            coverage_updates = {
                'modified_coverages': [] if not coverage_updated else [coverage_updated],
                'cancelled_coverages': [],
                'unaltered_coverages': []
            }

            only_new_coverages = len(coverage_updates['modified_coverages']) == 0
            time_updated = False
            state_changed = False
            coverage_modified = False

            # Send notification for only these state changes
            notify_states = [WORKFLOW_STATE.CANCELLED, WORKFLOW_STATE.RESCHEDULED, WORKFLOW_STATE.POSTPONED,
                             WORKFLOW_STATE.KILLED, WORKFLOW_STATE.SCHEDULED]

            if not coverage_updated:  # If not story updates - but from planning side
                if not related_planning_removed:
                    # Send notification if time got updated
                    if original_agenda.get('dates') and agenda.get('dates'):
                        time_updated = (original_agenda.get('dates') or {}).get('start').replace(tzinfo=None) != \
                                       (agenda.get('dates') or {}).get('start').replace(tzinfo=None) or \
                            (original_agenda.get('dates') or {}).get('end').replace(tzinfo=None) != \
                            (agenda.get('dates') or {}).get('end').replace(tzinfo=None)

                    if agenda.get('state') and agenda.get('state') != original_agenda.get('state'):
                        state_changed = agenda.get('state') in notify_states

                    if not state_changed:
                        if time_updated:
                            fill_all_coverages()
                        else:
                            for coverage in agenda.get('coverages') or []:
                                existing_coverage = next((c for c in original_agenda.get('coverages') or []
                                                          if c['coverage_id'] == coverage['coverage_id']), None)
                                detailed_coverage = get_detailed_coverage(coverage)
                                if detailed_coverage:
                                    if not existing_coverage:
                                        if coverage['workflow_status'] != WORKFLOW_STATE.CANCELLED:
                                            coverage_updates['modified_coverages'].append(detailed_coverage)
                                    elif coverage.get('workflow_status') == WORKFLOW_STATE.CANCELLED and \
                                            existing_coverage.get('workflow_status') != coverage.get('workflow_status'):
                                        coverage_updates['cancelled_coverages'].append(detailed_coverage)
                                    elif (coverage.get('delivery_state') != existing_coverage.get('delivery_state') and
                                            coverage.get('delivery_state') == 'published') or \
                                        (coverage.get('workflow_status') != existing_coverage.get('workflow_status') and
                                            coverage.get('workflow_status') == 'completed') or \
                                            (existing_coverage.get('scheduled') != coverage.get('scheduled')):
                                        coverage_updates['modified_coverages'].append(detailed_coverage)
                                        only_new_coverages = False
                                    elif detailed_coverage['coverage_id'] != \
                                            (coverage_updated or {}).get('coverage_id'):
                                        coverage_updates['unaltered_coverages'].append(detailed_coverage)

                            # Check for removed coverages - show it as cancelled
                            if item and item.get('type') == 'planning':
                                for original_cov in original_agenda.get('coverages') or []:
                                    updated_cov = next((c for c in (agenda.get('coverages') or [])
                                                        if c.get('coverage_id') ==
                                                        original_cov.get('coverage_id')), None)
                                    if not updated_cov:
                                        coverage_updates['cancelled_coverages'].append(original_cov)
                    else:
                        fill_all_coverages(cancelled=False if agenda.get('state') == WORKFLOW_STATE.SCHEDULED else True,
                                           use_original_agenda=True)
                else:
                    fill_all_coverages(related_planning_removed.get('coverages') or [])
                    # Add removed coverages:
                    for coverage in related_planning_removed.get('coverages') or []:
                        detailed_coverage = get_detailed_coverage(coverage)
                        if detailed_coverage:
                            coverage_updates['cancelled_coverages'].append(detailed_coverage)

            if len(coverage_updates['modified_coverages']) > 0 or len(coverage_updates['cancelled_coverages']) > 0:
                coverage_modified = True

            if coverage_updated or related_planning_removed or time_updated or state_changed or coverage_modified:
                agenda['name'] = agenda.get('name', original_agenda.get('name'))
                agenda['definition_short'] = agenda.get('definition_short', original_agenda.get('definition_short'))
                agenda['ednote'] = agenda.get('ednote', original_agenda.get('ednote'))
                agenda['state_reason'] = agenda.get('state_reason', original_agenda.get('state_reason'))
                subject = '{} -{} updated'.format(agenda['name'] or agenda['headline'] or agenda['slugline'],
                                                  ' Coverage' if coverage_modified else '')
                action = 'been updated.'
                if state_changed:
                    action = 'been {}.'.format(agenda.get('state') if agenda.get('state') != WORKFLOW_STATE.KILLED else
                                               'removed from the Agenda calendar')

                if len(coverage_updates['modified_coverages']) > 0 and only_new_coverages and \
                        len(coverage_updates['cancelled_coverages']) == 0:
                    action = 'new coverage(s).'

                message = 'The {} you have been following has {}'.format(
                    'event' if agenda.get('event') else 'coverage plan', action
                )
                if agenda.get('state_reason'):
                    reason_prefix = agenda.get('state_reason').find(':')
                    if reason_prefix > 0:
                        message = '{} {}'.format(
                                message, agenda['state_reason'][(reason_prefix+1):len(agenda['state_reason'])])

                # append coverage watching users too - except for unaltered_coverages
                for c in coverage_updates['cancelled_coverages'] + coverage_updates['modified_coverages']:
                    if c.get('watches'):
                        notify_user_ids = filter_active_users(c['watches'], user_dict, company_dict, events_only)
                        users = users + [user_dict[str(user_id)] for user_id in notify_user_ids]

                # Send notifications to users
                for user in users:
                    app.data.insert('notifications', [{
                        'item': agenda.get('_id'),
                        'user': user['_id']
                    }])

                    send_agenda_notification_email(
                        user,
                        agenda,
                        message,
                        subject,
                        original_agenda,
                        coverage_updates,
                        related_planning_removed,
                        coverage_updated,
                        time_updated,
                    )
Esempio n. 11
0
    def set_delivery(self, wire_item):
        if not wire_item.get('coverage_id'):
            return

        def is_delivery_validated(coverage, item):
            latest_delivery = get_latest_available_delivery(coverage)
            if not latest_delivery or not item.get('rewrite_sequence'):
                return True

            if (item.get('rewrite_sequence') or 0) >= latest_delivery.get('sequence_no', 0) or \
                    (item.get('publish_schedule') or item.get('firstpublished')) >= latest_delivery.get('publish_time'):
                return True

            return False

        query = {
            'bool': {
                'must': [
                    {'nested': {
                        'path': 'coverages',
                        'query': {
                            'bool': {
                                'must': [
                                    {'term': {'coverages.coverage_id': wire_item['coverage_id']}}
                                ]
                            }
                        },
                    }}
                ],
            }
        }

        agenda_items = self.get_items_by_query(query)
        for item in agenda_items:
            self.enhance_coverage_watches(item)
            coverages = item['coverages']
            for coverage in coverages:
                if coverage['coverage_id'] == wire_item['coverage_id'] and is_delivery_validated(coverage, item):
                    coverage['delivery_id'] = wire_item['guid']
                    coverage['delivery_href'] = url_for_wire(None, _external=False, section='wire.item',
                                                             _id=wire_item['guid'])
                    coverage['workflow_status'] = ASSIGNMENT_WORKFLOW_STATE.COMPLETED
                    deliveries = coverage['deliveries']
                    d = next((d for d in deliveries if d.get('delivery_id') == wire_item['guid']), None)
                    if d and d.get('delivery_state') != 'published':
                        d['delivery_state'] = 'published'
                        d['publish_time'] = parse_date_str(wire_item.get('publish_schedule') or
                                                           wire_item.get('firstpublished'))

                    self.system_update(item['_id'], {'coverages': coverages}, item)
                    updated_agenda = get_entity_or_404(item.get('_id'), 'agenda')

                    # Notify agenda to update itself with new details of coverage
                    self.enhance_coverage_with_wire_details(coverage, wire_item)
                    push_notification('new_item', _items=[item])

                    # If published first time, coverage completion will trigger email - not needed now
                    if (d or {}).get('sequence_no', 0) > 0:
                        self.notify_agenda_update(updated_agenda, updated_agenda, None, True, None, coverage)
                    break
        return agenda_items