private void RemoveThread(Thread thread) { Program.Log(true, $"Removing thread {thread.URL}! thread.isGone: {thread.Gone}"); if (Properties.Settings.Default.addThreadSubjectToFolder) { string currentPath = thread.SaveTo.Replace("\r", ""); string cleanSubject = Utils.CleanSubjectString(thread.Subject); // There are \r characters appearing from the custom subjects, TODO: need to get to the bottom of the cause of this. string destinationPath; if ((ThreadFolderNameFormat)Properties.Settings.Default.threadFolderNameFormat == ThreadFolderNameFormat.IdName) { destinationPath = (thread.SaveTo + " - " + cleanSubject); } else //NameId { destinationPath = Path.Combine(Path.GetDirectoryName(thread.SaveTo), $"{thread.Subject} - {thread.ID}"); } destinationPath = destinationPath.Replace("\r", "").Trim('\\', '/'); if (Directory.Exists(currentPath)) { int number = 0; string numberText() => (number == 0) ? "" : $" ({number})"; //string calculatedDestination() => Path.GetDirectoryName(destinationPath) + "\\" + Path.GetFileName(destinationPath) + numberText(); string calculatedDestination() => destinationPath + numberText(); while (Directory.Exists(calculatedDestination())) { number++; } Program.Log(true, $"Directory.Moving {currentPath} to {destinationPath}"); Directory.Move(currentPath, calculatedDestination()); } else { Program.Log(true, $"While attempting to rename thread {thread.URL} the current folder could not be found, renaming abandoned."); } } Invoke((MethodInvoker) delegate() { ThreadListBindingSource.Remove(thread); }); }
public void RenameThreadSubjectPrompt(int threadBindingSourceIndex) { Thread thread = Model.Threads[threadBindingSourceIndex]; GetStringMessageBox dialog = new GetStringMessageBox(thread.Subject); dialog.StartPosition = FormStartPosition.CenterParent; DialogResult result = dialog.ShowDialog(); if (result == DialogResult.OK) { string newSubject = string.IsNullOrWhiteSpace(dialog.UserEntry) ? Thread.NO_SUBJECT : dialog.UserEntry; thread.Subject = newSubject; } }
public void LoadTrackers() { ///Require the save on close setting to be true to load threads on application open. const bool requireSaveOnCloseToBeTrueToLoadThreadsAndBoards = true; if (!requireSaveOnCloseToBeTrueToLoadThreadsAndBoards || Properties.Settings.Default.SaveListsOnClose) // If enabled load URLs from file { string boards = Utils.LoadURLs(true); string threads = Utils.LoadURLs(false); if (!string.IsNullOrWhiteSpace(boards)) { lock (boardLock) { string[] URLs = boards.Split('\n'); for (int i = 0; i < URLs.Length; i++) { if (!string.IsNullOrWhiteSpace(URLs[i])) { Board newBoard = (Board)Utils.CreateNewTracker(URLs[i].Trim()); AddURLToList(newBoard); } } } } if (!string.IsNullOrWhiteSpace(threads)) { string[] URLs = threads.Split('\n'); new SysThread(() => { // END TODO Parallel.ForEach(URLs, (url) => { if (!string.IsNullOrWhiteSpace(url)) { Thread newThread = (Thread)Utils.CreateNewTracker(url.Trim()); Form.BeginInvoke(new Action(() => { AddURLToList(newThread); })); } }); Form.Invoke((MethodInvoker) delegate { Done(); }); }).Start(); } else { Done(); } } /// Executed once everything has finished being loaded. void Done() { scanTimer.Enabled = true; Scan(this, new EventArgs()); // Check for updates. if (Properties.Settings.Default.CheckForUpdatesOnStart) { UpdateController.Instance.CheckForUpdates(false); } } }
public void RemoveThread(Thread thread, bool manualRemove = false) { Program.Log(true, $"Removing thread {thread.URL}! thread.isGone: {thread.Gone}"); thread.Scraping = false; try { if (Properties.Settings.Default.AddThreadSubjectToFolder) { string currentPath = thread.SaveTo.Replace("\r", ""); string cleanSubject = Utils.CleanSubjectString(thread.Subject); // There are \r characters appearing from the custom subjects, TODO: need to get to the bottom of the cause of this. string destinationPath; if ((ThreadFolderNameFormat)Properties.Settings.Default.ThreadFolderNameFormat == ThreadFolderNameFormat.IdName) { destinationPath = (thread.SaveTo + " - " + cleanSubject); } else //NameId { destinationPath = Path.Combine(Path.GetDirectoryName(thread.SaveTo), $"{thread.Subject} - {thread.ID}"); } destinationPath = destinationPath.Replace("\r", "").Trim('\\', '/'); if (Directory.Exists(currentPath)) { int number = 0; string numberText() => (number == 0) ? "" : $" ({number})"; string calculatedDestination() => destinationPath + numberText(); while (Directory.Exists(calculatedDestination())) { number++; } Program.Log(true, $"Directory.Moving {currentPath} to {destinationPath}"); Directory.Move(currentPath, calculatedDestination()); } else { Program.Log(true, $"While attempting to rename thread \"{thread.Subject}\" the current folder could not be found, renaming abandoned."); } } lock (threadLock) { // Remove on UI thread because this method can be called from non-ui thread. Form.Invoke((MethodInvoker) delegate() { Model.Threads.Remove(thread); }); } } catch (Exception e) { Program.Log(true, $"Exception occured attempting to remove thread \"{thread.Subject}\" (URL: {thread.URL})."); Program.Log(e); if (manualRemove) { MessageBox.Show( $"An error occured when trying to remove the thread \"{thread.Subject}\". Please check the logs file in the ProgramData folder for more information.", "Remove Thread Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); } } }
private void ScanRoutine() { lock (threadLock) { // Remove 404'd threads for (int i = 0; i < Model.Threads.Count; i++) { if (Model.Threads[i].Gone) { RemoveThread(Model.Threads[i]); i--; } } if (Properties.Settings.Default.SaveListsOnClose) { Utils.SaveURLs(Model.Boards, Model.Threads.ToList()); } } // Make a copy of the current boards and scrape them for new threads. var boards = Model.Boards.ToList(); for (int i = 0; i < boards.Count; i++) { if (boards[i].Scraping) { // OrderBy because we need the threads to be in ascending order by ID for LargestAddedThreadNo to be useful. string[] boardThreadUrls = boards[i].GetThreadLinks().OrderBy(t => t).ToArray(); int largestNo = 0; Parallel.ForEach(boardThreadUrls, (url) => { if (boards[i].Scraping) { int?id = GetThreadID(boards[i], url); if (id.HasValue) { if (id.Value > boards[i].LargestAddedThreadNo) { Thread newThread = (Thread)Utils.CreateNewTracker(url); if (newThread != null && IsUnique(newThread, Model.Threads)) { bool urlWasAdded = AddURLToList(newThread); if (urlWasAdded) { if (id.Value > largestNo) //Not exactly safe in multithreaded but should work fine. { largestNo = id.Value; } } } } } } }); boards[i].LargestAddedThreadNo = largestNo; } } // Make a copy of the current threads and download them. var threads = Model.Threads.ToList(); for (int i = 0; i < Model.Threads.Count; i++) { if (Model.Threads[i].Scraping) { ThreadPool.QueueUserWorkItem(new WaitCallback(Model.Threads[i].Download)); } } }
private void MainForm_Load(object sender, EventArgs e) { if (!Properties.Settings.Default.minimizeToTray) // If trayicon deactivated { nfTray.Visible = false; // Hide it } scanTimer.Enabled = false; // Disable timer scanTimer.Interval = Properties.Settings.Default.timer; // Set interval scanTimer.Tick += new EventHandler(Scan); // When Timer ticks call scan() ThreadPool.SetMaxThreads(Environment.ProcessorCount, Environment.ProcessorCount); ///Require the save on close setting to be true to load threads on application open. const bool requireSaveOnCloseToBeTrueToLoadThreadsAndBoards = true; if (!requireSaveOnCloseToBeTrueToLoadThreadsAndBoards || Properties.Settings.Default.saveOnClose) // If enabled load URLs from file { string boards = Utils.LoadURLs(true); string threads = Utils.LoadURLs(false); if (!String.IsNullOrWhiteSpace(boards)) { lock (boardLock) { string[] URLs = boards.Split('\n'); for (int i = 0; i < URLs.Length; i++) { if (!string.IsNullOrWhiteSpace(URLs[i])) { Board newBoard = (Board)Utils.CreateNewTracker(URLs[i].Trim()); AddURLToList(newBoard); } } } } if (!String.IsNullOrWhiteSpace(threads)) { lock (threadLock) { string[] URLs = threads.Split('\n'); new SysThread(() => { // Without setting ScrollBars to None and then setting to Vertical the program will crash. // It doesnt like items being added in parallel in this method... // User cannot also resize columns while adding, or else program crashes. CheckForIllegalCrossThreadCalls = false; Invoke((MethodInvoker) delegate { threadGridView.ScrollBars = ScrollBars.None; }); threadGridView.AllowUserToResizeColumns = false; ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(URLs, options, (url) => { if (!string.IsNullOrWhiteSpace(url)) { Thread newThread = (Thread)Utils.CreateNewTracker(url.Trim()); AddURLToList(newThread); } }); Invoke((MethodInvoker) delegate { Done(); }); }).Start(); } } else { Done(); } } ///Executed once everything has finished being loaded. void Done() { threadGridView.ScrollBars = ScrollBars.Vertical; threadGridView.AllowUserToResizeColumns = true; scanTimer.Enabled = true; Scan(this, new EventArgs()); } }
private void ScanThread() { //List<Imageboard> goneThreads = new List<Imageboard>(); lock (threadLock) { // Removes 404'd threads Thread[] array = ThreadListBindingSource.ToArray(); for (int i = 0; i < array.Length; i++) { Thread thread = array[i]; if (thread.Gone) { RemoveThread(thread); //goneThreads.Add(thread); } } if (Properties.Settings.Default.saveOnClose) { Utils.SaveURLs(BoardList, ThreadListBindingSource.ToList()); } } lock (boardLock) { // Searches for new threads on the watched boards for (int i = 0; i < BoardList.Count; i++) { string[] threads = { }; try { threads = BoardList[i].GetThreadLinks(); } catch { } finally { for (int i1 = 0; i1 < threads.Length; i1++) { Thread newThread = (Thread)Utils.CreateNewTracker(threads[i1]); if (newThread != null && IsUnique(newThread.URL, ThreadListBindingSource)) { AddURLToList(newThread); } } } } } lock (threadLock) { // Download threads for (int i = 0; i < ThreadListBindingSource.Count; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadListBindingSource[i].Download)); } } }