def publish(self, doc, updates, target_output_channels=None): any_channel_closed, wrong_formatted_channels, queued = \ self.queue_transmission(doc=doc, target_output_channels=target_output_channels) if updates: desk = None if doc.get('task', {}).get('desk'): desk = get_resource_service('desks').find_one(req=None, _id=doc['task']['desk']) if not doc.get('ingest_provider'): updates['source'] = desk['source'] if desk and desk.get('source', '') \ else DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES user = get_user() if wrong_formatted_channels and len(wrong_formatted_channels) > 0: push_notification('item:publish:wrong:format', item=str(doc['_id']), unique_name=doc['unique_name'], desk=str(doc['task']['desk']), user=str(user.get('_id', '')), output_channels=[c['name'] for c in wrong_formatted_channels]) if not target_output_channels and not queued: raise PublishQueueError.item_not_queued_error(Exception('Nothing is saved to publish queue'), None) return any_channel_closed, queued
def update(self, id, updates, original): """ Handles workflow of each Publish, Corrected and Killed. """ try: user = get_user() last_updated = updates.get(config.LAST_UPDATED, utcnow()) if original[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE: self._publish_package_items(original, last_updated) set_sign_off(updates, original) queued_digital = False package_id = None if original[ITEM_TYPE] != CONTENT_TYPE.COMPOSITE: # if target_for is set the we don't to digital client. if not updates.get('targeted_for', original.get('targeted_for')): # check if item is in a digital package package_id = TakesPackageService().get_take_package_id(original) if package_id: queued_digital, takes_package = self._publish_takes_package(package_id, updates, original, last_updated) else: # if item is going to be sent to digital subscribers, package it as a take if self.sending_to_digital_subscribers(updates): updated = copy(original) updated.update(updates) # create a takes package package_id = TakesPackageService().package_story_as_a_take(updated, {}, None) original = get_resource_service('archive').find_one(req=None, _id=original['_id']) queued_digital, takes_package = self._publish_takes_package(package_id, updates, original, last_updated) # queue only text items queued_wire = \ self.publish(doc=original, updates=updates, target_media_type=WIRE if package_id else None) queued = queued_digital or queued_wire if not queued: raise PublishQueueError.item_not_queued_error(Exception('Nothing is saved to publish queue'), None) self._set_version_last_modified_and_state(original, updates, last_updated) self._update_archive(original=original, updates=updates, should_insert_into_versions=False) push_notification('item:publish', item=str(id), unique_name=original['unique_name'], desk=str(original.get('task', {}).get('desk', '')), user=str(user.get('_id', ''))) except SuperdeskApiError as e: raise e except KeyError as e: raise SuperdeskApiError.badRequestError( message="Key is missing on article to be published: {}".format(str(e))) except Exception as e: logger.exception("Something bad happened while publishing %s".format(id)) raise SuperdeskApiError.internalError(message="Failed to publish the item: {}".format(str(e)))
def update(self, id, updates, original): archived_item = super().find_one(req=None, _id=id) try: any_channel_closed = False if archived_item['type'] == 'composite': self.__publish_package_items(archived_item, updates[config.LAST_UPDATED]) # document is saved to keep the initial changes set_sign_off(updates, original) self.backend.update(self.datasource, id, updates, original) # document is saved to change the status if (original.get('publish_schedule') or updates.get('publish_schedule')) \ and original[config.CONTENT_STATE] not in PUBLISH_STATES: updates[config.CONTENT_STATE] = 'scheduled' else: updates['publish_schedule'] = None updates[config.CONTENT_STATE] = self.published_state original.update(updates) get_component(ItemAutosave).clear(original['_id']) if archived_item['type'] != 'composite': # check if item is in a digital package package_id = TakesPackageService().get_take_package_id(original) if package_id: # process the takes to form digital master file content package, package_updates = self.process_takes(take=original, package_id=package_id) package_updates[config.CONTENT_STATE] = self.published_state resolve_document_version(document=package_updates, resource=ARCHIVE, method='PATCH', latest_doc=package) self.backend.update(self.datasource, package['_id'], package_updates, package) package.update(package_updates) insert_into_versions(doc=package) # send it to the digital channels any_channel_closed_digital, queued_digital = \ self.publish(doc=package, updates=None, target_output_channels=DIGITAL) self.update_published_collection(published_item=package) else: any_channel_closed_digital = False queued_digital = False # queue only text items any_channel_closed_wire, queued_wire = \ self.publish(doc=original, updates=updates, target_output_channels=WIRE if package_id else None) any_channel_closed = any_channel_closed_digital or any_channel_closed_wire queued = queued_digital or queued_wire if not queued: raise PublishQueueError.item_not_queued_error(Exception('Nothing is saved to publish queue'), None) self.backend.update(self.datasource, id, updates, original) user = get_user() push_notification('item:publish:closed:channels' if any_channel_closed else 'item:publish', item=str(id), unique_name=archived_item['unique_name'], desk=str(archived_item.get('task', {}).get('desk', '')), user=str(user.get('_id', ''))) original.update(super().find_one(req=None, _id=id)) except SuperdeskApiError as e: raise e except KeyError as e: raise SuperdeskApiError.badRequestError( message="Key is missing on article to be published: {}" .format(str(e))) except Exception as e: logger.error("Something bad happened while publishing %s".format(id), e) raise SuperdeskApiError.internalError(message="Failed to publish the item: {}" .format(str(e)))
def publish(self, doc, updates, target_media_type=None): """ 1. Sets the Metadata Properties - source and pubstatus 2. Formats and queues the article to subscribers based on the state of the article: a. If the state of the article is killed then: i. An email should be sent to all Subscribers irrespective of their status. ii. The article should be formatted as per the type of the format and then queue article to the Subscribers who received the article previously. b. If the state of the article is corrected then: i. The article should be formatted as per the type of the format and then queue article to the Subscribers who received the article previously. ii. Fetch Active Subscribers and exclude those who received the article previously. iii. If article has 'targeted_for' property then exclude subscribers of type Internet from Subscribers list. iv. For each subscriber in the list, check if the article matches against publish filters and global filters if configured for the subscriber. If matches then the article should be formatted as per the type of the format and then queue article to the subscribers. c. If the state of the article is published then: i. Fetch Active Subscribers. ii. If article has 'targeted_for' property then exclude subscribers of type Internet from Subscribers list. iii. For each subscriber in the list, check if the article matches against publish filters and global filters if configured for the subscriber. If matches then the article should be formatted as per the type of the format and then queue article. 3. Sends notification if no formatter has found for any of the formats configured in Subscriber. """ queued = True no_formatters = [] updated = doc.copy() # Step 1 if updates: desk = None if doc.get('task', {}).get('desk'): desk = get_resource_service('desks').find_one(req=None, _id=doc['task']['desk']) if not doc.get('ingest_provider'): updates['source'] = desk['source'] if desk and desk.get('source', '') \ else DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES updates['pubstatus'] = PUB_STATUS.CANCELED if self.publish_type == 'killed' else PUB_STATUS.USABLE updated.update(updates) # Step 2(a) if self.published_state == 'killed': req = ParsedRequest() req.sort = '[("completed_at", 1)]' queued_items = get_resource_service('publish_queue').get( req=req, lookup={'item_id': updated[config.ID_FIELD]}) if queued_items.count(): queued_items = list(queued_items) # Step 2(a)(i) subscribers = list(get_resource_service('subscribers').get(req=None, lookup=None)) recipients = [s.get('email') for s in subscribers if s.get('email')] send_article_killed_email(doc, recipients, queued_items[0].get('completed_at')) # Step 2(a)(ii) no_formatters, queued = self.queue_transmission(updated, subscribers, None) elif self.published_state == 'corrected': # Step 2(b) subscribers, subscribers_yet_to_receive = self.get_subscribers(updated) if subscribers: no_formatters, queued = self.queue_transmission(updated, subscribers) if subscribers_yet_to_receive: # Step 2(b)(iv) formatters_not_found, queued_new_subscribers = \ self.queue_transmission(updated, subscribers_yet_to_receive, target_media_type) no_formatters.extend(formatters_not_found) elif self.published_state == 'published': # Step 2(c) subscribers, subscribers_yet_to_receive = self.get_subscribers(updated) # Step 2(c)(iii) no_formatters, queued = self.queue_transmission(updated, subscribers, target_media_type) # Step 3 user = get_user() if len(no_formatters) > 0: push_notification('item:publish:wrong:format', item=str(doc[config.ID_FIELD]), unique_name=doc['unique_name'], desk=str(doc.get('task', {}).get('desk', '')), user=str(user.get(config.ID_FIELD, '')), formats=no_formatters) if not target_media_type and not queued: raise PublishQueueError.item_not_queued_error(Exception('Nothing is saved to publish queue'), None) return queued
def publish(self, doc, updates, target_media_type=None): """ Queue the content for publishing. 1. Sets the Metadata Properties - source and pubstatus 2. Get the subscribers. 3. Queue the content for subscribers 4. Queue the content for previously published subscribers if any. 5. Sends notification if no formatter has found for any of the formats configured in Subscriber. 6. If not queued and not formatters then raise exception. :param dict doc: document to publish :param dict updates: updates for the document :param str target_media_type: dictate if the doc being queued is a Takes Package or an Individual Article. Valid values are - Wire, Digital. If Digital then the doc being queued is a Takes Package and if Wire then the doc being queues is an Individual Article. :return bool: if content is queued then True else False :raises PublishQueueError.item_not_queued_error: If the nothing is queued. """ queued = True no_formatters = [] updated = doc.copy() # Step 1 if updates: desk = None if doc.get('task', {}).get('desk'): desk = get_resource_service('desks').find_one(req=None, _id=doc['task']['desk']) if not doc.get('ingest_provider'): updates['source'] = desk['source'] if desk and desk.get('source', '') \ else DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES updates['pubstatus'] = PUB_STATUS.CANCELED if self.publish_type == 'killed' else PUB_STATUS.USABLE updated.update(updates) # Step 2 subscribers, subscribers_yet_to_receive = self.get_subscribers(doc, target_media_type) # Step 3 no_formatters, queued = self.queue_transmission(updated, subscribers) # Step 4 if subscribers_yet_to_receive: formatters_not_found, queued_new_subscribers = self.queue_transmission(updated, subscribers_yet_to_receive) no_formatters.extend(formatters_not_found) queued = queued or queued_new_subscribers # Step 5 user = get_user() if len(no_formatters) > 0: push_notification('item:publish:wrong:format', item=str(doc[config.ID_FIELD]), unique_name=doc['unique_name'], desk=str(doc.get('task', {}).get('desk', '')), user=str(user.get(config.ID_FIELD, '')), formats=no_formatters) # Step 6 if not target_media_type and not queued: raise PublishQueueError.item_not_queued_error(Exception('Nothing is saved to publish queue'), None) return queued