private void GetPlaylistMetadata()
        {
            MetadataScraper scraper = new MetadataScraper();

            GlobalMetadataScrape = scraper.GetPlaylistMetadata(playListURL);
            List <VideoMetadataDisplay> newList = new List <VideoMetadataDisplay>();

            ListOfVideos.Background.Opacity = 0.45;
            foreach (MetadataScrape scrape in GlobalMetadataScrape.VideoMetadataList)
            {
                List <string> QualitiesList = new List <string>();
                foreach (VidQuality quality in scrape.VidQualities)
                {
                    QualitiesList.Add(quality.Format + " - " + quality.Resolution + " (ID:" + quality.VidNo + ")");
                }
                newList.Add(new VideoMetadataDisplay()
                {
                    VideoTitleText = scrape.VidTitle, VideoStatusText = "", VideoThumbnailURL = scrape.ThumbnailURL, VideoTotalSizeText = "Please select an audio and video quality", AudioCount = scrape.AudQualities.Count, VideoQualitiesList = QualitiesList
                });
            }
            ListOfVideos.ItemsSource = newList;
        }
        private void GetPlaylistMetadata()
        {
            MetadataScraper scraper = new MetadataScraper();

            GlobalMetadataScrape            = scraper.GetPlaylistMetadata(playListURL);
            ListOfVideos.Background.Opacity = 0.45;
            VidQualityInfoList = new List <VideoQualityInfo>();
            ItemsControlLock   = new object();
            foreach (MetadataScrape scrape in GlobalMetadataScrape.VideoMetadataList)
            {
                VideoQualityInfo VidQualInfo = new VideoQualityInfo();
                VidQualInfo.HasSelectedAudio   = false;
                VidQualInfo.HasSelectedVideo   = false;
                VidQualInfo.IsMP3Only          = false;
                VidQualInfo.SelectedAudQuality = 0;
                VidQualInfo.SelectedVidQuality = 0;
                VidQualInfo.VidTitle           = scrape.VidTitle;
                VidQualInfo.VidID          = scrape.VidID;
                VidQualInfo.AudQualityList = scrape.AudQualities;
                VidQualInfo.VidQualityList = scrape.VidQualities;
                List <string> QualitiesList = new List <string>();
                foreach (VidQuality quality in scrape.VidQualities)
                {
                    QualitiesList.Add(quality.Format + " - " + quality.Resolution + " (ID:" + quality.VidNo + ")");
                }
                QualitiesList.Add("MP3 Only");
                VidQualityInfoList.Add(VidQualInfo);
                newList.Add(new VideoMetadataDisplay()
                {
                    VideoTitleText = scrape.VidTitle, VideoStatusText = "", VideoThumbnailURL = scrape.ThumbnailURL, VideoTotalSizeText = "Please select an audio and video quality", AudioCount = scrape.AudQualities.Count, VideoQualitiesList = QualitiesList
                });
            }
            ListOfVideos.ItemsSource = newList;
            TotalVideos = VidQualityInfoList.Count;
            BindingOperations.EnableCollectionSynchronization(newList, ItemsControlLock);
        }
        private async Task ProcessRequest(HttpListenerContext context)
        {
            HttpListenerRequest request = context.Request;

            Log.WriteLog(LogType.Info, "Recieved a request for " + request.Url);
            if (request.RawUrl.Contains("getmetadata"))
            {
StartCheckMaintainance:
                if (File.Exists(downloadPath + "\\maintainance.lck"))
                {
                    Log.WriteLog(LogType.Info, "Delaying request for 4 seconds as maintainance is currently running");
                    Thread.Sleep(4000);
                    goto StartCheckMaintainance;
                }
                string          VidID   = request.QueryString.GetValues(request.QueryString.AllKeys[0])[0];
                string          VidURL  = "https://www.youtube.com/watch?v=" + VidID;
                MetadataScraper scraper = new MetadataScraper();
                MetadataScrape  scrape  = new MetadataScrape();
                scrape = scraper.GetMetadata(VidURL);
                HttpListenerResponse response = context.Response;
                MemoryStream         xmlData  = new MemoryStream();
                //from https://stackoverflow.com/questions/16371037/save-xml-content-to-a-variable answer by Adil and https://csharp.net-tutorials.com/xml/writing-xml-with-the-xmlwriter-class/
                using (XmlWriter writer = XmlWriter.Create(xmlData))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("VideoMetadata");
                    writer.WriteStartElement("VideoID");
                    writer.WriteString(VidID);
                    writer.WriteEndElement();
                    writer.WriteStartElement("Title");
                    writer.WriteString(scrape.VidTitle);
                    writer.WriteEndElement();
                    writer.WriteStartElement("ThumbnailURL");
                    writer.WriteString(scrape.ThumbnailURL);
                    writer.WriteEndElement();
                    writer.WriteStartElement("VideoQualities");
                    foreach (VidQuality quality in scrape.VidQualities)
                    {
                        writer.WriteStartElement("vidquality");
                        writer.WriteAttributeString("format", quality.Format);
                        writer.WriteAttributeString("size", quality.FileSize);
                        writer.WriteAttributeString("resolution", quality.Resolution);
                        writer.WriteAttributeString("ID", quality.VidNo);
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    writer.WriteStartElement("AudioQualities");
                    foreach (AudQuality quality in scrape.AudQualities)
                    {
                        writer.WriteStartElement("audquality");
                        writer.WriteAttributeString("format", quality.Format);
                        writer.WriteAttributeString("size", quality.FileSize);
                        writer.WriteAttributeString("ID", quality.AudNo);
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }
                string xmlString = ASCIIEncoding.UTF8.GetString(xmlData.ToArray());
                if (request.HttpMethod == "OPTIONS")
                {
                    response.AddHeader("Access-Control-Allow-Headers", "*");
                }
                response.AppendHeader("Access-Control-Allow-Origin", "*");
                byte[] buffer = Encoding.UTF8.GetBytes(xmlString);
                context.Response.ContentLength64 = buffer.Length;
                context.Response.StatusCode      = (int)HttpStatusCode.OK;
                context.Response.ContentType     = "text/xml; encoding='utf-8'";
                context.Response.OutputStream.Write(buffer, 0, buffer.Length);
                Log.WriteLog(LogType.Info, "Successfully sent output");
                response.Close();
            }
            else if (request.RawUrl.Contains("getplaylistmetadata"))
            {
StartCheckMaintainance:
                if (File.Exists(downloadPath + "\\maintainance.lck"))
                {
                    Log.WriteLog(LogType.Info, "Delaying request for 4 seconds as maintainance is currently running");
                    Thread.Sleep(4000);
                    goto StartCheckMaintainance;
                }
                string                 playlistID     = request.QueryString.GetValues(request.QueryString.AllKeys[0])[0];
                string                 playlistURL    = "https://www.youtube.com/playlist?list=" + playlistID;
                MetadataScraper        scraper        = new MetadataScraper();
                PlaylistMetadataScrape playlistScrape = scraper.GetPlaylistMetadata(playlistURL);
                HttpListenerResponse   response       = context.Response;
                MemoryStream           xmlData        = new MemoryStream();
                using (XmlWriter writer = XmlWriter.Create(xmlData))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("PlaylistMetadata");
                    writer.WriteStartElement("PlaylistID");
                    writer.WriteString(playlistID);
                    writer.WriteEndElement();
                    writer.WriteStartElement("PlaylistName");
                    writer.WriteString(playlistScrape.PlaylistName);
                    writer.WriteEndElement();
                    writer.WriteStartElement("Videos");
                    foreach (MetadataScrape eachVideo in playlistScrape.VideoMetadataList)
                    {
                        writer.WriteStartElement("VideoMetadata");
                        writer.WriteStartElement("VideoID");
                        writer.WriteString(eachVideo.VidID);
                        writer.WriteEndElement();
                        writer.WriteStartElement("Title");
                        writer.WriteString(eachVideo.VidTitle);
                        writer.WriteEndElement();
                        writer.WriteStartElement("ThumbnailURL");
                        writer.WriteString(eachVideo.ThumbnailURL);
                        writer.WriteEndElement();
                        writer.WriteStartElement("VideoQualities");
                        foreach (VidQuality quality in eachVideo.VidQualities)
                        {
                            writer.WriteStartElement("vidquality");
                            writer.WriteAttributeString("format", quality.Format);
                            writer.WriteAttributeString("size", quality.FileSize);
                            writer.WriteAttributeString("resolution", quality.Resolution);
                            writer.WriteAttributeString("ID", quality.VidNo);
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();
                        writer.WriteStartElement("AudioQualities");
                        foreach (AudQuality quality in eachVideo.AudQualities)
                        {
                            writer.WriteStartElement("audquality");
                            writer.WriteAttributeString("format", quality.Format);
                            writer.WriteAttributeString("size", quality.FileSize);
                            writer.WriteAttributeString("ID", quality.AudNo);
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }
                string xmlString = ASCIIEncoding.UTF8.GetString(xmlData.ToArray());
                if (request.HttpMethod == "OPTIONS")
                {
                    response.AddHeader("Access-Control-Allow-Headers", "*");
                }
                response.AppendHeader("Access-Control-Allow-Origin", "*");
                byte[] buffer = Encoding.UTF8.GetBytes(xmlString);
                context.Response.ContentLength64 = buffer.Length;
                context.Response.StatusCode      = (int)HttpStatusCode.OK;
                context.Response.ContentType     = "text/xml; encoding='utf-8'";
                context.Response.OutputStream.Write(buffer, 0, buffer.Length);
                Log.WriteLog(LogType.Info, "Successfully sent output");
                response.Close();
            }
            else if (request.RawUrl.Contains("downloadvid"))
            {
StartCheckMaintainance:
                if (File.Exists(downloadPath + "\\maintainance.lck"))
                {
                    Log.WriteLog(LogType.Info, "Delaying request for 4 seconds as maintainance is currently running");
                    Thread.Sleep(4000);
                    goto StartCheckMaintainance;
                }
                YTDownloader downloader = new YTDownloader();
                downloader.DownloadCompleted       += Downloader_DownloadCompleted;
                downloader.DownloadProgressChanged += Downloader_DownloadProgressChanged;
                string urlID     = request.QueryString.GetValues(request.QueryString.AllKeys[0])[0];
                string isMP3Only = request.QueryString.GetValues(request.QueryString.AllKeys[1])[0];
                if (isMP3Only.ToLower().Contains("true"))
                {
                    string       isUsingThumbnail = request.QueryString.GetValues(request.QueryString.AllKeys[2])[0];
                    DownloadType mp3DownloadType;
                    if (isUsingThumbnail.ToLower().Contains("true"))
                    {
                        mp3DownloadType = DownloadType.MP3Pic;
                    }
                    else
                    {
                        mp3DownloadType = DownloadType.MP3Only;
                    }
                    string     vidURL   = "https://www.youtube.com/watch?v=" + urlID;
                    VidQuality vQuality = new VidQuality();
                    vQuality.VidNo = "MP3-Only";
                    AudQuality aQuality = new AudQuality();
                    aQuality.AudNo = urlID;
                    YTDownload download = new YTDownload();
                    download.context  = context;
                    download.aQuality = aQuality;
                    download.vQuality = vQuality;
                    download.VidID    = urlID;
                    download.DownType = mp3DownloadType;
                    RunningDownloads.Add(download);
                    HttpListenerResponse response = context.Response;
                    if (request.HttpMethod == "OPTIONS")
                    {
                        response.AddHeader("Access-Control-Allow-Headers", "*");
                    }
                    response.AppendHeader("Access-Control-Allow-Origin", "*");
                    context.Response.SendChunked = true;
                    downloader.DownloadVideo(vidURL, mp3DownloadType, aQuality, vQuality);
                }
                else
                {
                    try
                    {
                        int        VidID    = int.Parse(request.QueryString.GetValues(request.QueryString.AllKeys[2])[0]);
                        int        AudID    = int.Parse(request.QueryString.GetValues(request.QueryString.AllKeys[3])[0]);
                        string     vidURL   = "https://www.youtube.com/watch?v=" + urlID;
                        VidQuality vQuality = new VidQuality();
                        vQuality.VidNo = VidID.ToString();
                        AudQuality aQuality = new AudQuality();
                        aQuality.AudNo = AudID.ToString();
                        YTDownload download = new YTDownload();
                        download.aQuality = aQuality;
                        download.vQuality = vQuality;
                        download.VidID    = urlID;
                        download.context  = context;
                        download.DownType = DownloadType.CustomQuality;
                        RunningDownloads.Add(download);
                        HttpListenerResponse response = context.Response;
                        if (request.HttpMethod == "OPTIONS")
                        {
                            response.AddHeader("Access-Control-Allow-Headers", "*");
                        }
                        response.AppendHeader("Access-Control-Allow-Origin", "*");
                        context.Response.SendChunked = true;
                        downloader.DownloadVideo(vidURL, DownloadType.CustomQuality, aQuality, vQuality);
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLog(LogType.Error, ex.ToString());
                    }
                }
            }
            else if (request.RawUrl.Contains("download"))
            {
StartCheckMaintainance:
                if (File.Exists(downloadPath + "\\maintainance.lck"))
                {
                    Log.WriteLog(LogType.Info, "Delaying request for 4 seconds as maintainance is currently running");
                    Thread.Sleep(4000);
                    goto StartCheckMaintainance;
                }
                try
                {
                    HttpListenerResponse response = context.Response;
                    string linkName = request.QueryString.GetValues(request.QueryString.AllKeys[0])[0];
                    string fileName = linkName.Replace('*', ' ');
                    fileName = fileName.Replace('|', '&');
                    fileName = fileName.Replace('<', '=');
                    if (request.HttpMethod == "OPTIONS")
                    {
                        response.AddHeader("Access-Control-Allow-Headers", "*");
                    }
                    response.AppendHeader("Access-Control-Allow-Origin", "*");
                    if (File.Exists(downloadPath + "\\" + fileName))
                    {
                        string   contentType = "";
                        FileInfo info        = new FileInfo(fileName);
                        if (info.Extension.ToLower().Contains("mp4"))
                        {
                            contentType = "video/mp4";
                        }
                        else if (info.Extension.ToLower().Contains("mp3"))
                        {
                            contentType = "audio/mpeg";
                        }
                        else if (info.Extension.ToLower().Contains("webm"))
                        {
                            contentType = "video/webm";
                        }
                        else if (info.Extension.ToLower().Contains("mkv"))
                        {
                            contentType = "video/x-matroska";
                        }
                        response.StatusCode = (int)HttpStatusCode.OK;
                        using (FileStream stream = File.OpenRead(downloadPath + "\\" + fileName))
                        {
                            response.ContentType     = contentType;
                            response.ContentLength64 = info.Length;
                            response.AddHeader(
                                "Content-Disposition",
                                "Attachment; filename=\"" + Path.GetFileName(downloadPath + "\\" + fileName) + "\"");
                            stream.CopyTo(response.OutputStream);
                        }
                    }
                    else
                    {
                        response.StatusCode = (int)HttpStatusCode.NotFound;
                        string responseString = "File not found";
                        byte[] data           = Encoding.UTF8.GetBytes(responseString);
                        response.OutputStream.Write(data, 0, data.Length);
                    }
                    response.Close();
                }
                catch (Exception ex)
                {
                    Log.WriteLog(LogType.Error, "Error while downloading a file from server: " + ex.ToString());
                }
            }
        }