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
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)
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)
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
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)
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)
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)
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)
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)
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, )
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