Merge branch 'main' of https://github.com/Moonlight-Panel/Moonlight
This commit is contained in:
@@ -0,0 +1,146 @@
|
|||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Moonlight.App.Database.Entities.Notification;
|
||||||
|
using Moonlight.App.Models.Notifications;
|
||||||
|
using Moonlight.App.Repositories;
|
||||||
|
using Moonlight.App.Services;
|
||||||
|
using Moonlight.App.Services.Notifications;
|
||||||
|
using Moonlight.App.Services.Sessions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Http.Controllers.Api.Moonlight.Notifications;
|
||||||
|
|
||||||
|
public class ListenController : ControllerBase
|
||||||
|
{
|
||||||
|
internal WebSocket ws;
|
||||||
|
private bool active = true;
|
||||||
|
private bool isAuth = false;
|
||||||
|
private NotificationClient Client;
|
||||||
|
|
||||||
|
private readonly IdentityService IdentityService;
|
||||||
|
private readonly NotificationRepository NotificationRepository;
|
||||||
|
private readonly OneTimeJwtService OneTimeJwtService;
|
||||||
|
private readonly NotificationClientService NotificationClientService;
|
||||||
|
private readonly NotificationServerService NotificationServerService;
|
||||||
|
|
||||||
|
public ListenController(IdentityService identityService,
|
||||||
|
NotificationRepository notificationRepository,
|
||||||
|
OneTimeJwtService oneTimeJwtService,
|
||||||
|
NotificationClientService notificationClientService,
|
||||||
|
NotificationServerService notificationServerService)
|
||||||
|
{
|
||||||
|
IdentityService = identityService;
|
||||||
|
NotificationRepository = notificationRepository;
|
||||||
|
OneTimeJwtService = oneTimeJwtService;
|
||||||
|
NotificationClientService = notificationClientService;
|
||||||
|
NotificationServerService = notificationServerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/api/moonlight/notifications/listen")]
|
||||||
|
public async Task Get()
|
||||||
|
{
|
||||||
|
if (HttpContext.WebSockets.IsWebSocketRequest)
|
||||||
|
{
|
||||||
|
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
||||||
|
ws = webSocket;
|
||||||
|
await Echo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Echo()
|
||||||
|
{
|
||||||
|
while (active)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[1024 * 16];
|
||||||
|
var asg = new ArraySegment<byte>(bytes);
|
||||||
|
var res = await ws.ReceiveAsync(asg, CancellationToken.None);
|
||||||
|
|
||||||
|
var text = Encoding.UTF8.GetString(bytes).Trim('\0');
|
||||||
|
|
||||||
|
var obj = JsonConvert.DeserializeObject<BasicWSModel>(text);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(obj.Action))
|
||||||
|
{
|
||||||
|
await HandleRequest(text, obj.Action);
|
||||||
|
}
|
||||||
|
|
||||||
|
active = ws.State == WebSocketState.Open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleRequest(string text, string action)
|
||||||
|
{
|
||||||
|
if (!isAuth && action == "login")
|
||||||
|
await Login(text);
|
||||||
|
else if (!isAuth)
|
||||||
|
await ws.SendAsync(Encoding.UTF8.GetBytes("{\"error\": \"Unauthorised\"}"), WebSocketMessageType.Text,
|
||||||
|
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||||
|
else switch (action)
|
||||||
|
{
|
||||||
|
case "received":
|
||||||
|
await Received(text);
|
||||||
|
break;
|
||||||
|
case "read":
|
||||||
|
await Read(text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Login(string json)
|
||||||
|
{
|
||||||
|
var jwt = JsonConvert.DeserializeObject<Login>(json).token;
|
||||||
|
|
||||||
|
var dict = await OneTimeJwtService.Validate(jwt);
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
{
|
||||||
|
string error = "{\"status\":false}";
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(error);
|
||||||
|
await ws.SendAsync(bytes, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _clientId = dict["clientId"];
|
||||||
|
var clientId = int.Parse(_clientId);
|
||||||
|
|
||||||
|
var client = NotificationRepository.GetClients().Include(x => x.User).First(x => x.Id == clientId);
|
||||||
|
|
||||||
|
Client = client;
|
||||||
|
await InitWebsocket();
|
||||||
|
|
||||||
|
string success = "{\"status\":true}";
|
||||||
|
var byt = Encoding.UTF8.GetBytes(success);
|
||||||
|
await ws.SendAsync(byt, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InitWebsocket()
|
||||||
|
{
|
||||||
|
NotificationClientService.listenController = this;
|
||||||
|
NotificationClientService.WebsocketReady(Client);
|
||||||
|
|
||||||
|
isAuth = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Received(string json)
|
||||||
|
{
|
||||||
|
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
|
||||||
|
|
||||||
|
//TODO: Implement ws notification received
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Read(string json)
|
||||||
|
{
|
||||||
|
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
|
||||||
|
|
||||||
|
await NotificationServerService.SendAction(NotificationClientService.User,
|
||||||
|
JsonConvert.SerializeObject(new NotificationById() {Action = "hide", notification = id}));
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Moonlight/App/Models/Notifications/BasicWSModel.cs
Normal file
9
Moonlight/App/Models/Notifications/BasicWSModel.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Notifications;
|
||||||
|
|
||||||
|
public class BasicWSModel
|
||||||
|
{
|
||||||
|
[JsonProperty("action")]
|
||||||
|
public string Action { get; set; }
|
||||||
|
}
|
||||||
6
Moonlight/App/Models/Notifications/Login.cs
Normal file
6
Moonlight/App/Models/Notifications/Login.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Moonlight.App.Models.Notifications;
|
||||||
|
|
||||||
|
public class Login : BasicWSModel
|
||||||
|
{
|
||||||
|
public string token { get; set; }
|
||||||
|
}
|
||||||
6
Moonlight/App/Models/Notifications/NotificationById.cs
Normal file
6
Moonlight/App/Models/Notifications/NotificationById.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Moonlight.App.Models.Notifications;
|
||||||
|
|
||||||
|
public class NotificationById : BasicWSModel
|
||||||
|
{
|
||||||
|
public int notification { get; set; }
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using Moonlight.App.Database.Entities;
|
using System.Net.WebSockets;
|
||||||
|
using System.Text;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Database.Entities.Notification;
|
using Moonlight.App.Database.Entities.Notification;
|
||||||
|
using Moonlight.App.Http.Controllers.Api.Moonlight.Notifications;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
using Moonlight.App.Services.Sessions;
|
using Moonlight.App.Services.Sessions;
|
||||||
|
|
||||||
@@ -9,6 +12,7 @@ public class NotificationClientService
|
|||||||
{
|
{
|
||||||
private readonly NotificationRepository NotificationRepository;
|
private readonly NotificationRepository NotificationRepository;
|
||||||
private readonly NotificationServerService NotificationServerService;
|
private readonly NotificationServerService NotificationServerService;
|
||||||
|
internal ListenController listenController;
|
||||||
|
|
||||||
public NotificationClientService(NotificationRepository notificationRepository, NotificationServerService notificationServerService)
|
public NotificationClientService(NotificationRepository notificationRepository, NotificationServerService notificationServerService)
|
||||||
{
|
{
|
||||||
@@ -20,9 +24,10 @@ public class NotificationClientService
|
|||||||
|
|
||||||
public NotificationClient NotificationClient { get; set; }
|
public NotificationClient NotificationClient { get; set; }
|
||||||
|
|
||||||
public void SendAction(string action)
|
public async Task SendAction(string action)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
await listenController.ws.SendAsync(Encoding.UTF8.GetBytes(action), WebSocketMessageType.Text,
|
||||||
|
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WebsocketReady(NotificationClient client)
|
public void WebsocketReady(NotificationClient client)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Moonlight.App.Database.Entities;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Database.Entities.Notification;
|
using Moonlight.App.Database.Entities.Notification;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
|
|
||||||
@@ -40,9 +41,9 @@ public class NotificationServerService
|
|||||||
return connectedClients.Where(x => x.User == user).ToList();
|
return connectedClients.Where(x => x.User == user).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAction(User user, string action)
|
public async Task SendAction(User user, string action)
|
||||||
{
|
{
|
||||||
var clients = NotificationRepository.GetClients().Where(x => x.User == user).ToList();
|
var clients = NotificationRepository.GetClients().Include(x => x.User).Where(x => x.User == user).ToList();
|
||||||
|
|
||||||
foreach (var client in clients)
|
foreach (var client in clients)
|
||||||
{
|
{
|
||||||
@@ -52,12 +53,12 @@ public class NotificationServerService
|
|||||||
NotificationClient = client
|
NotificationClient = client
|
||||||
};
|
};
|
||||||
|
|
||||||
var connected = connectedClients.Where(x => x.NotificationClient == client).ToList();
|
var connected = connectedClients.Where(x => x.NotificationClient.Id == client.Id).ToList();
|
||||||
|
|
||||||
if (connected.Count > 0)
|
if (connected.Count > 0)
|
||||||
{
|
{
|
||||||
var clientService = connected[0];
|
var clientService = connected[0];
|
||||||
clientService.SendAction(action);
|
await clientService.SendAction(action);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ namespace Moonlight
|
|||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseWebSockets();
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user