def validate_input(input_str): valid_regex = r"^\d+((,\d+)*|(\-\d+)*)+(\d+)?$" input_str = CommonFuncs.remove_inner_spaces(input_str) if re.match(valid_regex, input_str): expanded = [] sequences = input_str.split(',') for sequence in sequences: if '-' in sequence: limits = sequence.split('-') limits = tuple(int(limit) for limit in limits) if len(limits) == 2: lower_limit, upper_limit = limits else: limits = CommonFuncs.sorted_unique_list(limits) lower_limit, upper_limit = limits[0], limits[-1] if not CommonFuncs.are_ascending(limits): return None expanded.extend(range(lower_limit, upper_limit + 1)) else: expanded.append(int(sequence)) return CommonFuncs.sorted_unique_list( list( filter(lambda x: x > 0, CommonFuncs.sorted_unique_list(expanded)))) else: return None
def ask_input_for_item_from_list(items_list, item_word, action_word="view", with_clear=True, inside_call=False): if with_clear: CommonFuncs.clear() if not inside_call: for prev_item in CommonVars.chosen_items_till_now.values(): print(prev_item) print(f"Select the {item_word} you want to {action_word}:") width = len(str(len(items_list))) for i, item in enumerate(items_list, 1): print(f"[{i:{width}}] {item}") selected_item = None selected_item_isvalid = False while not selected_item_isvalid: chosen_item = input(f"And the {item_word} that you selected is >>> ") action = handle_action(chosen_item) if action.state == ActionState.found_and_handled: return action if not chosen_item.isdigit(): continue item_idx = int(chosen_item) - 1 if 0 <= item_idx < len(items_list): confirm_message = f"You chose: {CommonFuncs.trim_inner_spaces(items_list[item_idx])} right? [Y/N] " def on_yes_action(): nonlocal selected_item nonlocal selected_item_isvalid selected_item = items_list[item_idx] selected_item_isvalid = True ask_yes_no_question(confirm_message, on_yes_action) else: print(f"The {item_word} you chose is out of bounds! Try again.") if not inside_call: CommonVars.chosen_items_till_now[ item_word] = f"You chose {CommonFuncs.trim_inner_spaces(selected_item)}" return selected_item
def __create_session(cls): session = requests.session() login = None while True: print("Establishing connection with courses") try: login = session.get( "http://courses.finki.ukim.mk/login/index.php", allow_redirects=True) except (MaxRetryError, requests.exceptions.ConnectionError): print("Connection cannot be established") should_retry = ask_yes_no_question( "Do you want to try again? [Y/N] ", None) if not should_retry: quit() else: CommonFuncs.clear() continue break print("Preparing CAS login") login_html = lxml.html.fromstring(login.text) hidden_inputs = login_html.xpath(r'//form//input[@type="hidden"]') login_data = { x.attrib["name"]: x.attrib["value"] for x in hidden_inputs } login_data['username'] = '******' login_data['password'] = keyring.get_password( 'https://cas.finki.ukim.mk/', login_data['username']) print("Logging into CAS") session.post(login.url, data=login_data) cls.__login_time = datetime.now() cls.session = session
def _download_selected_links(cls): total_len = len(CommonVars.selected_links) if total_len == 1: CommonVars.selected_links[0].download() elif total_len > 1: downloaded_names = [] for idx, link in enumerate(CommonVars.selected_links, 1): CommonFuncs.clear() print(f"Downloading {link.name} {idx} / {total_len}") downloaded_names.append(link.name) link.download(ambiguous=True) print(f"Downloaded {total_len} successfully") for i, downloaded_name in enumerate(downloaded_names, 1): print(f"{i} {downloaded_name}")
def download(self, ambiguous=False): if not ambiguous: CommonFuncs.clear() print(f"Downloading {self.name}") if CommonVars.using_name_from_courses_instead_of_name_from_url: # old way filename = FileTypeNotKnown.prepare_filename_for_downloading( self.name) self._get_and_save_file(filename) filename = FileTypeNotKnown.handle_file_name_and_type_and_if_duplicate( filename) else: # new way filename = self._get_and_save_file(None) filename = FileTypeKnown.get_filename_without_path(filename) pass if not ambiguous: print(f"Downloaded {self.name} as {filename}")
def ask_input_for_items_from_list(items_list, items_word, action_word="download"): private_funcs = PrivateFuncs() validate_input = private_funcs.validate_input build_ranges_str = private_funcs.build_ranges_str del private_funcs CommonFuncs.clear() for prev_item in CommonVars.chosen_items_till_now.values(): print(prev_item) print( f"Select the {items_word} you want to {action_word}: (range:x-y or set:x,y,z)" ) width = len(str(len(items_list))) for i, item in enumerate(items_list, 1): print(f"[{i:{width}}] {item}") selected_items = [] selected_item_isvalid = False while not selected_item_isvalid: items_idx = input(f"And the {items_word} that you selected are >>> ") action = handle_action(items_idx) if action.state == ActionState.found_and_handled: return action result = validate_input(items_idx) if not result: continue result.extend(selected_items) result = CommonFuncs.sorted_unique_list(result) if result: fit_result = CommonFuncs.sorted_unique_list( list(filter(lambda x: x <= len(items_list), result))) valid = CommonFuncs.sorted_unique_list(fit_result) valid_str = build_ranges_str(valid) set_result = set(result) set_fit_result = set(fit_result) if set_result != set_fit_result: invalid = CommonFuncs.sorted_unique_list( list(set_result - set_fit_result)) invalid_str = build_ranges_str(invalid) if valid_str: print( f"The following {items_word} are out of range: {invalid_str}" ) print( f"However these {items_word} are in range: {valid_str}" ) choices_possible = [ f"Download only {valid_str} and ignore {invalid_str}", f"Download only {valid_str} and change {invalid_str}", f"Don't download {valid_str} and change the whole selection" ] else: print( f"All of the following {items_word} are out of range: {invalid_str}" ) continue choice_selected = ask_input_for_item_from_list( choices_possible, "choice", "choose", with_clear=False, inside_call=True) if choice_selected == choices_possible[0]: selected_items.extend(valid) selected_item_isvalid = True elif choice_selected == choices_possible[1]: selected_items.extend(valid) elif choice_selected == choices_possible[2]: selected_items.clear() else: print(f"These {items_word} will be downloaded: {valid_str}") def on_yes_action(): nonlocal selected_item_isvalid selected_items.extend(valid) selected_item_isvalid = True def on_no_action(): selected_items.clear() ask_yes_no_question("Is that your choice? [Y/N] ", on_yes_action, on_no_action) selected_items = CommonFuncs.sorted_unique_list(selected_items) CommonVars.chosen_items_till_now[ items_word] = f"You chose {build_ranges_str(selected_items)}" return list( map(lambda list_item: items_list[list_item - 1], selected_items))
def run(self): CommonFuncs.disable_stdio() self.handle_mps() CommonFuncs.enable_stdio()