def post(self): description = self.normalized_payload.get('description') linked_topic_ids = self.normalized_payload.get('linked_topic_ids') explanation_dict = self.normalized_payload.get('explanation_dict') rubrics = self.normalized_payload.get('rubrics') files = self.normalized_payload.get('files') new_skill_id = skill_services.get_new_skill_id() if linked_topic_ids is not None: topics = topic_fetchers.get_topics_by_ids(linked_topic_ids) for topic in topics: if topic is None: raise self.InvalidInputException topic_services.add_uncategorized_skill(self.user_id, topic.id, new_skill_id) if skill_services.does_skill_with_description_exist(description): raise self.InvalidInputException( 'Skill description should not be a duplicate.') skill = skill_domain.Skill.create_default_skill( new_skill_id, description, rubrics) skill.update_explanation(explanation_dict) image_filenames = skill_services.get_image_filenames_from_skill(skill) skill_services.save_new_skill(self.user_id, skill) for filename in image_filenames: base64_image = files.get(filename) bytes_image = base64.decodebytes(base64_image.encode('utf-8')) file_format = ( image_validation_services.validate_image_and_filename( bytes_image, filename)) image_is_compressible = (file_format in feconf.COMPRESSIBLE_IMAGE_FORMATS) fs_services.save_original_and_compressed_versions_of_image( filename, feconf.ENTITY_TYPE_SKILL, skill.id, bytes_image, 'image', image_is_compressible) self.render_json({'skillId': new_skill_id})
def post(self): description = self.payload.get('description') linked_topic_ids = self.payload.get('linked_topic_ids') explanation_dict = self.payload.get('explanation_dict') rubrics = self.payload.get('rubrics') if not isinstance(rubrics, list): raise self.InvalidInputException('Rubrics should be a list.') if not isinstance(explanation_dict, dict): raise self.InvalidInputException('Explanation should be a dict.') try: subtitled_html = ( state_domain.SubtitledHtml.from_dict(explanation_dict)) subtitled_html.validate() except Exception as e: raise self.InvalidInputException( 'Explanation should be a valid SubtitledHtml dict.') from e rubrics = [skill_domain.Rubric.from_dict(rubric) for rubric in rubrics] new_skill_id = skill_services.get_new_skill_id() if linked_topic_ids is not None: topics = topic_fetchers.get_topics_by_ids(linked_topic_ids) for topic in topics: if topic is None: raise self.InvalidInputException topic_services.add_uncategorized_skill(self.user_id, topic.id, new_skill_id) skill_domain.Skill.require_valid_description(description) if skill_services.does_skill_with_description_exist(description): raise self.InvalidInputException( 'Skill description should not be a duplicate.') skill = skill_domain.Skill.create_default_skill( new_skill_id, description, rubrics) skill.update_explanation( state_domain.SubtitledHtml.from_dict(explanation_dict)) image_filenames = skill_services.get_image_filenames_from_skill(skill) skill_services.save_new_skill(self.user_id, skill) image_validation_error_message_suffix = ( 'Please go to oppia.org/skill_editor/%s to edit ' 'the image.' % skill.id) for filename in image_filenames: image = self.request.get(filename) if not image: logging.exception( 'Image not provided for file with name %s when the skill ' 'with id %s was created.' % (filename, skill.id)) raise self.InvalidInputException( 'No image data provided for file with name %s. %s' % (filename, image_validation_error_message_suffix)) try: file_format = ( image_validation_services.validate_image_and_filename( image, filename)) except utils.ValidationError as e: e = '%s %s' % (e, image_validation_error_message_suffix) raise self.InvalidInputException(e) image_is_compressible = (file_format in feconf.COMPRESSIBLE_IMAGE_FORMATS) fs_services.save_original_and_compressed_versions_of_image( filename, feconf.ENTITY_TYPE_SKILL, skill.id, image, 'image', image_is_compressible) self.render_json({'skillId': new_skill_id})