From 3ab9c9baf1c158ca08a9570fac5abd3dfea4c8b4 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sat, 17 Jan 2026 20:04:28 -0500 Subject: [PATCH] configure grpc client + scanner fixes; need to figure out cors issue --- AZKiServer/AZKi Server.csproj | 1 + AZKiServer/Models/MediaEntry.cs | 1 + AZKiServer/Program.cs | 31 ++++++++++++++++++-- AZKiServer/Services/AZKiRpcService.cs | 1 + AZKiServer/Services/FileScannerService.cs | 20 ++++++++++--- client/src/components/playback/player.rs | 35 +++++++++++++++++++++-- client/src/main.rs | 2 +- client/src/rpc.rs | 12 ++++++++ 8 files changed, 94 insertions(+), 9 deletions(-) diff --git a/AZKiServer/AZKi Server.csproj b/AZKiServer/AZKi Server.csproj index 0c9054a..9ad9d00 100644 --- a/AZKiServer/AZKi Server.csproj +++ b/AZKiServer/AZKi Server.csproj @@ -13,6 +13,7 @@ + diff --git a/AZKiServer/Models/MediaEntry.cs b/AZKiServer/Models/MediaEntry.cs index b1f51b9..caa7c55 100644 --- a/AZKiServer/Models/MediaEntry.cs +++ b/AZKiServer/Models/MediaEntry.cs @@ -35,6 +35,7 @@ public partial class MediaEntry return new MediaEntry { + Version = 0, CameraId = int.Parse(cam.Value), Filepath = relativePath, Date = ParseDate(date.Value), diff --git a/AZKiServer/Program.cs b/AZKiServer/Program.cs index c759de4..de1fc04 100644 --- a/AZKiServer/Program.cs +++ b/AZKiServer/Program.cs @@ -4,6 +4,21 @@ using AZKiServer.Services; using MongoDB.Driver; 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 dbString = config["DB_STRING"]; @@ -13,8 +28,8 @@ var db = dbClient.GetDatabase("AZKi"); // Add services to the container. builder.Services.AddSingleton(dbClient); builder.Services.AddSingleton(db); -builder.Services.AddGrpc(); builder.Services.AddControllers(opt => opt.ModelBinderProviders.Add(new BsonIdModelBinderProvider())); +builder.Services.AddGrpc(); builder.Services.AddHostedService(); builder.Services.AddTransient(); @@ -38,8 +53,20 @@ builder.Services.AddCors(o => 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. -//app.MapGrpcService(); +app.MapControllers(); +app.MapGrpcService() + .AllowAnonymous() + .RequireCors("RPC"); app.MapFallbackToFile("index.html"); app.Run(); diff --git a/AZKiServer/Services/AZKiRpcService.cs b/AZKiServer/Services/AZKiRpcService.cs index 5bd7f5d..e0e44b7 100644 --- a/AZKiServer/Services/AZKiRpcService.cs +++ b/AZKiServer/Services/AZKiRpcService.cs @@ -13,6 +13,7 @@ public class AZKiRpcService(MediaService mediaService) : RPC.AZKi.AZKiBase var from = request.From.ToDateTime(); var to = request.To.ToDateTime(); var items = await mediaService.GetEntriesInRangeAsync(request.Type.FromRpc(), from, to); + var result = new MediaList(); result.Entries.AddRange(items.Select(e => e.ToRpc())); return result; diff --git a/AZKiServer/Services/FileScannerService.cs b/AZKiServer/Services/FileScannerService.cs index c5e6424..d766506 100644 --- a/AZKiServer/Services/FileScannerService.cs +++ b/AZKiServer/Services/FileScannerService.cs @@ -14,13 +14,13 @@ public class FileScannerService(MediaService mediaService, IConfiguration config public Task StartAsync(CancellationToken cancellationToken) { - var path = config["SCAN_PATH"]; + var path = config["SCAN_LOCATION"]; if (string.IsNullOrWhiteSpace(path)) return Task.CompletedTask; _timer = new Timer((_) => { ScanFilesAsync(path).Wait(); - }, null, TimeSpan.FromMinutes(1), TimeSpan.FromHours(1)); + }, null, TimeSpan.FromMinutes(0), TimeSpan.FromHours(1)); return Task.CompletedTask; } @@ -33,6 +33,7 @@ public class FileScannerService(MediaService mediaService, IConfiguration config private async Task ScanFilesAsync(string path) { + logger.LogInformation("Scanning Files"); try { var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); @@ -41,11 +42,22 @@ public class FileScannerService(MediaService mediaService, IConfiguration config foreach (var filePath in files) { var relativePath = Path.GetRelativePath(path, filePath); + if (relativePath[0] == '.') //Ignore hidden folders + continue; if (existingFiles.Contains(relativePath)) 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); + logger.LogInformation("Added {count} file entries", entries.Count); } - await mediaService.AddMediaBulkAsync(entries); } catch (Exception ex) { diff --git a/client/src/components/playback/player.rs b/client/src/components/playback/player.rs index 9ffc5e0..76627e3 100644 --- a/client/src/components/playback/player.rs +++ b/client/src/components/playback/player.rs @@ -1,16 +1,47 @@ 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"); #[component] 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! { document::Link { rel: "stylesheet", href: PLAYER_CSS } div{ id: "player", div { - id: "head" + id: "head", + "r {len}" } Viewport { } Timeline { } diff --git a/client/src/main.rs b/client/src/main.rs index a196b71..357cb75 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -8,7 +8,7 @@ mod rpc; mod views; #[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))] pub const RPC_HOST: &'static str = "https://grpc.aoba.app:8443"; diff --git a/client/src/rpc.rs b/client/src/rpc.rs index 10153a3..6960bd3 100644 --- a/client/src/rpc.rs +++ b/client/src/rpc.rs @@ -47,3 +47,15 @@ impl Interceptor for AuthInterceptor { return Ok(request); } } + +pub fn get_rpc_client() -> AzKiClient> { + 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; +}