コード例 #1
0
        public string SubstituteWildcards(string filename, TwitchVideo video)
        {
            if (video == null)
            {
                throw new ArgumentNullException(nameof(video));
            }

            if (string.IsNullOrWhiteSpace(filename))
            {
                return(filename);
            }

            string result = filename;

            DateTime recorded = video.RecordedDate;

            TwitchVideoQuality resolution = video.Resolutions.First();

            result = result.Replace(FilenameWildcards.CHANNEL, video.Channel);
            result = result.Replace(FilenameWildcards.GAME, video.Game);
            result = result.Replace(FilenameWildcards.DATE, recorded.ToString("yyyyMMdd"));
            result = result.Replace(FilenameWildcards.TIME, recorded.ToString("hhmmsstt", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.TIME24, recorded.ToString("HHmmss", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.ID, video.IdTrimmed);
            result = result.Replace(FilenameWildcards.TITLE, video.Title);
            result = result.Replace(FilenameWildcards.RES, resolution.Resolution);
            result = result.Replace(FilenameWildcards.FPS, resolution.Fps);

            result = this.SubstituteInvalidChars(result, "_");

            return(result);
        }
コード例 #2
0
        private TwitchPlaylist GetVodPlaylist(Action <string> log, string tempDir, Dictionary <TwitchVideoQuality, string> playlistInfo, TwitchVideoQuality selectedQuality)
        {
            TwitchVideoQuality quality = playlistInfo.Keys.First(q => q.Equals(selectedQuality));

            string playlistUrl = playlistInfo[quality];

            log(Environment.NewLine + Environment.NewLine + "Playlist url for selected quality '" + quality.DisplayString + "' is '" + playlistUrl + "'");

            using (WebClient webClient = new WebClient())
            {
                log(Environment.NewLine + Environment.NewLine + "Retrieving playlist...");
                string playlistStr = webClient.DownloadString(playlistUrl);
                log(" done!");

                if (string.IsNullOrWhiteSpace(playlistStr))
                {
                    throw new ApplicationException("The playlist is empty!");
                }

                string urlPrefix = playlistUrl.Substring(0, playlistUrl.LastIndexOf("/") + 1);

                log(Environment.NewLine + "Parsing playlist...");
                TwitchPlaylist vodPlaylist = TwitchPlaylist.Parse(tempDir, playlistStr, urlPrefix);
                log(" done!");

                log(Environment.NewLine + "Number of video chunks: " + vodPlaylist.Count());

                return(vodPlaylist);
            }
        }
コード例 #3
0
        private void DownloadVideo(string id)
        {
            try
            {
                lock (_commandLockObject)
                {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideo video = Videos.Where(v => v.Id == id).FirstOrDefault();

                        if (video != null)
                        {
                            TwitchVideoAuthInfo vodAuthInfo = _apiService.GetVodAuthInfo(video.Id);

                            if (!vodAuthInfo.Privileged && vodAuthInfo.SubOnly)
                            {
                                if (_isAuthenticatedSubOnly)
                                {
                                    _dialogService.ShowMessageBox("This video is sub-only but you are not subscribed to the channel!", "Download", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }
                                else
                                {
                                    _dialogService.ShowMessageBox("This video is sub-only! You need to enable sub-only video download support first!", "Download", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }

                                return;
                            }

                            Dictionary <TwitchVideoQuality, string> playlistInfo = _apiService.GetPlaylistInfo(id, vodAuthInfo);
                            List <TwitchVideoQuality> qualities = playlistInfo.Keys.OrderBy(q => q).ToList();

                            Preferences currentPrefs = _preferencesService.CurrentPreferences.Clone();

                            TwitchVideoQuality selectedQuality = GetSelectedQuality(qualities, currentPrefs.DownloadDefaultQuality);

                            string folder = currentPrefs.DownloadSubfoldersForFav && _preferencesService.IsChannelInFavourites(video.Channel)
                                ? Path.Combine(currentPrefs.DownloadFolder, video.Channel)
                                : currentPrefs.DownloadFolder;

                            string filename = _filenameService.SubstituteWildcards(currentPrefs.DownloadFileName, video, selectedQuality);
                            filename = _filenameService.EnsureExtension(filename, currentPrefs.DownloadDisableConversion);

                            DownloadParameters downloadParams = new DownloadParameters(video, qualities, selectedQuality, folder, filename, currentPrefs.DownloadDisableConversion);

                            if (video.StartTime.HasValue)
                            {
                                downloadParams.CropStartTime = video.StartTime.Value;
                            }

                            _navigationService.ShowDownload(downloadParams);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _dialogService.ShowAndLogException(ex);
            }
        }
コード例 #4
0
        private TwitchVideoQuality GetSelectedQuality(List <TwitchVideoQuality> qualities, DefaultQuality defaultQuality)
        {
            TwitchVideoQuality sourceQuality = qualities.Find(q => q.IsSource);

            if (defaultQuality.IsSource)
            {
                return(sourceQuality);
            }

            if (defaultQuality.IsAudioOnly)
            {
                TwitchVideoQuality audioOnlyQuality = qualities.FirstOrDefault(q => q.IsAudioOnly);

                if (audioOnlyQuality != null)
                {
                    return(audioOnlyQuality);
                }
                else
                {
                    return(sourceQuality);
                }
            }

            IEnumerable <TwitchVideoQuality> visualQualities = qualities.Where(q => !q.IsAudioOnly);

            int defaultRes = defaultQuality.VerticalResolution;

            TwitchVideoQuality selectedQuality = null;

            foreach (TwitchVideoQuality quality in visualQualities)
            {
                if (quality.VerticalResolution <= defaultRes && (selectedQuality == null || selectedQuality.VerticalResolution < quality.VerticalResolution))
                {
                    selectedQuality = quality;
                }
            }

            if (selectedQuality != null)
            {
                return(selectedQuality);
            }

            foreach (TwitchVideoQuality quality in visualQualities)
            {
                if (quality.VerticalResolution >= defaultRes && (selectedQuality == null || selectedQuality.VerticalResolution > quality.VerticalResolution))
                {
                    selectedQuality = quality;
                }
            }

            if (selectedQuality != null)
            {
                return(selectedQuality);
            }

            return(sourceQuality);
        }
コード例 #5
0
        private void DownloadVideo(string id)
        {
            try
            {
                lock (this.commandLockObject)
                {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideo video = this.Videos.Where(v => v.Id == id).FirstOrDefault();

                        if (video != null)
                        {
                            VodAuthInfo vodAuthInfo = this.twitchService.RetrieveVodAuthInfo(video.IdTrimmed);

                            if (!vodAuthInfo.Privileged && vodAuthInfo.SubOnly)
                            {
                                if (!this.twitchService.IsAuthorized)
                                {
                                    this.dialogService.ShowMessageBox("This video is sub-only! Please authorize your Twitch account by clicking the Twitch button in the menu.", "SUB HYPE!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }
                                else
                                {
                                    this.dialogService.ShowMessageBox("This video is sub-only but you are not subscribed to '" + video.Channel + "'!", "SUB HYPE!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }

                                return;
                            }

                            Preferences currentPrefs = this.preferencesService.CurrentPreferences.Clone();

                            TwitchVideoQuality resolution = video.Resolutions.Where(r => r.QualityFormatted == currentPrefs.DownloadVideoQuality).FirstOrDefault();

                            if (resolution == null)
                            {
                                resolution = video.Resolutions.First();
                            }

                            string filename = this.filenameService.SubstituteWildcards(currentPrefs.DownloadFileName, video);

                            DownloadParameters downloadParams = new DownloadParameters(video, resolution, vodAuthInfo, currentPrefs.DownloadFolder, filename);

                            this.navigationService.ShowDownload(downloadParams);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.dialogService.ShowAndLogException(ex);
            }
        }
コード例 #6
0
        public Dictionary <TwitchVideoQuality, string> GetPlaylistInfo(string vodId, TwitchVideoAuthInfo vodAuthInfo)
        {
            using (WebClient webClient = CreateWebClientWithEncoding())
            {
                webClient.Headers.Add("Accept", "*/*");

                webClient.QueryString.Add("allow_source", "true");
                webClient.QueryString.Add("allow_audio_only", "true");
                webClient.QueryString.Add("token", vodAuthInfo.Token);
                webClient.QueryString.Add("sig", vodAuthInfo.Signature);

                string playlist = webClient.DownloadString(string.Format(PLAYLISTS_URL, vodId));

                List <string> lines = playlist.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();

                Dictionary <TwitchVideoQuality, string> playlistInfo = new Dictionary <TwitchVideoQuality, string>();

                for (int i = 0; i < lines.Count; i++)
                {
                    string line = lines[i];

                    if (!line.StartsWith("#"))
                    {
                        string mediaInfo  = lines[i - 2];
                        string streamInfo = lines[i - 1];

                        Match  groupMatch = _rxGroup.Match(mediaInfo);
                        string id         = groupMatch.Groups["group"].Value;

                        Match  nameMatch = _rxName.Match(mediaInfo);
                        string name      = nameMatch.Groups["name"].Value;

                        string resolution = null;

                        Match resolutionMatch = _rxResolution.Match(streamInfo);

                        if (resolutionMatch.Success)
                        {
                            resolution = resolutionMatch.Groups["resolution"].Value;
                        }

                        TwitchVideoQuality quality = new TwitchVideoQuality(id, name, resolution);

                        playlistInfo.Add(quality, line);
                    }
                }

                return(playlistInfo);
            }
        }
コード例 #7
0
        public string SubstituteWildcards(string filename, string folder, FilenameWildcards.IsFileNameUsedsDelegate IsFileNameUsed, TwitchVideo video, TwitchVideoQuality quality = null, TimeSpan?cropStart = null, TimeSpan?cropEnd = null)
        {
            if (video == null)
            {
                throw new ArgumentNullException(nameof(video));
            }

            if (string.IsNullOrWhiteSpace(filename))
            {
                return(filename);
            }

            string result = filename;

            DateTime recorded = video.RecordedDate;

            TwitchVideoQuality selectedQuality   = quality ?? video.Qualities.First();
            TimeSpan           selectedCropStart = cropStart ?? TimeSpan.Zero;
            TimeSpan           selectedCropEnd   = cropEnd ?? video.Length;

            result = result.Replace(FilenameWildcards.CHANNEL, video.Channel);
            result = result.Replace(FilenameWildcards.GAME, video.Game);
            result = result.Replace(FilenameWildcards.DATE, recorded.ToString("yyyyMMdd"));
            result = result.Replace(FilenameWildcards.TIME, recorded.ToString("hhmmsstt", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.TIME24, recorded.ToString("HHmmss", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.DATE_, recorded.ToString("yyyy-MM-dd"));
            result = result.Replace(FilenameWildcards.TIME_, recorded.ToString("hh-mm-ss_tt", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.TIME24_, recorded.ToString("HH-mm-ss", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.ID, video.Id);
            result = result.Replace(FilenameWildcards.TITLE, video.Title);
            result = result.Replace(FilenameWildcards.RES, !string.IsNullOrWhiteSpace(selectedQuality.Resolution) ? selectedQuality.Resolution : TwitchVideoQuality.UNKNOWN);
            result = result.Replace(FilenameWildcards.FPS, selectedQuality.Fps.HasValue ? selectedQuality.Fps.ToString() : TwitchVideoQuality.UNKNOWN);
            result = result.Replace(FilenameWildcards.START, selectedCropStart.ToShortDaylessString());
            result = result.Replace(FilenameWildcards.END, selectedCropEnd.ToShortDaylessString());

            result = SubstituteInvalidChars(result, "_");

            if (result.Contains(FilenameWildcards.UNIQNUMBER))
            {
                int index = 1;
                while (File.Exists(Path.Combine(folder, result.Replace(FilenameWildcards.UNIQNUMBER, index.ToString()))) || IsFileNameUsed(Path.Combine(folder, result.Replace(FilenameWildcards.UNIQNUMBER, index.ToString()))))
                {
                    index++;
                }
                result = result.Replace(FilenameWildcards.UNIQNUMBER, index.ToString());
            }

            return(result);
        }
コード例 #8
0
        private TwitchVideoQuality TryFindQuality(List <TwitchVideoQuality> qualities, VideoQuality shouldQuality)
        {
            if (shouldQuality == VideoQuality.Source)
            {
                return(qualities.First());
            }
            if (shouldQuality == Core.Enums.VideoQuality.AudioOnly)
            {
                return(qualities.Find(x => x.QualityString == TwitchVideoQuality.GetQualityString(TwitchVideoQuality.QUALITY_AUDIO)));
            }
            int fpsShould         = shouldQuality.GetFps();
            int resolutionYShould = shouldQuality.GetResolutionY();

            //sometimes fps is near value, like 61 or 59 instead 60
            return(qualities.Find(x => x.Fps.HasValue && Math.Abs(x.Fps.Value - fpsShould) < 3 && x.ResolutionY.HasValue && x.ResolutionY.Value == resolutionYShould));
        }
コード例 #9
0
ファイル: FilenameService.cs プロジェクト: p2s/TwitchLeecher
        public string SubstituteWildcards(string filename, TwitchVideo video, TwitchVideoQuality quality = null, TimeSpan?cropStart = null, TimeSpan?cropEnd = null, int?splitPartNumber = null)
        {
            if (video == null)
            {
                throw new ArgumentNullException(nameof(video));
            }

            if (string.IsNullOrWhiteSpace(filename))
            {
                return(filename);
            }

            string result = filename;

            DateTime recorded = video.RecordedDate;

            TwitchVideoQuality selectedQuality   = quality ?? video.Qualities.First();
            TimeSpan           selectedCropStart = cropStart ?? TimeSpan.Zero;
            TimeSpan           selectedCropEnd   = cropEnd ?? video.Length;

            if (splitPartNumber.HasValue && !(result.Contains(FilenameWildcards.START) && result.Contains(FilenameWildcards.END)))
            {
                result = ((int)splitPartNumber).ToString("000") + "_" + result;
            }

            result = result.Replace(FilenameWildcards.CHANNEL, video.Channel);
            result = result.Replace(FilenameWildcards.GAME, video.Game);
            result = result.Replace(FilenameWildcards.DATE, recorded.ToString("yyyyMMdd"));
            result = result.Replace(FilenameWildcards.TIME, recorded.ToString("hhmmsstt", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.TIME24, recorded.ToString("HHmmss", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.ID, video.Id);
            result = result.Replace(FilenameWildcards.TITLE, video.Title);
            result = result.Replace(FilenameWildcards.RES, !string.IsNullOrWhiteSpace(selectedQuality.Resolution) ? selectedQuality.Resolution : TwitchVideoQuality.UNKNOWN);
            result = result.Replace(FilenameWildcards.FPS, selectedQuality.Fps.HasValue ? selectedQuality.Fps.ToString() : TwitchVideoQuality.UNKNOWN);
            result = result.Replace(FilenameWildcards.START, selectedCropStart.ToShortDaylessString());
            result = result.Replace(FilenameWildcards.END, selectedCropEnd.ToShortDaylessString());

            result = SubstituteInvalidChars(result, "_");

            return(result);
        }
コード例 #10
0
        public string SubstituteWildcards(string filename, TwitchVideo video, TwitchVideoQuality quality, TimeSpan?cropStart = null, TimeSpan?cropEnd = null)
        {
            if (video == null)
            {
                throw new ArgumentNullException(nameof(video));
            }

            if (string.IsNullOrWhiteSpace(filename))
            {
                return(filename);
            }

            string result = filename;

            DateTime recorded = video.RecordedDate;

            TimeSpan selectedCropStart = cropStart ?? TimeSpan.Zero;
            TimeSpan selectedCropEnd   = cropEnd ?? video.Length;

            result = result.Replace(FilenameWildcards.ID, video.Id);
            result = result.Replace(FilenameWildcards.CHANNEL, video.Channel);
            result = result.Replace(FilenameWildcards.TITLE, video.Title);
            result = result.Replace(FilenameWildcards.RES, quality.Resolution);
            result = result.Replace(FilenameWildcards.YEAR, recorded.ToString("yyyy", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.MONTH, recorded.ToString("MM", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.DAY, recorded.ToString("dd", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.HOUR24, recorded.ToString("HH", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.HOUR, recorded.ToString("hh", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.MINUTES, recorded.ToString("mm", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.SECONDS, recorded.ToString("ss", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.AMPM, recorded.ToString("tt", CultureInfo.InvariantCulture));
            result = result.Replace(FilenameWildcards.START, selectedCropStart.ToShortDaylessString());
            result = result.Replace(FilenameWildcards.END, selectedCropEnd.ToShortDaylessString());

            result = SubstituteInvalidChars(result, "_");

            return(result);
        }
コード例 #11
0
        private void StartQueuedDownloadIfExists()
        {
            if (_paused)
            {
                return;
            }

            if (Monitor.TryEnter(_changeDownloadLockObject))
            {
                try
                {
                    if (!_downloads.Where(d => d.DownloadState == DownloadState.Downloading).Any())
                    {
                        TwitchVideoDownload download = _downloads.Where(d => d.DownloadState == DownloadState.Queued).FirstOrDefault();

                        if (download == null)
                        {
                            return;
                        }

                        DownloadParameters downloadParams = download.DownloadParams;

                        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                        CancellationToken       cancellationToken       = cancellationTokenSource.Token;

                        string downloadId = download.Id;
                        string vodId      = downloadParams.Video.Id;
                        string tempDir    = Path.Combine(_preferencesService.CurrentPreferences.DownloadTempFolder, downloadId);
                        string ffmpegFile = _processingService.FFMPEGExe;
                        string concatFile = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(downloadParams.FullPath) + ".ts");
                        string outputFile = downloadParams.FullPath;

                        bool disableConversion = downloadParams.DisableConversion;
                        bool cropStart         = downloadParams.CropStart;
                        bool cropEnd           = downloadParams.CropEnd;

                        TimeSpan cropStartTime = downloadParams.CropStartTime;
                        TimeSpan cropEndTime   = downloadParams.CropEndTime;

                        TwitchVideoQuality quality = downloadParams.SelectedQuality;

                        Action <DownloadState> setDownloadState = download.SetDownloadState;
                        Action <string>        log                = download.AppendLog;
                        Action <string>        setStatus          = download.SetStatus;
                        Action <double>        setProgress        = download.SetProgress;
                        Action <bool>          setIsIndeterminate = download.SetIsIndeterminate;

                        Task downloadVideoTask = new Task(() =>
                        {
                            setStatus("Initializing");

                            log("Download task has been started!");

                            WriteDownloadInfo(log, downloadParams, ffmpegFile, tempDir);

                            cancellationToken.ThrowIfCancellationRequested();

                            log(Environment.NewLine + Environment.NewLine + "Retrieving VOD access information...");
                            TwitchVideoAuthInfo vodAuthInfo = _apiService.GetVodAuthInfo(vodId);
                            log(" done!");

                            cancellationToken.ThrowIfCancellationRequested();

                            WriteVodAuthInfo(log, vodAuthInfo);

                            cancellationToken.ThrowIfCancellationRequested();

                            CheckTempDirectory(log, tempDir);

                            cancellationToken.ThrowIfCancellationRequested();

                            log(Environment.NewLine + Environment.NewLine + "Retrieving playlist information for all VOD qualities...");
                            Dictionary <TwitchVideoQuality, string> playlistInfo = _apiService.GetPlaylistInfo(vodId, vodAuthInfo);
                            log(" done!");

                            cancellationToken.ThrowIfCancellationRequested();

                            WritePlaylistInfo(log, playlistInfo);

                            cancellationToken.ThrowIfCancellationRequested();

                            TwitchPlaylist vodPlaylist = GetVodPlaylist(log, tempDir, playlistInfo, quality);

                            cancellationToken.ThrowIfCancellationRequested();

                            CropInfo cropInfo = CropVodPlaylist(vodPlaylist, cropStart, cropEnd, cropStartTime, cropEndTime);

                            cancellationToken.ThrowIfCancellationRequested();

                            DownloadParts(log, setStatus, setProgress, vodPlaylist, cancellationToken);

                            cancellationToken.ThrowIfCancellationRequested();

                            _processingService.ConcatParts(log, setStatus, setProgress, vodPlaylist, disableConversion ? outputFile : concatFile);

                            if (!disableConversion)
                            {
                                cancellationToken.ThrowIfCancellationRequested();
                                _processingService.ConvertVideo(log, setStatus, setProgress, setIsIndeterminate, concatFile, outputFile, cropInfo);
                            }
                        }, cancellationToken);

                        Task continueTask = downloadVideoTask.ContinueWith(task =>
                        {
                            log(Environment.NewLine + Environment.NewLine + "Starting temporary download folder cleanup!");
                            CleanUp(tempDir, log);

                            setProgress(100);
                            setIsIndeterminate(false);

                            bool success = false;

                            if (task.IsFaulted)
                            {
                                setDownloadState(DownloadState.Error);
                                log(Environment.NewLine + Environment.NewLine + "Download task ended with an error!");

                                if (task.Exception != null)
                                {
                                    log(Environment.NewLine + Environment.NewLine + task.Exception.ToString());
                                }
                            }
                            else if (task.IsCanceled)
                            {
                                setDownloadState(DownloadState.Canceled);
                                log(Environment.NewLine + Environment.NewLine + "Download task was canceled!");
                            }
                            else
                            {
                                success = true;
                                setDownloadState(DownloadState.Done);
                                log(Environment.NewLine + Environment.NewLine + "Download task ended successfully!");
                            }

                            if (!_downloadTasks.TryRemove(downloadId, out DownloadTask downloadTask))
                            {
                                throw new ApplicationException("Could not remove download task with ID '" + downloadId + "' from download task collection!");
                            }

                            if (success && _preferencesService.CurrentPreferences.DownloadRemoveCompleted)
                            {
                                _eventAggregator.GetEvent <RemoveDownloadEvent>().Publish(downloadId);
                            }
                        });

                        if (_downloadTasks.TryAdd(downloadId, new DownloadTask(downloadVideoTask, continueTask, cancellationTokenSource)))
                        {
                            downloadVideoTask.Start();
                            setDownloadState(DownloadState.Downloading);
                        }
                    }
                }
                finally
                {
                    Monitor.Exit(_changeDownloadLockObject);
                }
            }
        }
コード例 #12
0
        private void DownloadVideo(string id)
        {
            try
            {
                lock (_commandLockObject)
                {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideo video = Videos.Where(v => v.Id == id).FirstOrDefault();

                        if (video != null)
                        {
                            VodAuthInfo vodAuthInfo = _twitchService.RetrieveVodAuthInfo(video.Id);

                            if (!vodAuthInfo.Privileged && vodAuthInfo.SubOnly)
                            {
                                if (!_twitchService.IsAuthorized)
                                {
                                    _dialogService.ShowMessageBox("This video is sub-only! Please authorize your Twitch account by clicking the Twitch button in the menu.", "SUB HYPE!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }
                                else
                                {
                                    _dialogService.ShowMessageBox("This video is sub-only but you are not subscribed to '" + video.Channel + "'!", "SUB HYPE!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                                }

                                return;
                            }

                            Preferences currentPrefs = _preferencesService.CurrentPreferences.Clone();

                            string folder = currentPrefs.DownloadSubfoldersForFav && _preferencesService.IsChannelInFavourites(video.Channel)
                                ? Path.Combine(currentPrefs.DownloadFolder, video.Channel)
                                : currentPrefs.DownloadFolder;

                            string filename = currentPrefs.DownloadFileName;
                            filename = _filenameService.EnsureExtension(filename, currentPrefs.DownloadDisableConversion);

                            if (currentPrefs.DownloadDisableConversion || video.Length.TotalSeconds < currentPrefs.DownloadSplitTime.TotalSeconds + Preferences.MinSplitLength)
                            {
                                currentPrefs.DownloadSplitUse = false;
                            }

                            if (currentPrefs.DownloadSplitUse)
                            {//Keep UNIQNUMBER wildcard in name to split file (only in conversation mode)
                                string tempUniqWildcard = FilenameWildcards.UNIQNUMBER.Insert(FilenameWildcards.UNIQNUMBER.Length - 1, "_TEMP");
                                filename = filename.Replace(FilenameWildcards.UNIQNUMBER, tempUniqWildcard);
                                filename = _filenameService.SubstituteWildcards(filename, folder, _twitchService.IsFileNameUsed, video);
                                filename = filename.Replace(tempUniqWildcard, FilenameWildcards.UNIQNUMBER);
                            }
                            else
                            {
                                filename = _filenameService.SubstituteWildcards(filename, folder, _twitchService.IsFileNameUsed, video);
                            }

                            TwitchVideoQuality shouldQualityOrNull = TryFindQuality(video.Qualities, currentPrefs.DownloadQuality);

                            DownloadParameters downloadParams = new DownloadParameters(video, vodAuthInfo, shouldQualityOrNull, folder, filename, currentPrefs.DownloadDisableConversion,
                                                                                       currentPrefs.DownloadSplitUse, currentPrefs.DownloadSplitTime, currentPrefs.SplitOverlapSeconds);

                            _navigationService.ShowDownload(downloadParams);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _dialogService.ShowAndLogException(ex);
            }
        }