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 get(self): user_data = models.UserData.current() question_key = self.request.get("question_key") question = db.get(question_key) if question: video = question.video() dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) answers = models_discussion.Feedback.gql( "WHERE types = :1 AND targets = :2 AND deleted = :3 AND is_hidden_by_flags = :4", models_discussion.FeedbackType.Answer, question.key(), False, False).fetch(1000) answers = voting.VotingSortOrder.sort(answers) for answer in answers: voting.add_vote_expando_properties(answer, dict_votes) template_values = { "answers": answers, "is_mod": util_discussion.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 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 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 get(self): user_data = models.UserData.current() if not user_data: self.redirect(util.create_login_url(self.request.uri)) return answers = feedback_answers_for_user_data(user_data) # Whenever looking at this page, make sure the feedback count is recalculated # in case the user was notified about deleted or flagged posts. user_data.count_feedback_notification = -1 user_data.put() dict_videos = {} dict_answers = {} for answer in answers: video = answer.video() dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) voting.add_vote_expando_properties(answer, dict_votes) if video == None or type(video).__name__ != "Video": continue video_key = video.key() dict_videos[video_key] = video if dict_answers.has_key(video_key): dict_answers[video_key].append(answer) else: dict_answers[video_key] = [answer] videos = sorted( dict_videos.values(), key=lambda video: video.first_topic().title + video.title) context = { "email": user_data.email, "videos": videos, "dict_answers": dict_answers } self.render_jinja2_template( 'discussion/video_feedback_notification_list.html', context)
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 get(self): user_data = models.UserData.current() if not user_data: self.redirect(util.create_login_url(self.request.uri)) return answers = feedback_answers_for_user_data(user_data) # Whenever looking at this page, make sure the feedback count is recalculated # in case the user was notified about deleted or flagged posts. user_data.count_feedback_notification = -1 user_data.put() dict_videos = {} dict_answers = {} for answer in answers: video = answer.video() dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video(user_data, video) voting.add_vote_expando_properties(answer, dict_votes) if video == None or type(video).__name__ != "Video": continue video_key = video.key() dict_videos[video_key] = video if dict_answers.has_key(video_key): dict_answers[video_key].append(answer) else: dict_answers[video_key] = [answer] videos = sorted(dict_videos.values(), key=lambda video: video.first_topic().title + video.title) context = { "email": user_data.email, "videos": videos, "dict_answers": dict_answers } self.render_jinja2_template('discussion/video_feedback_notification_list.html', context)
def get(self): user_data = models.UserData.current() if not user_data: self.redirect(util.create_login_url(self.request.uri)) return answers = feedback_answers_for_user_data(user_data) dict_videos = {} dict_answers = {} for answer in answers: video = answer.video() dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video( user_data, video) voting.add_vote_expando_properties(answer, dict_votes) if video == None or type(video).__name__ != "Video": continue video_key = video.key() dict_videos[video_key] = video if dict_answers.has_key(video_key): dict_answers[video_key].append(answer) else: dict_answers[video_key] = [answer] videos = sorted(dict_videos.values(), key=lambda video: video.playlists[0] + video.title) context = { "email": user_data.email, "videos": videos, "dict_answers": dict_answers } self.render_jinja2_template( 'discussion/video_feedback_notification_list.html', context)
def add_feedback(text, feedback_type, parent_key_or_id): """Add a question to a video, or an answer to a question. Returns a util_discussion.ClientFeedback entity for the added feedback, if successful, or None. Arguments: 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() if not util_discussion.is_post_allowed(user_data, None): return None if feedback_type == discussion_models.FeedbackType.Question: parent = video_models.Video.get_for_readable_id(parent_key_or_id) else: parent = db.get(parent_key_or_id) if parent and text: # TODO(drew): see if answers need to be truncated # Truncate feedback to a maximum length of 500 characters text = text[:500] # Grab stats before putting the feedback in case of building stats now # and double-counting stats = discussion_models.UserDiscussionStats.get_or_build_for( user_data) feedback = discussion_models.Feedback.insert_feedback(text, feedback_type, parent, user_data) stats.record(feedback) stats.put() voting.add_vote_expando_properties(feedback, {}) return util_discussion.ClientFeedback.from_feedback(feedback, with_extra_vote_properties=True) return None
def add_feedback(text, feedback_type, parent_key_or_id): """Add a question to a video, or an answer to a question. Returns a util_discussion.ClientFeedback entity for the added feedback, if successful, or None. Arguments: 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() if not util_discussion.is_post_allowed(user_data, None): return None if feedback_type == discussion_models.FeedbackType.Question: parent = video_models.Video.get_for_readable_id(parent_key_or_id) else: parent = db.get(parent_key_or_id) if parent and text: # TODO(drew): see if answers need to be truncated # Truncate feedback to a maximum length of 500 characters text = text[:500] # Grab stats before putting the feedback in case of building stats now # and double-counting stats = discussion_models.UserDiscussionStats.get_or_build_for( user_data) feedback = discussion_models.Feedback.insert_feedback( text, feedback_type, parent, user_data) stats.record(feedback) stats.put() voting.add_vote_expando_properties(feedback, {}) return util_discussion.ClientFeedback.from_feedback( feedback, with_extra_vote_properties=True) return None
def video_comments_context( video, playlist, 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": util_discussion.is_current_user_moderator(), "video": video, "playlist": playlist, "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 get(self): user_data = models.UserData.current() question_key = self.request.get("question_key") question = db.get(question_key) if question: video = question.video() dict_votes = models_discussion.FeedbackVote.get_dict_for_user_data_and_video(user_data, video) answers = models_discussion.Feedback.gql("WHERE types = :1 AND targets = :2 AND deleted = :3 AND is_hidden_by_flags = :4", models_discussion.FeedbackType.Answer, question.key(), False, False).fetch(1000) answers = voting.VotingSortOrder.sort(answers) for answer in answers: voting.add_vote_expando_properties(answer, dict_votes) template_values = { "answers": answers, "is_mod": util_discussion.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 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, }