def set_delivery(coverage, deliveries, orig_coverage=None): cov_deliveries = [] if coverage['coverage_type'] == 'text': for d in (deliveries or []): cov_deliveries.append({ 'delivery_id': d.get('item_id'), 'delivery_href': url_for_wire(None, _external=False, section='wire.item', _id=d.get('item_id')), 'delivery_state': d.get('item_state'), 'sequence_no': d.get('sequence_no') or 0, 'publish_time': parse_date_str(d.get('publish_time')) }) else: if coverage.get('workflow_status') == 'completed': if orig_coverage.get( 'workflow_status') != coverage['workflow_status']: cov_deliveries.append({ 'sequence_no': 0, 'delivery_state': 'published', 'publish_time': (next( (parse_date_str(d.get('publish_time')) for d in deliveries), None) or utcnow()) }) try: cov_deliveries[0][ 'delivery_href'] = app.set_photo_coverage_href( coverage, planning_item, cov_deliveries) except Exception as e: logger.exception(e) logger.error( 'Failed to generate delivery_href for coverage={}'. format(coverage.get('coverage_id'))) elif (len((orig_coverage or {}).get('deliveries') or []) > 0): cov_deliveries.append(orig_coverage['deliveries'][0]) coverage['deliveries'] = cov_deliveries # Sort the deliveries in reverse sequence order here, so sorting required anywhere else coverage['deliveries'].sort(key=lambda d: d['sequence_no'], reverse=True) # Get latest delivery that was 'published' latest_available_delivery = get_latest_available_delivery( coverage) or {} coverage['delivery_id'] = latest_available_delivery.get('delivery_id') coverage['delivery_href'] = latest_available_delivery.get( 'delivery_href') coverage['publish_time'] = latest_available_delivery.get( 'publish_time')
def set_agenda_metadata_from_planning(agenda, planning_item): """Sets agenda metadata from a given planning""" parse_dates(planning_item) set_dates(agenda) if not planning_item.get('event_item'): # adhoc planning item agenda['name'] = planning_item.get('name') agenda['headline'] = planning_item.get('headline') agenda['slugline'] = planning_item.get('slugline') agenda['ednote'] = planning_item.get('ednote') agenda['place'] = planning_item.get('place') agenda['subject'] = format_qcode_items(planning_item.get('subject')) agenda['products'] = planning_item.get('products') agenda['urgency'] = planning_item.get('urgency') agenda['definition_short'] = planning_item.get('description_text') or agenda.get('definition_short') agenda['definition_long'] = planning_item.get('abstract') or agenda.get('definition_long') agenda['service'] = format_qcode_items(planning_item.get('anpa_category')) agenda['state'] = planning_item.get('state') agenda['state_reason'] = planning_item.get('state_reason') if not agenda.get('planning_items'): agenda['planning_items'] = [] new_plan = False plan = next( (p for p in (agenda.get('planning_items')) if p.get('guid') == planning_item.get('guid')), {} ) if not plan: new_plan = True plan['_id'] = planning_item.get('_id') plan['guid'] = planning_item.get('guid') plan['slugline'] = planning_item.get('slugline') plan['description_text'] = planning_item.get('description_text') plan['headline'] = planning_item.get('headline') plan['abstract'] = planning_item.get('abstract') plan['place'] = planning_item.get('place') plan['subject'] = format_qcode_items(planning_item.get('subject')) plan['service'] = format_qcode_items(planning_item.get('anpa_category')) plan['urgency'] = planning_item.get('urgency') plan['planning_date'] = planning_item.get('planning_date') plan['coverages'] = planning_item.get('coverages') plan['ednote'] = planning_item.get('ednote') plan['internal_note'] = planning_item.get('internal_note') plan['versioncreated'] = parse_date_str(planning_item.get('versioncreated')) plan['firstcreated'] = parse_date_str(planning_item.get('firstcreated')) plan['state'] = planning_item.get('state') plan['state_reason'] = planning_item.get('state_reason') plan['products'] = planning_item.get('products') plan['agendas'] = planning_item.get('agendas') if new_plan: agenda['planning_items'].append(plan) return new_plan
def publish_item(doc, original): """Duplicating the logic from content_api.publish service.""" set_dates(doc) doc['firstpublished'] = parse_date_str(doc.get('firstpublished')) doc['publish_schedule'] = parse_date_str(doc.get('publish_schedule')) doc.setdefault('wordcount', get_word_count(doc.get('body_html', ''))) doc.setdefault('charcount', get_char_count(doc.get('body_html', ''))) service = superdesk.get_resource_service('content_api') service.datasource = 'items' if 'evolvedfrom' in doc: parent_item = service.find_one(req=None, _id=doc['evolvedfrom']) if parent_item: doc['ancestors'] = copy(parent_item.get('ancestors', [])) doc['ancestors'].append(doc['evolvedfrom']) doc['bookmarks'] = parent_item.get('bookmarks', []) doc['planning_id'] = parent_item.get('planning_id') doc['coverage_id'] = parent_item.get('coverage_id') else: logger.warning("Failed to find evolvedfrom item %s for %s", doc['evolvedfrom'], doc['guid']) fix_hrefs(doc) logger.debug('publishing %s', doc['guid']) for assoc in doc.get('associations', {}).values(): if assoc: assoc.setdefault('subscribers', []) if doc.get('associations', {}).get('featuremedia'): app.generate_renditions(doc) # If there is a function defined that generates renditions for embedded images call it. if app.generate_embed_renditions: app.generate_embed_renditions(doc) try: if doc.get('coverage_id'): agenda_items = superdesk.get_resource_service( 'agenda').set_delivery(doc) if agenda_items: [ notify_new_item(item, check_topics=False) for item in agenda_items ] except Exception as ex: logger.info('Failed to notify new wire item for Agenda watches') logger.exception(ex) publish_item_signal.send(app._get_current_object(), item=doc, is_new=original is None) _id = service.create([doc])[0] if 'associations' not in doc and original is not None and bool( original.get('associations', {})): service.patch(_id, updates={'associations': None}) if 'evolvedfrom' in doc and parent_item: service.system_update(parent_item['_id'], {'nextversion': _id}, parent_item) return _id
def set_delivery(coverage, deliveries): cov_deliveries = [] if coverage['coverage_type'] == 'text': for d in (deliveries or []): cov_deliveries.append({ 'delivery_id': d.get('item_id'), 'delivery_href': url_for_wire(None, _external=False, section='wire.item', _id=d.get('item_id')), 'delivery_state': d.get('item_state'), 'sequence_no': d.get('sequence_no', 0), 'publish_time': parse_date_str(d.get('publish_time')) }) else: if coverage.get('workflow_status') == 'completed': cov_deliveries.append({ 'delivery_href': app.set_photo_coverage_href(coverage, planning_item), 'sequence_no': 0 }) coverage['deliveries'] = cov_deliveries # Sort the deliveries in reverse sequence order here, so sorting required anywhere else coverage['deliveries'].sort(key=lambda d: d['sequence_no'], reverse=True) # Get latest delivery that was 'published' latest_available_delivery = get_latest_available_delivery(coverage) or {} coverage['delivery_id'] = latest_available_delivery.get('delivery_id') coverage['delivery_href'] = latest_available_delivery.get('delivery_href') coverage['publish_time'] = latest_available_delivery.get('publish_time')
def publish_item(doc, is_new): """Duplicating the logic from content_api.publish service.""" set_dates(doc) doc['firstpublished'] = parse_date_str(doc.get('firstpublished')) doc.setdefault('wordcount', get_word_count(doc.get('body_html', ''))) doc.setdefault('charcount', get_char_count(doc.get('body_html', ''))) service = superdesk.get_resource_service('content_api') if 'evolvedfrom' in doc: parent_item = service.find_one(req=None, _id=doc['evolvedfrom']) if parent_item: doc['ancestors'] = copy(parent_item.get('ancestors', [])) doc['ancestors'].append(doc['evolvedfrom']) doc['bookmarks'] = parent_item.get('bookmarks', []) doc['planning_id'] = parent_item.get('planning_id') doc['coverage_id'] = parent_item.get('coverage_id') else: logger.warning("Failed to find evolvedfrom item %s for %s", doc['evolvedfrom'], doc['guid']) fix_hrefs(doc) logger.debug('publishing %s', doc['guid']) for assoc in doc.get('associations', {}).values(): if assoc: assoc.setdefault('subscribers', []) if doc.get('associations', {}).get('featuremedia'): app.generate_renditions(doc) if doc.get('coverage_id'): agenda_items = superdesk.get_resource_service('agenda').set_delivery(doc) if agenda_items: [notify_new_item(item, check_topics=False) for item in agenda_items] publish_item_signal.send(app._get_current_object(), item=doc, is_new=is_new) _id = service.create([doc])[0] if 'evolvedfrom' in doc and parent_item: service.system_update(parent_item['_id'], {'nextversion': _id}, parent_item) return _id
def get_display_dates(agenda_date, planning_items): """ Returns the list of dates where a planning item or a coverage falls outside of the agenda item dates """ display_dates = [] for planning_item in planning_items: if not planning_item.get('coverages'): parsed_date = parse_date_str(planning_item['planning_date']) display_dates.append({'date': parsed_date}) for coverage in planning_item.get('coverages') or []: parsed_date = parse_date_str(coverage['planning']['scheduled']) display_dates.append({'date': parsed_date}) return display_dates
def add_to_send_list(self, alert_monitoring, profile, now, one_hour_ago, two_hours_ago, four_hours_ago, yesterday, last_week): last_run_time = parse_date_str( profile['last_run_time']) if profile.get('last_run_time') else None if last_run_time: last_run_time = utc_to_local(app.config['DEFAULT_TIMEZONE'], last_run_time) # Convert time to current date for range comparision if profile['schedule'].get('time'): hour_min = profile['schedule']['time'].split(':') schedule_today_plus_five_mins = utc_to_local( app.config['DEFAULT_TIMEZONE'], utcnow()) schedule_today_plus_five_mins = schedule_today_plus_five_mins.replace( hour=int(hour_min[0]), minute=int(hour_min[1])) schedule_today_plus_five_mins = schedule_today_plus_five_mins + datetime.timedelta( minutes=5) # Check if the time window is according to schedule if (profile['schedule']['interval'] == 'daily' and self.is_within_five_minutes( schedule_today_plus_five_mins, now) and self.is_past_range(last_run_time, yesterday)): alert_monitoring['daily']['w_lists'].append(profile) return # Check if the time window is according to schedule # Check if 'day' is according to schedule if (profile['schedule']['interval'] == 'weekly' and self.is_within_five_minutes( schedule_today_plus_five_mins, now) and schedule_today_plus_five_mins.strftime('%a').lower() == profile['schedule']['day'] and self.is_past_range(last_run_time, last_week)): alert_monitoring['weekly']['w_lists'].append(profile) return else: # Check if current time is within 'hourly' window if now.minute > 4: return if profile['schedule'][ 'interval'] == 'one_hour' and self.is_past_range( last_run_time, one_hour_ago): alert_monitoring['one']['w_lists'].append(profile) return if profile['schedule']['interval'] == 'two_hour' and now.hour % 2 == 0 and \ self.is_past_range(last_run_time, two_hours_ago): alert_monitoring['two']['w_lists'].append(profile) return if profile['schedule']['interval'] == 'four_hour' and now.hour % 4 == 0 and \ self.is_past_range(last_run_time, four_hours_ago): alert_monitoring['four']['w_lists'].append(profile) return
def publish_planning(planning): logger.debug('publishing planning %s', planning) service = superdesk.get_resource_service('agenda') agenda = None # update dates planning['planning_date'] = parse_date_str(planning['planning_date']) if planning.get('event_item'): # this is a planning for an event item # if there's an event then _id field will have the same value as event_id agenda = app.data.find_one('agenda', req=None, guid=planning['event_item']) if not agenda: # event id exists in planning item but event is not in the system logger.warning( 'Event {} for planning {} couldn\'t be found'.format( planning['event_item'], planning)) # create new agenda agenda = init_adhoc_agenda(planning) else: if planning.get('state') in [WORKFLOW_STATE.CANCELLED, WORKFLOW_STATE.KILLED] or \ planning.get('pubstatus') == 'cancelled': # remove the planning item from the list set_agenda_planning_items(agenda, planning, action='remove') service.patch(agenda['_id'], agenda) return agenda else: # there's no event item (ad-hoc planning item) agenda = init_adhoc_agenda(planning) # update agenda metadata new_plan = set_agenda_metadata_from_planning(agenda, planning) # add the planning item to the list set_agenda_planning_items(agenda, planning, action='add' if new_plan else 'update') if not agenda.get('_id'): # setting _id of agenda to be equal to planning if there's no event id agenda.setdefault( '_id', planning.get('event_item', planning['guid']) or planning['guid']) agenda.setdefault( 'guid', planning.get('event_item', planning['guid']) or planning['guid']) service.create([agenda])[0] else: # replace the original document service.patch(agenda['_id'], agenda) return agenda
def set_photo_coverage_href(coverage, planning_item, deliveries=[]): plan_coverage = next( (c for c in (planning_item or {}).get('coverages') or [] if c.get('coverage_id') == coverage.get('coverage_id')), coverage) content_type = plan_coverage.get('coverage_type') or ( plan_coverage.get('planning') or {}).get('g2_content_type') if not plan_coverage or plan_coverage['workflow_status'] != 'completed' or \ (content_type in ['picture', 'video', ] and \ not app.config.get('MULTIMEDIA_WEBSITE_SEARCH_URL')) or \ (content_type == 'video_explainer' and \ not app.config.get('EXPLAINERS_WEBSITE_URL')): return slugline = parse.quote( plan_coverage.get('slugline') or (plan_coverage.get( 'planning', {}).get('slugline', (planning_item or {}).get('slugline')))) scheduled = parse_date_str(deliveries[0]['publish_time']) if len(deliveries) > 0 and \ (deliveries[0] or {}).get('publish_time') else utcnow() from_date = scheduled - timedelta(hours=10) to_date = scheduled + timedelta(hours=2) video_keywords = '{"Keyword":"NZN","Operator":"NOT"}, ' if content_type == 'video' else '' date_range_filter = '"DateRange":[{"Start":"%s","End":"%s"}],"DateCreatedFilter":"false"' % ( from_date.strftime('%Y-%m-%dT%H:%M:%S'), to_date.strftime('%Y-%m-%dT%H:%M:%S')) keyword_filter = '"SearchKeywords":[%s{"Keyword":"%s","Operator":"AND"}]' % ( video_keywords, '\\"{}\\"'.format(slugline)) if content_type == 'video': return '{}(credit:"aap video") OR (credit:"pr video")/AAP VIDEO?q={{{}, {}}}'.format( app.config.get('MULTIMEDIA_WEBSITE_SEARCH_URL'), keyword_filter, date_range_filter) elif content_type == 'video_explainer': return '{}?q={{{}, {}}}'.format( app.config.get('EXPLAINERS_WEBSITE_URL'), keyword_filter, date_range_filter) elif content_type == 'graphic': return '{}"supplementalcategory:gra/Static Graphics/?q={{{}, {}}}'.format( app.config.get('MULTIMEDIA_WEBSITE_SEARCH_URL'), keyword_filter, date_range_filter) else: return '{}"{}"?q={{"MediaTypes":["image"],{}}}'.format( app.config.get('MULTIMEDIA_WEBSITE_SEARCH_URL'), slugline, date_range_filter)
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