def __init__(self, username, password, course_id, es_metadata_host, es_metadata_index, es_metadata_type, es_question_host, es_question_index, es_question_type, query_function): self.piazza = PiazzaAPI(username, password) self.course_id = course_id self.es_metadata = Elasticsearch(es_metadata_host) self.es_metadata_index = es_metadata_index self.es_metadata_type = es_metadata_type self.es_question_host = es_question_host self.es_question_index = es_question_index self.es_question_type = es_question_type self.query_function = query_function
def get_answer_stats(username, password, bot_id, start_id, end_id, course_id): """ Returns a dictionary with total answers, good answers, bad answers, and answers that have not been responded to. """ piazza = PiazzaAPI(username, password) answer_stats = {} answer_stats["total"] = 0 answer_stats["good"] = 0 answer_stats["bad"] = 0 answer_stats["good_and_bad"] = 0 answer_stats["no_response"] = 0 curr_id = start_id while curr_id <= end_id: question_doc = piazza.get_question_data(curr_id, course_id) if "error" not in question_doc: answer_type = get_answer_type(question_doc, bot_id) if "no_answer" != answer_type: answer_stats["total"] += 1 answer_stats[answer_type] += 1 curr_id += 1 return answer_stats
from piazza_api import PiazzaAPI from course_data import courses if __name__ == '__main__': parser = argparse.ArgumentParser(description='Get Piazza question data.') parser.add_argument('--username', help='The username to login with.', required=True) parser.add_argument('--password', help='The password for the username.', required=True) parser.add_argument('--elasticsearch_hosts', help='Store raw data into elasticsearch.', required=True, nargs='+') parser.add_argument('--elasticsearch_index', help='Store raw data into this elasticsearch index.', required=True) parser.add_argument('--elasticsearch_type', help='Store raw data into this elasticsearch type.', required=True) args = parser.parse_args() course = courses['cs225'] piazza_api = PiazzaAPI(args.username, args.password) for course in courses: piazza_api.write_course_data_elasticsearch( es_hosts=args.elasticsearch_hosts, es_index=args.elasticsearch_index, es_type=args.elasticsearch_type, course_id=course['course_id'], start_id=1, end_id=course['max_id'], course_name=course['name'])
class PiazzaScanner: """ Scans piazza and answers unanswered questions. Should be run in cron. """ def __init__(self, username, password, course_id, es_metadata_host, es_metadata_index, es_metadata_type, es_question_host, es_question_index, es_question_type, query_function): self.piazza = PiazzaAPI(username, password) self.course_id = course_id self.es_metadata = Elasticsearch(es_metadata_host) self.es_metadata_index = es_metadata_index self.es_metadata_type = es_metadata_type self.es_question_host = es_question_host self.es_question_index = es_question_index self.es_question_type = es_question_type self.query_function = query_function def run(self): """ Runs the Scanner from the last_id, answering all new questions in a followup post. """ self.answer_questions(self.get_new_questions()) def answer_questions(self, questions): """ Answers questions given a list of question objects. """ for question in questions: answers = get_answers(self.es_question_host, self.es_question_index, self.es_question_type, question, 10, self.query_function) response = self.generate_response_string(answers) if response: self.piazza.post_followup(self.course_id, response, cid=question['cid']) def generate_response_string(self, answers): """ Generates a response string message with the answers object. """ response = '' if len(answers) > 0: response += answers[0][1] if response: response += ('<p>\n</p>--This is an autogenerated message. If it\'s' + ' helpful please comment a \'+1\'. Otherwise comment a ' + ' \'-1\'. Thank you. <3.') return response def get_new_questions(self): """ Returns list of all unanswered question objects from last_id. """ last_id = self.get_last_id() failed_reads = 0 curr_id = last_id new_questions = [] while failed_reads < 5: curr_id += 1 new_data = self.piazza.get_question_data(curr_id, self.course_id) if ('error' in new_data and new_data['error'] == 'Content_id out of range.'): failed_reads += 1 elif 'error' not in new_data: failed_reads = 0 last_id = curr_id new_questions.append(new_data) self.write_last_id(last_id) return new_questions def get_last_id(self): """ Reads the last_id from the elasticsearch store. """ return self.es_metadata.get(index=self.es_metadata_index, doc_type=self.es_metadata_type, id=1)['_source']['last_read'] def write_last_id(self, last_id): """ Writes the new value of last_id to elasticsearch store. """ self.es_metadata.update(index=self.es_metadata_index, doc_type=self.es_metadata_type, id=1, body='{"doc":{"last_read": %s}}' % last_id)
parser.add_argument('--password', help='The password for the username.', required=True) parser.add_argument('--course_id', help='The id of the desired course.', required=True) parser.add_argument('--es_dest_hosts', help='Store test data into elasticsearch.', required=True, nargs='+') parser.add_argument('--es_dest_index', help='Write test data into this index.', required=True) parser.add_argument('--es_dest_type', help='Write test data into this type.', required=True) args = parser.parse_args() piazza = PiazzaAPI(args.username, args.password) dest_es = Elasticsearch(args.es_dest_hosts) c_ids = range(1,3000) shuffle(c_ids) current_id = c_ids.pop() completed = 0 while completed < 100: question_doc = piazza.get_question_data(current_id, args.course_id) while 'error' in question_doc: current_id = c_ids.pop() question_doc = piazza.get_question_data(current_id, args.course_id) question_doc['c_id'] = current_id dest_es.index(args.es_dest_index, args.es_dest_type,