don't look at me

This commit is contained in:
Fishandchips321 2025-12-24 18:23:06 +00:00
parent e9f444e5b4
commit cedbad8fba
56 changed files with 1111 additions and 294 deletions

View file

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -1 +0,0 @@
namespace JellyGlass.Application.Services;

View file

@ -0,0 +1,51 @@
using JellyGlass.Models;
using JellyGlass.Services;
using Microsoft.AspNetCore.Mvc;
namespace JellyGlass.Controllers;
[ApiController]
[Route("/api/[controller]")]
public class LibraryController : ControllerBase
{
private ILogger<LibraryController> _logger;
private ILibraryService _service;
public LibraryController(ILogger<LibraryController> logger, ILibraryService service)
{
_logger = logger;
_service = service;
}
[HttpGet()]
public async Task<IActionResult> GetLibrares()
{
var libraries = await _service.GetLibraries();
return Ok(libraries);
}
[HttpGet("{libraryName}")]
public async Task<IActionResult> GetLibraryItems([FromRoute] string libraryName)
{
throw new NotImplementedException();
}
// [HttpGet("{libraryName}/Item/{itemName}")]
// public async Task<IActionResult> GetLibraryItem([FromRoute] string libraryName, string itemName)
// {
// }
// [HttpGet("TvShows/{seriesName}")]
// public async Task<IActionResult> GetSeasonsForTvSeries([FromRoute] string seriesName)
// {
// }
// [HttpGet("TvShows/{seriesName}/Season/{seasonName}")]
// public async Task<IActionResult> GetEpisodesForTvSeriesSeason([FromRoute] string seriesName, string seasonName)
// {
// }
}

View file

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -1,9 +0,0 @@
namespace JellyGlass.Core.Entities;
public class Item
{
public string ID { get; set; }
public string Name { get; set; }
public Uri ThumbnailUrl { get; set; }
public Uri Url { get; set; }
}

View file

@ -1,8 +0,0 @@
namespace JellyGlass.Core.Entities;
public class Library
{
public string ID { get; set; }
public string Name { get; set; }
public Uri ThumbnailUrl { get; set; }
}

View file

@ -1,7 +0,0 @@
namespace JellyGlass.Core.Entities;
public class Server
{
public string Owner { get; set; }
public Uri Url { get; set; }
}

View file

@ -1,8 +0,0 @@
using JellyGlass.Core.Entities;
namespace JellyGlass.Core.Interfaces;
public interface IItemRepository
{
public Task<Item[]> GetItemsFromLibrary(string libraryId);
}

View file

@ -1,8 +0,0 @@
using JellyGlass.Core.Entities;
namespace JellyGlass.Core.Interfaces;
public interface IItemService
{
public Task<Item[]> GetItemsFromLibrary(string libraryId);
}

View file

@ -1,8 +0,0 @@
using JellyGlass.Core.Entities;
namespace JellyGlass.Core.Interfaces;
public interface ILibraryRepository
{
public Task<Library[]> GetLibraries();
}

View file

@ -1,8 +0,0 @@
using JellyGlass.Core.Entities;
namespace JellyGlass.Core.Interfaces;
public interface ILibraryService
{
public Task<Library[]> GetLibraries();
}

View file

@ -1,8 +0,0 @@
using JellyGlass.Core.Entities;
namespace JellyGlass.Core.Interfaces;
public interface IServerService
{
public Task<Server[]> GetServers();
}

View file

@ -0,0 +1,9 @@
namespace JellyGlass.Exceptions;
[Serializable]
public class JellyfinApiClientException : Exception
{
public JellyfinApiClientException() { }
public JellyfinApiClientException(string message) : base(message) { }
public JellyfinApiClientException(string message, Exception inner) : base(message, inner) { }
}

View file

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\Application\Application.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -1,4 +0,0 @@
using JellyGlass.Core.Entities;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.Infrastructure.Repositories;

View file

