// Copyright (C) 2024 Intro-Skipper contributors // SPDX-License-Identifier: GPL-3.0-only. using System; using System.Globalization; using System.IO; using System.Net.Mime; using System.Text; using IntroSkipper.Data; using IntroSkipper.Helper; using MediaBrowser.Common; using MediaBrowser.Common.Api; using MediaBrowser.Controller.Library; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace IntroSkipper.Controllers; /// /// Troubleshooting controller. /// [Authorize(Policy = Policies.RequiresElevation)] [ApiController] [Produces(MediaTypeNames.Application.Json)] [Route("IntroSkipper")] public class TroubleshootingController : ControllerBase { private readonly ILibraryManager _libraryManager; private readonly IApplicationHost _applicationHost; private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// Application host. /// Library Manager. /// Logger. public TroubleshootingController( IApplicationHost applicationHost, ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; _applicationHost = applicationHost; _logger = logger; } /// /// Gets a Markdown formatted support bundle. /// /// Support bundle created. /// Support bundle. [HttpGet("SupportBundle")] [Produces(MediaTypeNames.Text.Plain)] public ActionResult GetSupportBundle() { ArgumentNullException.ThrowIfNull(Plugin.Instance); var bundle = new StringBuilder(); bundle.Append("* Jellyfin version: "); bundle.Append(_applicationHost.ApplicationVersionString); bundle.Append('\n'); var version = Plugin.Instance.Version.ToString(3); try { var commit = Commit.CommitHash; if (!string.IsNullOrWhiteSpace(commit)) { version += string.Concat("+", commit.AsSpan(0, 12)); } } catch (Exception ex) { _logger.LogWarning("Unable to append commit to version: {Exception}", ex); } bundle.Append("* Plugin version: "); bundle.Append(version); bundle.Append('\n'); bundle.Append("* Queue contents: "); bundle.Append(Plugin.Instance.TotalQueued); bundle.Append(" episodes, "); bundle.Append(Plugin.Instance.TotalSeasons); bundle.Append(" seasons\n"); bundle.Append("* Warnings: `"); bundle.Append(WarningManager.GetWarnings()); bundle.Append("`\n"); bundle.Append(FFmpegWrapper.GetChromaprintLogs()); return bundle.ToString(); } /// /// Gets a Markdown formatted support bundle. /// /// Support bundle created. /// Support bundle. [HttpGet("Storage")] [Produces(MediaTypeNames.Text.Plain)] public ActionResult GetFreeSpace() { ArgumentNullException.ThrowIfNull(Plugin.Instance); var bundle = new StringBuilder(); var libraries = _libraryManager.GetVirtualFolders(); foreach (var library in libraries) { try { DriveInfo driveInfo = new DriveInfo(library.Locations[0]); // Get available free space in bytes long availableFreeSpace = driveInfo.AvailableFreeSpace; // Get total size of the drive in bytes long totalSize = driveInfo.TotalSize; // Get total used space in Percentage double usedSpacePercentage = totalSize > 0 ? (totalSize - availableFreeSpace) / (double)totalSize * 100 : 0; bundle.Append(CultureInfo.CurrentCulture, $"Library: {library.Name}\n"); bundle.Append(CultureInfo.CurrentCulture, $"Drive: {driveInfo.Name}\n"); bundle.Append(CultureInfo.CurrentCulture, $"Total Size: {GetHumanReadableSize(totalSize)}\n"); bundle.Append(CultureInfo.CurrentCulture, $"Available Free Space: {GetHumanReadableSize(availableFreeSpace)}\n"); bundle.Append(CultureInfo.CurrentCulture, $"Total used in Percentage: {Math.Round(usedSpacePercentage, 2)}%\n\n"); } catch (Exception ex) { _logger.LogWarning("Unable to get DriveInfo: {Exception}", ex); } } return bundle.ToString().TrimEnd('\n'); } private static string GetHumanReadableSize(long bytes) { string[] sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; double len = bytes; int order = 0; while (len >= 1024 && order < sizes.Length - 1) { order++; len /= 1024; } return $"{len:0.##} {sizes[order]}"; } }