Skip to content

Commit

Permalink
Add library paths, free format and video resolution options
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentroyc authored and AECX committed May 12, 2024
1 parent ce404f5 commit 2685520
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 19 deletions.
64 changes: 54 additions & 10 deletions Jellyfin.Plugin.FinTube/Api/FinTubeActivityController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,33 @@ public class FinTubeActivityController : ControllerBase
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _config;
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;

public FinTubeActivityController(
ILoggerFactory loggerFactory,
IFileSystem fileSystem,
IServerConfigurationManager config,
IUserManager userManager)
IUserManager userManager,
ILibraryManager libraryManager)
{
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<FinTubeActivityController>();
_fileSystem = fileSystem;
_config = config;
_userManager = userManager;
_libraryManager = libraryManager;

_logger.LogInformation("FinTubeActivityController Loaded");
}

public class FinTubeData
{
public string ytid {get; set;} = "";
public string targetfolder{get; set;} = "/tmp";
public string targetlibrary{get; set;} = "";
public string targetfolder{get; set;} = "";
public bool audioonly{get; set;} = false;
public bool preferfreeformat{get; set;} = false;
public string videoresolution{get; set;} = "";
public string artist{get; set;} = "";
public string album{get; set;} = "";
public string title{get; set;} = "";
Expand All @@ -61,7 +67,7 @@ public ActionResult<Dictionary<string, object>> FinTubeDownload([FromBody] FinTu
{
try
{
_logger.LogInformation("FinTubeDownload : {ytid} to {targetfoldeer} audio only: {audioonly}", data.ytid, data.targetfolder, data.audioonly);
_logger.LogInformation("FinTubeDownload : {ytid} to {targetfoldeer}, prefer free format: {preferfreeformat} audio only: {audioonly}", data.ytid, data.targetfolder, data.preferfreeformat, data.audioonly);

Dictionary<string, object> response = new Dictionary<string, object>();
PluginConfiguration? config = Plugin.Instance.Configuration;
Expand All @@ -72,24 +78,28 @@ public ActionResult<Dictionary<string, object>> FinTubeDownload([FromBody] FinTu
if(!System.IO.File.Exists(config.exec_YTDL))
throw new Exception("YT-DL Executable configured incorrectly");


bool hasid3v2 = System.IO.File.Exists(config.exec_ID3);


// Ensure proper / separator
data.targetfolder = String.Join("/", data.targetfolder.Split("/", StringSplitOptions.RemoveEmptyEntries));
String targetPath = data.targetlibrary.EndsWith("/") ? data.targetlibrary + data.targetfolder : data.targetlibrary + "/" + data.targetfolder;
// Create Folder if it doesn't exist
if(!System.IO.Directory.CreateDirectory(data.targetfolder).Exists)
if(!System.IO.Directory.CreateDirectory(targetPath).Exists)
throw new Exception("Directory could not be created");


// Check for tags
bool hasTags = 1 < (data.title.Length + data.album.Length + data.artist.Length + data.track.ToString().Length);

// Save file with ytdlp as mp4 or mp3 depending on audioonly
String targetFilename;
String targetExtension = (data.audioonly ? @".mp3" : @".mp4");
String targetExtension = (data.preferfreeformat ? (data.audioonly ? @".opus" : @".webm") : (data.audioonly ? @".mp3" : @".mp4"));

if(data.audioonly && hasTags && data.title.Length > 1) // Use title Tag for filename
targetFilename = System.IO.Path.Combine(data.targetfolder, $"{data.title}");
targetFilename = System.IO.Path.Combine(targetPath, $"{data.title}");
else // Use YTID as filename
targetFilename = System.IO.Path.Combine(data.targetfolder, $"{data.ytid}");
targetFilename = System.IO.Path.Combine(targetPath, $"{data.ytid}");

// Check if filename exists
if(System.IO.File.Exists(targetFilename))
Expand All @@ -99,9 +109,24 @@ public ActionResult<Dictionary<string, object>> FinTubeDownload([FromBody] FinTu

String args;
if(data.audioonly)
args = $"-x --audio-format mp3 -o \"{targetFilename}.%(ext)s\" {data.ytid}";
{
args = "-x";
if(data.preferfreeformat)
args += " --prefer-free-format";
else
args += " --audio-format mp3";
args += $" -o \"{targetFilename}.%(ext)s\" {data.ytid}";
}
else
args = $"-f mp4 -o \"{targetFilename}-%(title)s.%(ext)s\" {data.ytid}";
{
if(data.preferfreeformat)
args = "--prefer-free-format";
else
args = "-f mp4";
if(!string.IsNullOrEmpty(data.videoresolution))
args += $" -S res:{data.videoresolution}";
args += $" -o \"{targetFilename}-%(title)s.%(ext)s\" {data.ytid}";
}

status += $"Exec: {config.exec_YTDL} {args}<br>";

Expand Down Expand Up @@ -133,6 +158,25 @@ public ActionResult<Dictionary<string, object>> FinTubeDownload([FromBody] FinTu
}
}

[HttpGet("libraries")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<Dictionary<string, object>> FinTubeLibraries()
{
try
{
_logger.LogInformation("FinTubeDLibraries count: {count}", _libraryManager.GetVirtualFolders().Count);

Dictionary<string, object> response = new Dictionary<string, object>();
response.Add("data", _libraryManager.GetVirtualFolders().Select(i => i.Locations).ToArray());
return Ok(response);
}
catch(Exception e)
{
_logger.LogError(e, e.Message);
return StatusCode(500, new Dictionary<string, object>() {{"message", e.Message}});
}
}

private static Process createProcess(String exe, String args)
{
ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = exe, Arguments = args };
Expand Down
75 changes: 66 additions & 9 deletions Jellyfin.Plugin.FinTube/Pages/downloadPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,26 @@ <h2>FinTube Download</h2>
<input id="fintube-ytid" class="emby-input" name="fintube-ytid" value="dQw4w9WgXcQ" />
</div>

<div class="selectContainer">
<label class="inputLabel" for="fintube-targetlibrary">Target library</label>
<select id="fintube-targetlibrary" class="emby-input" name="fintube-targetlibrary">
</select>
<div class="fieldDescription">Base library destination path to download file</div>
</div>

<div class="selectContainer">
<label class="inputLabel" for="fintube-targetfolder">Target Folder</label>
<input id="fintube-targetfolder" class="emby-input" name="fintube-targetfolder" value="/opt/media/" />
<div class="fieldDescription">Your Media file will be stored here assuming JellyFin has Write Permissions, this will also recursively create the folder(s) required</div>
<input id="fintube-targetfolder" class="emby-input" name="fintube-targetfolder" />
<div class="fieldDescription">Your Media file will be stored here assuming JellyFin has Write Permissions, this will also recursively create the folder(s) required<br />Relative path from target library (optional)</div>
</div>

<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="fintube-preferfreeformat" name="preferfreeformat" type="checkbox" is="emby-checkbox" data-embycheckbox="true" class="emby-checkbox">
<span class="checkboxLabel">Prefer free format</span>
<span class="checkboxOutline"><span class="material-icons checkboxIcon checkboxIcon-checked check" aria-hidden="true"></span><span class="material-icons checkboxIcon checkboxIcon-unchecked " aria-hidden="true"></span></span></label>
<div class="fieldDescription">Will usually download audio as .opus and videos as .webm</div>
</div>

<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
Expand All @@ -30,6 +44,23 @@ <h2>FinTube Download</h2>
<div class="fieldDescription">Check this if you want to store as mp3, otherwise the file is saved in mp4</div>
</div>

<div id="fintube-videosettings">
<div class="selectContainer">
<label class="inputLabel" for="fintube-videoresolution">Video resolution</label>
<select id="fintube-videoresolution" class="emby-input" name="fintube-videoresolution">
<option value="">default</option>
<option value="240">240p</option>
<option value="360">360p</option>
<option value="480">480p</option>
<option value="720">720p</option>
<option value="1080" selected>1080p</option>
<option value="1440">2k</option>
<option value="2160">4k</option>
</select>
<div class="fieldDescription">Maximum desired resolution if available. Set to default if you want to download the best available.</div>
</div>
</div>

<div id="fintube-audiosettings" hidden>
<h3>Audio Settings (Require id3v2 to be configured properly)</h3>

Expand Down Expand Up @@ -119,6 +150,7 @@ <h3>Audio Settings (Require id3v2 to be configured properly)</h3>
document.getElementById('fintube-audioonly')
.addEventListener("change", function() {
document.getElementById('fintube-audiosettings').hidden = !this.checked;
document.getElementById('fintube-videosettings').hidden = this.checked;
});

document.querySelector('#FinTubeDLForm')
Expand All @@ -128,13 +160,16 @@ <h3>Audio Settings (Require id3v2 to be configured properly)</h3>
document.getElementById('fintube-result').innerHTML = "";

let payload = {
"ytid": parseYT(getfintubeValue("ytid")),
"targetfolder": getfintubeValue("targetfolder"),
"audioonly": document.getElementById("fintube-audioonly").checked,
"artist": getfintubeValue("artist"),
"album": getfintubeValue("album"),
"title": getfintubeValue("title"),
"track": Number(getfintubeValue("track"))
"ytid": parseYT(getfintubeValue("ytid")),
"targetlibrary": getfintubeValue("targetlibrary"),
"targetfolder": getfintubeValue("targetfolder"),
"videoresolution": getfintubeValue("videoresolution"),
"audioonly": document.getElementById("fintube-audioonly").checked,
"preferfreeformat": document.getElementById("fintube-preferfreeformat").checked,
"artist": getfintubeValue("artist"),
"album": getfintubeValue("album"),
"title": getfintubeValue("title"),
"track": Number(getfintubeValue("track"))
}


Expand All @@ -146,6 +181,28 @@ <h3>Audio Settings (Require id3v2 to be configured properly)</h3>
document.getElementById('fintube-result').innerHTML = message;
});
});

window.ApiClient.getLibraries = function() {
const url = window.ApiClient.getUrl("fintube/libraries");
return this.ajax({
type: "GET",
url: url,
dataType: "json",
contentType: 'application/json'
});
};

(function() {
window.ApiClient.getLibraries().then(function(result) {
let librariesHtml = ""
for (let library of result.data) {
for (let location of library) {
librariesHtml += '<option value="' + location + '">' + location + '</option>'
}
}
document.getElementById('fintube-targetlibrary').innerHTML = librariesHtml;
});
})();
</script>
</div>
</div>
Expand Down

0 comments on commit 2685520

Please sign in to comment.