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;
示例#2
0
        /// <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);
        }
示例#3
0
        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);
            }));
        }
示例#4
0
        private static IEnumerable <IDownloadableLink> AskForMultipleLinks()
        {
            var result = MenuChooseItem.AskInputForMultipleItemsFromList(SharedVars.SelectedSection.Links, "files").ToList();

            SharedVars.DownloadQueue.AddUnique(result);
            return(result);
        }
示例#5
0
        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);
        }
示例#6
0
        private static async Task <ISection> AskForSection()
        {
            await SectionExtractor.ExtractSectionsForCourse(SharedVars.SelectedCourseLink);

            var result = MenuChooseItem.AskInputForSingleItemFromList(SharedVars.Sections, "section");

            SharedVars.SelectedSection = result;
            return(result);
        }
示例#7
0
        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);
        }
示例#9
0
        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);
        }
示例#10
0
        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;
        }
示例#11
0
        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] "));
        }
示例#12
0
        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;
                }
            }
        }
示例#13
0
        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;
        }