def changes_to_notify(self) -> [Course]: changed_courses = [] conn = sqlite3.connect(self.db_file) conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute( """SELECT course_id, course_fullname FROM files WHERE notified = 0 GROUP BY course_id;""" ) curse_rows = cursor.fetchall() for course_row in curse_rows: course = Course(course_row['course_id'], course_row['course_fullname']) cursor.execute( """SELECT * FROM files WHERE notified = 0 AND course_id = ?;""", (course.id,), ) file_rows = cursor.fetchall() course.files = [] for file_row in file_rows: notify_file = File.fromRow(file_row) if notify_file.modified or notify_file.moved: # add reference to new file cursor.execute( """SELECT * FROM files WHERE old_file_id = ?;""", (notify_file.file_id,), ) file_row = cursor.fetchone() if file_row is not None: notify_file.new_file = File.fromRow(file_row) course.files.append(notify_file) changed_courses.append(course) conn.close() return changed_courses
def fetch_courses_info(self, course_ids: [int]) -> [Course]: """ Queries the Moodle system for info about courses in a list. @param course_ids: A list of courses ids @return: A list of courses """ # API is only available since version 3.2 if len(course_ids) == 0 or self.version < 2016120500: return [] data = { "field": "ids", "value": ",".join(list(map(str, course_ids))), } result = self.request_helper.post_REST( 'core_course_get_courses_by_field', data) courses = result.get('courses', []) results = [] for course in courses: results.append( Course(course.get('id', 0), course.get('fullname', ''))) # We could also extract here the course summary and intro files return results
def get_old_files(self) -> [Course]: # get all stored files (that are not yet deleted) conn = sqlite3.connect(self.db_file) conn.row_factory = sqlite3.Row cursor = conn.cursor() stored_courses = [] cursor.execute("""SELECT DISTINCT course_id, course_fullname FROM files WHERE old_file_id IS NOT NULL""") course_rows = cursor.fetchall() for course_row in course_rows: course = Course(course_row['course_id'], course_row['course_fullname']) cursor.execute( """SELECT * FROM files WHERE course_id = ? AND old_file_id IS NOT NULL""", (course.id, ), ) updated_files = cursor.fetchall() course.files = [] for updated_file in updated_files: cursor.execute( """SELECT * FROM files WHERE file_id = ?""", (updated_file['old_file_id'], ), ) old_file = cursor.fetchone() notify_file = File.fromRow(old_file) course.files.append(notify_file) stored_courses.append(course) conn.close() return stored_courses
def __get_new_files(self, changed_courses: [Course], stored_courses: [Course], current_courses: [Course]) -> [Course]: # check for new files for current_course in current_courses: # check if that file does not exist in stored same_course_in_stored = None for stored_course in stored_courses: if stored_course.id == current_course.id: same_course_in_stored = stored_course break if same_course_in_stored is None: # current_course is not saved yet changed_courses.append(current_course) # skip the next checks! continue # Does anyone know why it is necessary to give # a course an empty list of files O.o # if I don't do this then a course will be created # with the files of the previous course changed_course = Course(current_course.id, current_course.fullname, []) for current_file in current_course.files: matching_file = None for stored_file in same_course_in_stored.files: # Try to find a matching file if self.__files_have_same_path( current_file, stored_file) or self.__file_was_moved( current_file, stored_file): matching_file = current_file break if matching_file is None: # current_file is a new file changed_course.files.append(current_file) if len(changed_course.files) > 0: matched_changed_course = None for ch_course in changed_courses: if ch_course.id == changed_course.id: matched_changed_course = ch_course break if matched_changed_course is None: changed_courses.append(changed_course) else: matched_changed_course.files += changed_course.files return changed_courses
def get_stored_files(self) -> [Course]: # get all stored files (that are not yet deleted) conn = sqlite3.connect(self.db_file) conn.row_factory = sqlite3.Row cursor = conn.cursor() stored_courses = [] cursor.execute( """SELECT course_id, course_fullname FROM files WHERE deleted = 0 AND modified = 0 AND moved = 0 GROUP BY course_id;""" ) curse_rows = cursor.fetchall() for course_row in curse_rows: course = Course(course_row['course_id'], course_row['course_fullname']) cursor.execute( """SELECT * FROM files WHERE deleted = 0 AND modified = 0 AND moved = 0 AND course_id = ?;""", (course.id,), ) file_rows = cursor.fetchall() course.files = [] for file_row in file_rows: notify_file = File.fromRow(file_row) course.files.append(notify_file) stored_courses.append(course) conn.close() return stored_courses
def __get_new_files(self, changed_courses: [Course], stored_courses: [Course], current_courses: [Course]) -> [Course]: # check for new files for current_course in current_courses: # check if that file does not exist in stored same_course_in_stored = None for stored_course in stored_courses: if stored_course.id == current_course.id: same_course_in_stored = stored_course break if same_course_in_stored is None: # current_course is not saved yet changed_courses.append(current_course) # skip the next checks! continue changed_course = Course(current_course.id, current_course.fullname) for current_file in current_course.files: matching_file = None for stored_file in same_course_in_stored.files: # Try to find a matching file if self.__files_have_same_path( current_file, stored_file) or self.__file_was_moved( current_file, stored_file): matching_file = current_file break if matching_file is None: # current_file is a new file changed_course.files.append(current_file) if len(changed_course.files) > 0: matched_changed_course = None for ch_course in changed_courses: if ch_course.id == changed_course.id: matched_changed_course = ch_course break if matched_changed_course is None: changed_courses.append(changed_course) else: matched_changed_course.files += changed_course.files return changed_courses
def fetch_courses(self, userid: str) -> [Course]: """ Queries the Moodle system for all courses the user is enrolled in. @param userid: the user id @return: A list of courses """ data = {'userid': userid} result = self.request_helper.post_REST('core_enrol_get_users_courses', data) results = [] for course in result: results.append(Course(course.get('id', 0), course.get('fullname', ''))) return results
def fetch_all_visible_courses(self, log_all_courses_to: str = None) -> [Course]: """ Queries the Moodle system for all courses available on the system and returns: @return: A list of all visible courses """ # API is only available since version 3.2 if self.version < 2016120500: return [] result = self.request_helper.post_REST( 'core_course_get_courses_by_field', timeout=1200) if log_all_courses_to is not None: with open(log_all_courses_to, 'w', encoding='utf-8') as log_file: log_file.write(json.dumps(result, indent=4, ensure_ascii=False)) courses = result.get('courses', []) results = [] for course in courses: if course.get('visible', 0) == 1: results.append( Course(course.get('id', 0), course.get('fullname', ''))) return results
def __get_modified_files(self, stored_courses: [Course], current_courses: [Course]) -> [Course]: # returns courses with modified and deleted files changed_courses = [] for stored_course in stored_courses: same_course_in_current = None for current_course in current_courses: if current_course.id == stored_course.id: same_course_in_current = current_course break if same_course_in_current is None: # stroed_course does not exist anymore! # maybe it would be better # to not notify about this changes? for stored_file in stored_course.files: stored_file.deleted = True stored_file.notified = False changed_courses.append(stored_course) # skip the next checks! continue # there is the same course in the current set # so try to find removed files, that are still exist in storage # also find modified files changed_course = Course(stored_course.id, stored_course.fullname, []) for stored_file in stored_course.files: matching_file = None for current_file in same_course_in_current.files: # Try to find a matching file with same path if self.__files_have_same_path(current_file, stored_file): matching_file = current_file # file does still exist break if matching_file is not None: # An matching file was found # Test for modification if self.__files_are_diffrent(matching_file, stored_file): # file is modified matching_file.modified = True matching_file.old_file = stored_file changed_course.files.append(matching_file) continue # No matching file was found --> file was deleted or moved # check for moved files for current_file in same_course_in_current.files: # Try to find a matching file that was moved if self.__file_was_moved(current_file, stored_file): matching_file = current_file # file does still exist break if matching_file is None and not self.__ignore_deleted( stored_file): # No matching file was found --> file was deleted stored_file.deleted = True stored_file.notified = False changed_course.files.append(stored_file) elif matching_file is not None: matching_file.moved = True matching_file.old_file = stored_file changed_course.files.append(matching_file) if len(changed_course.files) > 0: changed_courses.append(changed_course) return changed_courses