don't look at me
This commit is contained in:
parent
e9f444e5b4
commit
cedbad8fba
56 changed files with 1111 additions and 294 deletions
|
|
@ -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>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
namespace JellyGlass.Application.Services;
|
|
||||||
51
backend/src/Controllers/LibraryController.cs
Normal file
51
backend/src/Controllers/LibraryController.cs
Normal 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)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
namespace JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
public class Server
|
|
||||||
{
|
|
||||||
public string Owner { get; set; }
|
|
||||||
public Uri Url { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
public interface IItemRepository
|
|
||||||
{
|
|
||||||
public Task<Item[]> GetItemsFromLibrary(string libraryId);
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
public interface IItemService
|
|
||||||
{
|
|
||||||
public Task<Item[]> GetItemsFromLibrary(string libraryId);
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
public interface ILibraryRepository
|
|
||||||
{
|
|
||||||
public Task<Library[]> GetLibraries();
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
public interface ILibraryService
|
|
||||||
{
|
|
||||||
public Task<Library[]> GetLibraries();
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
public interface IServerService
|
|
||||||
{
|
|
||||||
public Task<Server[]> GetServers();
|
|
||||||
}
|
|
||||||
9
backend/src/Exceptions/JellyfinApiClientExceptions.cs
Normal file
9
backend/src/Exceptions/JellyfinApiClientExceptions.cs
Normal 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) { }
|
||||||
|
}
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
using JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
namespace JellyGlass.Infrastructure.Repositories;
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
using JellyGlass.Core.Entities;
|
|
||||||
using JellyGlass.Core.Interfaces;
|
|
||||||
|
|
||||||
namespace JellyGlass.Infrastructure.Repositories;
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
namespace JellyGlass.Infrastructure.Services;
|
|
||||||
18
backend/src/JellyGlass-Backend.csproj
Normal file
18
backend/src/JellyGlass-Backend.csproj
Normal 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>
|
||||||
BIN
backend/src/JellyGlass-test.db
Normal file
BIN
backend/src/JellyGlass-test.db
Normal file
Binary file not shown.
|
|
@ -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
|
|
||||||
50
backend/src/Migrations/20251224181902_initial.Designer.cs
generated
Normal file
50
backend/src/Migrations/20251224181902_initial.Designer.cs
generated
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
backend/src/Migrations/20251224181902_initial.cs
Normal file
36
backend/src/Migrations/20251224181902_initial.cs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
backend/src/Migrations/DatabaseContextModelSnapshot.cs
Normal file
47
backend/src/Migrations/DatabaseContextModelSnapshot.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
backend/src/Models/ItemDTO.cs
Normal file
29
backend/src/Models/ItemDTO.cs
Normal 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; }
|
||||||
|
}
|
||||||
14
backend/src/Models/JellyfinApi/AuthResponseModels.cs
Normal file
14
backend/src/Models/JellyfinApi/AuthResponseModels.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
|
||||||
24
backend/src/Models/JellyfinApi/Item.cs
Normal file
24
backend/src/Models/JellyfinApi/Item.cs
Normal 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; }
|
||||||
|
}
|
||||||
8
backend/src/Models/JellyfinApi/ItemsResponse.cs
Normal file
8
backend/src/Models/JellyfinApi/ItemsResponse.cs
Normal 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; }
|
||||||
|
}
|
||||||
8
backend/src/Models/Library.cs
Normal file
8
backend/src/Models/Library.cs
Normal 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;
|
||||||
|
}
|
||||||
10
backend/src/Models/Server.cs
Normal file
10
backend/src/Models/Server.cs
Normal 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
41
backend/src/Program.cs
Normal 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();
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": false,
|
"launchBrowser": false,
|
||||||
"applicationUrl": "http://localhost:5152",
|
"applicationUrl": "http://localhost:5092",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": false,
|
"launchBrowser": false,
|
||||||
"applicationUrl": "https://localhost:7106;http://localhost:5152",
|
"applicationUrl": "https://localhost:7226;http://localhost:5092",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
15
backend/src/Repositories/DatabaseContext.cs
Normal file
15
backend/src/Repositories/DatabaseContext.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using JellyGlass.Core.Entities;
|
using JellyGlass.Models;
|
||||||
|
|
||||||
namespace JellyGlass.Core.Interfaces;
|
namespace JellyGlass.Repositories;
|
||||||
|
|
||||||
public interface IServerRepository
|
public interface IServerRepository
|
||||||
{
|
{
|
||||||
149
backend/src/Repositories/JellyfinApiClient.cs
Normal file
149
backend/src/Repositories/JellyfinApiClient.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
backend/src/Repositories/ServerRepository.cs
Normal file
21
backend/src/Repositories/ServerRepository.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
backend/src/Services/ILibraryService.cs
Normal file
14
backend/src/Services/ILibraryService.cs
Normal 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);
|
||||||
|
}
|
||||||
10
backend/src/Services/IServerService.cs
Normal file
10
backend/src/Services/IServerService.cs
Normal 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);
|
||||||
|
}
|
||||||
74
backend/src/Services/LibraryService.cs
Normal file
74
backend/src/Services/LibraryService.cs
Normal 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)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
52
backend/src/Services/ServerService.cs
Normal file
52
backend/src/Services/ServerService.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
@WebApi_HostAddress = http://localhost:5152
|
|
||||||
|
|
||||||
GET {{WebApi_HostAddress}}/weatherforecast/
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
backend/src/appsettings.Development.json
Normal file
8
backend/src/appsettings.Development.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
backend/src/src.http
Normal file
6
backend/src/src.http
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
@src_HostAddress = http://localhost:5092
|
||||||
|
|
||||||
|
GET {{src_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
247
pythonBackend/venv/bin/Activate.ps1
Normal file
247
pythonBackend/venv/bin/Activate.ps1
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Activate a Python virtual environment for the current PowerShell session.
|
||||||
|
|
||||||
|
.Description
|
||||||
|
Pushes the python executable for a virtual environment to the front of the
|
||||||
|
$Env:PATH environment variable and sets the prompt to signify that you are
|
||||||
|
in a Python virtual environment. Makes use of the command line switches as
|
||||||
|
well as the `pyvenv.cfg` file values present in the virtual environment.
|
||||||
|
|
||||||
|
.Parameter VenvDir
|
||||||
|
Path to the directory that contains the virtual environment to activate. The
|
||||||
|
default value for this is the parent of the directory that the Activate.ps1
|
||||||
|
script is located within.
|
||||||
|
|
||||||
|
.Parameter Prompt
|
||||||
|
The prompt prefix to display when this virtual environment is activated. By
|
||||||
|
default, this prompt is the name of the virtual environment folder (VenvDir)
|
||||||
|
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Verbose
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and shows extra information about the activation as it executes.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
||||||
|
Activates the Python virtual environment located in the specified location.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Prompt "MyPython"
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and prefixes the current prompt with the specified string (surrounded in
|
||||||
|
parentheses) while the virtual environment is active.
|
||||||
|
|
||||||
|
.Notes
|
||||||
|
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
||||||
|
execution policy for the user. You can do this by issuing the following PowerShell
|
||||||
|
command:
|
||||||
|
|
||||||
|
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
|
||||||
|
For more information on Execution Policies:
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=135170
|
||||||
|
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$VenvDir,
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$Prompt
|
||||||
|
)
|
||||||
|
|
||||||
|
<# Function declarations --------------------------------------------------- #>
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Remove all shell session elements added by the Activate script, including the
|
||||||
|
addition of the virtual environment's Python executable from the beginning of
|
||||||
|
the PATH variable.
|
||||||
|
|
||||||
|
.Parameter NonDestructive
|
||||||
|
If present, do not remove this function from the global namespace for the
|
||||||
|
session.
|
||||||
|
|
||||||
|
#>
|
||||||
|
function global:deactivate ([switch]$NonDestructive) {
|
||||||
|
# Revert to original values
|
||||||
|
|
||||||
|
# The prior prompt:
|
||||||
|
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
||||||
|
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
||||||
|
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PYTHONHOME:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PATH:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the VIRTUAL_ENV altogether:
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove VIRTUAL_ENV_PROMPT altogether.
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
||||||
|
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
||||||
|
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Leave deactivate function in the global namespace if requested:
|
||||||
|
if (-not $NonDestructive) {
|
||||||
|
Remove-Item -Path function:deactivate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Description
|
||||||
|
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
||||||
|
given folder, and returns them in a map.
|
||||||
|
|
||||||
|
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
||||||
|
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
||||||
|
then it is considered a `key = value` line. The left hand string is the key,
|
||||||
|
the right hand is the value.
|
||||||
|
|
||||||
|
If the value starts with a `'` or a `"` then the first and last character is
|
||||||
|
stripped from the value before being captured.
|
||||||
|
|
||||||
|
.Parameter ConfigDir
|
||||||
|
Path to the directory that contains the `pyvenv.cfg` file.
|
||||||
|
#>
|
||||||
|
function Get-PyVenvConfig(
|
||||||
|
[String]
|
||||||
|
$ConfigDir
|
||||||
|
) {
|
||||||
|
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
||||||
|
|
||||||
|
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
||||||
|
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
||||||
|
|
||||||
|
# An empty map will be returned if no config file is found.
|
||||||
|
$pyvenvConfig = @{ }
|
||||||
|
|
||||||
|
if ($pyvenvConfigPath) {
|
||||||
|
|
||||||
|
Write-Verbose "File exists, parse `key = value` lines"
|
||||||
|
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
||||||
|
|
||||||
|
$pyvenvConfigContent | ForEach-Object {
|
||||||
|
$keyval = $PSItem -split "\s*=\s*", 2
|
||||||
|
if ($keyval[0] -and $keyval[1]) {
|
||||||
|
$val = $keyval[1]
|
||||||
|
|
||||||
|
# Remove extraneous quotations around a string value.
|
||||||
|
if ("'""".Contains($val.Substring(0, 1))) {
|
||||||
|
$val = $val.Substring(1, $val.Length - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
$pyvenvConfig[$keyval[0]] = $val
|
||||||
|
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $pyvenvConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<# Begin Activate script --------------------------------------------------- #>
|
||||||
|
|
||||||
|
# Determine the containing directory of this script
|
||||||
|
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$VenvExecDir = Get-Item -Path $VenvExecPath
|
||||||
|
|
||||||
|
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
||||||
|
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
||||||
|
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
||||||
|
|
||||||
|
# Set values required in priority: CmdLine, ConfigFile, Default
|
||||||
|
# First, get the location of the virtual environment, it might not be
|
||||||
|
# VenvExecDir if specified on the command line.
|
||||||
|
if ($VenvDir) {
|
||||||
|
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
||||||
|
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
||||||
|
Write-Verbose "VenvDir=$VenvDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Next, read the `pyvenv.cfg` file to determine any required value such
|
||||||
|
# as `prompt`.
|
||||||
|
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
||||||
|
|
||||||
|
# Next, set the prompt from the command line, or the config file, or
|
||||||
|
# just use the name of the virtual environment folder.
|
||||||
|
if ($Prompt) {
|
||||||
|
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
||||||
|
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
||||||
|
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
||||||
|
$Prompt = $pyvenvCfg['prompt'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
|
||||||
|
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
||||||
|
$Prompt = Split-Path -Path $venvDir -Leaf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Prompt = '$Prompt'"
|
||||||
|
Write-Verbose "VenvDir='$VenvDir'"
|
||||||
|
|
||||||
|
# Deactivate any currently active virtual environment, but leave the
|
||||||
|
# deactivate function in place.
|
||||||
|
deactivate -nondestructive
|
||||||
|
|
||||||
|
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
||||||
|
# that there is an activated venv.
|
||||||
|
$env:VIRTUAL_ENV = $VenvDir
|
||||||
|
|
||||||
|
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||||
|
|
||||||
|
Write-Verbose "Setting prompt to '$Prompt'"
|
||||||
|
|
||||||
|
# Set the prompt to include the env name
|
||||||
|
# Make sure _OLD_VIRTUAL_PROMPT is global
|
||||||
|
function global:_OLD_VIRTUAL_PROMPT { "" }
|
||||||
|
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
||||||
|
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
||||||
|
|
||||||
|
function global:prompt {
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
||||||
|
_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
$env:VIRTUAL_ENV_PROMPT = $Prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear PYTHONHOME
|
||||||
|
if (Test-Path -Path Env:PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
Remove-Item -Path Env:PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the venv to the PATH
|
||||||
|
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
||||||
|
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
||||||
70
pythonBackend/venv/bin/activate
Normal file
70
pythonBackend/venv/bin/activate
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# This file must be used with "source bin/activate" *from bash*
|
||||||
|
# You cannot run it directly
|
||||||
|
|
||||||
|
deactivate () {
|
||||||
|
# reset old environment variables
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||||
|
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||||
|
export PATH
|
||||||
|
unset _OLD_VIRTUAL_PATH
|
||||||
|
fi
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||||
|
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||||
|
export PYTHONHOME
|
||||||
|
unset _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
||||||
|
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||||
|
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||||
|
export PS1
|
||||||
|
unset _OLD_VIRTUAL_PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset VIRTUAL_ENV
|
||||||
|
unset VIRTUAL_ENV_PROMPT
|
||||||
|
if [ ! "${1:-}" = "nondestructive" ] ; then
|
||||||
|
# Self destruct!
|
||||||
|
unset -f deactivate
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
# on Windows, a path can contain colons and backslashes and has to be converted:
|
||||||
|
if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
|
||||||
|
# transform D:\path\to\venv to /d/path/to/venv on MSYS
|
||||||
|
# and to /cygdrive/d/path/to/venv on Cygwin
|
||||||
|
export VIRTUAL_ENV=$(cygpath /home/fox/Documents/programming/Projects/JellyGlass/pythonBackend/venv)
|
||||||
|
else
|
||||||
|
# use the path as-is
|
||||||
|
export VIRTUAL_ENV=/home/fox/Documents/programming/Projects/JellyGlass/pythonBackend/venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
_OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
PATH="$VIRTUAL_ENV/"bin":$PATH"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||||
|
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||||
|
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||||
|
unset PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||||
|
PS1='(venv) '"${PS1:-}"
|
||||||
|
export PS1
|
||||||
|
VIRTUAL_ENV_PROMPT='(venv) '
|
||||||
|
export VIRTUAL_ENV_PROMPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
||||||
27
pythonBackend/venv/bin/activate.csh
Normal file
27
pythonBackend/venv/bin/activate.csh
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# This file must be used with "source bin/activate.csh" *from csh*.
|
||||||
|
# You cannot run it directly.
|
||||||
|
|
||||||
|
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
||||||
|
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||||
|
|
||||||
|
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
|
||||||
|
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
setenv VIRTUAL_ENV /home/fox/Documents/programming/Projects/JellyGlass/pythonBackend/venv
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
|
||||||
|
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||||
|
|
||||||
|
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||||
|
set prompt = '(venv) '"$prompt"
|
||||||
|
setenv VIRTUAL_ENV_PROMPT '(venv) '
|
||||||
|
endif
|
||||||
|
|
||||||
|
alias pydoc python -m pydoc
|
||||||
|
|
||||||
|
rehash
|
||||||
69
pythonBackend/venv/bin/activate.fish
Normal file
69
pythonBackend/venv/bin/activate.fish
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
|
||||||
|
# (https://fishshell.com/). You cannot run it directly.
|
||||||
|
|
||||||
|
function deactivate -d "Exit virtual environment and return to normal shell environment"
|
||||||
|
# reset old environment variables
|
||||||
|
if test -n "$_OLD_VIRTUAL_PATH"
|
||||||
|
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||||
|
set -e _OLD_VIRTUAL_PATH
|
||||||
|
end
|
||||||
|
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
||||||
|
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
set -e _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||||
|
set -e _OLD_FISH_PROMPT_OVERRIDE
|
||||||
|
# prevents error when using nested fish instances (Issue #93858)
|
||||||
|
if functions -q _old_fish_prompt
|
||||||
|
functions -e fish_prompt
|
||||||
|
functions -c _old_fish_prompt fish_prompt
|
||||||
|
functions -e _old_fish_prompt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -e VIRTUAL_ENV
|
||||||
|
set -e VIRTUAL_ENV_PROMPT
|
||||||
|
if test "$argv[1]" != "nondestructive"
|
||||||
|
# Self-destruct!
|
||||||
|
functions -e deactivate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
set -gx VIRTUAL_ENV /home/fox/Documents/programming/Projects/JellyGlass/pythonBackend/venv
|
||||||
|
|
||||||
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
|
set -gx PATH "$VIRTUAL_ENV/"bin $PATH
|
||||||
|
|
||||||
|
# Unset PYTHONHOME if set.
|
||||||
|
if set -q PYTHONHOME
|
||||||
|
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
||||||
|
set -e PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||||
|
# fish uses a function instead of an env var to generate the prompt.
|
||||||
|
|
||||||
|
# Save the current fish_prompt function as the function _old_fish_prompt.
|
||||||
|
functions -c fish_prompt _old_fish_prompt
|
||||||
|
|
||||||
|
# With the original prompt function renamed, we can override with our own.
|
||||||
|
function fish_prompt
|
||||||
|
# Save the return status of the last command.
|
||||||
|
set -l old_status $status
|
||||||
|
|
||||||
|
# Output the venv prompt; color taken from the blue of the Python logo.
|
||||||
|
printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal)
|
||||||
|
|
||||||
|
# Restore the return status of the previous command.
|
||||||
|
echo "exit $old_status" | .
|
||||||
|
# Output the original/"old" prompt.
|
||||||
|
_old_fish_prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
||||||
|
set -gx VIRTUAL_ENV_PROMPT '(venv) '
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue