public override BaseAction Handle(string inputString) { State = ActionState.NotFound; var actionWord = Type.ToLower(); if (inputString.ToLower().Contains(actionWord)) { IEnumerable <int> sequence = null; foreach (var piece in inputString.Split(' ')) { sequence = MenuChooseItem.ValidateInput(piece); if (sequence != null) { sequence = sequence.Select(i => i - 1).Where(i => i >= 0); break; } } ConfirmAction($"{actionWord} the last selection", () => { State = ActionState.FoundAndHandled; var stagesDepth = SharedVars.ChosenItemsTillNow.Count; switch (stagesDepth) { case 0 when sequence == null: HandleLink("https://courses.finki.ukim.mk/"); break;
/// <summary> /// if no numbers given => add/remove previously selected links or whole course or section /// if numbers given => add/remove selected links or whole course or section /// </summary> public override BaseAction Handle(string inputString) { State = ActionState.NotFound; if (inputString.ToLower().Contains(Type.ToLower())) { IEnumerable <int> sequence = null; foreach (var piece in inputString.Split(' ')) { sequence = MenuChooseItem.ValidateInput(piece); if (sequence != null) { sequence = sequence.Select(i => i - 1).Where(i => i >= 0); break; } } ConfirmAction( $"will {Type.ToLower()} selected/chosen items (recursively) {ToFromWord.ToLower()} download queue", () => { State = ActionState.FoundAndHandled; AddRemoveSelectedItems(sequence); }); } return(this); }
private void ShowQueue() { State = ActionState.FoundAndHandled; string linksPage; var page = 0; const int pageSize = 20; string message; do { Console.Clear(); Console.WriteLine("Queue:"); var totalPages = (int)Math.Ceiling(SharedVars.DownloadQueue.Count / 20.0); linksPage = SharedVars.DownloadQueue.Skip(page * pageSize).Take(pageSize) .Select((link, i) => $"{i + 1}. {link.Name}").Join(); ConsoleUtils.WriteLine(linksPage, ConsoleColor.White); message = FormatMessage(page, totalPages, pageSize, linksPage); page++; if (page * pageSize > SharedVars.DownloadQueue.Count) { page = 0; } } while (MenuChooseItem.AskYesNoQuestion(message, onOther: fullInputString => { page = OnInQueueActionWords(fullInputString, linksPage, page, pageSize); })); }
private static IEnumerable <IDownloadableLink> AskForMultipleLinks() { var result = MenuChooseItem.AskInputForMultipleItemsFromList(SharedVars.SelectedSection.Links, "files").ToList(); SharedVars.DownloadQueue.AddUnique(result); return(result); }
private static async Task <NamingMethod> AskForNamingMethod() { const string secondChoice = "Use the file name that appears on courses (Recommended)"; const string examplesChoice = "Show examples and ask again (will show random 5 examples, BUT slower)"; var choicesPossible = new List <string> { "Use the file name from the url (default behavior when downloading from browser)", secondChoice, examplesChoice }; while (true) { var result = MenuChooseItem.AskInputForSingleItemFromList(choicesPossible, "choice", "choose"); if (result == choicesPossible[0]) { SharedVars.NamingMethod = NamingMethod.UrlName; break; } if (result == choicesPossible[1]) { SharedVars.NamingMethod = NamingMethod.CoursesName; break; } if (result == choicesPossible[2]) { // because we're displaying in place but AskInputForSingleItemFromList still appends to breadcrumbs SharedVars.ChosenItemsTillNow.Remove(SharedVars.ChosenItemsTillNow.Keys.Last()); choicesPossible.Remove(examplesChoice); var randomN = SharedVars.DownloadQueue.TakeRandomN(5); var table = new ConsoleTableUtil("From Courses", "From URL (Default)"); foreach (var link in randomN) { await link.GetNameFromUrlNow(); table.AddRow( link.FileFromCourses.FileNameAndExtensionOnly, link.FileFromUrl.FileNameAndExtensionOnly ); } var examples = $"Some examples:\n\n{table}"; choicesPossible.Remove(secondChoice); choicesPossible.Add($"{secondChoice}\n{examples}"); } } return(SharedVars.NamingMethod); }
private static async Task <ISection> AskForSection() { await SectionExtractor.ExtractSectionsForCourse(SharedVars.SelectedCourseLink); var result = MenuChooseItem.AskInputForSingleItemFromList(SharedVars.Sections, "section"); SharedVars.SelectedSection = result; return(result); }
private static async Task <ICourseLink> AskForCourse() { await CoursesExtractor.ExtractCourses(); var result = MenuChooseItem.AskInputForSingleItemFromList(SharedVars.Courses, "course"); SharedVars.SelectedCourseLink = result; return(result); }
protected void ConfirmAction(string outcome, Action onIsYes) { var confirmMessage = string.Join("\n", $"I noticed that you entered {Type.ToLower()}, which will {outcome}", "Is that the action you wanted to perform (answer no if it was entered by mistake)? [Y/N] " ); MenuChooseItem.AskYesNoQuestion(confirmMessage, onIsYes); }
private static int OnInQueueActionWords(string fullInputString, string linksPage, int page, int pageSize) { if (fullInputString.ToLower().Contains("clear")) { SharedVars.DownloadQueue.Clear(); return(0); } if (fullInputString.ToLower().Contains("download")) { throw new DownloadAction(); } if (fullInputString.ToLower().Contains("remove")) { IEnumerable <int> sequence = null; foreach (var piece in fullInputString.Split(' ')) { sequence = MenuChooseItem.ValidateInput(piece); if (sequence != null) { sequence = sequence.Select(i => i - 1) .Where(i => i >= 0 && i < linksPage.Split('\n').Length); break; } if (piece.ToLower() == "all") { SharedVars.DownloadQueue.Clear(); return(0); } } if (sequence != null) { page = page > 0 ? --page : page; var matchingLinks = SharedVars.DownloadQueue.Skip(page * pageSize) .Take(pageSize) .Where((_, i) => sequence.Contains(i)); SharedVars.DownloadQueue.RemoveAll(link => matchingLinks.Contains(link)); } } return(page); }
private static async Task HandleSwitchSemesterAction() { var namedSemesters = new List <string> { "1st Semester", "2nd Semester", "3rd Semester" }; namedSemesters.AddRange(Enumerable.Range(4, 5).Select(i => $"{i}th Semester")); var semestersCount = await CoursesExtractor.ExtractSemestersCount(); var itemsList = namedSemesters.Take(semestersCount).ToList(); var chosenItem = MenuChooseItem.AskInputForSingleItemFromList(itemsList, "semester", "switch to", breadcrumbs: false); var chosenSemester = namedSemesters.IndexOf(chosenItem) + 1; SharedVars.CurrentSemesterNumber = chosenSemester; }
private static void HandleQueueModificationBaseAction(QueueModificationBaseAction action) { List <IDownloadableLink> matchingLinks; switch (action.MatchingItemType) { case ItemTypeToAddRemove.Course: matchingLinks = SharedVars.Courses .Where((course, j) => action.MatchingItems.Contains(j)) .SelectMany(course => SectionExtractor.ExtractSectionsForCourse(course).Result .SelectMany(section => section.Links)) .ToList(); break; case ItemTypeToAddRemove.Section: matchingLinks = SharedVars.Sections .Where((section, j) => action.MatchingItems.Contains(j)) .SelectMany(section => section.Links) .ToList(); break; case ItemTypeToAddRemove.Link: matchingLinks = SharedVars.SelectedSection.Links .Where((link, j) => action.MatchingItems.Contains(j)) .ToList(); break; default: matchingLinks = Enumerable.Empty <IDownloadableLink>().ToList(); break; } if (!matchingLinks.Any()) { ConsoleUtils.WriteLine("Unfortunately downloading files using multiple naming methods at once is not possible", ConsoleIOType.Error); return; } do { string message; if (action is AddAction) { var count = matchingLinks.Except(SharedVars.DownloadQueue).Count(); SharedVars.DownloadQueue.AddUnique(matchingLinks); message = $"Added {count} items (to revert, " + "simply call Remove like you did with Add in the same way and location"; } else { var count = SharedVars.DownloadQueue.Intersect(matchingLinks).Count(); SharedVars.DownloadQueue.RemoveAll(link => matchingLinks.Contains(link)); message = $"Removed {count} items (to revert, " + "simply call Add like you did with Remove in the same way and location"; } ConsoleUtils.WriteLine(message, ConsoleColor.Yellow); if (action is AddAction) { action = new RemoveAction(); } else { action = new AddAction(); } } while (MenuChooseItem.AskYesNoQuestion("Do you want to revert now? [Y/N] ")); }
public static async Task Run() { SharedVars.CurrentRunningActionType = RunningActionType.AskForCourse; while (true) { try { switch (SharedVars.CurrentRunningActionType) { case RunningActionType.AskForCourse: await AskForCourse(); break; case RunningActionType.AskForSection: await AskForSection(); break; case RunningActionType.AskForMultipleLinks: AskForMultipleLinks(); break; case RunningActionType.AskForNamingMethod: await AskForNamingMethod(); break; case RunningActionType.DownloadSelectedLinks: await DownloadSelectedLinks(); break; } SharedVars.CurrentRunningActionType++; } catch (BaseAction action) { await ActionHandler.HandleAction(action); } if (SharedVars.CurrentRunningActionType == RunningActionType.Repeat) { var startAgain = MenuChooseItem.AskYesNoQuestion("Do you want to start again? [Y/N] ", () => { SharedVars.ChosenItemsTillNow.Clear(); SharedVars.CurrentRunningActionType = RunningActionType.AskForCourse; }, Dispose); if (!startAgain) // onNo { break; } } if (SharedVars.CurrentRunningActionType == RunningActionType.End) { Dispose(); break; } } }
private static async Task CreateSession() { var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false }; _downloadProgressTrackingHandler = new ProgressMessageHandler(httpClientHandler); SessionClient = new HttpClient(_downloadProgressTrackingHandler) { BaseAddress = new Uri("http://courses.finki.ukim.mk/"), }; SessionClient.DefaultRequestHeaders.UserAgent.ParseAdd("CoursesDownloader-C# Console App"); HttpResponseMessage login = null; while (true) { Console.WriteLine("Establishing connection with courses"); try { login = await SessionClient.GetAsyncHttp("http://courses.finki.ukim.mk/login/index.php"); if (!login.IsSuccessStatusCode) { throw new HttpRequestException(); } } catch (HttpRequestException) { Console.WriteLine("Connection cannot be established"); var shouldRetry = MenuChooseItem.AskYesNoQuestion("Do you want to try again? [Y/N] ", Console.Clear, () => { Environment.Exit(0); }); if (shouldRetry) // onYes { continue; } } break; } Console.WriteLine("Preparing CAS login"); var text = await login.Content.ReadAsStringAsync(); login.Dispose(); var doc = new HtmlDocument(); doc.LoadHtml(text); var hiddenInput = doc.DocumentNode.SelectNodes("//form//input[@type=\"hidden\"]"); var loginData = new Dictionary <string, string>(); foreach (var x in hiddenInput) { loginData[x.Attributes.First(t => t.Name == "name").Value] = x.Attributes.First(t => t.Name == "value").Value; } EnterCredentialsAgain: var(username, password) = CredentialUtil.GetCredential(CASTarget); while (username.IsNullOrEmpty() || password.IsNullOrEmpty()) { username = ConsoleUtils.ReadLine("Please enter your CAS username >>> ", ConsoleIOType.Question); password = ConsoleUtils.ReadLine("Please enter your CAS password >>> ", ConsoleIOType.Question, true); CredentialUtil.SetCredentials(CASTarget, username, password); } loginData["username"] = username; loginData["password"] = password; using (var loginDataContent = new FormUrlEncodedContent(loginData.ToArray())) { Console.WriteLine("Logging into CAS"); using (var response = await SessionClient.PostAsyncHttp(login.RequestMessage.RequestUri, loginDataContent)) { // if redirected to CAS, wrong password or username if (response.RequestMessage.RequestUri.Host == new Uri(CASTarget).Host) { ConsoleUtils.WriteLine("The username or password you entered is incorrect. Please try again"); CredentialUtil.RemoveCredentials(CASTarget); // remove incorrect credentials goto EnterCredentialsAgain; } FindSessKey(await response.Content.ReadAsStringAsync()); } } LoginTime = DateTime.Now; }