Skip to content

Commit

Permalink
v2.38
Browse files Browse the repository at this point in the history
  • Loading branch information
reawoken committed Jan 13, 2024
0 parents commit 0bfbd57
Show file tree
Hide file tree
Showing 198 changed files with 12,486 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User-specific files
.vs/
.idea/
*.suo
*.user

# Build results
bin/
obj/

# Test results
TestResults/
13 changes: 13 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project>

<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>2.38</Version>
<Company>Reawoken</Company>
<Copyright>Copyright (C) Reawoken</Copyright>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

</Project>
10 changes: 10 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
<config>
<add key="defaultPushSource" value="https://api.nuget.org/v3/index.json" />
</config>
</configuration>
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Денацифицированный YoutubeDownloader (RU)
**YoutubeDownloaderRU** основан на данном репозитории: https://github.com/Tyrrrz/YoutubeDownloader

# Как скачать
Последняя версия: v2.38
<br />Дата: 13.01.2024
<br />Ссылка в **Releases** : [Нажмите, чтобы скачать](https://github.com/reawoken/YoutubeDownloaderRU/releases/download/v2.38/YoutubeDownloaderRU.v2.38.zip)

# Почему я сделал YoutubeDownloaderRU
Чтобы каждый мог им пользоваться, независимо от идеологии и местопложения. Автор данного приложения закоренелый нацист и русособ, который распространяет недопустимую пропаганду в приложении, вообще не имеющем отношения к политике, войнам и прочему.

# Что было изменено
Основано на версии оригинального репозитория 12.01.2024
- Полностью удалена проверка национальной принадлежности по локали системы, которая запрещала запуск приложения в России и Белоруссии. Приложение может запустить **кто угодно и где угодно**, будь то житель России, Украины, Белоруссии и любой другой страны.
- Больше не опирается на внешние библиотеки автора через NuGet, теперь они часть проекта в репозитории. Также удалёна зависимость от омерзительной библиотеки автора с омерзительным названием **deorcify**, которая не делает ничего, кроме дискриминации по национальному признаку.
- Вычищена подчистую вся политическая повестка (кроме скромной сноски в настройках), удалена вся агрессивная пропаганда и русофобия.
- Интерфейс полностью переведён на русский
- Убраны все упоминания авторства безумного пропагандиста, который изначально делал это приложение.
- Отключены обновления (возможно временно, в будущем смогу добавить свою систему обновлений, не опираясь на изначальный модуль если буду вообще обновлять этот репозиторий)

# Как собрать
Просто скачать и открыть **YoutubeDownloader.sln** в Visual Studio 2022 последней версии с установленным .NET 8.0 и собрать.
<br />Собранный проект появится в директории **YoutubeDownloaderRU\bin**.
50 changes: 50 additions & 0 deletions YoutubeDownloader.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeDownloaderRU", "YoutubeDownloaderRU\YoutubeDownloaderRU.csproj", "{AF6D645E-DDDD-4034-B644-D5328CC893C1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{131C2561-E5A1-43E8-BF38-40E2E23DB0A4}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
License.txt = License.txt
Readme.md = Readme.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeDownloaderRU.Core", "YoutubeDownloaderRU.Core\YoutubeDownloaderRU.Core.csproj", "{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeExplode", "YoutubeExplode\YoutubeExplode\YoutubeExplode.csproj", "{B4A40CD2-DB77-4074-9F3D-F60F86B57891}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeExplode.Converter", "YoutubeExplode\YoutubeExplode.Converter\YoutubeExplode.Converter.csproj", "{77476989-6DD0-49E4-BAB6-8468F8C82734}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Release|Any CPU.Build.0 = Release|Any CPU
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Release|Any CPU.Build.0 = Release|Any CPU
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Release|Any CPU.Build.0 = Release|Any CPU
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1455235F-4357-4DB9-BCC1-41A5A8B10AC5}
EndGlobalSection
EndGlobal
32 changes: 32 additions & 0 deletions YoutubeDownloaderRU.Core/Downloading/FileNameTemplate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using YoutubeDownloaderRU.Core.Utils;
using YoutubeExplode.Videos;
using YoutubeExplode.Videos.Streams;

namespace YoutubeDownloaderRU.Core.Downloading;

public static class FileNameTemplate
{
public static string Apply(
string template,
IVideo video,
Container container,
string? number = null
) =>
PathEx.EscapeFileName(
template
.Replace("$numc", number ?? "", StringComparison.Ordinal)
.Replace("$num", number is not null ? $"[{number}]" : "", StringComparison.Ordinal)
.Replace("$id", video.Id, StringComparison.Ordinal)
.Replace("$title", video.Title, StringComparison.Ordinal)
.Replace("$author", video.Author.ChannelTitle, StringComparison.Ordinal)
.Replace(
"$uploadDate",
(video as Video)?.UploadDate.ToString("yyyy-MM-dd") ?? "",
StringComparison.Ordinal
)
.Trim()
+ '.'
+ container.Name
);
}
119 changes: 119 additions & 0 deletions YoutubeDownloaderRU.Core/Downloading/VideoDownloadOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Lazy;
using YoutubeDownloaderRU.Core.Utils.Extensions;
using YoutubeExplode.Videos.Streams;

namespace YoutubeDownloaderRU.Core.Downloading;

public partial record VideoDownloadOption(
Container Container,
bool IsAudioOnly,
IReadOnlyList<IStreamInfo> StreamInfos
)
{
[Lazy]
public VideoQuality? VideoQuality =>
StreamInfos.OfType<IVideoStreamInfo>().MaxBy(s => s.VideoQuality)?.VideoQuality;
}

public partial record VideoDownloadOption
{
internal static IReadOnlyList<VideoDownloadOption> ResolveAll(StreamManifest manifest)
{
IEnumerable<VideoDownloadOption> GetVideoAndAudioOptions()
{
var videoStreamInfos = manifest
.GetVideoStreams()
.OrderByDescending(v => v.VideoQuality);

foreach (var videoStreamInfo in videoStreamInfos)
{
// Muxed stream
if (videoStreamInfo is MuxedStreamInfo)
{
yield return new VideoDownloadOption(
videoStreamInfo.Container,
false,
[videoStreamInfo]
);
}
// Separate audio + video stream
else
{
// Prefer audio stream with the same container
var audioStreamInfo = manifest
.GetAudioStreams()
.OrderByDescending(s => s.Container == videoStreamInfo.Container)
.ThenByDescending(s => s is AudioOnlyStreamInfo)
.ThenByDescending(s => s.Bitrate)
.FirstOrDefault();

if (audioStreamInfo is not null)
{
yield return new VideoDownloadOption(
videoStreamInfo.Container,
false,
new IStreamInfo[] { videoStreamInfo, audioStreamInfo }
);
}
}
}
}

IEnumerable<VideoDownloadOption> GetAudioOnlyOptions()
{
// WebM-based audio-only containers
{
var audioStreamInfo = manifest
.GetAudioStreams()
.OrderByDescending(s => s.Container == Container.WebM)
.ThenByDescending(s => s is AudioOnlyStreamInfo)
.ThenByDescending(s => s.Bitrate)
.FirstOrDefault();

if (audioStreamInfo is not null)
{
yield return new VideoDownloadOption(Container.WebM, true, [audioStreamInfo]);

yield return new VideoDownloadOption(Container.Mp3, true, [audioStreamInfo]);

yield return new VideoDownloadOption(
new Container("ogg"),
true,
[audioStreamInfo]
);
}
}

// Mp4-based audio-only containers
{
var audioStreamInfo = manifest
.GetAudioStreams()
.OrderByDescending(s => s.Container == Container.Mp4)
.ThenByDescending(s => s is AudioOnlyStreamInfo)
.ThenByDescending(s => s.Bitrate)
.FirstOrDefault();

if (audioStreamInfo is not null)
{
yield return new VideoDownloadOption(Container.Mp4, true, [audioStreamInfo]);
}
}
}

// Deduplicate download options by video quality and container
var comparer = EqualityComparer<VideoDownloadOption>.Create(
(x, y) => x?.VideoQuality == y?.VideoQuality && x?.Container == y?.Container,
x => HashCode.Combine(x.VideoQuality, x.Container)
);

var options = new HashSet<VideoDownloadOption>(comparer);

options.AddRange(GetVideoAndAudioOptions());
options.AddRange(GetAudioOnlyOptions());

return options.ToArray();
}
}
53 changes: 53 additions & 0 deletions YoutubeDownloaderRU.Core/Downloading/VideoDownloadPreference.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using YoutubeExplode.Videos.Streams;

namespace YoutubeDownloaderRU.Core.Downloading;

public record VideoDownloadPreference(
Container PreferredContainer,
VideoQualityPreference PreferredVideoQuality
)
{
public VideoDownloadOption? TryGetBestOption(IReadOnlyList<VideoDownloadOption> options)
{
// Short-circuit for audio-only formats
if (PreferredContainer.IsAudioOnly)
return options.FirstOrDefault(o => o.Container == PreferredContainer);

var orderedOptions = options.OrderBy(o => o.VideoQuality).ToArray();

var preferredOption = PreferredVideoQuality switch
{
VideoQualityPreference.Highest
=> orderedOptions.LastOrDefault(o => o.Container == PreferredContainer),

VideoQualityPreference.UpTo1080p
=> orderedOptions
.Where(o => o.VideoQuality?.MaxHeight <= 1080)
.LastOrDefault(o => o.Container == PreferredContainer),

VideoQualityPreference.UpTo720p
=> orderedOptions
.Where(o => o.VideoQuality?.MaxHeight <= 720)
.LastOrDefault(o => o.Container == PreferredContainer),

VideoQualityPreference.UpTo480p
=> orderedOptions
.Where(o => o.VideoQuality?.MaxHeight <= 480)
.LastOrDefault(o => o.Container == PreferredContainer),

VideoQualityPreference.Lowest
=> orderedOptions.LastOrDefault(o => o.Container == PreferredContainer),

_
=> throw new InvalidOperationException(
$"Unknown video quality preference '{PreferredVideoQuality}'."
)
};

return preferredOption
?? orderedOptions.FirstOrDefault(o => o.Container == PreferredContainer);
}
}
Loading

0 comments on commit 0bfbd57

Please sign in to comment.