def get(self, opportunity_type): """Handles GET requests.""" if not feconf.COMMUNITY_DASHBOARD_ENABLED: raise self.PageNotFoundException search_cursor = self.request.get('cursor', None) if opportunity_type == constants.OPPORTUNITY_TYPE_TRANSLATION: language_code = self.request.get('language_code') if language_code is None or not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException opportunities, next_cursor, more = ( opportunity_services.get_translation_opportunities( language_code, search_cursor)) elif opportunity_type == constants.OPPORTUNITY_TYPE_VOICEOVER: language_code = self.request.get('language_code') if language_code is None or not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException opportunities, next_cursor, more = ( opportunity_services.get_voiceover_opportunities( language_code, search_cursor)) else: raise self.PageNotFoundException self.values = { 'opportunities': opportunities, 'next_cursor': next_cursor, 'more': more } self.render_json(self.values)
def post(self): username = self.payload.get('username') user_id = user_services.get_user_id_from_username(username) if user_id is None: raise self.InvalidInputException('Invalid username: %s' % username) category = self.payload.get('category') language_code = self.payload.get('language_code', None) if category == constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_TRANSLATION: if not utils.is_supported_audio_language_code(language_code): raise self.InvalidInputException( 'Invalid language_code: %s' % language_code) if user_services.can_review_translation_suggestions( user_id, language_code=language_code): raise self.InvalidInputException( 'User %s already has rights to review translation in ' 'language code %s' % (username, language_code)) user_services.allow_user_to_review_translation_in_language( user_id, language_code) elif category == constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_VOICEOVER: if not utils.is_supported_audio_language_code(language_code): raise self.InvalidInputException( 'Invalid language_code: %s' % language_code) if user_services.can_review_voiceover_applications( user_id, language_code=language_code): raise self.InvalidInputException( 'User %s already has rights to review voiceover in ' 'language code %s' % (username, language_code)) user_services.allow_user_to_review_voiceover_in_language( user_id, language_code) elif category == constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_QUESTION: if user_services.can_review_question_suggestions(user_id): raise self.InvalidInputException( 'User %s already has rights to review question.' % ( username)) user_services.allow_user_to_review_question(user_id) elif category == constants.CONTRIBUTION_RIGHT_CATEGORY_SUBMIT_QUESTION: if user_services.can_submit_question_suggestions(user_id): raise self.InvalidInputException( 'User %s already has rights to submit question.' % ( username)) user_services.allow_user_to_submit_question(user_id) else: raise self.InvalidInputException( 'Invalid category: %s' % category) if category in [ constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_TRANSLATION, constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_VOICEOVER, constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_QUESTION ]: email_manager.send_email_to_new_contribution_reviewer( user_id, category, language_code=language_code) self.render_json({})
def validate(self): """Validates properties of the MachineTranslation. Raises: ValidationError. One or more attributes of the MachineTranslation are invalid. """ if not isinstance(self.source_language_code, python_utils.BASESTRING): raise utils.ValidationError( 'Expected source_language_code to be a string, received %s' % self.source_language_code ) # TODO(#12341): Tidy up this logic once we have a canonical list of # language codes. if not utils.is_supported_audio_language_code( self.source_language_code ) and not utils.is_valid_language_code( self.source_language_code ): raise utils.ValidationError( 'Invalid source language code: %s' % self.source_language_code) if not isinstance(self.target_language_code, python_utils.BASESTRING): raise utils.ValidationError( 'Expected target_language_code to be a string, received %s' % self.target_language_code ) # TODO(#12341): Tidy up this logic once we have a canonical list of # language codes. if not utils.is_supported_audio_language_code( self.target_language_code ) and not utils.is_valid_language_code( self.target_language_code ): raise utils.ValidationError( 'Invalid target language code: %s' % self.target_language_code) if self.source_language_code == self.target_language_code: raise utils.ValidationError( ( 'Expected source_language_code to be different from ' 'target_language_code: "%s" = "%s"') % ( self.source_language_code, self.target_language_code)) if not isinstance(self.source_text, python_utils.BASESTRING): raise utils.ValidationError( 'Expected source_text to be a string, received %s' % self.source_text ) if not isinstance(self.translated_text, python_utils.BASESTRING): raise utils.ValidationError( 'Expected translated_text to be a string, received %s' % self.translated_text )
def post(self): new_reviewer_username = self.payload.get('username') new_reviewer_user_id = ( user_services.get_user_id_from_username(new_reviewer_username)) if new_reviewer_user_id is None: raise self.InvalidInputException('Invalid username: %s' % new_reviewer_username) review_category = self.payload.get('review_category') language_code = self.payload.get('language_code', None) if review_category == constants.REVIEW_CATEGORY_TRANSLATION: if not utils.is_supported_audio_language_code(language_code): raise self.InvalidInputException('Invalid language_code: %s' % language_code) if user_services.can_review_translation_suggestions( new_reviewer_user_id, language_code=language_code): raise self.InvalidInputException( 'User %s already has rights to review translation in ' 'language code %s' % (new_reviewer_username, language_code)) user_services.allow_user_to_review_translation_in_language( new_reviewer_user_id, language_code) elif review_category == constants.REVIEW_CATEGORY_VOICEOVER: if not utils.is_supported_audio_language_code(language_code): raise self.InvalidInputException('Invalid language_code: %s' % language_code) if user_services.can_review_voiceover_applications( new_reviewer_user_id, language_code=language_code): raise self.InvalidInputException( 'User %s already has rights to review voiceover in ' 'language code %s' % (new_reviewer_username, language_code)) user_services.allow_user_to_review_voiceover_in_language( new_reviewer_user_id, language_code) elif review_category == constants.REVIEW_CATEGORY_QUESTION: if user_services.can_review_question_suggestions( new_reviewer_user_id): raise self.InvalidInputException( 'User %s already has rights to review question.' % (new_reviewer_username)) user_services.allow_user_to_review_question(new_reviewer_user_id) else: raise self.InvalidInputException('Invalid review_category: %s' % review_category) email_manager.send_email_to_new_community_reviewer( new_reviewer_user_id, review_category, language_code=language_code) self.render_json({})
def validate(self): """Validates a suggestion object of type SuggestionTranslateContent. Raises: ValidationError. One or more attributes of the SuggestionTranslateContent object are invalid. """ super(SuggestionTranslateContent, self).validate() if not isinstance(self.change, exp_domain.ExplorationChange): raise utils.ValidationError( 'Expected change to be an ExplorationChange, received %s' % type(self.change)) # The score sub_type needs to match the validation for exploration # category, i.e the second part of the score_category should match # the target exploration's category and we have a prod validation # for the same. if self.get_score_type() != suggestion_models.SCORE_TYPE_TRANSLATION: raise utils.ValidationError( 'Expected the first part of score_category to be %s ' ', received %s' % (suggestion_models.SCORE_TYPE_TRANSLATION, self.get_score_type())) if self.change.cmd != exp_domain.CMD_ADD_TRANSLATION: raise utils.ValidationError( 'Expected cmd to be %s, received %s' % (exp_domain.CMD_ADD_TRANSLATION, self.change.cmd)) if not utils.is_supported_audio_language_code( self.change.language_code): raise utils.ValidationError('Invalid language_code: %s' % self.change.language_code)
def get(self): """Handles GET requests.""" language_code = self.request.get('language_code') exp_id = self.request.get('exp_id') if not utils.is_supported_audio_language_code(language_code): raise self.InvalidInputException('Invalid language_code: %s' % (language_code)) if not opportunity_services.is_exploration_available_for_contribution( exp_id): raise self.InvalidInputException('Invalid exp_id: %s' % exp_id) exp = exp_fetchers.get_exploration_by_id(exp_id) state_names_to_content_id_mapping = exp.get_translatable_text( language_code) self.values = { 'state_names_to_content_id_mapping': (state_names_to_content_id_mapping), 'version': exp.version } self.render_json(self.values)
def validate(self): """Validates a suggestion object of type SuggestionTranslateContent. Raises: ValidationError: One or more attributes of the SuggestionTranslateContent object are invalid. """ super(SuggestionTranslateContent, self).validate() if not isinstance(self.change, exp_domain.ExplorationChange): raise utils.ValidationError( 'Expected change to be an ExplorationChange, received %s' % type(self.change)) if self.get_score_type() != suggestion_models.SCORE_TYPE_TRANSLATION: raise utils.ValidationError( 'Expected the first part of score_category to be %s ' ', received %s' % (suggestion_models.SCORE_TYPE_TRANSLATION, self.get_score_type())) if self.get_score_sub_type() not in constants.ALL_CATEGORIES: raise utils.ValidationError( 'Expected the second part of score_category to be a valid' ' category, received %s' % self.get_score_sub_type()) if self.change.cmd != exp_domain.CMD_ADD_TRANSLATION: raise utils.ValidationError( 'Expected cmd to be %s, received %s' % (exp_domain.CMD_ADD_TRANSLATION, self.change.cmd)) if not utils.is_supported_audio_language_code( self.change.language_code): raise utils.ValidationError('Invalid language_code: %s' % self.change.language_code)
def validate(self): """Validates different attributes of the class.""" if not isinstance(self.can_review_translation_for_language_codes, list): raise utils.ValidationError( 'Expected can_review_translation_for_language_codes to be a ' 'list, found: %s' % type(self.can_review_translation_for_language_codes)) for language_code in self.can_review_translation_for_language_codes: if not utils.is_supported_audio_language_code(language_code): raise utils.ValidationError('Invalid language_code: %s' % (language_code)) if len(self.can_review_translation_for_language_codes) != len( set(self.can_review_translation_for_language_codes)): raise utils.ValidationError( 'Expected can_review_translation_for_language_codes list not ' 'to have duplicate values, found: %s' % (self.can_review_translation_for_language_codes)) if not isinstance(self.can_review_voiceover_for_language_codes, list): raise utils.ValidationError( 'Expected can_review_voiceover_for_language_codes to be a ' 'list, found: %s' % type(self.can_review_voiceover_for_language_codes)) for language_code in self.can_review_voiceover_for_language_codes: if not utils.is_supported_audio_language_code(language_code): raise utils.ValidationError('Invalid language_code: %s' % (language_code)) if len(self.can_review_voiceover_for_language_codes) != len( set(self.can_review_voiceover_for_language_codes)): raise utils.ValidationError( 'Expected can_review_voiceover_for_language_codes list not to ' 'have duplicate values, found: %s' % (self.can_review_voiceover_for_language_codes)) if not isinstance(self.can_review_questions, bool): raise utils.ValidationError( 'Expected can_review_questions to be a boolean value, ' 'found: %s' % type(self.can_review_questions)) if not isinstance(self.can_submit_questions, bool): raise utils.ValidationError( 'Expected can_submit_questions to be a boolean value, ' 'found: %s' % type(self.can_submit_questions))
def is_supported_audio_language_code(obj): """Checks if the given obj (a string) represents a valid language code. Args: obj: str. A string. Returns: bool. Whether the given object is a valid audio language code. """ return utils.is_supported_audio_language_code(obj)
def validate(self): """Validates the CommunityContributionStats object. Raises: ValidationError. One or more attributes of the CommunityContributionStats object is invalid. """ for language_code, reviewer_count in ( self.translation_reviewer_counts_by_lang_code.items()): if reviewer_count < 0: raise utils.ValidationError( 'Expected the translation reviewer count to be ' 'non-negative for %s language code, recieved: %s.' % (language_code, reviewer_count)) # Translation languages are a part of audio languages. if not utils.is_supported_audio_language_code(language_code): raise utils.ValidationError( 'Invalid language code for the translation reviewer ' 'counts: %s.' % language_code) for language_code, suggestion_count in ( self.translation_suggestion_counts_by_lang_code.items()): if suggestion_count < 0: raise utils.ValidationError( 'Expected the translation suggestion count to be ' 'non-negative for %s language code, recieved: %s.' % (language_code, suggestion_count)) # Translation languages are a part of audio languages. if not utils.is_supported_audio_language_code(language_code): raise utils.ValidationError( 'Invalid language code for the translation suggestion ' 'counts: %s.' % language_code) if self.question_reviewer_count < 0: raise utils.ValidationError( 'Expected the question reviewer count to be non-negative, ' 'recieved: %s.' % (self.question_reviewer_count)) if self.question_suggestion_count < 0: raise utils.ValidationError( 'Expected the question suggestion count to be non-negative, ' 'recieved: %s.' % (self.question_suggestion_count))
def put(self): username = self.payload.get('username', None) if username is None: raise self.InvalidInputException('Missing username param') removal_type = self.payload.get('removal_type') user_id = user_services.get_user_id_from_username(username) if user_id is None: raise self.InvalidInputException( 'Invalid username: %s' % username) language_code = self.payload.get('language_code', None) if language_code is not None and not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException( 'Invalid language_code: %s' % language_code) if removal_type == constants.ACTION_REMOVE_ALL_REVIEW_RIGHTS: user_services.remove_community_reviewer(user_id) elif removal_type == constants.ACTION_REMOVE_SPECIFIC_REVIEW_RIGHTS: review_category = self.payload.get('review_category') if review_category == constants.REVIEW_CATEGORY_TRANSLATION: if not user_services.can_review_translation_suggestions( user_id, language_code=language_code): raise self.InvalidInputException( '%s does not have rights to review translation in ' 'language %s.' % (username, language_code)) user_services.remove_translation_review_rights_in_language( user_id, language_code) elif review_category == constants.REVIEW_CATEGORY_VOICEOVER: if not user_services.can_review_voiceover_applications( user_id, language_code=language_code): raise self.InvalidInputException( '%s does not have rights to review voiceover in ' 'language %s.' % (username, language_code)) user_services.remove_voiceover_review_rights_in_language( user_id, language_code) elif review_category == constants.REVIEW_CATEGORY_QUESTION: if not user_services.can_review_question_suggestions(user_id): raise self.InvalidInputException( '%s does not have rights to review question.' % ( username)) user_services.remove_question_review_rights(user_id) else: raise self.InvalidInputException( 'Invalid review_category: %s' % review_category) email_manager.send_email_to_removed_community_reviewer( user_id, review_category, language_code=language_code) else: raise self.InvalidInputException( 'Invalid removal_type: %s' % removal_type) self.render_json({})
def get(self, opportunity_type): """Handles GET requests.""" if not config_domain.CONTRIBUTOR_DASHBOARD_IS_ENABLED.value: raise self.PageNotFoundException search_cursor = self.request.get('cursor', None) if opportunity_type == constants.OPPORTUNITY_TYPE_SKILL: opportunities, next_cursor, more = ( self._get_skill_opportunities_with_corresponding_topic_name( search_cursor)) elif opportunity_type == constants.OPPORTUNITY_TYPE_TRANSLATION: language_code = self.request.get('language_code') if language_code is None or not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException opportunities, next_cursor, more = ( self._get_translation_opportunity_dicts( language_code, search_cursor)) elif opportunity_type == constants.OPPORTUNITY_TYPE_VOICEOVER: language_code = self.request.get('language_code') if language_code is None or not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException opportunities, next_cursor, more = ( self._get_voiceover_opportunity_dicts(language_code, search_cursor)) else: raise self.PageNotFoundException self.values = { 'opportunities': opportunities, 'next_cursor': next_cursor, 'more': more } self.render_json(self.values)
def get(self): category = self.request.get('category') language_code = self.request.get('language_code', None) if language_code is not None and not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException( 'Invalid language_code: %s' % language_code) if category not in [ constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_TRANSLATION, constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_VOICEOVER, constants.CONTRIBUTION_RIGHT_CATEGORY_REVIEW_QUESTION, constants.CONTRIBUTION_RIGHT_CATEGORY_SUBMIT_QUESTION]: raise self.InvalidInputException('Invalid category: %s' % category) usernames = user_services.get_contributor_usernames( category, language_code=language_code) self.render_json({'usernames': usernames})
def get(self): review_category = self.request.get('review_category') language_code = self.request.get('language_code', None) if language_code is not None and not ( utils.is_supported_audio_language_code(language_code)): raise self.InvalidInputException( 'Invalid language_code: %s' % language_code) if review_category not in [ constants.REVIEW_CATEGORY_TRANSLATION, constants.REVIEW_CATEGORY_VOICEOVER, constants.REVIEW_CATEGORY_QUESTION]: raise self.InvalidInputException( 'Invalid review_category: %s' % review_category) usernames = user_services.get_contribution_reviewer_usernames( review_category, language_code=language_code) self.render_json({'usernames': usernames})
def validate(self): """Validates various properties of the object. Raises: ValidationError: One or more attributes of the object are invalid. """ if not isinstance(self.topic_id, python_utils.BASESTRING): raise utils.ValidationError( 'Expected topic_id to be a string, received %s' % self.topic_id) if not isinstance(self.topic_name, python_utils.BASESTRING): raise utils.ValidationError( 'Expected topic_name to be a string, received %s' % self.topic_name) if not isinstance(self.story_id, python_utils.BASESTRING): raise utils.ValidationError( 'Expected story_id to be a string, received %s' % self.story_id) if not isinstance(self.story_title, python_utils.BASESTRING): raise utils.ValidationError( 'Expected story_title to be a string, received %s' % self.story_title) if not isinstance(self.chapter_title, python_utils.BASESTRING): raise utils.ValidationError( 'Expected chapter_title to be a string, received %s' % self.chapter_title) if not isinstance(self.content_count, int): raise utils.ValidationError( 'Expected content_count to be an integer, received %s' % self.content_count) if self.content_count < 0: raise utils.ValidationError( 'Expected content_count to be a non-negative integer, ' 'received %s' % self.content_count) allowed_language_codes = [ language['id'] for language in (constants.SUPPORTED_AUDIO_LANGUAGES) ] if not set(self.assigned_voice_artist_in_language_codes).isdisjoint( self.need_voice_artist_in_language_codes): raise utils.ValidationError( 'Expected voice_artist "needed" and "assigned" list of ' 'languages to be disjoint, received: %s, %s' % (self.need_voice_artist_in_language_codes, self.assigned_voice_artist_in_language_codes)) for language_code, count in (self.translation_counts.items()): if not utils.is_supported_audio_language_code(language_code): raise utils.ValidationError('Invalid language_code: %s' % language_code) if not isinstance(count, int): raise utils.ValidationError( 'Expected count for language_code %s to be an integer, ' 'received %s' % (language_code, count)) if count < 0: raise utils.ValidationError( 'Expected count for language_code %s to be a non-negative ' 'integer, received %s' % (language_code, count)) if count > self.content_count: raise utils.ValidationError( 'Expected translation count for language_code %s to be ' 'less than or equal to content_count(%s), received %s' % (language_code, self.content_count, count)) expected_set_of_all_languages = set( self.incomplete_translation_language_codes + self.need_voice_artist_in_language_codes + self.assigned_voice_artist_in_language_codes) for language_code in expected_set_of_all_languages: if language_code not in allowed_language_codes: raise utils.ValidationError('Invalid language_code: %s' % language_code) if expected_set_of_all_languages != set(allowed_language_codes): raise utils.ValidationError( 'Expected set of all languages available in ' 'incomplete_translation, needs_voiceover and assigned_voiceover' ' to be the same as the supported audio languages, ' 'received %s' % list(expected_set_of_all_languages))
def validate(self): """Validates the BaseVoiceoverApplication object. Raises: ValidationError. One or more attributes of the BaseVoiceoverApplication object are invalid. """ if self.target_type not in suggestion_models.TARGET_TYPE_CHOICES: raise utils.ValidationError( 'Expected target_type to be among allowed choices, ' 'received %s' % self.target_type) if not isinstance(self.target_id, python_utils.BASESTRING): raise utils.ValidationError( 'Expected target_id to be a string, received %s' % type(self.target_id)) if self.status not in suggestion_models.STATUS_CHOICES: raise utils.ValidationError( 'Expected status to be among allowed choices, ' 'received %s' % self.status) if not isinstance(self.author_id, python_utils.BASESTRING): raise utils.ValidationError( 'Expected author_id to be a string, received %s' % type(self.author_id)) if self.status == suggestion_models.STATUS_IN_REVIEW: if self.final_reviewer_id is not None: raise utils.ValidationError( 'Expected final_reviewer_id to be None as the ' 'voiceover application is not yet handled.') else: if not isinstance(self.final_reviewer_id, python_utils.BASESTRING): raise utils.ValidationError( 'Expected final_reviewer_id to be a string, received %s' % (type(self.final_reviewer_id))) if self.status == suggestion_models.STATUS_REJECTED: if not isinstance(self.rejection_message, python_utils.BASESTRING): raise utils.ValidationError( 'Expected rejection_message to be a string for a ' 'rejected application, received %s' % type(self.final_reviewer_id)) if self.status == suggestion_models.STATUS_ACCEPTED: if self.rejection_message is not None: raise utils.ValidationError( 'Expected rejection_message to be None for the ' 'accepted voiceover application, received %s' % (self.rejection_message)) if not isinstance(self.language_code, python_utils.BASESTRING): raise utils.ValidationError( 'Expected language_code to be a string, received %s' % self.language_code) if not utils.is_supported_audio_language_code(self.language_code): raise utils.ValidationError('Invalid language_code: %s' % self.language_code) if not isinstance(self.filename, python_utils.BASESTRING): raise utils.ValidationError( 'Expected filename to be a string, received %s' % type(self.filename)) if not isinstance(self.content, python_utils.BASESTRING): raise utils.ValidationError( 'Expected content to be a string, received %s' % type(self.content))
def test_is_supported_audio_language_code(self): self.assertTrue(utils.is_supported_audio_language_code('hi-en')) self.assertFalse(utils.is_supported_audio_language_code('unknown'))
def get(self): """Handles GET requests. Responds with a mapping from content id to translation of form: dict('translated_texts', dict(str, str|None)) If no translation is found for a given content id, that id is mapped to None. Params: exp_id: str. The ID of the exploration being translated. state_name: str. The name of the exploration state being translated. content_ids: str[]. The content IDs of the texts to be translated. target_language_code: str. The language code of the target translation language. Data Response: dict('translated_texts': dict(str, str|None)) A dictionary containing the translated texts stored as a mapping from content ID to the translated text. If an error occured during retrieval of some content translations, but not others, failed translations are mapped to None. Raises: 400 (Bad Request): InvalidInputException. At least one input is missing or improperly formatted. 404 (Not Found): PageNotFoundException. At least one identifier does not correspond to an entry in the datastore. """ exp_id = self.request.get('exp_id') if not exp_id: raise self.InvalidInputException('Missing exp_id') state_name = self.request.get('state_name') if not state_name: raise self.InvalidInputException('Missing state_name') content_ids_string = self.request.get('content_ids') content_ids = [] try: content_ids = json.loads(content_ids_string) except: raise self.InvalidInputException( 'Improperly formatted content_ids: %s' % content_ids_string) target_language_code = self.request.get('target_language_code') if not target_language_code: raise self.InvalidInputException('Missing target_language_code') # TODO(#12341): Tidy up this logic once we have a canonical list of # language codes. if not utils.is_supported_audio_language_code( target_language_code) and not utils.is_valid_language_code( target_language_code): raise self.InvalidInputException( 'Invalid target_language_code: %s' % target_language_code) exp = exp_fetchers.get_exploration_by_id(exp_id, strict=False) if exp is None: raise self.PageNotFoundException() state_names_to_content_id_mapping = exp.get_translatable_text( target_language_code) if state_name not in state_names_to_content_id_mapping: raise self.PageNotFoundException() content_id_to_text_mapping = ( state_names_to_content_id_mapping[state_name]) translated_texts = {} for content_id in content_ids: if content_id not in content_id_to_text_mapping: translated_texts[content_id] = None continue source_text = content_id_to_text_mapping[content_id] translated_texts[content_id] = ( translation_services.get_and_cache_machine_translation( exp.language_code, target_language_code, source_text)) self.values = {'translated_texts': translated_texts} self.render_json(self.values)