public static void LoadOnlineFavourites()
        {
            if (OnlineFavouritesLoaded)
            {
                return;
            }
            OnlineFavouritesLoaded = true;

            NotificationManager.ShowMessageMassive("Loading online favourites...", 1000);

            pWebRequest dnr = new pWebRequest(string.Format(Urls.GET_FAVOURITES, ConfigManager.sUsername, ConfigManager.sPassword));

            dnr.Finished += delegate(pWebRequest r, Exception e)
            {
                foreach (string s in r.ResponseString.Split('\n'))
                {
                    if (s.Length == 0)
                    {
                        continue;
                    }

                    int beatmapSetId = Int32.Parse(s);
                    Beatmaps.FindAll(b => b.BeatmapSetId == beatmapSetId).ForEach(b => b.OnlineFavourite = true);
                }

                InvokeOnOnlineFavouritesLoaded();
            };
            dnr.Perform();
        }
        internal static void GetOnlineBeatmapInfo()
        {
            long tick = DateTime.Now.Ticks;

            const long check_interval = 10000L * 1000 * 60 * 60 * 24; //24 hours

            List <Beatmap> bm = Beatmaps.FindAll(b => b.BeatmapPresent && tick - b.LastInfoUpdate > check_interval && (b.BeatmapTopicId == 0 || b.PlayerRank == Ranks.N || b.SubmissionStatus == SubmissionStatus.Unknown));

            GetOnlineBeatmapInfo(bm);
        }
        internal static void ProcessBeatmaps(bool newFilesOnly = false, bool quickFolderChecks = false)
        {
            SongWatcher.EnableRaisingEvents = false;
            QuickFolderChecks = quickFolderChecks;

            //Doing a full pass over the song folder is an expensive operation.
            //We should only do so if it is requested, or if we can't find the local osu!.db
            if (!newFilesOnly)
            {
                //FULL PROCESS
                Logger.LogPrint(@"_______________ Full process initiated. _______________");

                //Mark every single beatmap as "not found" to begin with, then remove any remaining at the end which were not found.
                Beatmaps.ForEach(b =>
                {
                    b.DatabaseNotFound = true;
                    b.HeadersLoaded    = false;
                });

                Root.Children.Clear();
                Root.Beatmaps.Clear();

                TotalUniqueSets = 0;
                TotalAudioOnly  = 0;

                ProcessFolder(BeatmapManager.SongsDirectory);

                int removed = Beatmaps.RemoveAll(b => b.DatabaseNotFound);

                if (removed > 0)
                {
                    InvokeOnStatusUpdate(string.Format(LocalisationManager.GetString(OsuString.BeatmapManager_RemoveMissingMaps), removed));
                }

                ReloadDictionaries();

                InvokeOnStatusUpdate(string.Format(LocalisationManager.GetString(OsuString.BeatmapManager_LoadedMaps), Beatmaps.Count));
            }
            else
            {
                //PARTIAL PROCESS

                for (int j = 0; j < ChangedPackages.Count; j++)
                {
                    string package = ChangedPackages[j];

                    if (!File.Exists(package))
                    {
                        //Package is no longer with us :(

                        Logger.Log($@"{package} could not be loaded. It no longer exists.");

                        List <Beatmap> matches = Beatmaps.FindAll(b => b.ContainingFolderAbsolute == package);
                        matches.ForEach(b => Remove(b));

                        continue;
                    }
                    else
                    {
                        BeatmapTreeLevel level = GetTreeLevel(Path.GetDirectoryName(package));
                        if (level != null)
                        {
                            ProcessPackage(package, level);
                        }
                    }
                }

                //Special processing for importing new maps
                //Changed to for loop because foreach was getting modified internally.  not sure how this could happen.
                for (int j = 0; j < ChangedFolders.Count; j++)
                {
                    string folder = ChangedFolders[j];

                    bool folderStillExists = Directory.Exists(folder);

                    if (!folder.StartsWith(BeatmapManager.SongsDirectory))
                    {
                        ProcessBeatmaps();
                        return;
                    }

                    BeatmapTreeLevel level = GetTreeLevel(folder);

                    if (level == null)
                    {
                        continue;
                    }

                    if (level.Children.Count > 0 && folderStillExists)
                    {
                        //ignore this folder change for now?
                        //sure, unless it was deleted.
                        continue;
                    }

                    ResetTreeLevel(level);
                    if (folderStillExists)
                    {
                        ProcessTree(level);
                    }
                    else
                    {
                        if (level.Parent != null)
                        {
                            level.Parent.Children.Remove(level);
                        }
                    }
                }
            }

            if (Current != null && newFilesOnly)
            {
                SetCurrentFromFilename(Current.Filename, false);
            }

            InitialLoadComplete = true;

            SongWatcher.EnableRaisingEvents = true;
        }