@ -1,12 +0,0 @@
using JellyGlass.Core.Entities;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.Infrastructure.Repositories;
public class LibraryRepository : ILibraryRepository
{
public Task<Library[]> GetLibraries()
{
throw new NotImplementedException();
}
}

View file

@ -1,4 +0,0 @@
using JellyGlass.Core.Entities;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.Infrastructure.Repositories;

View file

@ -1 +0,0 @@
namespace JellyGlass.Infrastructure.Services;

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.11">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.9" />
</ItemGroup>
</Project>

Binary file not shown.

View file

@ -1,40 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "WebApi\WebApi.csproj", "{870696BA-371D-455E-B39A-7B3B14FDE62D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application", "Application\Application.csproj", "{5C6D5937-49DA-4758-9AE5-C1290975DBB4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{DFE2D8D3-3174-44D9-AC91-C129D208A37B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{7BA1276D-3AF5-4E09-B996-2D91556F8939}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{870696BA-371D-455E-B39A-7B3B14FDE62D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{870696BA-371D-455E-B39A-7B3B14FDE62D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{870696BA-371D-455E-B39A-7B3B14FDE62D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{870696BA-371D-455E-B39A-7B3B14FDE62D}.Release|Any CPU.Build.0 = Release|Any CPU
{5C6D5937-49DA-4758-9AE5-C1290975DBB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C6D5937-49DA-4758-9AE5-C1290975DBB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C6D5937-49DA-4758-9AE5-C1290975DBB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C6D5937-49DA-4758-9AE5-C1290975DBB4}.Release|Any CPU.Build.0 = Release|Any CPU
{DFE2D8D3-3174-44D9-AC91-C129D208A37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFE2D8D3-3174-44D9-AC91-C129D208A37B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFE2D8D3-3174-44D9-AC91-C129D208A37B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFE2D8D3-3174-44D9-AC91-C129D208A37B}.Release|Any CPU.Build.0 = Release|Any CPU
{7BA1276D-3AF5-4E09-B996-2D91556F8939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7BA1276D-3AF5-4E09-B996-2D91556F8939}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7BA1276D-3AF5-4E09-B996-2D91556F8939}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7BA1276D-3AF5-4E09-B996-2D91556F8939}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,50 @@
// <auto-generated />
using JellyGlass.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace JellyGlassBackend.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20251224181902_initial")]
partial class initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.11");
modelBuilder.Entity("JellyGlass.Models.Server", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Servers");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JellyGlassBackend.Migrations
{
/// <inheritdoc />
public partial class initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Servers",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
Owner = table.Column<string>(type: "TEXT", nullable: false),
Url = table.Column<string>(type: "TEXT", nullable: false),
Password = table.Column<string>(type: "TEXT", nullable: false),
Username = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Servers", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Servers");
}
}
}

View file

