configure grpc client + scanner fixes; need to figure out cors issue

This commit is contained in:
2026-01-17 20:04:28 -05:00
parent b762139243
commit 3ab9c9baf1
8 changed files with 94 additions and 9 deletions

View File

@@ -13,6 +13,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.64.0" /> <PackageReference Include="Grpc.AspNetCore" Version="2.64.0" />
<PackageReference Include="Grpc.AspNetCore.Web" Version="2.76.0" />
<PackageReference Include="MaybeError" Version="1.2.0" /> <PackageReference Include="MaybeError" Version="1.2.0" />
<PackageReference Include="MongoDB.Driver" Version="3.5.2" /> <PackageReference Include="MongoDB.Driver" Version="3.5.2" />
</ItemGroup> </ItemGroup>

View File

@@ -35,6 +35,7 @@ public partial class MediaEntry
return new MediaEntry return new MediaEntry
{ {
Version = 0,
CameraId = int.Parse(cam.Value), CameraId = int.Parse(cam.Value),
Filepath = relativePath, Filepath = relativePath,
Date = ParseDate(date.Value), Date = ParseDate(date.Value),

View File

@@ -4,6 +4,21 @@ using AZKiServer.Services;
using MongoDB.Driver; using MongoDB.Driver;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(o =>
{
//o.Limits.MaxRequestBodySize = null;
#if !DEBUG
o.ListenAnyIP(8081, lo =>
{
lo.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
});
o.ListenAnyIP(8080, lo =>
{
lo.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http1AndHttp2;
});
#endif
});
var config = builder.Configuration; var config = builder.Configuration;
var dbString = config["DB_STRING"]; var dbString = config["DB_STRING"];
@@ -13,8 +28,8 @@ var db = dbClient.GetDatabase("AZKi");
// Add services to the container. // Add services to the container.
builder.Services.AddSingleton(dbClient); builder.Services.AddSingleton(dbClient);
builder.Services.AddSingleton<IMongoDatabase>(db); builder.Services.AddSingleton<IMongoDatabase>(db);
builder.Services.AddGrpc();
builder.Services.AddControllers(opt => opt.ModelBinderProviders.Add(new BsonIdModelBinderProvider())); builder.Services.AddControllers(opt => opt.ModelBinderProviders.Add(new BsonIdModelBinderProvider()));
builder.Services.AddGrpc();
builder.Services.AddHostedService<FileScannerService>(); builder.Services.AddHostedService<FileScannerService>();
builder.Services.AddTransient<MediaService>(); builder.Services.AddTransient<MediaService>();
@@ -38,8 +53,20 @@ builder.Services.AddCors(o =>
var app = builder.Build(); var app = builder.Build();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
//app.UseAuthentication();
//app.UseAuthorization();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
//app.MapGrpcService<GreeterService>(); app.MapControllers();
app.MapGrpcService<AZKiRpcService>()
.AllowAnonymous()
.RequireCors("RPC");
app.MapFallbackToFile("index.html"); app.MapFallbackToFile("index.html");
app.Run(); app.Run();

View File

@@ -13,6 +13,7 @@ public class AZKiRpcService(MediaService mediaService) : RPC.AZKi.AZKiBase
var from = request.From.ToDateTime(); var from = request.From.ToDateTime();
var to = request.To.ToDateTime(); var to = request.To.ToDateTime();
var items = await mediaService.GetEntriesInRangeAsync(request.Type.FromRpc(), from, to); var items = await mediaService.GetEntriesInRangeAsync(request.Type.FromRpc(), from, to);
var result = new MediaList(); var result = new MediaList();
result.Entries.AddRange(items.Select(e => e.ToRpc())); result.Entries.AddRange(items.Select(e => e.ToRpc()));
return result; return result;

View File

@@ -14,13 +14,13 @@ public class FileScannerService(MediaService mediaService, IConfiguration config
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
var path = config["SCAN_PATH"]; var path = config["SCAN_LOCATION"];
if (string.IsNullOrWhiteSpace(path)) if (string.IsNullOrWhiteSpace(path))
return Task.CompletedTask; return Task.CompletedTask;
_timer = new Timer((_) => _timer = new Timer((_) =>
{ {
ScanFilesAsync(path).Wait(); ScanFilesAsync(path).Wait();
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromHours(1)); }, null, TimeSpan.FromMinutes(0), TimeSpan.FromHours(1));
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -33,6 +33,7 @@ public class FileScannerService(MediaService mediaService, IConfiguration config
private async Task ScanFilesAsync(string path) private async Task ScanFilesAsync(string path)
{ {
logger.LogInformation("Scanning Files");
try try
{ {
var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
@@ -41,11 +42,22 @@ public class FileScannerService(MediaService mediaService, IConfiguration config
foreach (var filePath in files) foreach (var filePath in files)
{ {
var relativePath = Path.GetRelativePath(path, filePath); var relativePath = Path.GetRelativePath(path, filePath);
if (relativePath[0] == '.') //Ignore hidden folders
continue;
if (existingFiles.Contains(relativePath)) if (existingFiles.Contains(relativePath))
continue; continue;
entries.Add(MediaEntry.Parse(relativePath)); var entry = MediaEntry.Parse(relativePath);
if(entry.HasError)
{
logger.LogError(entry.Error.GetException(), "Failed to parse file data");
continue;
} }
entries.Add(entry);
}
if(entries.Count > 0) {
await mediaService.AddMediaBulkAsync(entries); await mediaService.AddMediaBulkAsync(entries);
logger.LogInformation("Added {count} file entries", entries.Count);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,16 +1,47 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::components::playback::{Timeline, Viewport}; use crate::{
components::playback::{Timeline, Viewport},
rpc::{
azki::{MediaRangeRequest, MediaType},
get_rpc_client,
},
};
const PLAYER_CSS: Asset = asset!("/assets/styling/player.scss"); const PLAYER_CSS: Asset = asset!("/assets/styling/player.scss");
#[component] #[component]
pub fn Player() -> Element { pub fn Player() -> Element {
let entries = use_resource(|| async move {
let mut client = get_rpc_client();
let result = client
.get_media_entries_in_range(MediaRangeRequest {
r#type: MediaType::Video.into(),
..Default::default()
})
.await;
if let Ok(entries) = result {
let res = entries.into_inner();
return Ok(res.entries);
} else {
let err = result.err().unwrap();
let msg = err.message();
return Err(format!("Failed to load results: {msg}"));
}
});
let len = match entries.cloned() {
Some(value) => match value {
Ok(result) => result.len().to_string(),
Err(err) => err,
},
_ => "Not Loaded".to_string(),
};
rsx! { rsx! {
document::Link { rel: "stylesheet", href: PLAYER_CSS } document::Link { rel: "stylesheet", href: PLAYER_CSS }
div{ div{
id: "player", id: "player",
div { div {
id: "head" id: "head",
"r {len}"
} }
Viewport { } Viewport { }
Timeline { } Timeline { }

View File

@@ -8,7 +8,7 @@ mod rpc;
mod views; mod views;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub const RPC_HOST: &'static str = "http://localhost:8081"; pub const RPC_HOST: &'static str = "http://localhost:5177";
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
pub const RPC_HOST: &'static str = "https://grpc.aoba.app:8443"; pub const RPC_HOST: &'static str = "https://grpc.aoba.app:8443";

View File

@@ -47,3 +47,15 @@ impl Interceptor for AuthInterceptor {
return Ok(request); return Ok(request);
} }
} }
pub fn get_rpc_client() -> AzKiClient<InterceptedService<Client, AuthInterceptor>> {
return RPC_CLIENT.get_client();
}
pub fn login(jwt: String) {
*RPC_CLIENT.jwt.write().unwrap() = Some(jwt);
}
pub fn logout() {
*RPC_CLIENT.jwt.write().unwrap() = None;
}