def update_feedback(feedback_key, text, feedback_type, parent_key_or_id=None): """Update the text of a question or answer. Returns a util_discussion.ClientFeedback entity for the added feedback, if successful, or None. Arguments: feedback_key: the key of feedback that is to be updated text: the desired feedback text property feedback_type: either FeedbackType.Question or FeedbackType.Answer parent_key_or_id: readable_id if adding a question, question_key if adding an answer """ user_data = user_models.UserData.current() # parent will only be initialized if parent_key_or_id was initialized if parent_key_or_id: parent = video_models.Video.get_for_readable_id(parent_key_or_id) feedback = db.get(feedback_key) is_answer = feedback_type == discussion_models.FeedbackType.Answer # TODO(drew): Do we really need to use video here? if feedback and text and (is_answer or parent): if (feedback.authored_by(user_data) or user_util.is_current_user_moderator()): feedback.content = text # If a moderator rewrote the content, then it's not spam. # Otherwise, reset the var to false (it could have turned into # spam) feedback.definitely_not_spam = ( user_util.is_current_user_moderator()) # Recalculate the low quality metric as the content changed feedback.low_quality_score = ( discussion_models.Heuristics.get_low_quality_score( text, feedback_type)) feedback.put() if is_answer: dict_votes = discussion_models.FeedbackVote.get_dict_for_feedback( feedback, user_data) else: dict_votes = (discussion_models.FeedbackVote. get_dict_for_user_data_and_video(user_data, parent)) voting.add_vote_expando_properties(feedback, dict_votes) return util_discussion.ClientFeedback.from_feedback( feedback, with_extra_vote_properties=True) return None
def post(self): user_data = user_models.UserData.current() key = self.request.get("entity_key") text = self.request.get("question_text") or self.request.get( "answer_text") if key and text: feedback = db.get(key) if feedback: if feedback.authored_by( user_data) or user_util.is_current_user_moderator(): feedback.content = text feedback.put() # Redirect to appropriate list of entities depending on type of # feedback entity being edited. if feedback.is_type( discussion_models.FeedbackType.Question): page = self.request.get("page") video = feedback.video() self.redirect( "/discussion/pagequestions?video_key=%s&page=%s&qa_expand_key=%s" % (video.key(), page, feedback.key())) elif feedback.is_type( discussion_models.FeedbackType.Answer): question = feedback.question() self.redirect("/discussion/answers?question_key=%s" % question.key())
def get(self): user_data = user_models.UserData.current() question_key = self.request.get("question_key") question = db.get(question_key) if question: video = question.video() dict_votes = discussion_models.FeedbackVote.get_dict_for_user_data_and_video(user_data, video) answers = discussion_models.Feedback.gql("WHERE types = :1 AND targets = :2", discussion_models.FeedbackType.Answer, question.key()).fetch(1000) answers = filter(lambda answer: answer.is_visible_to(user_data), answers) answers = voting.VotingSortOrder.sort(answers) for answer in answers: voting.add_vote_expando_properties(answer, dict_votes) template_values = { "answers": answers, "is_mod": user_util.is_current_user_moderator() } html = self.render_jinja2_template_to_string('discussion/question_answers_only.html', template_values) self.render_json({"html": html}) return
def post(self): user_data = models.UserData.current() if not user_data: return key = self.request.get("entity_key") topic_key = self.request.get("topic_key") text = self.request.get("question_text") or self.request.get("answer_text") if key and text: feedback = db.get(key) if feedback: if feedback.authored_by(user_data) or user_util.is_current_user_moderator(): feedback.content = text feedback.put() # Redirect to appropriate list of entities depending on type of # feedback entity being edited. if feedback.is_type(models_discussion.FeedbackType.Question): page = self.request.get("page") video = feedback.video() self.redirect( "/discussion/pagequestions?video_key=%s&topic_key=%s&page=%s&qa_expand_key=%s" % (video.key(), topic_key, page, feedback.key()) ) elif feedback.is_type(models_discussion.FeedbackType.Answer): question = feedback.question() self.redirect("/discussion/answers?question_key=%s" % question.key())
def get(self): user_data = user_models.UserData.current() question_key = self.request.get("question_key") question = db.get(question_key) if question: video = question.video() dict_votes = discussion_models.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) answers = discussion_models.Feedback.gql( "WHERE types = :1 AND targets = :2", discussion_models.FeedbackType.Answer, question.key()).fetch(1000) answers = filter(lambda answer: answer.is_visible_to(user_data), answers) answers = voting.VotingSortOrder.sort(answers) for answer in answers: voting.add_vote_expando_properties(answer, dict_votes) template_values = { "answers": answers, "is_mod": user_util.is_current_user_moderator() } html = self.render_jinja2_template_to_string( 'discussion/question_answers_only.html', template_values) self.render_json({"html": html}) return
def update_feedback(feedback_key, text, feedback_type, parent_key_or_id=None): """Update the text of a question or answer. Returns a util_discussion.ClientFeedback entity for the added feedback, if successful, or None. Arguments: feedback_key: the key of feedback that is to be updated text: the desired feedback text property feedback_type: either FeedbackType.Question or FeedbackType.Answer parent_key_or_id: readable_id if adding a question, question_key if adding an answer """ user_data = user_models.UserData.current() # parent will only be initialized if parent_key_or_id was initialized if parent_key_or_id: parent = video_models.Video.get_for_readable_id(parent_key_or_id) feedback = db.get(feedback_key) is_answer = feedback_type == discussion_models.FeedbackType.Answer # TODO(drew): Do we really need to use video here? if feedback and text and (is_answer or parent): if (feedback.authored_by(user_data) or user_util.is_current_user_moderator()): feedback.content = text # If a moderator rewrote the content, then it's not spam. # Otherwise, reset the var to false (it could have turned into # spam) feedback.definitely_not_spam = (user_util. is_current_user_moderator()) # Recalculate the low quality metric as the content changed feedback.low_quality_score = (discussion_models. Heuristics.get_low_quality_score(text, feedback_type)) feedback.put() if is_answer: dict_votes = discussion_models.FeedbackVote.get_dict_for_feedback( feedback, user_data) else: dict_votes = (discussion_models. FeedbackVote.get_dict_for_user_data_and_video( user_data, parent)) voting.add_vote_expando_properties(feedback, dict_votes) return util_discussion.ClientFeedback.from_feedback(feedback, with_extra_vote_properties=True) return None
def post(self): if not user_util.is_current_user_moderator(): return key = self.request.get("entity_key") if key: entity = db.get(key) if entity: entity.clear_flags() entity.put() self.redirect("/discussion/flaggedfeedback")
def post(self): # Must be a moderator to change types of anything if not user_util.is_current_user_moderator(): return key = self.request.get("entity_key") target_type = self.request.get("target_type") if key: entity = db.get(key) if entity: clear_flags = self.request_bool("clear_flags", default=False) entity.change_type(target_type, clear_flags) self.redirect("/discussion/flaggedfeedback")
def video_comments_context( video, topic, page=0, comments_hidden=True, sort_order=voting.VotingSortOrder.HighestPointsFirst): user_data = models.UserData.current() if page > 0: comments_hidden = False # Never hide questions if specifying specific page else: page = 1 limit_per_page = 10 limit_initially_visible = 2 if comments_hidden else limit_per_page comments = util_discussion.get_feedback_by_type_for_video( video, models_discussion.FeedbackType.Comment, user_data) comments = voting.VotingSortOrder.sort(comments, sort_order=sort_order) count_total = len(comments) comments = comments[((page - 1) * limit_per_page):(page * limit_per_page)] dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) for comment in comments: voting.add_vote_expando_properties(comment, dict_votes) count_page = len(comments) pages_total = max(1, ((count_total - 1) / limit_per_page) + 1) return { "is_mod": user_util.is_current_user_moderator(), "video": video, "topic": topic, "comments": comments, "count_total": count_total, "comments_hidden": count_page > limit_initially_visible, "limit_initially_visible": limit_initially_visible, "pages": range(1, pages_total + 1), "pages_total": pages_total, "prev_page_1_based": page - 1, "current_page_1_based": page, "next_page_1_based": page + 1, "show_page_controls": pages_total > 1, }
def post(self): # Must be a moderator to change types of anything if not user_util.is_current_user_moderator(): return key = self.request.get("entity_key") target_type = self.request.get("target_type") if key and models_discussion.FeedbackType.is_valid(target_type): entity = db.get(key) if entity: entity.types = [target_type] if self.request_bool("clear_flags", default=False): entity.clear_flags() entity.put() self.redirect("/discussion/flaggedfeedback")
def post(self): user_data = models.UserData.current() if not user_data: return key = self.request.get("entity_key") if key: entity = db.get(key) if entity: # Must be a moderator or author of entity to delete if entity.authored_by(user_data): # Entity authors can completely delete their posts. # Posts that are flagged as deleted by moderators won't show up # as deleted to authors, so we just completely delete in this special case. entity.delete() elif user_util.is_current_user_moderator(): entity.deleted = True entity.put() self.redirect("/discussion/flaggedfeedback")
def post(self): user_data = user_models.UserData.current() if not user_data: return key = self.request.get("entity_key") if key: entity = db.get(key) if entity: # Must be a moderator or author of entity to delete if entity.authored_by(user_data): # Entity authors can completely delete their posts. # Posts that are flagged as deleted by moderators won't show up # as deleted to authors, so we just completely delete in this special case. entity.delete() elif user_util.is_current_user_moderator(): entity.deleted = True entity.put() self.redirect("/discussion/flaggedfeedback")
def video_comments_context(video, topic, page=0, comments_hidden=True, sort_order=voting.VotingSortOrder.HighestPointsFirst): user_data = models.UserData.current() if page > 0: comments_hidden = False # Never hide questions if specifying specific page else: page = 1 limit_per_page = 10 limit_initially_visible = 2 if comments_hidden else limit_per_page comments = util_discussion.get_feedback_by_type_for_video(video, models_discussion.FeedbackType.Comment, user_data) comments = voting.VotingSortOrder.sort(comments, sort_order=sort_order) count_total = len(comments) comments = comments[((page - 1) * limit_per_page):(page * limit_per_page)] dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video(user_data, video) for comment in comments: voting.add_vote_expando_properties(comment, dict_votes) count_page = len(comments) pages_total = max(1, ((count_total - 1) / limit_per_page) + 1) return { "is_mod": user_util.is_current_user_moderator(), "video": video, "topic": topic, "comments": comments, "count_total": count_total, "comments_hidden": count_page > limit_initially_visible, "limit_initially_visible": limit_initially_visible, "pages": range(1, pages_total + 1), "pages_total": pages_total, "prev_page_1_based": page - 1, "current_page_1_based": page, "next_page_1_based": page + 1, "show_page_controls": pages_total > 1, }
def hide_feedback(feedback_key): """Hide the specified feedback entity from the general public. If initiated by the entity author, the entity is deleted from the datastore. If initiated by a moderator, the entity is marked as deleted and thus hidden from the general public but not from the author. """ if not feedback_key: return feedback = db.get(feedback_key) if not feedback: return user_data = user_models.UserData.current() client_feedback = None stats = discussion_models.UserDiscussionStats.get_or_build_for( feedback.get_author()) stats.forget(feedback) if feedback.authored_by(user_data): stats.put() # Entity authors can completely delete their posts. Posts that are # flagged as deleted by moderators won't show up as deleted to # authors, so we just completely delete in this special case. feedback.delete() elif user_util.is_current_user_moderator(): feedback.deleted = True stats.record(feedback) stats.put() feedback.put() # Feedback put does extra stuff so don't multi-put client_feedback = util_discussion.ClientFeedback.from_feedback( feedback) return client_feedback
def video_qa_context(user_data, video, topic=None, page=0, qa_expand_key=None, sort_override=-1): limit_per_page = 5 if page <= 0: page = 1 sort_order = voting.VotingSortOrder.HighestPointsFirst if user_data: sort_order = user_data.question_sort_order if sort_override >= 0: sort_order = sort_override questions = util_discussion.get_feedback_by_type_for_video( video, models_discussion.FeedbackType.Question, user_data ) questions = voting.VotingSortOrder.sort(questions, sort_order=sort_order) if qa_expand_key: # If we're showing an initially expanded question, # make sure we're on the correct page question = models_discussion.Feedback.get(qa_expand_key) if question: count_preceding = 0 for question_test in questions: if question_test.key() == question.key(): break count_preceding += 1 page = 1 + (count_preceding / limit_per_page) answers = util_discussion.get_feedback_by_type_for_video(video, models_discussion.FeedbackType.Answer, user_data) answers.reverse() # Answers are initially in date descending -- we want ascending before the points sort answers = voting.VotingSortOrder.sort(answers) dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video(user_data, video) count_total = len(questions) questions = questions[((page - 1) * limit_per_page) : (page * limit_per_page)] dict_questions = {} # Store each question in this page in a dict for answer population for question in questions: voting.add_vote_expando_properties(question, dict_votes) dict_questions[question.key()] = question # Just grab all answers for this video and cache in page's questions for answer in answers: # Grab the key only for each answer, don't run a full gql query on the ReferenceProperty question_key = answer.question_key() if dict_questions.has_key(question_key): question = dict_questions[question_key] voting.add_vote_expando_properties(answer, dict_votes) question.children_cache.append(answer) count_page = len(questions) pages_total = max(1, ((count_total - 1) / limit_per_page) + 1) return { "is_mod": user_util.is_current_user_moderator(), "video": video, "topic": topic, "questions": questions, "count_total": count_total, "pages": range(1, pages_total + 1), "pages_total": pages_total, "prev_page_1_based": page - 1, "current_page_1_based": page, "next_page_1_based": page + 1, "show_page_controls": pages_total > 1, "qa_expand_key": qa_expand_key, "sort_order": sort_order, }
def video_qa_context(user_data, video, page=0, qa_expand_key=None, sort_override=-1): limit_per_page = 5 if page <= 0: page = 1 sort_order = voting.VotingSortOrder.HighestPointsFirst if user_data: sort_order = user_data.question_sort_order if sort_override >= 0: sort_order = sort_override questions = util_discussion.get_feedback_by_type_for_video( video, discussion_models.FeedbackType.Question, user_data) questions = voting.VotingSortOrder.sort(questions, sort_order=sort_order) if qa_expand_key: # If we're showing an initially expanded question, # make sure we're on the correct page question = discussion_models.Feedback.get(qa_expand_key) if question: count_preceding = 0 for question_test in questions: if question_test.key() == question.key(): break count_preceding += 1 page = 1 + (count_preceding / limit_per_page) answers = util_discussion.get_feedback_by_type_for_video( video, discussion_models.FeedbackType.Answer, user_data) answers.reverse( ) # Answers are initially in date descending -- we want ascending before the points sort answers = voting.VotingSortOrder.sort(answers) dict_votes = discussion_models.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) count_total = len(questions) questions = questions[((page - 1) * limit_per_page):(page * limit_per_page)] dict_questions = {} # Store each question in this page in a dict for answer population for question in questions: voting.add_vote_expando_properties(question, dict_votes) dict_questions[question.key()] = question # Just grab all answers for this video and cache in page's questions for answer in answers: # Grab the key only for each answer, don't run a full gql query on the ReferenceProperty question_key = answer.question_key() if (dict_questions.has_key(question_key)): question = dict_questions[question_key] voting.add_vote_expando_properties(answer, dict_votes) question.children_cache.append(answer) count_page = len(questions) pages_total = max(1, ((count_total - 1) / limit_per_page) + 1) return { "is_mod": user_util.is_current_user_moderator(), "video": video, "questions": questions, "count_total": count_total, "pages": range(1, pages_total + 1), "pages_total": pages_total, "prev_page_1_based": page - 1, "current_page_1_based": page, "next_page_1_based": page + 1, "show_page_controls": pages_total > 1, "qa_expand_key": qa_expand_key, "sort_order": sort_order, }