mirror of
https://github.com/CannedNet/CannedNet.git
synced 2026-10-25 23:18:54 -07:00
a few changes
- fixes nullrefs on notifications
This commit is contained in:
@@ -50,3 +50,4 @@ public class NotificationsHub : Hub
|
|||||||
return Context.GetHttpContext()?.RequestServices.GetService(typeof(T)) as T;
|
return Context.GetHttpContext()?.RequestServices.GetService(typeof(T)) as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"CDN": "https://cdn.lapis.codes",
|
"CDN": "https://cdn.lapis.codes",
|
||||||
"Commerce": "https://commerce.lapis.codes",
|
"Commerce": "https://commerce.lapis.codes",
|
||||||
"Matchmaking": "https://match.lapis.codes",
|
"Matchmaking": "https://match.lapis.codes",
|
||||||
"Storage": "https://storage.lapis.codes",
|
"Storage": "https://cdn.lapis.codes",
|
||||||
"Chat": "https://chatrr.lapis.codes",
|
"Chat": "https://chatrr.lapis.codes",
|
||||||
"Leaderboard": "https://leaderboard.lapis.codes",
|
"Leaderboard": "https://leaderboard.lapis.codes",
|
||||||
"Accounts": "https://accounts.lapis.codes",
|
"Accounts": "https://accounts.lapis.codes",
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ public class APIController
|
|||||||
var storefrontService = app.Services.GetRequiredService<StorefrontFillService>();
|
var storefrontService = app.Services.GetRequiredService<StorefrontFillService>();
|
||||||
var notificationService = app.Services.GetRequiredService<NotificationService>();
|
var notificationService = app.Services.GetRequiredService<NotificationService>();
|
||||||
|
|
||||||
|
MapImageEndpoints(app);
|
||||||
|
|
||||||
app.MapGet("/api/config/v1/amplitude", () => Results.Ok(new
|
app.MapGet("/api/config/v1/amplitude", () => Results.Ok(new
|
||||||
{
|
{
|
||||||
AmplitudeKey = "a",
|
AmplitudeKey = "a",
|
||||||
@@ -1371,11 +1373,11 @@ public class APIController
|
|||||||
var receivedGift = new ReceivedGift
|
var receivedGift = new ReceivedGift
|
||||||
{
|
{
|
||||||
ReceiverAccountId = receiverAccountId,
|
ReceiverAccountId = receiverAccountId,
|
||||||
FromPlayerId = senderPlayerId,
|
FromPlayerId = 1,
|
||||||
Message = buyRequest.Gift?.Message ?? "A gift for you <3",
|
Message = buyRequest.Gift?.Message ?? "A gift for you <3",
|
||||||
ConsumableItemDesc = giftDrop.ConsumableItemDesc ?? string.Empty,
|
ConsumableItemDesc = giftDrop.ConsumableItemDesc ?? string.Empty,
|
||||||
AvatarItemDesc = giftDrop.AvatarItemDesc ?? string.Empty,
|
AvatarItemDesc = giftDrop.AvatarItemDesc ?? string.Empty,
|
||||||
FriendlyName = giftDrop.FriendlyName ?? string.Empty,
|
// FriendlyName = giftDrop.FriendlyName ?? string.Empty,
|
||||||
AvatarItemType = giftDrop.AvatarItemType,
|
AvatarItemType = giftDrop.AvatarItemType,
|
||||||
EquipmentPrefabName = giftDrop.EquipmentPrefabName ?? string.Empty,
|
EquipmentPrefabName = giftDrop.EquipmentPrefabName ?? string.Empty,
|
||||||
EquipmentModificationGuid = giftDrop.EquipmentModificationGuid ?? string.Empty,
|
EquipmentModificationGuid = giftDrop.EquipmentModificationGuid ?? string.Empty,
|
||||||
@@ -1442,10 +1444,10 @@ public class APIController
|
|||||||
toAccountId: id,
|
toAccountId: id,
|
||||||
data: new Dictionary<string, object>
|
data: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "ItemId", buyRequest.PurchasableItemId },
|
{ "BalanceAddType", 1400 },
|
||||||
{ "Price", price.Price },
|
{ "Delta", -price.Price },
|
||||||
{ "CurrencyType", buyRequest.CurrencyType },
|
{ "Balance", tokenBalance.Balance },
|
||||||
{ "NewBalance", tokenBalance.Balance }
|
{ "CurrencyType", buyRequest.CurrencyType }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await notificationService.SendNotificationToPlayer(id, purchaseNotification);
|
await notificationService.SendNotificationToPlayer(id, purchaseNotification);
|
||||||
@@ -1570,7 +1572,7 @@ public class APIController
|
|||||||
var receivedGift = new ReceivedGift
|
var receivedGift = new ReceivedGift
|
||||||
{
|
{
|
||||||
ReceiverAccountId = id,
|
ReceiverAccountId = id,
|
||||||
FromPlayerId = null,
|
FromPlayerId = 1,
|
||||||
Message = message,
|
Message = message,
|
||||||
ConsumableItemDesc = consumableItemDesc,
|
ConsumableItemDesc = consumableItemDesc,
|
||||||
AvatarItemDesc = avatarItemDesc,
|
AvatarItemDesc = avatarItemDesc,
|
||||||
@@ -1597,7 +1599,7 @@ public class APIController
|
|||||||
var giftData = new
|
var giftData = new
|
||||||
{
|
{
|
||||||
Id = receivedGift.Id,
|
Id = receivedGift.Id,
|
||||||
FromPlayerId = (object?)null,
|
FromPlayerId = 1,
|
||||||
ConsumableItemDesc = consumableItemDesc,
|
ConsumableItemDesc = consumableItemDesc,
|
||||||
AvatarItemDesc = avatarItemDesc,
|
AvatarItemDesc = avatarItemDesc,
|
||||||
FriendlyName = friendlyName,
|
FriendlyName = friendlyName,
|
||||||
@@ -1746,39 +1748,7 @@ public class APIController
|
|||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
try
|
return Results.Ok(RecNetResult.Ok());
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(receivedGift.ConsumableItemDesc))
|
|
||||||
{
|
|
||||||
var consumableNotification = notificationService.CreateNotification(
|
|
||||||
PushNotificationId.ConsumableMappingAdded,
|
|
||||||
id: giftId,
|
|
||||||
toAccountId: id,
|
|
||||||
data: new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "Id", giftId },
|
|
||||||
{ "ConsumableType", "JfnVXFmilU6ysv-VbTAe3A" },
|
|
||||||
{ "PlatformMask", 4294967295 },
|
|
||||||
{ "Count", 1 },
|
|
||||||
{ "InitialCount", 1 },
|
|
||||||
{ "UnlockedLevel", 0 },
|
|
||||||
{ "CreatedAt", DateTime.UtcNow },
|
|
||||||
{ "IsActive", false },
|
|
||||||
{ "ActiveDurationMinutes", null },
|
|
||||||
{ "Category", 0 },
|
|
||||||
{ "IsPlatformLocked", false }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
await notificationService.SendNotificationToPlayer(id, consumableNotification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception notifEx)
|
|
||||||
{
|
|
||||||
// Log the error but don't fail the gift consumption
|
|
||||||
Console.WriteLine($"Error sending notification: {notifEx.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Ok(new { success = true });
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1855,4 +1825,58 @@ public class APIController
|
|||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly string ImagesDir;
|
||||||
|
static APIController()
|
||||||
|
{
|
||||||
|
var dir = "Images";
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
ImagesDir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapImageEndpoints(WebApplication app)
|
||||||
|
{
|
||||||
|
app.MapPost("/api/images/v4/uploadsaved", async (HttpContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var form = await context.Request.ReadFormAsync();
|
||||||
|
var file = form.Files.FirstOrDefault();
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { error = "No file found in request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageId = Guid.NewGuid().ToString("N");
|
||||||
|
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
||||||
|
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
extension = ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedFileName = imageId + extension;
|
||||||
|
var filePath = Path.Combine(ImagesDir, savedFileName);
|
||||||
|
|
||||||
|
using (var fileStream = File.Create(filePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Ok(new
|
||||||
|
{
|
||||||
|
ImageName = savedFileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Results.Problem($"Error uploading image: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,5 +453,61 @@ public class AccountsController
|
|||||||
|
|
||||||
return Results.Json(new { success = true });
|
return Results.Json(new { success = true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.MapPut("/account/me/profileimage", async (HttpRequest request, AppDbContext db) =>
|
||||||
|
{
|
||||||
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
var token = authHeader.Substring("Bearer ".Length);
|
||||||
|
var accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
if (!int.TryParse(accountId.AsSpan(), out var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newProfileImage = "";
|
||||||
|
|
||||||
|
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
request.EnableBuffering();
|
||||||
|
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body))
|
||||||
|
{
|
||||||
|
foreach (var pair in body.Split('&'))
|
||||||
|
{
|
||||||
|
var keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length == 2)
|
||||||
|
{
|
||||||
|
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
var value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "imageName")
|
||||||
|
newProfileImage = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
var account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
account.ProfileImage = newProfileImage;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,50 @@ public class CDNController
|
|||||||
var json = File.ReadAllText("JSON/loadingscreentipdata.json");
|
var json = File.ReadAllText("JSON/loadingscreentipdata.json");
|
||||||
return Results.Content(json, "application/json");
|
return Results.Content(json, "application/json");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.MapPost("/upload", async (HttpContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var form = await context.Request.ReadFormAsync();
|
||||||
|
var file = form.Files.FirstOrDefault();
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { error = "No file found in request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageId = Guid.NewGuid().ToString("N");
|
||||||
|
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
||||||
|
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
extension = ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedFileName = imageId + extension;
|
||||||
|
var filePath = Path.Combine("Images", savedFileName);
|
||||||
|
|
||||||
|
if (!Directory.Exists("Images"))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("Images");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var fileStream = File.Create(filePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Ok(new
|
||||||
|
{
|
||||||
|
filename = savedFileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Results.Problem($"Error uploading image: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,9 +8,54 @@ public class ImageController
|
|||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
public void MapEndpoints(WebApplication app)
|
||||||
{
|
{
|
||||||
|
var imagesDir = "Images";
|
||||||
|
if (!Directory.Exists(imagesDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(imagesDir);
|
||||||
|
}
|
||||||
|
|
||||||
app.MapGet("/{imageId}", (string imageId, HttpContext context) =>
|
app.MapGet("/{imageId}", (string imageId, HttpContext context) =>
|
||||||
{
|
{
|
||||||
var imagesDir = "Images";
|
if (!Directory.Exists(imagesDir))
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 404;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = Directory.GetFiles(imagesDir, $"{imageId}.*");
|
||||||
|
var filePath = files.FirstOrDefault();
|
||||||
|
|
||||||
|
if (filePath == null)
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 404;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = Path.GetExtension(filePath).ToLowerInvariant();
|
||||||
|
var contentType = extension switch
|
||||||
|
{
|
||||||
|
".png" => "image/png",
|
||||||
|
".jpg" or ".jpeg" => "image/jpeg",
|
||||||
|
".gif" => "image/gif",
|
||||||
|
".webp" => "image/webp",
|
||||||
|
".bmp" => "image/bmp",
|
||||||
|
_ => "application/octet-stream"
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Response.ContentType = contentType;
|
||||||
|
return File.OpenRead(filePath).CopyToAsync(context.Response.Body);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.MapGet("/", (HttpContext context) =>
|
||||||
|
{
|
||||||
|
var imageId = context.Request.Query["imageId"].FirstOrDefault();
|
||||||
|
var sig = context.Request.Query["sig"].FirstOrDefault();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(imageId))
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 400;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Directory.Exists(imagesDir))
|
if (!Directory.Exists(imagesDir))
|
||||||
{
|
{
|
||||||
@@ -41,5 +86,47 @@ public class ImageController
|
|||||||
context.Response.ContentType = contentType;
|
context.Response.ContentType = contentType;
|
||||||
return File.OpenRead(filePath).CopyToAsync(context.Response.Body);
|
return File.OpenRead(filePath).CopyToAsync(context.Response.Body);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.MapPost("/api/images/v4/uploadsaved", async (HttpContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var form = await context.Request.ReadFormAsync();
|
||||||
|
var file = form.Files.FirstOrDefault();
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
{
|
||||||
|
return Results.BadRequest(new { error = "No file found in request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageId = Guid.NewGuid().ToString("N");
|
||||||
|
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
var validExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp" };
|
||||||
|
if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
extension = ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedFileName = imageId + extension;
|
||||||
|
var filePath = Path.Combine(imagesDir, savedFileName);
|
||||||
|
|
||||||
|
using (var fileStream = File.Create(filePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Ok(new
|
||||||
|
{
|
||||||
|
imageId = imageId,
|
||||||
|
imageUrl = $"/{imageId}{extension}",
|
||||||
|
success = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Results.Problem($"Error uploading image: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,12 +96,10 @@ public class MatchmakingController
|
|||||||
RoomInstance? instanceToUse;
|
RoomInstance? instanceToUse;
|
||||||
string photonRoomId;
|
string photonRoomId;
|
||||||
|
|
||||||
// Check if player already has an instance in this room
|
|
||||||
var existingInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
var existingInstance = await db.RoomInstances.FirstOrDefaultAsync(r => r.OwnerAccountId == id && r.roomId == roomData.RoomId);
|
||||||
|
|
||||||
if (existingInstance != null)
|
if (existingInstance != null)
|
||||||
{
|
{
|
||||||
// Player already has an instance in this room, update it
|
|
||||||
photonRoomId = existingInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
photonRoomId = existingInstance.photonRoomId ?? Guid.NewGuid().ToString();
|
||||||
existingInstance.roomInstanceId = existingInstance.Id;
|
existingInstance.roomInstanceId = existingInstance.Id;
|
||||||
existingInstance.roomId = roomData.RoomId;
|
existingInstance.roomId = roomData.RoomId;
|
||||||
@@ -156,7 +154,7 @@ public class MatchmakingController
|
|||||||
name = roomData.Name,
|
name = roomData.Name,
|
||||||
maxCapacity = maxCapacity,
|
maxCapacity = maxCapacity,
|
||||||
isFull = false,
|
isFull = false,
|
||||||
isPrivate = roomData.IsDorm || roomData.RoomId == 1, // Private if it's a dorm or special room
|
isPrivate = roomData.IsDorm || roomData.RoomId == 1,
|
||||||
isInProgress = false,
|
isInProgress = false,
|
||||||
EncryptVoiceChat = roomData.EncryptVoiceChat
|
EncryptVoiceChat = roomData.EncryptVoiceChat
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using CannedNet.Hubs;
|
|
||||||
using CannedNet.Services.Infrastructure;
|
using CannedNet.Services.Infrastructure;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
@@ -9,16 +8,11 @@ public class NSController
|
|||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
public void MapEndpoints(WebApplication app)
|
||||||
{
|
{
|
||||||
|
// Rec Room automatically calls this and sets the endpoints that correspond to services in the JSON file. These will be moved to the main server config once I get there.
|
||||||
app.MapGet("/", () =>
|
app.MapGet("/", () =>
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText("JSON/endpoints.json");
|
var json = File.ReadAllText("JSON/endpoints.json");
|
||||||
return Results.Content(json, "application/json");
|
return Results.Content(json, "application/json");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.MapGet("/photon", () =>
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/photonsettings.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ public class JwtTokenService
|
|||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new Claim("iss", "https://rr.lapis.codes"),
|
new Claim("iss", "https://api.lapis.codes"),
|
||||||
new Claim("nbf", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
|
new Claim("nbf", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
|
||||||
new Claim("iat", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
|
new Claim("iat", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
|
||||||
new Claim("exp", ((DateTimeOffset)exp).ToUnixTimeSeconds().ToString()),
|
new Claim("exp", ((DateTimeOffset)exp).ToUnixTimeSeconds().ToString()),
|
||||||
new Claim("aud", "https://rr.lapis.codes/resources"),
|
new Claim("aud", "https://api.lapis.codes/resources"),
|
||||||
new Claim("amr", "cached_login"),
|
new Claim("amr", "cached_login"),
|
||||||
new Claim("client_id", "recroom"),
|
new Claim("client_id", "recroom"),
|
||||||
new Claim("sub", accountId),
|
new Claim("sub", accountId),
|
||||||
@@ -43,6 +43,8 @@ public class JwtTokenService
|
|||||||
new Claim("rn.ver", "20210129"),
|
new Claim("rn.ver", "20210129"),
|
||||||
new Claim("rn.plat", "0"),
|
new Claim("rn.plat", "0"),
|
||||||
new Claim("role", "gameClient"),
|
new Claim("role", "gameClient"),
|
||||||
|
new Claim("role", "developer"),
|
||||||
|
new Claim("role", "moderator"),
|
||||||
new Claim("jti", Guid.NewGuid().ToString("N").Substring(0, 32).ToUpper())
|
new Claim("jti", Guid.NewGuid().ToString("N").Substring(0, 32).ToUpper())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -205,55 +205,41 @@ public class NotificationService
|
|||||||
|
|
||||||
private static async Task SendToConnection(IHubContext<NotificationsHub> hubContext, string connectionId, NotificationMessage notification)
|
private static async Task SendToConnection(IHubContext<NotificationsHub> hubContext, string connectionId, NotificationMessage notification)
|
||||||
{
|
{
|
||||||
var notificationData = BuildNotificationObject(notification);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var json = JsonSerializer.Serialize(notificationData);
|
var msgData = new Dictionary<string, object>();
|
||||||
System.Console.WriteLine($"[NotificationService] Sending notification to {connectionId}: {json}");
|
if (notification.Data != null)
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"[NotificationService] Error serializing notification: {ex.Message}");
|
|
||||||
}
|
|
||||||
await hubContext.Clients.Client(connectionId).SendAsync("Notification", notificationData);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, object?> BuildNotificationObject(NotificationMessage notification)
|
|
||||||
{
|
|
||||||
var dict = new Dictionary<string, object?>
|
|
||||||
{
|
|
||||||
{ "notificationId", notification.NotificationId ?? "" },
|
|
||||||
{ "notificationType", (int?)notification.NotificationType ?? 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only add optional fields if they have values
|
|
||||||
if (notification.Id.HasValue)
|
|
||||||
dict.Add("id", notification.Id.Value);
|
|
||||||
if (notification.FromAccountId.HasValue)
|
|
||||||
dict.Add("fromAccountId", notification.FromAccountId.Value);
|
|
||||||
if (notification.ToAccountId.HasValue)
|
|
||||||
dict.Add("toAccountId", notification.ToAccountId.Value);
|
|
||||||
if (notification.CreatedAt.HasValue)
|
|
||||||
dict.Add("createdAt", notification.CreatedAt.Value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
|
||||||
|
|
||||||
// Properly serialize the data dictionary, converting DateTime objects to ISO 8601 strings
|
|
||||||
var serializedData = new Dictionary<string, object>();
|
|
||||||
if (notification.Data != null && notification.Data.Count > 0)
|
|
||||||
{
|
{
|
||||||
foreach (var kvp in notification.Data)
|
foreach (var kvp in notification.Data)
|
||||||
{
|
{
|
||||||
|
if (kvp.Value == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (kvp.Value is DateTime dt)
|
if (kvp.Value is DateTime dt)
|
||||||
{
|
{
|
||||||
serializedData[kvp.Key] = dt.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
|
msgData[kvp.Key] = dt.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
|
||||||
}
|
}
|
||||||
else if (kvp.Value != null)
|
else
|
||||||
{
|
{
|
||||||
serializedData[kvp.Key] = kvp.Value;
|
msgData[kvp.Key] = kvp.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dict.Add("data", serializedData);
|
var notificationData = new
|
||||||
return dict;
|
{
|
||||||
|
Id = (int?)notification.NotificationType ?? 0,
|
||||||
|
Msg = msgData
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonSerializer.Serialize(notificationData);
|
||||||
|
Console.WriteLine($"[NotificationService] Sending notification to {connectionId}: {json}");
|
||||||
|
|
||||||
|
await hubContext.Clients.Client(connectionId).SendAsync("Notification", json);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[NotificationService] Error sending notification: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user