Compare commits
	
		
			2 Commits
		
	
	
		
			bec294365f
			...
			b12e3315fe
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b12e3315fe | |||
| da4ee81c95 | 
| @@ -40,8 +40,7 @@ public class CloudflareRealtimeService : IRealtimeService | ||||
|         var requestBody = new | ||||
|         { | ||||
|             title = roomName, | ||||
|             preferred_region = _configuration["Realtime:Cloudflare:PreferredRegion"], | ||||
|             data = metadata | ||||
|             preferred_region = _configuration["Realtime:Cloudflare:PreferredRegion"] | ||||
|         }; | ||||
|  | ||||
|         var content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json"); | ||||
| @@ -106,11 +105,15 @@ public class CloudflareRealtimeService : IRealtimeService | ||||
|             } | ||||
|  | ||||
|             // Participant doesn't exist, create a new one | ||||
|             var baseUrl = _configuration["BaseUrl"]; | ||||
|             var requestBody = new | ||||
|             { | ||||
|                 name = "@" + account.Name, | ||||
|                 picture = account.Profile.Picture is not null | ||||
|                     ? $"{baseUrl}/api/files/{account.Profile.Picture.Id}" | ||||
|                     : null, | ||||
|                 preset_name = isAdmin ? "group_call_host" : "group_call_participant", | ||||
|                 custom_user_id = account.Id.ToString() | ||||
|                 custom_participant_id = account.Id.ToString() | ||||
|             }; | ||||
|  | ||||
|             var content = new StringContent( | ||||
|   | ||||
| @@ -6,11 +6,6 @@ using Swashbuckle.AspNetCore.Annotations; | ||||
|  | ||||
| namespace DysonNetwork.Sphere.Chat; | ||||
|  | ||||
| public class RealtimeChatConfiguration | ||||
| { | ||||
|     public string Endpoint { get; set; } = null!; | ||||
| } | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/chat/realtime")] | ||||
| public class RealtimeCallController( | ||||
| @@ -20,9 +15,6 @@ public class RealtimeCallController( | ||||
|     IRealtimeService realtime | ||||
| ) : ControllerBase | ||||
| { | ||||
|     private readonly RealtimeChatConfiguration _config = | ||||
|         configuration.GetSection("RealtimeChat").Get<RealtimeChatConfiguration>()!; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// This endpoint is especially designed for livekit webhooks, | ||||
|     /// for update the call participates and more. | ||||
| @@ -35,9 +27,9 @@ public class RealtimeCallController( | ||||
|         using var reader = new StreamReader(Request.Body); | ||||
|         var postData = await reader.ReadToEndAsync(); | ||||
|         var authHeader = Request.Headers.Authorization.ToString(); | ||||
|          | ||||
|  | ||||
|         await realtime.ReceiveWebhook(postData, authHeader); | ||||
|      | ||||
|  | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
| @@ -90,11 +82,17 @@ public class RealtimeCallController( | ||||
|             return BadRequest("Call session is not properly configured."); | ||||
|  | ||||
|         var isAdmin = member.Role >= ChatMemberRole.Moderator; | ||||
|         var userToken = realtime.GetUserToken(currentUser, ongoingCall.SessionId, isAdmin); | ||||
|         var userToken = await realtime.GetUserTokenAsync(currentUser, ongoingCall.SessionId, isAdmin); | ||||
|  | ||||
|         // Get LiveKit endpoint from configuration | ||||
|         var endpoint = _config.Endpoint ?? | ||||
|                    throw new InvalidOperationException("LiveKit endpoint configuration is missing"); | ||||
|         var endpoint = configuration[$"Realtime:{realtime.ProviderName}:Endpoint"] ?? realtime.ProviderName switch | ||||
|         { | ||||
|             // Unusable for sure, just for placeholder | ||||
|             "LiveKit" => "https://livekit.cloud", | ||||
|             "Cloudflare" => "https://rtk.realtime.cloudflare.com/v2", | ||||
|             // Unusable for sure, just for placeholder | ||||
|             _ => "https://example.com"  | ||||
|         }; | ||||
|  | ||||
|         // Create the response model | ||||
|         var response = new JoinCallResponse | ||||
| @@ -162,7 +160,7 @@ public class JoinCallResponse | ||||
|     public string Provider { get; set; } = null!; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The LiveKit server endpoint | ||||
|     /// The provider server endpoint | ||||
|     /// </summary> | ||||
|     public string Endpoint { get; set; } = null!; | ||||
|  | ||||
| @@ -196,24 +194,24 @@ public class CallParticipant | ||||
|     /// The participant's identity (username) | ||||
|     /// </summary> | ||||
|     public string Identity { get; set; } = null!; | ||||
|      | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The participant's display name | ||||
|     /// </summary> | ||||
|     public string Name { get; set; } = null!; | ||||
|      | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The participant's account ID if available | ||||
|     /// </summary> | ||||
|     public Guid? AccountId { get; set; } | ||||
|      | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The participant's profile in the chat | ||||
|     /// </summary> | ||||
|     public ChatMember? Profile { get; set; } | ||||
|      | ||||
|  | ||||
|     /// <summary> | ||||
|     /// When the participant joined the call | ||||
|     /// </summary> | ||||
|     public DateTime JoinedAt { get; set; } | ||||
| } | ||||
| } | ||||
| @@ -31,7 +31,10 @@ public class ClientTypeMiddleware(RequestDelegate next) | ||||
|  | ||||
|         context.Items["IsWebPage"] = isWebPage; | ||||
|  | ||||
|         if (!isWebPage && context.Request.Path != "/ws" && !context.Request.Path.StartsWithSegments("/api")) | ||||
|         var redirectWhiteList = new[] { "/ws", "/.well-known", "/swagger" }; | ||||
|         if(redirectWhiteList.Any(w => context.Request.Path.StartsWithSegments(w))) | ||||
|             await next(context); | ||||
|         else if (!isWebPage && !context.Request.Path.StartsWithSegments("/api")) | ||||
|             context.Response.Redirect( | ||||
|                 $"/api{context.Request.Path.Value}{context.Request.QueryString.Value}", | ||||
|                 permanent: false | ||||
|   | ||||
| @@ -86,7 +86,7 @@ | ||||
|     "SubjectPrefix": "Solar Network" | ||||
|   }, | ||||
|   "Realtime": { | ||||
|     "Provider": "LiveKit", | ||||
|     "Provider": "Cloudflare", | ||||
|     "LiveKit": { | ||||
|       "Endpoint": "https://solar-network-im44o8gq.livekit.cloud", | ||||
|       "ApiKey": "APIs6TiL8wj3A4j", | ||||
|   | ||||
| @@ -85,6 +85,7 @@ | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASourceCustom_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fdaa8d9c408cd4b4286bbef7e35f1a42e31c00_003F45_003F5839ca6c_003FSourceCustom_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStackFrameIterator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3bef61b8a21d4c8e96872ecdd7782fa0e55000_003F7a_003F870020d0_003FStackFrameIterator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStackFrameIterator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb6f0571a6bc744b0b551fd4578292582e54c00_003Fdf_003F3fcdc4d2_003FStackFrameIterator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStackFrameIterator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe6898c1ddf974e16b95b114722270029e55000_003F6b_003F7530575d_003FStackFrameIterator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStatusCodeResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0b5acdd962e549369896cece0026e556214600_003F7c_003F8b7572ae_003FStatusCodeResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASyndicationFeed_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5b43b9cf654743f8b9a2eee23c625dd21dd30_003Fad_003Fd26b4d73_003FSyndicationFeed_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASyndicationItem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5b43b9cf654743f8b9a2eee23c625dd21dd30_003Fe1_003Fb136d7be_003FSyndicationItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user