@ -0,0 +1,47 @@
// <auto-generated />
using JellyGlass.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace JellyGlassBackend.Migrations
{
[DbContext(typeof(DatabaseContext))]
partial class DatabaseContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.11");
modelBuilder.Entity("JellyGlass.Models.Server", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Servers");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,29 @@
using JellyGlass.Models.JellyfinApi;
namespace JellyGlass.Models;
public class ItemDTO
{
public ItemDTO() { }
public ItemDTO(Item item, string ServerUrl)
{
ID = item.Id;
Name = item.Name;
ServerID = item.ServerId;
this.ServerUrl = ServerUrl;
Type = item.Type;
Index = item.IndexNumber;
ParentId = item.ParentId;
ThumbnailUrl = $"{this.ServerUrl}/Items/{ID}/Images/Primary";
}
public string ID { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string ServerID { get; set; } = string.Empty;
public string ServerUrl { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public int? Index { get; set; }
public string? ParentId { get; set; }
public string? ThumbnailUrl { get; set; }
}

View file

@ -0,0 +1,14 @@
namespace JellyGlass.Models.JellyfinApi;
public class AuthResponse
{
public required User User { get; set; }
public required string AccessToken { get; set; }
public required string ServerId { get; set; }
}
public class User
{
public required string Id { get; set; }
}

View file

@ -0,0 +1,24 @@
namespace JellyGlass.Models.JellyfinApi;
public class Item
{
public string Name { get; set; } = string.Empty;
public string ServerId { get; set; } = string.Empty;
public string Id { get; set; } = string.Empty;
public DateTime DateCreated { get; set; }
public bool CanDownload { get; set; }
public string SortName { get; set; } = string.Empty;
public int? IndexNumber { get; set; }
public bool IsFolder { get; set; } //Whether item has children or not
public string? ParentId { get; set; }
public int? ParentIndexNumber { get; set; }
public string? PremiereDate { get; set; }
public int? ProductionYear { get; set; }
public string? SeriesName { get; set; }
public string? SeriesId { get; set; }
public string? SeasonId { get; set; }
public string? SeasonName { get; set; }
public string Type { get; set; } = string.Empty;
public double PrimaryImageAspectRatio { get; set; }
public string? CollectionType { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace JellyGlass.Models.JellyfinApi;
public class ItemResponse
{
public List<Item> Items { get; set; } = [];
public int TotalRecordCount { get; set; }
public int StartIndex { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace JellyGlass.Models;
public class Library
{
public string Name { get; set; } = string.Empty;
public string ThumbnailUrl { get; set; } = string.Empty;
}

View file

@ -0,0 +1,10 @@
namespace JellyGlass.Models;
public class Server
{
public string Owner { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Id { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string Username { get; set; } = string.Empty;
}

41
backend/src/Program.cs Normal file
View file

@ -0,0 +1,41 @@
using JellyGlass.Repositories;
using JellyGlass.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddControllers();
builder.Configuration.GetSection("TestingLogin");
string dbConnectionString;
if (builder.Environment.IsDevelopment())
{
dbConnectionString = "Data Source=JellyGlass-test.db;";
}
else
{
dbConnectionString = "Data Source./JellyGlass.db;";
}
builder.Services.AddSqlite<DatabaseContext>(dbConnectionString);
builder.Services.AddTransient<ILibraryService, LibraryService>();
builder.Services.AddTransient<IServerRepository, ServerRepository>();
builder.Services.AddScoped<IServerService, ServerService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();

View file

@ -5,7 +5,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5152",
"applicationUrl": "http://localhost:5092",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@ -14,7 +14,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7106;http://localhost:5152",
"applicationUrl": "https://localhost:7226;http://localhost:5092",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

View file

@ -0,0 +1,15 @@
using JellyGlass.Models;
using Microsoft.EntityFrameworkCore;
namespace JellyGlass.Repositories;
public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions options)
: base(options)
{
}
public DbSet<Server> Servers { get; set; }
}

View file

@ -1,6 +1,6 @@
using JellyGlass.Core.Entities;
using JellyGlass.Models;
namespace JellyGlass.Core.Interfaces;
namespace JellyGlass.Repositories;
public interface IServerRepository
{

View file

@ -0,0 +1,149 @@
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using JellyGlass.Exceptions;
using JellyGlass.Models;
using JellyGlass.Models.JellyfinApi;
namespace JellyGlass.Repositories;
public class JellyfinApiClient
{
private string _apiKey = string.Empty;
public readonly string InstanceUrl;
private readonly HttpClient _client;
private readonly string _username, _password;
public JellyfinApiClient(string instanceUrl, string username, string password)
{
InstanceUrl = instanceUrl;
_client = new HttpClient();
_client.DefaultRequestHeaders.Clear();
_username = username;
_password = password;
}
public async Task<ItemResponse> GetInstanceLibraries()
{
try
{
var request = new HttpRequestMessage(HttpMethod.Get, $"{InstanceUrl}/Library/MediaFolders");
var response = await MakeRequest(request);
response.EnsureSuccessStatusCode();
var apiResponse = await response.Content.ReadFromJsonAsync<ItemResponse>();
return apiResponse!;
}
catch (HttpRequestException e)
{
throw new JellyfinApiClientException(e.Message);
}
}
public async Task<ItemResponse> GetItemChildren(string itemId)
{
try
{
var request = new HttpRequestMessage(HttpMethod.Get, $"{InstanceUrl}/items?ParentId={itemId}");
var response = await MakeRequest(request);
response.EnsureSuccessStatusCode();
var apiResponse = await response.Content.ReadFromJsonAsync<ItemResponse>();
return apiResponse!;
}
catch (HttpRequestException e)
{
throw new JellyfinApiClientException(e.Message);
}
}
public async Task<ItemResponse> GetItems(string searchTerm = "", string years = "", string itemTypes = "", string limit = "", string parentId = "")
{
var query = new Dictionary<string, string>();
if (searchTerm != String.Empty)
{
query.Add("SearchTerm", searchTerm);
}
throw new NotImplementedException();
}
public async Task Authenticate()
{
var request = new HttpRequestMessage(HttpMethod.Post, $"{InstanceUrl}/Users/AuthenticateByName");
request.Headers.Authorization = new AuthenticationHeaderValue("MediaBrowser", GetAuthHeader());
var body = new
{
Username = _username,
Pw = _password
};
request.Content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
try
{
var response = await _client.SendAsync(request);
response.EnsureSuccessStatusCode();
var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>();
_apiKey = authResponse!.AccessToken;
}
catch (HttpRequestException e)
{
//TODO: What to do on an exception
throw new JellyfinApiClientException(e.Message);
}
}
private async Task<HttpResponseMessage> MakeRequest(HttpRequestMessage request)
{
request.Headers.Authorization = new AuthenticationHeaderValue("MediaBrowser", GetAuthHeader());
HttpResponseMessage response;
try
{
response = await _client.SendAsync(request);
}
catch (HttpRequestException e)
{
if (e.StatusCode == HttpStatusCode.Unauthorized)
{
await Authenticate();
request.Headers.Authorization = new AuthenticationHeaderValue("MediaBrowser", GetAuthHeader());
response = await _client.SendAsync(request);
}
else
{
throw new JellyfinApiClientException(e.Message);
}
}
return response;
}
private string GetAuthHeader()
{
var header = "Client=Test, Device=Test, DeviceId=Test, Version=1";
if (_apiKey != String.Empty)
{
header += ", Token=" + _apiKey;
}
return header;
}
}

View file

@ -0,0 +1,21 @@
using JellyGlass.Models;
using Microsoft.EntityFrameworkCore;
namespace JellyGlass.Repositories;
public class ServerRepository : IServerRepository
{
private DatabaseContext _context;
public ServerRepository(DatabaseContext context)
{
_context = context;
}
public async Task<Server[]> GetServers()
{
var servers = await _context.Servers.ToArrayAsync();
return servers;
}
}

View file

@ -0,0 +1,14 @@
using JellyGlass.Models;
namespace JellyGlass.Services;
public interface ILibraryService
{
public Task<Library[]> GetLibraries();
public Task<ItemDTO[]> GetItemsFromLibrary(string libraryName);
// public Task<ItemDTO[]> GetChildrenFromItems(ItemDTO[] items);
// public Task<ItemDTO[]> GetItemsByName(string name, string itemType);
// public Task<ItemDTO[]> GetItemsByType(string itemType);
}

View file

@ -0,0 +1,10 @@
using JellyGlass.Repositories;
namespace JellyGlass.Services;
public interface IServerService
{
public Task<JellyfinApiClient[]> GetJellyfinClients();
// public JellyfinApiClient GetClientForServer(string url);
// public JellyfinApiClient GetClientForServerId(string serverId);
}

View file

@ -0,0 +1,74 @@
using JellyGlass.Models;
namespace JellyGlass.Services;
public class LibraryService : ILibraryService
{
private IServerService _serverService;
public LibraryService(IServerService serverService)
{
_serverService = serverService;
}
public async Task<Library[]> GetLibraries()
{
var clients = await _serverService.GetJellyfinClients();
var libraries = new Dictionary<string, Library>();
foreach (var client in clients)
{
var clientLibraries = await client.GetInstanceLibraries();
foreach (var library in clientLibraries.Items)
{
if (!libraries.ContainsKey(library.Name))
{
libraries.Add(library.Name, new Library()
{
Name = library.Name,
ThumbnailUrl = $"{client.InstanceUrl}/Items/{library.Id}/Primary"
});
}
}
}
return libraries.Values.ToArray();
}
public async Task<ItemDTO[]> GetItemsFromLibrary(string libraryName)
{
throw new NotImplementedException();
}
// public async Task<ItemDTO[]> GetChildrenFromItems(ItemDTO[] items)
// {
// var children = new List<ItemDTO>();
// foreach (var item in items)
// {
// var client = _serverService.GetClientForServerId(item.ServerID);
// var itemChildren = await client.GetItemChildren(item.ID);
// foreach (var child in itemChildren.Items)
// {
// children.Add(new ItemDTO(child, client.InstanceUrl));
// }
// }
// return children.ToArray();
// }
// public async Task<ItemDTO> GetItemsByName(string name, string itemType)
// {
// }
// public async Task<ItemDTO> GetItemsByType(string itemType)
// {
// }
}

View file

@ -0,0 +1,52 @@
using JellyGlass.Exceptions;
using JellyGlass.Models;
using JellyGlass.Repositories;
namespace JellyGlass.Services;
public class ServerService : IServerService
{
private IServerRepository _repository;
private static JellyfinApiClient[] _clients = [];
private ILogger<ServerService> _logger;
public ServerService(IServerRepository repository, ILogger<ServerService> logger)
{
_repository = repository;
_logger = logger;
}
public async Task<JellyfinApiClient[]> GetJellyfinClients()
{
if (!_clients.Any())
{
await LoadClients();
}
return _clients;
}
private async Task LoadClients()
{
var servers = await _repository.GetServers();
var clients = new List<JellyfinApiClient>();
foreach (var server in servers)
{
var client = new JellyfinApiClient(server.Url, server.Username, server.Password);
try
{
await client.Authenticate();
}
catch (JellyfinApiClientException e)
{
}
clients.Add(client);
}
_clients = clients.ToArray();
}
}

View file

@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.WebApi.Controllers;
[ApiController]
[Route("[controller]")]
public class ItemController : ControllerBase
{
private ILogger<ItemController> _logger;
private IItemService _service;
public ItemController(ILogger<ItemController> logger, IItemService service)
{
_service = service;
_logger = logger;
}
public async Task<IActionResult> GetItemsForLibrary(string libraryId)
{
var items = await _service.GetItemsFromLibrary(libraryId);
return Ok(items);
}
}

View file

@ -1,26 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.WebApi.Controllers;
[ApiController]
[Route("[controller]")]
public class LibraryController : ControllerBase
{
private ILogger<LibraryController> _logger;
private ILibraryService _service;
public LibraryController(ILogger<LibraryController> logger, ILibraryService service)
{
_logger = logger;
_service = service;
}
[HttpGet]
public async Task<IActionResult> GetLibraries()
{
var libraries = await _service.GetLibraries();
return Ok(libraries);
}
}

View file

@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using JellyGlass.Core.Interfaces;
namespace JellyGlass.WebApi.Controllers;
[ApiController]
[Route("[controller]")]
public class ServerController : ControllerBase
{
private ILogger<ServerController> _logger;
private IServerService _service;
public ServerController(ILogger<ServerController> logger, IServerService service)
{
_logger = logger;
_service = service;
}
public async Task<IActionResult> GetServers()
{
var servers = await _service.GetServers();
return Ok(servers);
}
}

View file

@ -1,19 +0,0 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();

View file

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Application\Application.csproj" />
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
</ItemGroup>
</Project>

View file

@ -1,6 +0,0 @@
@WebApi_HostAddress = http://localhost:5152
GET {{WebApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View file

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

6
backend/src/src.http Normal file
View file

@ -0,0 +1,6 @@
@src_HostAddress = http://localhost:5092
GET {{src_HostAddress}}/weatherforecast/
Accept: application/json
###